mirror of
https://github.com/superseriousbusiness/gotosocial.git
synced 2025-11-26 03:03:31 -06:00
[chore] update otel libraries (#3740)
* chore: update otel dependencies * refactor: combine tracing & metrics in observability package * chore: update example tracing compose file
This commit is contained in:
parent
baed591a1d
commit
dd094e4012
217 changed files with 6873 additions and 2734 deletions
6
vendor/go.opentelemetry.io/otel/exporters/prometheus/config.go
generated
vendored
6
vendor/go.opentelemetry.io/otel/exporters/prometheus/config.go
generated
vendored
|
|
@ -7,6 +7,7 @@ import (
|
|||
"strings"
|
||||
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
"github.com/prometheus/common/model"
|
||||
|
||||
"go.opentelemetry.io/otel/attribute"
|
||||
"go.opentelemetry.io/otel/sdk/metric"
|
||||
|
|
@ -131,7 +132,10 @@ func WithoutScopeInfo() Option {
|
|||
// have special behavior based on their name.
|
||||
func WithNamespace(ns string) Option {
|
||||
return optionFunc(func(cfg config) config {
|
||||
ns = sanitizeName(ns)
|
||||
if model.NameValidationScheme != model.UTF8Validation {
|
||||
// Only sanitize if prometheus does not support UTF-8.
|
||||
ns = model.EscapeName(ns, model.NameEscapingScheme)
|
||||
}
|
||||
if !strings.HasSuffix(ns, "_") {
|
||||
// namespace and metric names should be separated with an underscore,
|
||||
// adds a trailing underscore if there is not one already.
|
||||
|
|
|
|||
204
vendor/go.opentelemetry.io/otel/exporters/prometheus/exporter.go
generated
vendored
204
vendor/go.opentelemetry.io/otel/exporters/prometheus/exporter.go
generated
vendored
|
|
@ -11,11 +11,10 @@ import (
|
|||
"slices"
|
||||
"strings"
|
||||
"sync"
|
||||
"unicode"
|
||||
"unicode/utf8"
|
||||
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
dto "github.com/prometheus/client_model/go"
|
||||
"github.com/prometheus/common/model"
|
||||
"google.golang.org/protobuf/proto"
|
||||
|
||||
"go.opentelemetry.io/otel"
|
||||
|
|
@ -34,15 +33,14 @@ const (
|
|||
scopeInfoMetricName = "otel_scope_info"
|
||||
scopeInfoDescription = "Instrumentation Scope metadata"
|
||||
|
||||
scopeNameLabel = "otel_scope_name"
|
||||
scopeVersionLabel = "otel_scope_version"
|
||||
|
||||
traceIDExemplarKey = "trace_id"
|
||||
spanIDExemplarKey = "span_id"
|
||||
)
|
||||
|
||||
var (
|
||||
scopeInfoKeys = [2]string{"otel_scope_name", "otel_scope_version"}
|
||||
|
||||
errScopeInvalid = errors.New("invalid scope")
|
||||
)
|
||||
var errScopeInvalid = errors.New("invalid scope")
|
||||
|
||||
// Exporter is a Prometheus Exporter that embeds the OTel metric.Reader
|
||||
// interface for easy instantiation with a MeterProvider.
|
||||
|
|
@ -188,7 +186,11 @@ func (c *collector) Collect(ch chan<- prometheus.Metric) {
|
|||
}
|
||||
|
||||
for _, scopeMetrics := range metrics.ScopeMetrics {
|
||||
var keys, values [2]string
|
||||
n := len(c.resourceKeyVals.keys) + 2 // resource attrs + scope name + scope version
|
||||
kv := keyVals{
|
||||
keys: make([]string, 0, n),
|
||||
vals: make([]string, 0, n),
|
||||
}
|
||||
|
||||
if !c.disableScopeInfo {
|
||||
scopeInfo, err := c.scopeInfo(scopeMetrics.Scope)
|
||||
|
|
@ -203,10 +205,13 @@ func (c *collector) Collect(ch chan<- prometheus.Metric) {
|
|||
|
||||
ch <- scopeInfo
|
||||
|
||||
keys = scopeInfoKeys
|
||||
values = [2]string{scopeMetrics.Scope.Name, scopeMetrics.Scope.Version}
|
||||
kv.keys = append(kv.keys, scopeNameLabel, scopeVersionLabel)
|
||||
kv.vals = append(kv.vals, scopeMetrics.Scope.Name, scopeMetrics.Scope.Version)
|
||||
}
|
||||
|
||||
kv.keys = append(kv.keys, c.resourceKeyVals.keys...)
|
||||
kv.vals = append(kv.vals, c.resourceKeyVals.vals...)
|
||||
|
||||
for _, m := range scopeMetrics.Metrics {
|
||||
typ := c.metricType(m)
|
||||
if typ == nil {
|
||||
|
|
@ -225,25 +230,27 @@ func (c *collector) Collect(ch chan<- prometheus.Metric) {
|
|||
|
||||
switch v := m.Data.(type) {
|
||||
case metricdata.Histogram[int64]:
|
||||
addHistogramMetric(ch, v, m, keys, values, name, c.resourceKeyVals)
|
||||
addHistogramMetric(ch, v, m, name, kv)
|
||||
case metricdata.Histogram[float64]:
|
||||
addHistogramMetric(ch, v, m, keys, values, name, c.resourceKeyVals)
|
||||
addHistogramMetric(ch, v, m, name, kv)
|
||||
case metricdata.Sum[int64]:
|
||||
addSumMetric(ch, v, m, keys, values, name, c.resourceKeyVals)
|
||||
addSumMetric(ch, v, m, name, kv)
|
||||
case metricdata.Sum[float64]:
|
||||
addSumMetric(ch, v, m, keys, values, name, c.resourceKeyVals)
|
||||
addSumMetric(ch, v, m, name, kv)
|
||||
case metricdata.Gauge[int64]:
|
||||
addGaugeMetric(ch, v, m, keys, values, name, c.resourceKeyVals)
|
||||
addGaugeMetric(ch, v, m, name, kv)
|
||||
case metricdata.Gauge[float64]:
|
||||
addGaugeMetric(ch, v, m, keys, values, name, c.resourceKeyVals)
|
||||
addGaugeMetric(ch, v, m, name, kv)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func addHistogramMetric[N int64 | float64](ch chan<- prometheus.Metric, histogram metricdata.Histogram[N], m metricdata.Metrics, ks, vs [2]string, name string, resourceKV keyVals) {
|
||||
func addHistogramMetric[N int64 | float64](ch chan<- prometheus.Metric, histogram metricdata.Histogram[N], m metricdata.Metrics, name string, kv keyVals) {
|
||||
for _, dp := range histogram.DataPoints {
|
||||
keys, values := getAttrs(dp.Attributes, ks, vs, resourceKV)
|
||||
keys, values := getAttrs(dp.Attributes)
|
||||
keys = append(keys, kv.keys...)
|
||||
values = append(values, kv.vals...)
|
||||
|
||||
desc := prometheus.NewDesc(name, m.Description, keys, nil)
|
||||
buckets := make(map[float64]uint64, len(dp.Bounds))
|
||||
|
|
@ -263,14 +270,16 @@ func addHistogramMetric[N int64 | float64](ch chan<- prometheus.Metric, histogra
|
|||
}
|
||||
}
|
||||
|
||||
func addSumMetric[N int64 | float64](ch chan<- prometheus.Metric, sum metricdata.Sum[N], m metricdata.Metrics, ks, vs [2]string, name string, resourceKV keyVals) {
|
||||
func addSumMetric[N int64 | float64](ch chan<- prometheus.Metric, sum metricdata.Sum[N], m metricdata.Metrics, name string, kv keyVals) {
|
||||
valueType := prometheus.CounterValue
|
||||
if !sum.IsMonotonic {
|
||||
valueType = prometheus.GaugeValue
|
||||
}
|
||||
|
||||
for _, dp := range sum.DataPoints {
|
||||
keys, values := getAttrs(dp.Attributes, ks, vs, resourceKV)
|
||||
keys, values := getAttrs(dp.Attributes)
|
||||
keys = append(keys, kv.keys...)
|
||||
values = append(values, kv.vals...)
|
||||
|
||||
desc := prometheus.NewDesc(name, m.Description, keys, nil)
|
||||
m, err := prometheus.NewConstMetric(desc, valueType, float64(dp.Value), values...)
|
||||
|
|
@ -278,14 +287,20 @@ func addSumMetric[N int64 | float64](ch chan<- prometheus.Metric, sum metricdata
|
|||
otel.Handle(err)
|
||||
continue
|
||||
}
|
||||
m = addExemplars(m, dp.Exemplars)
|
||||
// GaugeValues don't support Exemplars at this time
|
||||
// https://github.com/prometheus/client_golang/blob/aef8aedb4b6e1fb8ac1c90790645169125594096/prometheus/metric.go#L199
|
||||
if valueType != prometheus.GaugeValue {
|
||||
m = addExemplars(m, dp.Exemplars)
|
||||
}
|
||||
ch <- m
|
||||
}
|
||||
}
|
||||
|
||||
func addGaugeMetric[N int64 | float64](ch chan<- prometheus.Metric, gauge metricdata.Gauge[N], m metricdata.Metrics, ks, vs [2]string, name string, resourceKV keyVals) {
|
||||
func addGaugeMetric[N int64 | float64](ch chan<- prometheus.Metric, gauge metricdata.Gauge[N], m metricdata.Metrics, name string, kv keyVals) {
|
||||
for _, dp := range gauge.DataPoints {
|
||||
keys, values := getAttrs(dp.Attributes, ks, vs, resourceKV)
|
||||
keys, values := getAttrs(dp.Attributes)
|
||||
keys = append(keys, kv.keys...)
|
||||
values = append(values, kv.vals...)
|
||||
|
||||
desc := prometheus.NewDesc(name, m.Description, keys, nil)
|
||||
m, err := prometheus.NewConstMetric(desc, prometheus.GaugeValue, float64(dp.Value), values...)
|
||||
|
|
@ -297,61 +312,58 @@ func addGaugeMetric[N int64 | float64](ch chan<- prometheus.Metric, gauge metric
|
|||
}
|
||||
}
|
||||
|
||||
// getAttrs parses the attribute.Set to two lists of matching Prometheus-style
|
||||
// keys and values. It sanitizes invalid characters and handles duplicate keys
|
||||
// (due to sanitization) by sorting and concatenating the values following the spec.
|
||||
func getAttrs(attrs attribute.Set, ks, vs [2]string, resourceKV keyVals) ([]string, []string) {
|
||||
keysMap := make(map[string][]string)
|
||||
itr := attrs.Iter()
|
||||
for itr.Next() {
|
||||
kv := itr.Attribute()
|
||||
key := strings.Map(sanitizeRune, string(kv.Key))
|
||||
if _, ok := keysMap[key]; !ok {
|
||||
keysMap[key] = []string{kv.Value.Emit()}
|
||||
} else {
|
||||
// if the sanitized key is a duplicate, append to the list of keys
|
||||
keysMap[key] = append(keysMap[key], kv.Value.Emit())
|
||||
}
|
||||
}
|
||||
|
||||
// getAttrs converts the attribute.Set to two lists of matching Prometheus-style
|
||||
// keys and values.
|
||||
func getAttrs(attrs attribute.Set) ([]string, []string) {
|
||||
keys := make([]string, 0, attrs.Len())
|
||||
values := make([]string, 0, attrs.Len())
|
||||
for key, vals := range keysMap {
|
||||
keys = append(keys, key)
|
||||
slices.Sort(vals)
|
||||
values = append(values, strings.Join(vals, ";"))
|
||||
}
|
||||
itr := attrs.Iter()
|
||||
|
||||
if ks[0] != "" {
|
||||
keys = append(keys, ks[:]...)
|
||||
values = append(values, vs[:]...)
|
||||
if model.NameValidationScheme == model.UTF8Validation {
|
||||
// Do not perform sanitization if prometheus supports UTF-8.
|
||||
for itr.Next() {
|
||||
kv := itr.Attribute()
|
||||
keys = append(keys, string(kv.Key))
|
||||
values = append(values, kv.Value.Emit())
|
||||
}
|
||||
} else {
|
||||
// It sanitizes invalid characters and handles duplicate keys
|
||||
// (due to sanitization) by sorting and concatenating the values following the spec.
|
||||
keysMap := make(map[string][]string)
|
||||
for itr.Next() {
|
||||
kv := itr.Attribute()
|
||||
key := model.EscapeName(string(kv.Key), model.NameEscapingScheme)
|
||||
if _, ok := keysMap[key]; !ok {
|
||||
keysMap[key] = []string{kv.Value.Emit()}
|
||||
} else {
|
||||
// if the sanitized key is a duplicate, append to the list of keys
|
||||
keysMap[key] = append(keysMap[key], kv.Value.Emit())
|
||||
}
|
||||
}
|
||||
for key, vals := range keysMap {
|
||||
keys = append(keys, key)
|
||||
slices.Sort(vals)
|
||||
values = append(values, strings.Join(vals, ";"))
|
||||
}
|
||||
}
|
||||
|
||||
for idx := range resourceKV.keys {
|
||||
keys = append(keys, resourceKV.keys[idx])
|
||||
values = append(values, resourceKV.vals[idx])
|
||||
}
|
||||
|
||||
return keys, values
|
||||
}
|
||||
|
||||
func createInfoMetric(name, description string, res *resource.Resource) (prometheus.Metric, error) {
|
||||
keys, values := getAttrs(*res.Set(), [2]string{}, [2]string{}, keyVals{})
|
||||
keys, values := getAttrs(*res.Set())
|
||||
desc := prometheus.NewDesc(name, description, keys, nil)
|
||||
return prometheus.NewConstMetric(desc, prometheus.GaugeValue, float64(1), values...)
|
||||
}
|
||||
|
||||
func createScopeInfoMetric(scope instrumentation.Scope) (prometheus.Metric, error) {
|
||||
keys := scopeInfoKeys[:]
|
||||
desc := prometheus.NewDesc(scopeInfoMetricName, scopeInfoDescription, keys, nil)
|
||||
return prometheus.NewConstMetric(desc, prometheus.GaugeValue, float64(1), scope.Name, scope.Version)
|
||||
}
|
||||
attrs := make([]attribute.KeyValue, 0, scope.Attributes.Len()+2) // resource attrs + scope name + scope version
|
||||
attrs = append(attrs, scope.Attributes.ToSlice()...)
|
||||
attrs = append(attrs, attribute.String(scopeNameLabel, scope.Name))
|
||||
attrs = append(attrs, attribute.String(scopeVersionLabel, scope.Version))
|
||||
|
||||
func sanitizeRune(r rune) rune {
|
||||
if unicode.IsLetter(r) || unicode.IsDigit(r) || r == ':' || r == '_' {
|
||||
return r
|
||||
}
|
||||
return '_'
|
||||
keys, values := getAttrs(attribute.NewSet(attrs...))
|
||||
desc := prometheus.NewDesc(scopeInfoMetricName, scopeInfoDescription, keys, nil)
|
||||
return prometheus.NewConstMetric(desc, prometheus.GaugeValue, float64(1), values...)
|
||||
}
|
||||
|
||||
var unitSuffixes = map[string]string{
|
||||
|
|
@ -392,7 +404,11 @@ var unitSuffixes = map[string]string{
|
|||
|
||||
// getName returns the sanitized name, prefixed with the namespace and suffixed with unit.
|
||||
func (c *collector) getName(m metricdata.Metrics, typ *dto.MetricType) string {
|
||||
name := sanitizeName(m.Name)
|
||||
name := m.Name
|
||||
if model.NameValidationScheme != model.UTF8Validation {
|
||||
// Only sanitize if prometheus does not support UTF-8.
|
||||
name = model.EscapeName(name, model.NameEscapingScheme)
|
||||
}
|
||||
addCounterSuffix := !c.withoutCounterSuffixes && *typ == dto.MetricType_COUNTER
|
||||
if addCounterSuffix {
|
||||
// Remove the _total suffix here, as we will re-add the total suffix
|
||||
|
|
@ -411,59 +427,6 @@ func (c *collector) getName(m metricdata.Metrics, typ *dto.MetricType) string {
|
|||
return name
|
||||
}
|
||||
|
||||
func sanitizeName(n string) string {
|
||||
// This algorithm is based on strings.Map from Go 1.19.
|
||||
const replacement = '_'
|
||||
|
||||
valid := func(i int, r rune) bool {
|
||||
// Taken from
|
||||
// https://github.com/prometheus/common/blob/dfbc25bd00225c70aca0d94c3c4bb7744f28ace0/model/metric.go#L92-L102
|
||||
if (r >= 'a' && r <= 'z') || (r >= 'A' && r <= 'Z') || r == '_' || r == ':' || (r >= '0' && r <= '9' && i > 0) {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// This output buffer b is initialized on demand, the first time a
|
||||
// character needs to be replaced.
|
||||
var b strings.Builder
|
||||
for i, c := range n {
|
||||
if valid(i, c) {
|
||||
continue
|
||||
}
|
||||
|
||||
if i == 0 && c >= '0' && c <= '9' {
|
||||
// Prefix leading number with replacement character.
|
||||
b.Grow(len(n) + 1)
|
||||
_ = b.WriteByte(byte(replacement))
|
||||
break
|
||||
}
|
||||
b.Grow(len(n))
|
||||
_, _ = b.WriteString(n[:i])
|
||||
_ = b.WriteByte(byte(replacement))
|
||||
width := utf8.RuneLen(c)
|
||||
n = n[i+width:]
|
||||
break
|
||||
}
|
||||
|
||||
// Fast path for unchanged input.
|
||||
if b.Cap() == 0 { // b.Grow was not called above.
|
||||
return n
|
||||
}
|
||||
|
||||
for _, c := range n {
|
||||
// Due to inlining, it is more performant to invoke WriteByte rather then
|
||||
// WriteRune.
|
||||
if valid(1, c) { // We are guaranteed to not be at the start.
|
||||
_ = b.WriteByte(byte(c))
|
||||
} else {
|
||||
_ = b.WriteByte(byte(replacement))
|
||||
}
|
||||
}
|
||||
|
||||
return b.String()
|
||||
}
|
||||
|
||||
func (c *collector) metricType(m metricdata.Metrics) *dto.MetricType {
|
||||
switch v := m.Data.(type) {
|
||||
case metricdata.Histogram[int64], metricdata.Histogram[float64]:
|
||||
|
|
@ -489,7 +452,7 @@ func (c *collector) createResourceAttributes(res *resource.Resource) {
|
|||
defer c.mu.Unlock()
|
||||
|
||||
resourceAttrs, _ := res.Set().Filter(c.resourceAttributesFilter)
|
||||
resourceKeys, resourceValues := getAttrs(resourceAttrs, [2]string{}, [2]string{}, keyVals{})
|
||||
resourceKeys, resourceValues := getAttrs(resourceAttrs)
|
||||
c.resourceKeyVals = keyVals{keys: resourceKeys, vals: resourceValues}
|
||||
}
|
||||
|
||||
|
|
@ -584,7 +547,8 @@ func addExemplars[N int64 | float64](m prometheus.Metric, exemplars []metricdata
|
|||
func attributesToLabels(attrs []attribute.KeyValue) prometheus.Labels {
|
||||
labels := make(map[string]string)
|
||||
for _, attr := range attrs {
|
||||
labels[string(attr.Key)] = attr.Value.Emit()
|
||||
key := model.EscapeName(string(attr.Key), model.NameEscapingScheme)
|
||||
labels[key] = attr.Value.Emit()
|
||||
}
|
||||
return labels
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue