[chore] update dependencies (#4196)

- go.opentelemetry.io/contrib/exporters/autoexport v0.60.0 -> v0.61.0
- go.opentelemetry.io/contrib/instrumentation/runtime v0.60.0 -> v0.61.0

Reviewed-on: https://codeberg.org/superseriousbusiness/gotosocial/pulls/4196
Co-authored-by: kim <grufwub@gmail.com>
Co-committed-by: kim <grufwub@gmail.com>
This commit is contained in:
kim 2025-05-26 16:13:55 +02:00 committed by tobi
commit 143febb318
152 changed files with 2635 additions and 1688 deletions

View file

@ -13,6 +13,7 @@ import (
"strconv"
"strings"
"time"
"unicode"
"google.golang.org/grpc"
"google.golang.org/grpc/credentials"
@ -359,8 +360,9 @@ func WithTimeout(duration time.Duration) Option {
// explicitly returns a backoff time in the response, that time will take
// precedence over these settings.
//
// These settings do not define any network retry strategy. That is entirely
// handled by the gRPC ClientConn.
// These settings define the retry strategy implemented by the exporter.
// These settings do not define any network retry strategy.
// That is handled by the gRPC ClientConn.
//
// If unset, the default retry policy will be used. It will retry the export
// 5 seconds after receiving a retryable error and increase exponentially
@ -442,13 +444,15 @@ func convHeaders(s string) (map[string]string, error) {
continue
}
escKey, e := url.PathUnescape(rawKey)
if e != nil {
key := strings.TrimSpace(rawKey)
// Validate the key.
if !isValidHeaderKey(key) {
err = errors.Join(err, fmt.Errorf("invalid header key: %s", rawKey))
continue
}
key := strings.TrimSpace(escKey)
// Only decode the value.
escVal, e := url.PathUnescape(rawVal)
if e != nil {
err = errors.Join(err, fmt.Errorf("invalid header value: %s", rawVal))
@ -651,3 +655,22 @@ func fallback[T any](val T) resolver[T] {
return s
}
}
func isValidHeaderKey(key string) bool {
if key == "" {
return false
}
for _, c := range key {
if !isTokenChar(c) {
return false
}
}
return true
}
func isTokenChar(c rune) bool {
return c <= unicode.MaxASCII && (unicode.IsLetter(c) ||
unicode.IsDigit(c) ||
c == '!' || c == '#' || c == '$' || c == '%' || c == '&' || c == '\'' || c == '*' ||
c == '+' || c == '-' || c == '.' || c == '^' || c == '_' || c == '`' || c == '|' || c == '~')
}

View file

@ -1,4 +1,4 @@
// Code created by gotmpl. DO NOT MODIFY.
// Code generated by gotmpl. DO NOT MODIFY.
// source: internal/shared/otlp/retry/retry.go.tmpl
// Copyright The OpenTelemetry Authors
@ -14,7 +14,7 @@ import (
"fmt"
"time"
"github.com/cenkalti/backoff/v4"
"github.com/cenkalti/backoff/v5"
)
// DefaultConfig are the recommended defaults to use.
@ -77,12 +77,12 @@ func (c Config) RequestFunc(evaluate EvaluateFunc) RequestFunc {
RandomizationFactor: backoff.DefaultRandomizationFactor,
Multiplier: backoff.DefaultMultiplier,
MaxInterval: c.MaxInterval,
MaxElapsedTime: c.MaxElapsedTime,
Stop: backoff.Stop,
Clock: backoff.SystemClock,
}
b.Reset()
maxElapsedTime := c.MaxElapsedTime
startTime := time.Now()
for {
err := fn(ctx)
if err == nil {
@ -94,21 +94,17 @@ func (c Config) RequestFunc(evaluate EvaluateFunc) RequestFunc {
return err
}
bOff := b.NextBackOff()
if bOff == backoff.Stop {
if maxElapsedTime != 0 && time.Since(startTime) > maxElapsedTime {
return fmt.Errorf("max retry time elapsed: %w", err)
}
// Wait for the greater of the backoff or throttle delay.
var delay time.Duration
if bOff > throttle {
delay = bOff
} else {
elapsed := b.GetElapsedTime()
if b.MaxElapsedTime != 0 && elapsed+throttle > b.MaxElapsedTime {
return fmt.Errorf("max retry time would elapse: %w", err)
}
delay = throttle
bOff := b.NextBackOff()
delay := max(throttle, bOff)
elapsed := time.Since(startTime)
if maxElapsedTime != 0 && elapsed+throttle > maxElapsedTime {
return fmt.Errorf("max retry time would elapse: %w", err)
}
if ctxErr := waitFunc(ctx, delay); ctxErr != nil {

View file

@ -1,4 +1,4 @@
// Code created by gotmpl. DO NOT MODIFY.
// Code generated by gotmpl. DO NOT MODIFY.
// source: internal/shared/otlp/otlplog/transform/log.go.tmpl
// Copyright The OpenTelemetry Authors
@ -257,7 +257,7 @@ func stringSliceValues(vals []string) []*cpb.AnyValue {
return converted
}
// Attrs transforms a slice of [api.KeyValue] into OTLP key-values.
// LogAttrs transforms a slice of [api.KeyValue] into OTLP key-values.
func LogAttrs(attrs []api.KeyValue) []*cpb.KeyValue {
if len(attrs) == 0 {
return nil

View file

@ -5,5 +5,5 @@ package otlploggrpc // import "go.opentelemetry.io/otel/exporters/otlp/otlplog/o
// Version is the current release version of the OpenTelemetry OTLP over gRPC logs exporter in use.
func Version() string {
return "0.11.0"
return "0.12.2"
}

View file

@ -44,20 +44,23 @@ func newNoopClient() *client {
// newHTTPClient creates a new HTTP log client.
func newHTTPClient(cfg config) (*client, error) {
hc := &http.Client{
Transport: ourTransport,
Timeout: cfg.timeout.Value,
}
if cfg.tlsCfg.Value != nil || cfg.proxy.Value != nil {
clonedTransport := ourTransport.Clone()
hc.Transport = clonedTransport
if cfg.tlsCfg.Value != nil {
clonedTransport.TLSClientConfig = cfg.tlsCfg.Value
hc := cfg.httpClient
if hc == nil {
hc = &http.Client{
Transport: ourTransport,
Timeout: cfg.timeout.Value,
}
if cfg.proxy.Value != nil {
clonedTransport.Proxy = cfg.proxy.Value
if cfg.tlsCfg.Value != nil || cfg.proxy.Value != nil {
clonedTransport := ourTransport.Clone()
hc.Transport = clonedTransport
if cfg.tlsCfg.Value != nil {
clonedTransport.TLSClientConfig = cfg.tlsCfg.Value
}
if cfg.proxy.Value != nil {
clonedTransport.Proxy = cfg.proxy.Value
}
}
}

View file

@ -14,6 +14,7 @@ import (
"strconv"
"strings"
"time"
"unicode"
"go.opentelemetry.io/otel"
"go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploghttp/internal/retry"
@ -94,6 +95,7 @@ type config struct {
timeout setting[time.Duration]
proxy setting[HTTPTransportProxyFunc]
retryCfg setting[retry.Config]
httpClient *http.Client
}
func newConfig(options []Option) config {
@ -343,6 +345,25 @@ func WithProxy(pf HTTPTransportProxyFunc) Option {
})
}
// WithHTTPClient sets the HTTP client to used by the exporter.
//
// This option will take precedence over [WithProxy], [WithTimeout],
// [WithTLSClientConfig] options as well as OTEL_EXPORTER_OTLP_CERTIFICATE,
// OTEL_EXPORTER_OTLP_LOGS_CERTIFICATE, OTEL_EXPORTER_OTLP_TIMEOUT,
// OTEL_EXPORTER_OTLP_LOGS_TIMEOUT environment variables.
//
// Timeout and all other fields of the passed [http.Client] are left intact.
//
// Be aware that passing an HTTP client with transport like
// [go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp.NewTransport] can
// cause the client to be instrumented twice and cause infinite recursion.
func WithHTTPClient(c *http.Client) Option {
return fnOpt(func(cfg config) config {
cfg.httpClient = c
return cfg
})
}
// setting is a configuration setting value.
type setting[T any] struct {
Value T
@ -544,13 +565,15 @@ func convHeaders(s string) (map[string]string, error) {
continue
}
escKey, e := url.PathUnescape(rawKey)
if e != nil {
key := strings.TrimSpace(rawKey)
// Validate the key.
if !isValidHeaderKey(key) {
err = errors.Join(err, fmt.Errorf("invalid header key: %s", rawKey))
continue
}
key := strings.TrimSpace(escKey)
// Only decode the value.
escVal, e := url.PathUnescape(rawVal)
if e != nil {
err = errors.Join(err, fmt.Errorf("invalid header value: %s", rawVal))
@ -600,3 +623,22 @@ func fallback[T any](val T) resolver[T] {
return s
}
}
func isValidHeaderKey(key string) bool {
if key == "" {
return false
}
for _, c := range key {
if !isTokenChar(c) {
return false
}
}
return true
}
func isTokenChar(c rune) bool {
return c <= unicode.MaxASCII && (unicode.IsLetter(c) ||
unicode.IsDigit(c) ||
c == '!' || c == '#' || c == '$' || c == '%' || c == '&' || c == '\'' || c == '*' ||
c == '+' || c == '-' || c == '.' || c == '^' || c == '_' || c == '`' || c == '|' || c == '~')
}

View file

@ -1,4 +1,4 @@
// Code created by gotmpl. DO NOT MODIFY.
// Code generated by gotmpl. DO NOT MODIFY.
// source: internal/shared/otlp/retry/retry.go.tmpl
// Copyright The OpenTelemetry Authors
@ -14,7 +14,7 @@ import (
"fmt"
"time"
"github.com/cenkalti/backoff/v4"
"github.com/cenkalti/backoff/v5"
)
// DefaultConfig are the recommended defaults to use.
@ -77,12 +77,12 @@ func (c Config) RequestFunc(evaluate EvaluateFunc) RequestFunc {
RandomizationFactor: backoff.DefaultRandomizationFactor,
Multiplier: backoff.DefaultMultiplier,
MaxInterval: c.MaxInterval,
MaxElapsedTime: c.MaxElapsedTime,
Stop: backoff.Stop,
Clock: backoff.SystemClock,
}
b.Reset()
maxElapsedTime := c.MaxElapsedTime
startTime := time.Now()
for {
err := fn(ctx)
if err == nil {
@ -94,21 +94,17 @@ func (c Config) RequestFunc(evaluate EvaluateFunc) RequestFunc {
return err
}
bOff := b.NextBackOff()
if bOff == backoff.Stop {
if maxElapsedTime != 0 && time.Since(startTime) > maxElapsedTime {
return fmt.Errorf("max retry time elapsed: %w", err)
}
// Wait for the greater of the backoff or throttle delay.
var delay time.Duration
if bOff > throttle {
delay = bOff
} else {
elapsed := b.GetElapsedTime()
if b.MaxElapsedTime != 0 && elapsed+throttle > b.MaxElapsedTime {
return fmt.Errorf("max retry time would elapse: %w", err)
}
delay = throttle
bOff := b.NextBackOff()
delay := max(throttle, bOff)
elapsed := time.Since(startTime)
if maxElapsedTime != 0 && elapsed+throttle > maxElapsedTime {
return fmt.Errorf("max retry time would elapse: %w", err)
}
if ctxErr := waitFunc(ctx, delay); ctxErr != nil {

View file

@ -1,4 +1,4 @@
// Code created by gotmpl. DO NOT MODIFY.
// Code generated by gotmpl. DO NOT MODIFY.
// source: internal/shared/otlp/otlplog/transform/log.go.tmpl
// Copyright The OpenTelemetry Authors
@ -257,7 +257,7 @@ func stringSliceValues(vals []string) []*cpb.AnyValue {
return converted
}
// Attrs transforms a slice of [api.KeyValue] into OTLP key-values.
// LogAttrs transforms a slice of [api.KeyValue] into OTLP key-values.
func LogAttrs(attrs []api.KeyValue) []*cpb.KeyValue {
if len(attrs) == 0 {
return nil

View file

@ -5,5 +5,5 @@ package otlploghttp // import "go.opentelemetry.io/otel/exporters/otlp/otlplog/o
// Version is the current release version of the OpenTelemetry OTLP over HTTP/protobuf logs exporter in use.
func Version() string {
return "0.11.0"
return "0.12.2"
}

View file

@ -238,8 +238,9 @@ func WithTimeout(duration time.Duration) Option {
// explicitly returns a backoff time in the response, that time will take
// precedence over these settings.
//
// These settings do not define any network retry strategy. That is entirely
// handled by the gRPC ClientConn.
// These settings define the retry strategy implemented by the exporter.
// These settings do not define any network retry strategy.
// That is handled by the gRPC ClientConn.
//
// If unset, the default retry policy will be used. It will retry the export
// 5 seconds after receiving a retryable error and increase exponentially

View file

@ -1,9 +1,11 @@
// Code created by gotmpl. DO NOT MODIFY.
// Code generated by gotmpl. DO NOT MODIFY.
// source: internal/shared/otlp/envconfig/envconfig.go.tmpl
// Copyright The OpenTelemetry Authors
// SPDX-License-Identifier: Apache-2.0
// Package envconfig provides functionality to parse configuration from
// environment variables.
package envconfig // import "go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc/internal/envconfig"
import (

View file

@ -1,6 +1,7 @@
// Copyright The OpenTelemetry Authors
// SPDX-License-Identifier: Apache-2.0
// Package internal provides internal functionally for the otlpmetricgrpc package.
package internal // import "go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc/internal"
//go:generate gotmpl --body=../../../../../internal/shared/otlp/partialsuccess.go.tmpl "--data={}" --out=partialsuccess.go

View file

@ -1,4 +1,4 @@
// Code created by gotmpl. DO NOT MODIFY.
// Code generated by gotmpl. DO NOT MODIFY.
// source: internal/shared/otlp/otlpmetric/oconf/envconfig.go.tmpl
// Copyright The OpenTelemetry Authors
@ -80,8 +80,16 @@ func getOptionsFromEnv() []GenericOption {
}),
envconfig.WithCertPool("CERTIFICATE", func(p *x509.CertPool) { tlsConf.RootCAs = p }),
envconfig.WithCertPool("METRICS_CERTIFICATE", func(p *x509.CertPool) { tlsConf.RootCAs = p }),
envconfig.WithClientCert("CLIENT_CERTIFICATE", "CLIENT_KEY", func(c tls.Certificate) { tlsConf.Certificates = []tls.Certificate{c} }),
envconfig.WithClientCert("METRICS_CLIENT_CERTIFICATE", "METRICS_CLIENT_KEY", func(c tls.Certificate) { tlsConf.Certificates = []tls.Certificate{c} }),
envconfig.WithClientCert(
"CLIENT_CERTIFICATE",
"CLIENT_KEY",
func(c tls.Certificate) { tlsConf.Certificates = []tls.Certificate{c} },
),
envconfig.WithClientCert(
"METRICS_CLIENT_CERTIFICATE",
"METRICS_CLIENT_KEY",
func(c tls.Certificate) { tlsConf.Certificates = []tls.Certificate{c} },
),
envconfig.WithBool("INSECURE", func(b bool) { opts = append(opts, withInsecure(b)) }),
envconfig.WithBool("METRICS_INSECURE", func(b bool) { opts = append(opts, withInsecure(b)) }),
withTLSConfig(tlsConf, func(c *tls.Config) { opts = append(opts, WithTLSClientConfig(c)) }),
@ -91,8 +99,14 @@ func getOptionsFromEnv() []GenericOption {
WithEnvCompression("METRICS_COMPRESSION", func(c Compression) { opts = append(opts, WithCompression(c)) }),
envconfig.WithDuration("TIMEOUT", func(d time.Duration) { opts = append(opts, WithTimeout(d)) }),
envconfig.WithDuration("METRICS_TIMEOUT", func(d time.Duration) { opts = append(opts, WithTimeout(d)) }),
withEnvTemporalityPreference("METRICS_TEMPORALITY_PREFERENCE", func(t metric.TemporalitySelector) { opts = append(opts, WithTemporalitySelector(t)) }),
withEnvAggPreference("METRICS_DEFAULT_HISTOGRAM_AGGREGATION", func(a metric.AggregationSelector) { opts = append(opts, WithAggregationSelector(a)) }),
withEnvTemporalityPreference(
"METRICS_TEMPORALITY_PREFERENCE",
func(t metric.TemporalitySelector) { opts = append(opts, WithTemporalitySelector(t)) },
),
withEnvAggPreference(
"METRICS_DEFAULT_HISTOGRAM_AGGREGATION",
func(a metric.AggregationSelector) { opts = append(opts, WithAggregationSelector(a)) },
),
)
return opts
@ -157,7 +171,11 @@ func withEnvTemporalityPreference(n string, fn func(metric.TemporalitySelector))
case "lowmemory":
fn(lowMemory)
default:
global.Warn("OTEL_EXPORTER_OTLP_METRICS_TEMPORALITY_PREFERENCE is set to an invalid value, ignoring.", "value", s)
global.Warn(
"OTEL_EXPORTER_OTLP_METRICS_TEMPORALITY_PREFERENCE is set to an invalid value, ignoring.",
"value",
s,
)
}
}
}
@ -203,7 +221,11 @@ func withEnvAggPreference(n string, fn func(metric.AggregationSelector)) func(e
return metric.DefaultAggregationSelector(kind)
})
default:
global.Warn("OTEL_EXPORTER_OTLP_METRICS_DEFAULT_HISTOGRAM_AGGREGATION is set to an invalid value, ignoring.", "value", s)
global.Warn(
"OTEL_EXPORTER_OTLP_METRICS_DEFAULT_HISTOGRAM_AGGREGATION is set to an invalid value, ignoring.",
"value",
s,
)
}
}
}

View file

@ -1,9 +1,10 @@
// Code created by gotmpl. DO NOT MODIFY.
// Code generated by gotmpl. DO NOT MODIFY.
// source: internal/shared/otlp/otlpmetric/oconf/options.go.tmpl
// Copyright The OpenTelemetry Authors
// SPDX-License-Identifier: Apache-2.0
// Package oconf provides configuration for the otlpmetric exporters.
package oconf // import "go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc/internal/oconf"
import (
@ -56,13 +57,15 @@ type (
Timeout time.Duration
URLPath string
// gRPC configurations
GRPCCredentials credentials.TransportCredentials
TemporalitySelector metric.TemporalitySelector
AggregationSelector metric.AggregationSelector
Proxy HTTPTransportProxyFunc
// gRPC configurations
GRPCCredentials credentials.TransportCredentials
// HTTP configurations
Proxy HTTPTransportProxyFunc
HTTPClient *http.Client
}
Config struct {
@ -372,3 +375,10 @@ func WithProxy(pf HTTPTransportProxyFunc) GenericOption {
return cfg
})
}
func WithHTTPClient(c *http.Client) GenericOption {
return newGenericOption(func(cfg Config) Config {
cfg.Metrics.HTTPClient = c
return cfg
})
}

View file

@ -1,4 +1,4 @@
// Code created by gotmpl. DO NOT MODIFY.
// Code generated by gotmpl. DO NOT MODIFY.
// source: internal/shared/otlp/otlpmetric/oconf/optiontypes.go.tmpl
// Copyright The OpenTelemetry Authors

View file

@ -1,4 +1,4 @@
// Code created by gotmpl. DO NOT MODIFY.
// Code generated by gotmpl. DO NOT MODIFY.
// source: internal/shared/otlp/otlpmetric/oconf/tls.go.tmpl
// Copyright The OpenTelemetry Authors

View file

@ -1,4 +1,4 @@
// Code created by gotmpl. DO NOT MODIFY.
// Code generated by gotmpl. DO NOT MODIFY.
// source: internal/shared/otlp/partialsuccess.go
// Copyright The OpenTelemetry Authors

View file

@ -1,4 +1,4 @@
// Code created by gotmpl. DO NOT MODIFY.
// Code generated by gotmpl. DO NOT MODIFY.
// source: internal/shared/otlp/retry/retry.go.tmpl
// Copyright The OpenTelemetry Authors
@ -14,7 +14,7 @@ import (
"fmt"
"time"
"github.com/cenkalti/backoff/v4"
"github.com/cenkalti/backoff/v5"
)
// DefaultConfig are the recommended defaults to use.
@ -77,12 +77,12 @@ func (c Config) RequestFunc(evaluate EvaluateFunc) RequestFunc {
RandomizationFactor: backoff.DefaultRandomizationFactor,
Multiplier: backoff.DefaultMultiplier,
MaxInterval: c.MaxInterval,
MaxElapsedTime: c.MaxElapsedTime,
Stop: backoff.Stop,
Clock: backoff.SystemClock,
}
b.Reset()
maxElapsedTime := c.MaxElapsedTime
startTime := time.Now()
for {
err := fn(ctx)
if err == nil {
@ -94,21 +94,17 @@ func (c Config) RequestFunc(evaluate EvaluateFunc) RequestFunc {
return err
}
bOff := b.NextBackOff()
if bOff == backoff.Stop {
if maxElapsedTime != 0 && time.Since(startTime) > maxElapsedTime {
return fmt.Errorf("max retry time elapsed: %w", err)
}
// Wait for the greater of the backoff or throttle delay.
var delay time.Duration
if bOff > throttle {
delay = bOff
} else {
elapsed := b.GetElapsedTime()
if b.MaxElapsedTime != 0 && elapsed+throttle > b.MaxElapsedTime {
return fmt.Errorf("max retry time would elapse: %w", err)
}
delay = throttle
bOff := b.NextBackOff()
delay := max(throttle, bOff)
elapsed := time.Since(startTime)
if maxElapsedTime != 0 && elapsed+throttle > maxElapsedTime {
return fmt.Errorf("max retry time would elapse: %w", err)
}
if ctxErr := waitFunc(ctx, delay); ctxErr != nil {

View file

@ -1,4 +1,4 @@
// Code created by gotmpl. DO NOT MODIFY.
// Code generated by gotmpl. DO NOT MODIFY.
// source: internal/shared/otlp/otlpmetric/transform/attribute.go.tmpl
// Copyright The OpenTelemetry Authors

View file

@ -1,4 +1,4 @@
// Code created by gotmpl. DO NOT MODIFY.
// Code generated by gotmpl. DO NOT MODIFY.
// source: internal/shared/otlp/otlpmetric/transform/error.go.tmpl
// Copyright The OpenTelemetry Authors

View file

@ -1,4 +1,4 @@
// Code created by gotmpl. DO NOT MODIFY.
// Code generated by gotmpl. DO NOT MODIFY.
// source: internal/shared/otlp/otlpmetric/transform/metricdata.go.tmpl
// Copyright The OpenTelemetry Authors
@ -203,7 +203,9 @@ func HistogramDataPoints[N int64 | float64](dPts []metricdata.HistogramDataPoint
// ExponentialHistogram returns an OTLP Metric_ExponentialHistogram generated from h. An error is
// returned if the temporality of h is unknown.
func ExponentialHistogram[N int64 | float64](h metricdata.ExponentialHistogram[N]) (*mpb.Metric_ExponentialHistogram, error) {
func ExponentialHistogram[N int64 | float64](
h metricdata.ExponentialHistogram[N],
) (*mpb.Metric_ExponentialHistogram, error) {
t, err := Temporality(h.Temporality)
if err != nil {
return nil, err
@ -218,7 +220,9 @@ func ExponentialHistogram[N int64 | float64](h metricdata.ExponentialHistogram[N
// ExponentialHistogramDataPoints returns a slice of OTLP ExponentialHistogramDataPoint generated
// from dPts.
func ExponentialHistogramDataPoints[N int64 | float64](dPts []metricdata.ExponentialHistogramDataPoint[N]) []*mpb.ExponentialHistogramDataPoint {
func ExponentialHistogramDataPoints[N int64 | float64](
dPts []metricdata.ExponentialHistogramDataPoint[N],
) []*mpb.ExponentialHistogramDataPoint {
out := make([]*mpb.ExponentialHistogramDataPoint, 0, len(dPts))
for _, dPt := range dPts {
sum := float64(dPt.Sum)
@ -250,7 +254,9 @@ func ExponentialHistogramDataPoints[N int64 | float64](dPts []metricdata.Exponen
// ExponentialHistogramDataPointBuckets returns an OTLP ExponentialHistogramDataPoint_Buckets generated
// from bucket.
func ExponentialHistogramDataPointBuckets(bucket metricdata.ExponentialBucket) *mpb.ExponentialHistogramDataPoint_Buckets {
func ExponentialHistogramDataPointBuckets(
bucket metricdata.ExponentialBucket,
) *mpb.ExponentialHistogramDataPoint_Buckets {
return &mpb.ExponentialHistogramDataPoint_Buckets{
Offset: bucket.Offset,
BucketCounts: bucket.Counts,

View file

@ -5,5 +5,5 @@ package otlpmetricgrpc // import "go.opentelemetry.io/otel/exporters/otlp/otlpme
// Version is the current release version of the OpenTelemetry OTLP over gRPC metrics exporter in use.
func Version() string {
return "1.35.0"
return "1.36.0"
}

View file

@ -55,20 +55,23 @@ var ourTransport = &http.Transport{
// newClient creates a new HTTP metric client.
func newClient(cfg oconf.Config) (*client, error) {
httpClient := &http.Client{
Transport: ourTransport,
Timeout: cfg.Metrics.Timeout,
}
if cfg.Metrics.TLSCfg != nil || cfg.Metrics.Proxy != nil {
clonedTransport := ourTransport.Clone()
httpClient.Transport = clonedTransport
if cfg.Metrics.TLSCfg != nil {
clonedTransport.TLSClientConfig = cfg.Metrics.TLSCfg
httpClient := cfg.Metrics.HTTPClient
if httpClient == nil {
httpClient = &http.Client{
Transport: ourTransport,
Timeout: cfg.Metrics.Timeout,
}
if cfg.Metrics.Proxy != nil {
clonedTransport.Proxy = cfg.Metrics.Proxy
if cfg.Metrics.TLSCfg != nil || cfg.Metrics.Proxy != nil {
clonedTransport := ourTransport.Clone()
httpClient.Transport = clonedTransport
if cfg.Metrics.TLSCfg != nil {
clonedTransport.TLSClientConfig = cfg.Metrics.TLSCfg
}
if cfg.Metrics.Proxy != nil {
clonedTransport.Proxy = cfg.Metrics.Proxy
}
}
}
@ -277,7 +280,7 @@ type request struct {
// reset reinitializes the request Body and uses ctx for the request.
func (r *request) reset(ctx context.Context) {
r.Body = r.bodyReader()
r.Request = r.Request.WithContext(ctx)
r.Request = r.WithContext(ctx)
}
// retryableError represents a request failure that can be retried.

View file

@ -222,3 +222,19 @@ func WithAggregationSelector(selector metric.AggregationSelector) Option {
func WithProxy(pf HTTPTransportProxyFunc) Option {
return wrappedOption{oconf.WithProxy(oconf.HTTPTransportProxyFunc(pf))}
}
// WithHTTPClient sets the HTTP client to used by the exporter.
//
// This option will take precedence over [WithProxy], [WithTimeout],
// [WithTLSClientConfig] options as well as OTEL_EXPORTER_OTLP_CERTIFICATE,
// OTEL_EXPORTER_OTLP_METRICS_CERTIFICATE, OTEL_EXPORTER_OTLP_TIMEOUT,
// OTEL_EXPORTER_OTLP_METRICS_TIMEOUT environment variables.
//
// Timeout and all other fields of the passed [http.Client] are left intact.
//
// Be aware that passing an HTTP client with transport like
// [go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp.NewTransport] can
// cause the client to be instrumented twice and cause infinite recursion.
func WithHTTPClient(c *http.Client) Option {
return wrappedOption{oconf.WithHTTPClient(c)}
}

View file

@ -1,9 +1,11 @@
// Code created by gotmpl. DO NOT MODIFY.
// Code generated by gotmpl. DO NOT MODIFY.
// source: internal/shared/otlp/envconfig/envconfig.go.tmpl
// Copyright The OpenTelemetry Authors
// SPDX-License-Identifier: Apache-2.0
// Package envconfig provides functionality to parse configuration from
// environment variables.
package envconfig // import "go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp/internal/envconfig"
import (

View file

@ -1,6 +1,7 @@
// Copyright The OpenTelemetry Authors
// SPDX-License-Identifier: Apache-2.0
// Package internal provides internal functionally for the otlpmetrichttp package.
package internal // import "go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp/internal"
//go:generate gotmpl --body=../../../../../internal/shared/otlp/partialsuccess.go.tmpl "--data={}" --out=partialsuccess.go

View file

@ -1,4 +1,4 @@
// Code created by gotmpl. DO NOT MODIFY.
// Code generated by gotmpl. DO NOT MODIFY.
// source: internal/shared/otlp/otlpmetric/oconf/envconfig.go.tmpl
// Copyright The OpenTelemetry Authors
@ -80,8 +80,16 @@ func getOptionsFromEnv() []GenericOption {
}),
envconfig.WithCertPool("CERTIFICATE", func(p *x509.CertPool) { tlsConf.RootCAs = p }),
envconfig.WithCertPool("METRICS_CERTIFICATE", func(p *x509.CertPool) { tlsConf.RootCAs = p }),
envconfig.WithClientCert("CLIENT_CERTIFICATE", "CLIENT_KEY", func(c tls.Certificate) { tlsConf.Certificates = []tls.Certificate{c} }),
envconfig.WithClientCert("METRICS_CLIENT_CERTIFICATE", "METRICS_CLIENT_KEY", func(c tls.Certificate) { tlsConf.Certificates = []tls.Certificate{c} }),
envconfig.WithClientCert(
"CLIENT_CERTIFICATE",
"CLIENT_KEY",
func(c tls.Certificate) { tlsConf.Certificates = []tls.Certificate{c} },
),
envconfig.WithClientCert(
"METRICS_CLIENT_CERTIFICATE",
"METRICS_CLIENT_KEY",
func(c tls.Certificate) { tlsConf.Certificates = []tls.Certificate{c} },
),
envconfig.WithBool("INSECURE", func(b bool) { opts = append(opts, withInsecure(b)) }),
envconfig.WithBool("METRICS_INSECURE", func(b bool) { opts = append(opts, withInsecure(b)) }),
withTLSConfig(tlsConf, func(c *tls.Config) { opts = append(opts, WithTLSClientConfig(c)) }),
@ -91,8 +99,14 @@ func getOptionsFromEnv() []GenericOption {
WithEnvCompression("METRICS_COMPRESSION", func(c Compression) { opts = append(opts, WithCompression(c)) }),
envconfig.WithDuration("TIMEOUT", func(d time.Duration) { opts = append(opts, WithTimeout(d)) }),
envconfig.WithDuration("METRICS_TIMEOUT", func(d time.Duration) { opts = append(opts, WithTimeout(d)) }),
withEnvTemporalityPreference("METRICS_TEMPORALITY_PREFERENCE", func(t metric.TemporalitySelector) { opts = append(opts, WithTemporalitySelector(t)) }),
withEnvAggPreference("METRICS_DEFAULT_HISTOGRAM_AGGREGATION", func(a metric.AggregationSelector) { opts = append(opts, WithAggregationSelector(a)) }),
withEnvTemporalityPreference(
"METRICS_TEMPORALITY_PREFERENCE",
func(t metric.TemporalitySelector) { opts = append(opts, WithTemporalitySelector(t)) },
),
withEnvAggPreference(
"METRICS_DEFAULT_HISTOGRAM_AGGREGATION",
func(a metric.AggregationSelector) { opts = append(opts, WithAggregationSelector(a)) },
),
)
return opts
@ -157,7 +171,11 @@ func withEnvTemporalityPreference(n string, fn func(metric.TemporalitySelector))
case "lowmemory":
fn(lowMemory)
default:
global.Warn("OTEL_EXPORTER_OTLP_METRICS_TEMPORALITY_PREFERENCE is set to an invalid value, ignoring.", "value", s)
global.Warn(
"OTEL_EXPORTER_OTLP_METRICS_TEMPORALITY_PREFERENCE is set to an invalid value, ignoring.",
"value",
s,
)
}
}
}
@ -203,7 +221,11 @@ func withEnvAggPreference(n string, fn func(metric.AggregationSelector)) func(e
return metric.DefaultAggregationSelector(kind)
})
default:
global.Warn("OTEL_EXPORTER_OTLP_METRICS_DEFAULT_HISTOGRAM_AGGREGATION is set to an invalid value, ignoring.", "value", s)
global.Warn(
"OTEL_EXPORTER_OTLP_METRICS_DEFAULT_HISTOGRAM_AGGREGATION is set to an invalid value, ignoring.",
"value",
s,
)
}
}
}

View file

@ -1,9 +1,10 @@
// Code created by gotmpl. DO NOT MODIFY.
// Code generated by gotmpl. DO NOT MODIFY.
// source: internal/shared/otlp/otlpmetric/oconf/options.go.tmpl
// Copyright The OpenTelemetry Authors
// SPDX-License-Identifier: Apache-2.0
// Package oconf provides configuration for the otlpmetric exporters.
package oconf // import "go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp/internal/oconf"
import (
@ -56,13 +57,15 @@ type (
Timeout time.Duration
URLPath string
// gRPC configurations
GRPCCredentials credentials.TransportCredentials
TemporalitySelector metric.TemporalitySelector
AggregationSelector metric.AggregationSelector
Proxy HTTPTransportProxyFunc
// gRPC configurations
GRPCCredentials credentials.TransportCredentials
// HTTP configurations
Proxy HTTPTransportProxyFunc
HTTPClient *http.Client
}
Config struct {
@ -372,3 +375,10 @@ func WithProxy(pf HTTPTransportProxyFunc) GenericOption {
return cfg
})
}
func WithHTTPClient(c *http.Client) GenericOption {
return newGenericOption(func(cfg Config) Config {
cfg.Metrics.HTTPClient = c
return cfg
})
}

View file

@ -1,4 +1,4 @@
// Code created by gotmpl. DO NOT MODIFY.
// Code generated by gotmpl. DO NOT MODIFY.
// source: internal/shared/otlp/otlpmetric/oconf/optiontypes.go.tmpl
// Copyright The OpenTelemetry Authors

View file

@ -1,4 +1,4 @@
// Code created by gotmpl. DO NOT MODIFY.
// Code generated by gotmpl. DO NOT MODIFY.
// source: internal/shared/otlp/otlpmetric/oconf/tls.go.tmpl
// Copyright The OpenTelemetry Authors

View file

@ -1,4 +1,4 @@
// Code created by gotmpl. DO NOT MODIFY.
// Code generated by gotmpl. DO NOT MODIFY.
// source: internal/shared/otlp/partialsuccess.go
// Copyright The OpenTelemetry Authors

View file

@ -1,4 +1,4 @@
// Code created by gotmpl. DO NOT MODIFY.
// Code generated by gotmpl. DO NOT MODIFY.
// source: internal/shared/otlp/retry/retry.go.tmpl
// Copyright The OpenTelemetry Authors
@ -14,7 +14,7 @@ import (
"fmt"
"time"
"github.com/cenkalti/backoff/v4"
"github.com/cenkalti/backoff/v5"
)
// DefaultConfig are the recommended defaults to use.
@ -77,12 +77,12 @@ func (c Config) RequestFunc(evaluate EvaluateFunc) RequestFunc {
RandomizationFactor: backoff.DefaultRandomizationFactor,
Multiplier: backoff.DefaultMultiplier,
MaxInterval: c.MaxInterval,
MaxElapsedTime: c.MaxElapsedTime,
Stop: backoff.Stop,
Clock: backoff.SystemClock,
}
b.Reset()
maxElapsedTime := c.MaxElapsedTime
startTime := time.Now()
for {
err := fn(ctx)
if err == nil {
@ -94,21 +94,17 @@ func (c Config) RequestFunc(evaluate EvaluateFunc) RequestFunc {
return err
}
bOff := b.NextBackOff()
if bOff == backoff.Stop {
if maxElapsedTime != 0 && time.Since(startTime) > maxElapsedTime {
return fmt.Errorf("max retry time elapsed: %w", err)
}
// Wait for the greater of the backoff or throttle delay.
var delay time.Duration
if bOff > throttle {
delay = bOff
} else {
elapsed := b.GetElapsedTime()
if b.MaxElapsedTime != 0 && elapsed+throttle > b.MaxElapsedTime {
return fmt.Errorf("max retry time would elapse: %w", err)
}
delay = throttle
bOff := b.NextBackOff()
delay := max(throttle, bOff)
elapsed := time.Since(startTime)
if maxElapsedTime != 0 && elapsed+throttle > maxElapsedTime {
return fmt.Errorf("max retry time would elapse: %w", err)
}
if ctxErr := waitFunc(ctx, delay); ctxErr != nil {

View file

@ -1,4 +1,4 @@
// Code created by gotmpl. DO NOT MODIFY.
// Code generated by gotmpl. DO NOT MODIFY.
// source: internal/shared/otlp/otlpmetric/transform/attribute.go.tmpl
// Copyright The OpenTelemetry Authors

View file

@ -1,4 +1,4 @@
// Code created by gotmpl. DO NOT MODIFY.
// Code generated by gotmpl. DO NOT MODIFY.
// source: internal/shared/otlp/otlpmetric/transform/error.go.tmpl
// Copyright The OpenTelemetry Authors

View file

@ -1,4 +1,4 @@
// Code created by gotmpl. DO NOT MODIFY.
// Code generated by gotmpl. DO NOT MODIFY.
// source: internal/shared/otlp/otlpmetric/transform/metricdata.go.tmpl
// Copyright The OpenTelemetry Authors
@ -203,7 +203,9 @@ func HistogramDataPoints[N int64 | float64](dPts []metricdata.HistogramDataPoint
// ExponentialHistogram returns an OTLP Metric_ExponentialHistogram generated from h. An error is
// returned if the temporality of h is unknown.
func ExponentialHistogram[N int64 | float64](h metricdata.ExponentialHistogram[N]) (*mpb.Metric_ExponentialHistogram, error) {
func ExponentialHistogram[N int64 | float64](
h metricdata.ExponentialHistogram[N],
) (*mpb.Metric_ExponentialHistogram, error) {
t, err := Temporality(h.Temporality)
if err != nil {
return nil, err
@ -218,7 +220,9 @@ func ExponentialHistogram[N int64 | float64](h metricdata.ExponentialHistogram[N
// ExponentialHistogramDataPoints returns a slice of OTLP ExponentialHistogramDataPoint generated
// from dPts.
func ExponentialHistogramDataPoints[N int64 | float64](dPts []metricdata.ExponentialHistogramDataPoint[N]) []*mpb.ExponentialHistogramDataPoint {
func ExponentialHistogramDataPoints[N int64 | float64](
dPts []metricdata.ExponentialHistogramDataPoint[N],
) []*mpb.ExponentialHistogramDataPoint {
out := make([]*mpb.ExponentialHistogramDataPoint, 0, len(dPts))
for _, dPt := range dPts {
sum := float64(dPt.Sum)
@ -250,7 +254,9 @@ func ExponentialHistogramDataPoints[N int64 | float64](dPts []metricdata.Exponen
// ExponentialHistogramDataPointBuckets returns an OTLP ExponentialHistogramDataPoint_Buckets generated
// from bucket.
func ExponentialHistogramDataPointBuckets(bucket metricdata.ExponentialBucket) *mpb.ExponentialHistogramDataPoint_Buckets {
func ExponentialHistogramDataPointBuckets(
bucket metricdata.ExponentialBucket,
) *mpb.ExponentialHistogramDataPoint_Buckets {
return &mpb.ExponentialHistogramDataPoint_Buckets{
Offset: bucket.Offset,
BucketCounts: bucket.Counts,

View file

@ -5,5 +5,5 @@ package otlpmetrichttp // import "go.opentelemetry.io/otel/exporters/otlp/otlpme
// Version is the current release version of the OpenTelemetry OTLP over HTTP/protobuf metrics exporter in use.
func Version() string {
return "1.35.0"
return "1.36.0"
}

View file

@ -1,6 +1,8 @@
// Copyright The OpenTelemetry Authors
// SPDX-License-Identifier: Apache-2.0
// Package tracetransform provides conversion functionality for the otlptrace
// exporters.
package tracetransform // import "go.opentelemetry.io/otel/exporters/otlp/otlptrace/internal/tracetransform"
import (

View file

@ -1,9 +1,11 @@
// Code created by gotmpl. DO NOT MODIFY.
// Code generated by gotmpl. DO NOT MODIFY.
// source: internal/shared/otlp/envconfig/envconfig.go.tmpl
// Copyright The OpenTelemetry Authors
// SPDX-License-Identifier: Apache-2.0
// Package envconfig provides functionality to parse configuration from
// environment variables.
package envconfig // import "go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc/internal/envconfig"
import (

View file

@ -1,6 +1,7 @@
// Copyright The OpenTelemetry Authors
// SPDX-License-Identifier: Apache-2.0
// Package internal provides internal functionally for the otlptracegrpc package.
package internal // import "go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc/internal"
//go:generate gotmpl --body=../../../../../internal/shared/otlp/partialsuccess.go.tmpl "--data={}" --out=partialsuccess.go

View file

@ -1,4 +1,4 @@
// Code created by gotmpl. DO NOT MODIFY.
// Code generated by gotmpl. DO NOT MODIFY.
// source: internal/shared/otlp/otlptrace/otlpconfig/envconfig.go.tmpl
// Copyright The OpenTelemetry Authors
@ -77,8 +77,16 @@ func getOptionsFromEnv() []GenericOption {
}),
envconfig.WithCertPool("CERTIFICATE", func(p *x509.CertPool) { tlsConf.RootCAs = p }),
envconfig.WithCertPool("TRACES_CERTIFICATE", func(p *x509.CertPool) { tlsConf.RootCAs = p }),
envconfig.WithClientCert("CLIENT_CERTIFICATE", "CLIENT_KEY", func(c tls.Certificate) { tlsConf.Certificates = []tls.Certificate{c} }),
envconfig.WithClientCert("TRACES_CLIENT_CERTIFICATE", "TRACES_CLIENT_KEY", func(c tls.Certificate) { tlsConf.Certificates = []tls.Certificate{c} }),
envconfig.WithClientCert(
"CLIENT_CERTIFICATE",
"CLIENT_KEY",
func(c tls.Certificate) { tlsConf.Certificates = []tls.Certificate{c} },
),
envconfig.WithClientCert(
"TRACES_CLIENT_CERTIFICATE",
"TRACES_CLIENT_KEY",
func(c tls.Certificate) { tlsConf.Certificates = []tls.Certificate{c} },
),
withTLSConfig(tlsConf, func(c *tls.Config) { opts = append(opts, WithTLSClientConfig(c)) }),
envconfig.WithBool("INSECURE", func(b bool) { opts = append(opts, withInsecure(b)) }),
envconfig.WithBool("TRACES_INSECURE", func(b bool) { opts = append(opts, withInsecure(b)) }),

View file

@ -1,9 +1,10 @@
// Code created by gotmpl. DO NOT MODIFY.
// Code generated by gotmpl. DO NOT MODIFY.
// source: internal/shared/otlp/otlptrace/otlpconfig/options.go.tmpl
// Copyright The OpenTelemetry Authors
// SPDX-License-Identifier: Apache-2.0
// Package otlpconfig provides configuration for the otlptrace exporters.
package otlpconfig // import "go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc/internal/otlpconfig"
import (
@ -52,7 +53,9 @@ type (
// gRPC configurations
GRPCCredentials credentials.TransportCredentials
Proxy HTTPTransportProxyFunc
// HTTP configurations
Proxy HTTPTransportProxyFunc
HTTPClient *http.Client
}
Config struct {
@ -349,3 +352,10 @@ func WithProxy(pf HTTPTransportProxyFunc) GenericOption {
return cfg
})
}
func WithHTTPClient(c *http.Client) GenericOption {
return newGenericOption(func(cfg Config) Config {
cfg.Traces.HTTPClient = c
return cfg
})
}

View file

@ -1,4 +1,4 @@
// Code created by gotmpl. DO NOT MODIFY.
// Code generated by gotmpl. DO NOT MODIFY.
// source: internal/shared/otlp/otlptrace/otlpconfig/optiontypes.go.tmpl
// Copyright The OpenTelemetry Authors

View file

@ -1,4 +1,4 @@
// Code created by gotmpl. DO NOT MODIFY.
// Code generated by gotmpl. DO NOT MODIFY.
// source: internal/shared/otlp/otlptrace/otlpconfig/tls.go.tmpl
// Copyright The OpenTelemetry Authors

View file

@ -1,4 +1,4 @@
// Code created by gotmpl. DO NOT MODIFY.
// Code generated by gotmpl. DO NOT MODIFY.
// source: internal/shared/otlp/partialsuccess.go
// Copyright The OpenTelemetry Authors

View file

@ -1,4 +1,4 @@
// Code created by gotmpl. DO NOT MODIFY.
// Code generated by gotmpl. DO NOT MODIFY.
// source: internal/shared/otlp/retry/retry.go.tmpl
// Copyright The OpenTelemetry Authors
@ -14,7 +14,7 @@ import (
"fmt"
"time"
"github.com/cenkalti/backoff/v4"
"github.com/cenkalti/backoff/v5"
)
// DefaultConfig are the recommended defaults to use.
@ -77,12 +77,12 @@ func (c Config) RequestFunc(evaluate EvaluateFunc) RequestFunc {
RandomizationFactor: backoff.DefaultRandomizationFactor,
Multiplier: backoff.DefaultMultiplier,
MaxInterval: c.MaxInterval,
MaxElapsedTime: c.MaxElapsedTime,
Stop: backoff.Stop,
Clock: backoff.SystemClock,
}
b.Reset()
maxElapsedTime := c.MaxElapsedTime
startTime := time.Now()
for {
err := fn(ctx)
if err == nil {
@ -94,21 +94,17 @@ func (c Config) RequestFunc(evaluate EvaluateFunc) RequestFunc {
return err
}
bOff := b.NextBackOff()
if bOff == backoff.Stop {
if maxElapsedTime != 0 && time.Since(startTime) > maxElapsedTime {
return fmt.Errorf("max retry time elapsed: %w", err)
}
// Wait for the greater of the backoff or throttle delay.
var delay time.Duration
if bOff > throttle {
delay = bOff
} else {
elapsed := b.GetElapsedTime()
if b.MaxElapsedTime != 0 && elapsed+throttle > b.MaxElapsedTime {
return fmt.Errorf("max retry time would elapse: %w", err)
}
delay = throttle
bOff := b.NextBackOff()
delay := max(throttle, bOff)
elapsed := time.Since(startTime)
if maxElapsedTime != 0 && elapsed+throttle > maxElapsedTime {
return fmt.Errorf("max retry time would elapse: %w", err)
}
if ctxErr := waitFunc(ctx, delay); ctxErr != nil {

View file

@ -199,8 +199,9 @@ func WithTimeout(duration time.Duration) Option {
// explicitly returns a backoff time in the response. That time will take
// precedence over these settings.
//
// These settings do not define any network retry strategy. That is entirely
// handled by the gRPC ClientConn.
// These settings define the retry strategy implemented by the exporter.
// These settings do not define any network retry strategy.
// That is handled by the gRPC ClientConn.
//
// If unset, the default retry policy will be used. It will retry the export
// 5 seconds after receiving a retryable error and increase exponentially

View file

@ -71,20 +71,24 @@ var _ otlptrace.Client = (*client)(nil)
func NewClient(opts ...Option) otlptrace.Client {
cfg := otlpconfig.NewHTTPConfig(asHTTPOptions(opts)...)
httpClient := &http.Client{
Transport: ourTransport,
Timeout: cfg.Traces.Timeout,
}
httpClient := cfg.Traces.HTTPClient
if cfg.Traces.TLSCfg != nil || cfg.Traces.Proxy != nil {
clonedTransport := ourTransport.Clone()
httpClient.Transport = clonedTransport
if cfg.Traces.TLSCfg != nil {
clonedTransport.TLSClientConfig = cfg.Traces.TLSCfg
if httpClient == nil {
httpClient = &http.Client{
Transport: ourTransport,
Timeout: cfg.Traces.Timeout,
}
if cfg.Traces.Proxy != nil {
clonedTransport.Proxy = cfg.Traces.Proxy
if cfg.Traces.TLSCfg != nil || cfg.Traces.Proxy != nil {
clonedTransport := ourTransport.Clone()
httpClient.Transport = clonedTransport
if cfg.Traces.TLSCfg != nil {
clonedTransport.TLSClientConfig = cfg.Traces.TLSCfg
}
if cfg.Traces.Proxy != nil {
clonedTransport.Proxy = cfg.Traces.Proxy
}
}
}
@ -300,7 +304,7 @@ type request struct {
// reset reinitializes the request Body and uses ctx for the request.
func (r *request) reset(ctx context.Context) {
r.Body = r.bodyReader()
r.Request = r.Request.WithContext(ctx)
r.Request = r.WithContext(ctx)
}
// retryableError represents a request failure that can be retried.

View file

@ -1,9 +1,11 @@
// Code created by gotmpl. DO NOT MODIFY.
// Code generated by gotmpl. DO NOT MODIFY.
// source: internal/shared/otlp/envconfig/envconfig.go.tmpl
// Copyright The OpenTelemetry Authors
// SPDX-License-Identifier: Apache-2.0
// Package envconfig provides functionality to parse configuration from
// environment variables.
package envconfig // import "go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp/internal/envconfig"
import (

View file

@ -1,6 +1,7 @@
// Copyright The OpenTelemetry Authors
// SPDX-License-Identifier: Apache-2.0
// Package internal provides internal functionally for the otlptracehttp package.
package internal // import "go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp/internal"
//go:generate gotmpl --body=../../../../../internal/shared/otlp/partialsuccess.go.tmpl "--data={}" --out=partialsuccess.go

View file

@ -1,4 +1,4 @@
// Code created by gotmpl. DO NOT MODIFY.
// Code generated by gotmpl. DO NOT MODIFY.
// source: internal/shared/otlp/otlptrace/otlpconfig/envconfig.go.tmpl
// Copyright The OpenTelemetry Authors
@ -77,8 +77,16 @@ func getOptionsFromEnv() []GenericOption {
}),
envconfig.WithCertPool("CERTIFICATE", func(p *x509.CertPool) { tlsConf.RootCAs = p }),
envconfig.WithCertPool("TRACES_CERTIFICATE", func(p *x509.CertPool) { tlsConf.RootCAs = p }),
envconfig.WithClientCert("CLIENT_CERTIFICATE", "CLIENT_KEY", func(c tls.Certificate) { tlsConf.Certificates = []tls.Certificate{c} }),
envconfig.WithClientCert("TRACES_CLIENT_CERTIFICATE", "TRACES_CLIENT_KEY", func(c tls.Certificate) { tlsConf.Certificates = []tls.Certificate{c} }),
envconfig.WithClientCert(
"CLIENT_CERTIFICATE",
"CLIENT_KEY",
func(c tls.Certificate) { tlsConf.Certificates = []tls.Certificate{c} },
),
envconfig.WithClientCert(
"TRACES_CLIENT_CERTIFICATE",
"TRACES_CLIENT_KEY",
func(c tls.Certificate) { tlsConf.Certificates = []tls.Certificate{c} },
),
withTLSConfig(tlsConf, func(c *tls.Config) { opts = append(opts, WithTLSClientConfig(c)) }),
envconfig.WithBool("INSECURE", func(b bool) { opts = append(opts, withInsecure(b)) }),
envconfig.WithBool("TRACES_INSECURE", func(b bool) { opts = append(opts, withInsecure(b)) }),

View file

@ -1,9 +1,10 @@
// Code created by gotmpl. DO NOT MODIFY.
// Code generated by gotmpl. DO NOT MODIFY.
// source: internal/shared/otlp/otlptrace/otlpconfig/options.go.tmpl
// Copyright The OpenTelemetry Authors
// SPDX-License-Identifier: Apache-2.0
// Package otlpconfig provides configuration for the otlptrace exporters.
package otlpconfig // import "go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp/internal/otlpconfig"
import (
@ -52,7 +53,9 @@ type (
// gRPC configurations
GRPCCredentials credentials.TransportCredentials
Proxy HTTPTransportProxyFunc
// HTTP configurations
Proxy HTTPTransportProxyFunc
HTTPClient *http.Client
}
Config struct {
@ -349,3 +352,10 @@ func WithProxy(pf HTTPTransportProxyFunc) GenericOption {
return cfg
})
}
func WithHTTPClient(c *http.Client) GenericOption {
return newGenericOption(func(cfg Config) Config {
cfg.Traces.HTTPClient = c
return cfg
})
}

View file

@ -1,4 +1,4 @@
// Code created by gotmpl. DO NOT MODIFY.
// Code generated by gotmpl. DO NOT MODIFY.
// source: internal/shared/otlp/otlptrace/otlpconfig/optiontypes.go.tmpl
// Copyright The OpenTelemetry Authors

View file

@ -1,4 +1,4 @@
// Code created by gotmpl. DO NOT MODIFY.
// Code generated by gotmpl. DO NOT MODIFY.
// source: internal/shared/otlp/otlptrace/otlpconfig/tls.go.tmpl
// Copyright The OpenTelemetry Authors

View file

@ -1,4 +1,4 @@
// Code created by gotmpl. DO NOT MODIFY.
// Code generated by gotmpl. DO NOT MODIFY.
// source: internal/shared/otlp/partialsuccess.go
// Copyright The OpenTelemetry Authors

View file

@ -1,4 +1,4 @@
// Code created by gotmpl. DO NOT MODIFY.
// Code generated by gotmpl. DO NOT MODIFY.
// source: internal/shared/otlp/retry/retry.go.tmpl
// Copyright The OpenTelemetry Authors
@ -14,7 +14,7 @@ import (
"fmt"
"time"
"github.com/cenkalti/backoff/v4"
"github.com/cenkalti/backoff/v5"
)
// DefaultConfig are the recommended defaults to use.
@ -77,12 +77,12 @@ func (c Config) RequestFunc(evaluate EvaluateFunc) RequestFunc {
RandomizationFactor: backoff.DefaultRandomizationFactor,
Multiplier: backoff.DefaultMultiplier,
MaxInterval: c.MaxInterval,
MaxElapsedTime: c.MaxElapsedTime,
Stop: backoff.Stop,
Clock: backoff.SystemClock,
}
b.Reset()
maxElapsedTime := c.MaxElapsedTime
startTime := time.Now()
for {
err := fn(ctx)
if err == nil {
@ -94,21 +94,17 @@ func (c Config) RequestFunc(evaluate EvaluateFunc) RequestFunc {
return err
}
bOff := b.NextBackOff()
if bOff == backoff.Stop {
if maxElapsedTime != 0 && time.Since(startTime) > maxElapsedTime {
return fmt.Errorf("max retry time elapsed: %w", err)
}
// Wait for the greater of the backoff or throttle delay.
var delay time.Duration
if bOff > throttle {
delay = bOff
} else {
elapsed := b.GetElapsedTime()
if b.MaxElapsedTime != 0 && elapsed+throttle > b.MaxElapsedTime {
return fmt.Errorf("max retry time would elapse: %w", err)
}
delay = throttle
bOff := b.NextBackOff()
delay := max(throttle, bOff)
elapsed := time.Since(startTime)
if maxElapsedTime != 0 && elapsed+throttle > maxElapsedTime {
return fmt.Errorf("max retry time would elapse: %w", err)
}
if ctxErr := waitFunc(ctx, delay); ctxErr != nil {

View file

@ -153,3 +153,19 @@ func WithRetry(rc RetryConfig) Option {
func WithProxy(pf HTTPTransportProxyFunc) Option {
return wrappedOption{otlpconfig.WithProxy(otlpconfig.HTTPTransportProxyFunc(pf))}
}
// WithHTTPClient sets the HTTP client to used by the exporter.
//
// This option will take precedence over [WithProxy], [WithTimeout],
// [WithTLSClientConfig] options as well as OTEL_EXPORTER_OTLP_CERTIFICATE,
// OTEL_EXPORTER_OTLP_TRACES_CERTIFICATE, OTEL_EXPORTER_OTLP_TIMEOUT,
// OTEL_EXPORTER_OTLP_TRACES_TIMEOUT environment variables.
//
// Timeout and all other fields of the passed [http.Client] are left intact.
//
// Be aware that passing an HTTP client with transport like
// [go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp.NewTransport] can
// cause the client to be instrumented twice and cause infinite recursion.
func WithHTTPClient(c *http.Client) Option {
return wrappedOption{otlpconfig.WithHTTPClient(c)}
}

View file

@ -5,5 +5,5 @@ package otlptrace // import "go.opentelemetry.io/otel/exporters/otlp/otlptrace"
// Version is the current release version of the OpenTelemetry OTLP trace exporter in use.
func Version() string {
return "1.35.0"
return "1.36.0"
}

View file

@ -5,11 +5,13 @@ package prometheus // import "go.opentelemetry.io/otel/exporters/prometheus"
import (
"strings"
"sync"
"github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/common/model"
"go.opentelemetry.io/otel/attribute"
"go.opentelemetry.io/otel/internal/global"
"go.opentelemetry.io/otel/sdk/metric"
)
@ -25,6 +27,12 @@ type config struct {
resourceAttributesFilter attribute.Filter
}
var logDeprecatedLegacyScheme = sync.OnceFunc(func() {
global.Warn(
"prometheus exporter legacy scheme deprecated: support for the legacy NameValidationScheme will be removed in a future release",
)
})
// newConfig creates a validated config configured with options.
func newConfig(opts ...Option) config {
cfg := config{}
@ -132,7 +140,8 @@ func WithoutScopeInfo() Option {
// have special behavior based on their name.
func WithNamespace(ns string) Option {
return optionFunc(func(cfg config) config {
if model.NameValidationScheme != model.UTF8Validation {
if model.NameValidationScheme != model.UTF8Validation { // nolint:staticcheck // We need this check to keep supporting the legacy scheme.
logDeprecatedLegacyScheme()
// Only sanitize if prometheus does not support UTF-8.
ns = model.EscapeName(ns, model.NameEscapingScheme)
}

View file

@ -8,6 +8,7 @@ import (
"encoding/hex"
"errors"
"fmt"
"math"
"slices"
"strings"
"sync"
@ -40,7 +41,15 @@ const (
spanIDExemplarKey = "span_id"
)
var errScopeInvalid = errors.New("invalid scope")
var (
errScopeInvalid = errors.New("invalid scope")
metricsPool = sync.Pool{
New: func() interface{} {
return &metricdata.ResourceMetrics{}
},
}
)
// Exporter is a Prometheus Exporter that embeds the OTel metric.Reader
// interface for easy instantiation with a MeterProvider.
@ -144,9 +153,9 @@ func (c *collector) Describe(ch chan<- *prometheus.Desc) {
//
// This method is safe to call concurrently.
func (c *collector) Collect(ch chan<- prometheus.Metric) {
// TODO (#3047): Use a sync.Pool instead of allocating metrics every Collect.
metrics := metricdata.ResourceMetrics{}
err := c.reader.Collect(context.TODO(), &metrics)
metrics := metricsPool.Get().(*metricdata.ResourceMetrics)
defer metricsPool.Put(metrics)
err := c.reader.Collect(context.TODO(), metrics)
if err != nil {
if errors.Is(err, metric.ErrReaderShutdown) {
return
@ -233,6 +242,10 @@ func (c *collector) Collect(ch chan<- prometheus.Metric) {
addHistogramMetric(ch, v, m, name, kv)
case metricdata.Histogram[float64]:
addHistogramMetric(ch, v, m, name, kv)
case metricdata.ExponentialHistogram[int64]:
addExponentialHistogramMetric(ch, v, m, name, kv)
case metricdata.ExponentialHistogram[float64]:
addExponentialHistogramMetric(ch, v, m, name, kv)
case metricdata.Sum[int64]:
addSumMetric(ch, v, m, name, kv)
case metricdata.Sum[float64]:
@ -246,7 +259,67 @@ func (c *collector) Collect(ch chan<- prometheus.Metric) {
}
}
func addHistogramMetric[N int64 | float64](ch chan<- prometheus.Metric, histogram metricdata.Histogram[N], m metricdata.Metrics, name string, kv keyVals) {
func addExponentialHistogramMetric[N int64 | float64](
ch chan<- prometheus.Metric,
histogram metricdata.ExponentialHistogram[N],
m metricdata.Metrics,
name string,
kv keyVals,
) {
for _, dp := range histogram.DataPoints {
keys, values := getAttrs(dp.Attributes)
keys = append(keys, kv.keys...)
values = append(values, kv.vals...)
desc := prometheus.NewDesc(name, m.Description, keys, nil)
// From spec: note that Prometheus Native Histograms buckets are indexed by upper boundary while Exponential Histograms are indexed by lower boundary, the result being that the Offset fields are different-by-one.
positiveBuckets := make(map[int]int64)
for i, c := range dp.PositiveBucket.Counts {
if c > math.MaxInt64 {
otel.Handle(fmt.Errorf("positive count %d is too large to be represented as int64", c))
continue
}
positiveBuckets[int(dp.PositiveBucket.Offset)+i+1] = int64(c) // nolint: gosec // Size check above.
}
negativeBuckets := make(map[int]int64)
for i, c := range dp.NegativeBucket.Counts {
if c > math.MaxInt64 {
otel.Handle(fmt.Errorf("negative count %d is too large to be represented as int64", c))
continue
}
negativeBuckets[int(dp.NegativeBucket.Offset)+i+1] = int64(c) // nolint: gosec // Size check above.
}
m, err := prometheus.NewConstNativeHistogram(
desc,
dp.Count,
float64(dp.Sum),
positiveBuckets,
negativeBuckets,
dp.ZeroCount,
dp.Scale,
dp.ZeroThreshold,
dp.StartTime,
values...)
if err != nil {
otel.Handle(err)
continue
}
// TODO(GiedriusS): add exemplars here after https://github.com/prometheus/client_golang/pull/1654#pullrequestreview-2434669425 is done.
ch <- m
}
}
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)
keys = append(keys, kv.keys...)
@ -270,7 +343,13 @@ 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, name string, kv 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
@ -296,7 +375,13 @@ func addSumMetric[N int64 | float64](ch chan<- prometheus.Metric, sum metricdata
}
}
func addGaugeMetric[N int64 | float64](ch chan<- prometheus.Metric, gauge metricdata.Gauge[N], m metricdata.Metrics, name string, kv 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)
keys = append(keys, kv.keys...)
@ -319,7 +404,7 @@ func getAttrs(attrs attribute.Set) ([]string, []string) {
values := make([]string, 0, attrs.Len())
itr := attrs.Iter()
if model.NameValidationScheme == model.UTF8Validation {
if model.NameValidationScheme == model.UTF8Validation { // nolint:staticcheck // We need this check to keep supporting the legacy scheme.
// Do not perform sanitization if prometheus supports UTF-8.
for itr.Next() {
kv := itr.Attribute()
@ -405,8 +490,9 @@ 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 := m.Name
if model.NameValidationScheme != model.UTF8Validation {
if model.NameValidationScheme != model.UTF8Validation { // nolint:staticcheck // We need this check to keep supporting the legacy scheme.
// Only sanitize if prometheus does not support UTF-8.
logDeprecatedLegacyScheme()
name = model.EscapeName(name, model.NameEscapingScheme)
}
addCounterSuffix := !c.withoutCounterSuffixes && *typ == dto.MetricType_COUNTER
@ -436,11 +522,13 @@ func (c *collector) getName(m metricdata.Metrics, typ *dto.MetricType) string {
// underscore when the escaping scheme is underscore escaping. This is meant to
// capture any character that should be considered a "delimiter".
func convertsToUnderscore(b rune) bool {
return !((b >= 'a' && b <= 'z') || (b >= 'A' && b <= 'Z') || b == ':' || (b >= '0' && b <= '9'))
return (b < 'a' || b > 'z') && (b < 'A' || b > 'Z') && b != ':' && (b < '0' || b > '9')
}
func (c *collector) metricType(m metricdata.Metrics) *dto.MetricType {
switch v := m.Data.(type) {
case metricdata.ExponentialHistogram[int64], metricdata.ExponentialHistogram[float64]:
return dto.MetricType_HISTOGRAM.Enum()
case metricdata.Histogram[int64], metricdata.Histogram[float64]:
return dto.MetricType_HISTOGRAM.Enum()
case metricdata.Sum[float64]:

View file

@ -131,7 +131,9 @@ func redactAggregationTimestamps(orig metricdata.Aggregation) metricdata.Aggrega
}
}
func redactHistogramTimestamps[T int64 | float64](hdp []metricdata.HistogramDataPoint[T]) []metricdata.HistogramDataPoint[T] {
func redactHistogramTimestamps[T int64 | float64](
hdp []metricdata.HistogramDataPoint[T],
) []metricdata.HistogramDataPoint[T] {
out := make([]metricdata.HistogramDataPoint[T], len(hdp))
for i, dp := range hdp {
out[i] = metricdata.HistogramDataPoint[T]{