mirror of
https://gitea.com/Lydanne/buildx.git
synced 2025-07-25 12:48:04 +08:00
vendor: update buildkit to v0.19.0-rc1
Signed-off-by: Tonis Tiigi <tonistiigi@gmail.com>
This commit is contained in:
102
vendor/go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc/config.go
generated
vendored
102
vendor/go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc/config.go
generated
vendored
@@ -1,23 +1,15 @@
|
||||
// Copyright The OpenTelemetry Authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package otelgrpc // import "go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc"
|
||||
|
||||
import (
|
||||
"google.golang.org/grpc/stats"
|
||||
|
||||
"go.opentelemetry.io/otel"
|
||||
"go.opentelemetry.io/otel/attribute"
|
||||
"go.opentelemetry.io/otel/metric"
|
||||
"go.opentelemetry.io/otel/metric/noop"
|
||||
"go.opentelemetry.io/otel/propagation"
|
||||
semconv "go.opentelemetry.io/otel/semconv/v1.17.0"
|
||||
"go.opentelemetry.io/otel/trace"
|
||||
@@ -30,18 +22,28 @@ const (
|
||||
GRPCStatusCodeKey = attribute.Key("rpc.grpc.status_code")
|
||||
)
|
||||
|
||||
// Filter is a predicate used to determine whether a given request in
|
||||
// interceptor info should be traced. A Filter must return true if
|
||||
// InterceptorFilter is a predicate used to determine whether a given request in
|
||||
// interceptor info should be instrumented. A InterceptorFilter must return true if
|
||||
// the request should be traced.
|
||||
type Filter func(*InterceptorInfo) bool
|
||||
//
|
||||
// Deprecated: Use stats handlers instead.
|
||||
type InterceptorFilter func(*InterceptorInfo) bool
|
||||
|
||||
// Filter is a predicate used to determine whether a given request in
|
||||
// should be instrumented by the attached RPC tag info.
|
||||
// A Filter must return true if the request should be instrumented.
|
||||
type Filter func(*stats.RPCTagInfo) bool
|
||||
|
||||
// config is a group of options for this instrumentation.
|
||||
type config struct {
|
||||
Filter Filter
|
||||
Propagators propagation.TextMapPropagator
|
||||
TracerProvider trace.TracerProvider
|
||||
MeterProvider metric.MeterProvider
|
||||
SpanStartOptions []trace.SpanStartOption
|
||||
Filter Filter
|
||||
InterceptorFilter InterceptorFilter
|
||||
Propagators propagation.TextMapPropagator
|
||||
TracerProvider trace.TracerProvider
|
||||
MeterProvider metric.MeterProvider
|
||||
SpanStartOptions []trace.SpanStartOption
|
||||
SpanAttributes []attribute.KeyValue
|
||||
MetricAttributes []attribute.KeyValue
|
||||
|
||||
ReceivedEvent bool
|
||||
SentEvent bool
|
||||
@@ -89,6 +91,9 @@ func newConfig(opts []Option, role string) *config {
|
||||
metric.WithUnit("ms"))
|
||||
if err != nil {
|
||||
otel.Handle(err)
|
||||
if c.rpcDuration == nil {
|
||||
c.rpcDuration = noop.Float64Histogram{}
|
||||
}
|
||||
}
|
||||
|
||||
c.rpcRequestSize, err = c.meter.Int64Histogram("rpc."+role+".request.size",
|
||||
@@ -96,6 +101,9 @@ func newConfig(opts []Option, role string) *config {
|
||||
metric.WithUnit("By"))
|
||||
if err != nil {
|
||||
otel.Handle(err)
|
||||
if c.rpcRequestSize == nil {
|
||||
c.rpcRequestSize = noop.Int64Histogram{}
|
||||
}
|
||||
}
|
||||
|
||||
c.rpcResponseSize, err = c.meter.Int64Histogram("rpc."+role+".response.size",
|
||||
@@ -103,6 +111,9 @@ func newConfig(opts []Option, role string) *config {
|
||||
metric.WithUnit("By"))
|
||||
if err != nil {
|
||||
otel.Handle(err)
|
||||
if c.rpcResponseSize == nil {
|
||||
c.rpcResponseSize = noop.Int64Histogram{}
|
||||
}
|
||||
}
|
||||
|
||||
c.rpcRequestsPerRPC, err = c.meter.Int64Histogram("rpc."+role+".requests_per_rpc",
|
||||
@@ -110,6 +121,9 @@ func newConfig(opts []Option, role string) *config {
|
||||
metric.WithUnit("{count}"))
|
||||
if err != nil {
|
||||
otel.Handle(err)
|
||||
if c.rpcRequestsPerRPC == nil {
|
||||
c.rpcRequestsPerRPC = noop.Int64Histogram{}
|
||||
}
|
||||
}
|
||||
|
||||
c.rpcResponsesPerRPC, err = c.meter.Int64Histogram("rpc."+role+".responses_per_rpc",
|
||||
@@ -117,6 +131,9 @@ func newConfig(opts []Option, role string) *config {
|
||||
metric.WithUnit("{count}"))
|
||||
if err != nil {
|
||||
otel.Handle(err)
|
||||
if c.rpcResponsesPerRPC == nil {
|
||||
c.rpcResponsesPerRPC = noop.Int64Histogram{}
|
||||
}
|
||||
}
|
||||
|
||||
return c
|
||||
@@ -147,15 +164,30 @@ func (o tracerProviderOption) apply(c *config) {
|
||||
// WithInterceptorFilter returns an Option to use the request filter.
|
||||
//
|
||||
// Deprecated: Use stats handlers instead.
|
||||
func WithInterceptorFilter(f Filter) Option {
|
||||
func WithInterceptorFilter(f InterceptorFilter) Option {
|
||||
return interceptorFilterOption{f: f}
|
||||
}
|
||||
|
||||
type interceptorFilterOption struct {
|
||||
f Filter
|
||||
f InterceptorFilter
|
||||
}
|
||||
|
||||
func (o interceptorFilterOption) apply(c *config) {
|
||||
if o.f != nil {
|
||||
c.InterceptorFilter = o.f
|
||||
}
|
||||
}
|
||||
|
||||
// WithFilter returns an Option to use the request filter.
|
||||
func WithFilter(f Filter) Option {
|
||||
return filterOption{f: f}
|
||||
}
|
||||
|
||||
type filterOption struct {
|
||||
f Filter
|
||||
}
|
||||
|
||||
func (o filterOption) apply(c *config) {
|
||||
if o.f != nil {
|
||||
c.Filter = o.f
|
||||
}
|
||||
@@ -227,3 +259,29 @@ func (o spanStartOption) apply(c *config) {
|
||||
func WithSpanOptions(opts ...trace.SpanStartOption) Option {
|
||||
return spanStartOption{opts}
|
||||
}
|
||||
|
||||
type spanAttributesOption struct{ a []attribute.KeyValue }
|
||||
|
||||
func (o spanAttributesOption) apply(c *config) {
|
||||
if o.a != nil {
|
||||
c.SpanAttributes = o.a
|
||||
}
|
||||
}
|
||||
|
||||
// WithSpanAttributes returns an Option to add custom attributes to the spans.
|
||||
func WithSpanAttributes(a ...attribute.KeyValue) Option {
|
||||
return spanAttributesOption{a: a}
|
||||
}
|
||||
|
||||
type metricAttributesOption struct{ a []attribute.KeyValue }
|
||||
|
||||
func (o metricAttributesOption) apply(c *config) {
|
||||
if o.a != nil {
|
||||
c.MetricAttributes = o.a
|
||||
}
|
||||
}
|
||||
|
||||
// WithMetricAttributes returns an Option to add custom attributes to the metrics.
|
||||
func WithMetricAttributes(a ...attribute.KeyValue) Option {
|
||||
return metricAttributesOption{a: a}
|
||||
}
|
||||
|
@@ -1,16 +1,5 @@
|
||||
// Copyright The OpenTelemetry Authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
/*
|
||||
Package otelgrpc is the instrumentation library for [google.golang.org/grpc].
|
||||
|
@@ -1,16 +1,5 @@
|
||||
// Copyright The OpenTelemetry Authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package otelgrpc // import "go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc"
|
||||
|
||||
@@ -18,6 +7,7 @@ package otelgrpc // import "go.opentelemetry.io/contrib/instrumentation/google.g
|
||||
// https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/trace/semantic_conventions/rpc.md
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"io"
|
||||
"net"
|
||||
"strconv"
|
||||
@@ -59,7 +49,7 @@ var (
|
||||
)
|
||||
|
||||
// UnaryClientInterceptor returns a grpc.UnaryClientInterceptor suitable
|
||||
// for use in a grpc.Dial call.
|
||||
// for use in a grpc.NewClient call.
|
||||
//
|
||||
// Deprecated: Use [NewClientHandler] instead.
|
||||
func UnaryClientInterceptor(opts ...Option) grpc.UnaryClientInterceptor {
|
||||
@@ -81,7 +71,7 @@ func UnaryClientInterceptor(opts ...Option) grpc.UnaryClientInterceptor {
|
||||
Method: method,
|
||||
Type: UnaryClient,
|
||||
}
|
||||
if cfg.Filter != nil && !cfg.Filter(i) {
|
||||
if cfg.InterceptorFilter != nil && !cfg.InterceptorFilter(i) {
|
||||
return invoker(ctx, method, req, reply, cc, callOpts...)
|
||||
}
|
||||
|
||||
@@ -147,7 +137,7 @@ func (w *clientStream) RecvMsg(m interface{}) error {
|
||||
|
||||
if err == nil && !w.desc.ServerStreams {
|
||||
w.endSpan(nil)
|
||||
} else if err == io.EOF {
|
||||
} else if errors.Is(err, io.EOF) {
|
||||
w.endSpan(nil)
|
||||
} else if err != nil {
|
||||
w.endSpan(err)
|
||||
@@ -196,7 +186,7 @@ func (w *clientStream) CloseSend() error {
|
||||
return err
|
||||
}
|
||||
|
||||
func wrapClientStream(ctx context.Context, s grpc.ClientStream, desc *grpc.StreamDesc, span trace.Span, cfg *config) *clientStream {
|
||||
func wrapClientStream(s grpc.ClientStream, desc *grpc.StreamDesc, span trace.Span, cfg *config) *clientStream {
|
||||
return &clientStream{
|
||||
ClientStream: s,
|
||||
span: span,
|
||||
@@ -219,7 +209,7 @@ func (w *clientStream) endSpan(err error) {
|
||||
}
|
||||
|
||||
// StreamClientInterceptor returns a grpc.StreamClientInterceptor suitable
|
||||
// for use in a grpc.Dial call.
|
||||
// for use in a grpc.NewClient call.
|
||||
//
|
||||
// Deprecated: Use [NewClientHandler] instead.
|
||||
func StreamClientInterceptor(opts ...Option) grpc.StreamClientInterceptor {
|
||||
@@ -241,7 +231,7 @@ func StreamClientInterceptor(opts ...Option) grpc.StreamClientInterceptor {
|
||||
Method: method,
|
||||
Type: StreamClient,
|
||||
}
|
||||
if cfg.Filter != nil && !cfg.Filter(i) {
|
||||
if cfg.InterceptorFilter != nil && !cfg.InterceptorFilter(i) {
|
||||
return streamer(ctx, desc, cc, method, callOpts...)
|
||||
}
|
||||
|
||||
@@ -270,7 +260,7 @@ func StreamClientInterceptor(opts ...Option) grpc.StreamClientInterceptor {
|
||||
span.End()
|
||||
return s, err
|
||||
}
|
||||
stream := wrapClientStream(ctx, s, desc, span, cfg)
|
||||
stream := wrapClientStream(s, desc, span, cfg)
|
||||
return stream, nil
|
||||
}
|
||||
}
|
||||
@@ -296,7 +286,7 @@ func UnaryServerInterceptor(opts ...Option) grpc.UnaryServerInterceptor {
|
||||
UnaryServerInfo: info,
|
||||
Type: UnaryServer,
|
||||
}
|
||||
if cfg.Filter != nil && !cfg.Filter(i) {
|
||||
if cfg.InterceptorFilter != nil && !cfg.InterceptorFilter(i) {
|
||||
return handler(ctx, req)
|
||||
}
|
||||
|
||||
@@ -344,7 +334,7 @@ func UnaryServerInterceptor(opts ...Option) grpc.UnaryServerInterceptor {
|
||||
elapsedTime := float64(time.Since(before)) / float64(time.Millisecond)
|
||||
|
||||
metricAttrs = append(metricAttrs, grpcStatusCodeAttr)
|
||||
cfg.rpcDuration.Record(ctx, elapsedTime, metric.WithAttributes(metricAttrs...))
|
||||
cfg.rpcDuration.Record(ctx, elapsedTime, metric.WithAttributeSet(attribute.NewSet(metricAttrs...)))
|
||||
|
||||
return resp, err
|
||||
}
|
||||
@@ -422,7 +412,7 @@ func StreamServerInterceptor(opts ...Option) grpc.StreamServerInterceptor {
|
||||
StreamServerInfo: info,
|
||||
Type: StreamServer,
|
||||
}
|
||||
if cfg.Filter != nil && !cfg.Filter(i) {
|
||||
if cfg.InterceptorFilter != nil && !cfg.InterceptorFilter(i) {
|
||||
return handler(srv, wrapServerStream(ctx, ss, cfg))
|
||||
}
|
||||
|
||||
|
@@ -1,16 +1,5 @@
|
||||
// Copyright The OpenTelemetry Authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package otelgrpc // import "go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc"
|
||||
|
||||
|
@@ -1,16 +1,5 @@
|
||||
// Copyright The OpenTelemetry Authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package internal // import "go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc/internal"
|
||||
|
||||
|
@@ -1,16 +1,5 @@
|
||||
// Copyright The OpenTelemetry Authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package otelgrpc // import "go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc"
|
||||
|
||||
|
@@ -1,16 +1,5 @@
|
||||
// Copyright The OpenTelemetry Authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package otelgrpc // import "go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc"
|
||||
|
||||
|
@@ -1,16 +1,5 @@
|
||||
// Copyright The OpenTelemetry Authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package otelgrpc // import "go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc"
|
||||
|
||||
@@ -20,6 +9,7 @@ import (
|
||||
"time"
|
||||
|
||||
grpc_codes "google.golang.org/grpc/codes"
|
||||
"google.golang.org/grpc/peer"
|
||||
"google.golang.org/grpc/stats"
|
||||
"google.golang.org/grpc/status"
|
||||
|
||||
@@ -37,13 +27,14 @@ type gRPCContext struct {
|
||||
messagesReceived int64
|
||||
messagesSent int64
|
||||
metricAttrs []attribute.KeyValue
|
||||
record bool
|
||||
}
|
||||
|
||||
type serverHandler struct {
|
||||
*config
|
||||
}
|
||||
|
||||
// NewServerHandler creates a stats.Handler for gRPC server.
|
||||
// NewServerHandler creates a stats.Handler for a gRPC server.
|
||||
func NewServerHandler(opts ...Option) stats.Handler {
|
||||
h := &serverHandler{
|
||||
config: newConfig(opts, "server"),
|
||||
@@ -54,9 +45,6 @@ func NewServerHandler(opts ...Option) stats.Handler {
|
||||
|
||||
// TagConn can attach some information to the given context.
|
||||
func (h *serverHandler) TagConn(ctx context.Context, info *stats.ConnTagInfo) context.Context {
|
||||
span := trace.SpanFromContext(ctx)
|
||||
attrs := peerAttr(peerFromCtx(ctx))
|
||||
span.SetAttributes(attrs...)
|
||||
return ctx
|
||||
}
|
||||
|
||||
@@ -74,25 +62,30 @@ func (h *serverHandler) TagRPC(ctx context.Context, info *stats.RPCTagInfo) cont
|
||||
trace.ContextWithRemoteSpanContext(ctx, trace.SpanContextFromContext(ctx)),
|
||||
name,
|
||||
trace.WithSpanKind(trace.SpanKindServer),
|
||||
trace.WithAttributes(attrs...),
|
||||
trace.WithAttributes(append(attrs, h.config.SpanAttributes...)...),
|
||||
)
|
||||
|
||||
gctx := gRPCContext{
|
||||
metricAttrs: attrs,
|
||||
metricAttrs: append(attrs, h.config.MetricAttributes...),
|
||||
record: true,
|
||||
}
|
||||
if h.config.Filter != nil {
|
||||
gctx.record = h.config.Filter(info)
|
||||
}
|
||||
return context.WithValue(ctx, gRPCContextKey{}, &gctx)
|
||||
}
|
||||
|
||||
// HandleRPC processes the RPC stats.
|
||||
func (h *serverHandler) HandleRPC(ctx context.Context, rs stats.RPCStats) {
|
||||
h.handleRPC(ctx, rs)
|
||||
isServer := true
|
||||
h.handleRPC(ctx, rs, isServer)
|
||||
}
|
||||
|
||||
type clientHandler struct {
|
||||
*config
|
||||
}
|
||||
|
||||
// NewClientHandler creates a stats.Handler for gRPC client.
|
||||
// NewClientHandler creates a stats.Handler for a gRPC client.
|
||||
func NewClientHandler(opts ...Option) stats.Handler {
|
||||
h := &clientHandler{
|
||||
config: newConfig(opts, "client"),
|
||||
@@ -109,11 +102,15 @@ func (h *clientHandler) TagRPC(ctx context.Context, info *stats.RPCTagInfo) cont
|
||||
ctx,
|
||||
name,
|
||||
trace.WithSpanKind(trace.SpanKindClient),
|
||||
trace.WithAttributes(attrs...),
|
||||
trace.WithAttributes(append(attrs, h.config.SpanAttributes...)...),
|
||||
)
|
||||
|
||||
gctx := gRPCContext{
|
||||
metricAttrs: attrs,
|
||||
metricAttrs: append(attrs, h.config.MetricAttributes...),
|
||||
record: true,
|
||||
}
|
||||
if h.config.Filter != nil {
|
||||
gctx.record = h.config.Filter(info)
|
||||
}
|
||||
|
||||
return inject(context.WithValue(ctx, gRPCContextKey{}, &gctx), h.config.Propagators)
|
||||
@@ -121,14 +118,12 @@ func (h *clientHandler) TagRPC(ctx context.Context, info *stats.RPCTagInfo) cont
|
||||
|
||||
// HandleRPC processes the RPC stats.
|
||||
func (h *clientHandler) HandleRPC(ctx context.Context, rs stats.RPCStats) {
|
||||
h.handleRPC(ctx, rs)
|
||||
isServer := false
|
||||
h.handleRPC(ctx, rs, isServer)
|
||||
}
|
||||
|
||||
// TagConn can attach some information to the given context.
|
||||
func (h *clientHandler) TagConn(ctx context.Context, cti *stats.ConnTagInfo) context.Context {
|
||||
span := trace.SpanFromContext(ctx)
|
||||
attrs := peerAttr(cti.RemoteAddr.String())
|
||||
span.SetAttributes(attrs...)
|
||||
func (h *clientHandler) TagConn(ctx context.Context, info *stats.ConnTagInfo) context.Context {
|
||||
return ctx
|
||||
}
|
||||
|
||||
@@ -137,20 +132,26 @@ func (h *clientHandler) HandleConn(context.Context, stats.ConnStats) {
|
||||
// no-op
|
||||
}
|
||||
|
||||
func (c *config) handleRPC(ctx context.Context, rs stats.RPCStats) {
|
||||
func (c *config) handleRPC(ctx context.Context, rs stats.RPCStats, isServer bool) { // nolint: revive // isServer is not a control flag.
|
||||
span := trace.SpanFromContext(ctx)
|
||||
gctx, _ := ctx.Value(gRPCContextKey{}).(*gRPCContext)
|
||||
var metricAttrs []attribute.KeyValue
|
||||
var messageId int64
|
||||
metricAttrs := make([]attribute.KeyValue, 0, len(gctx.metricAttrs)+1)
|
||||
metricAttrs = append(metricAttrs, gctx.metricAttrs...)
|
||||
wctx := withoutCancel(ctx)
|
||||
|
||||
gctx, _ := ctx.Value(gRPCContextKey{}).(*gRPCContext)
|
||||
if gctx != nil {
|
||||
if !gctx.record {
|
||||
return
|
||||
}
|
||||
metricAttrs = make([]attribute.KeyValue, 0, len(gctx.metricAttrs)+1)
|
||||
metricAttrs = append(metricAttrs, gctx.metricAttrs...)
|
||||
}
|
||||
|
||||
switch rs := rs.(type) {
|
||||
case *stats.Begin:
|
||||
case *stats.InPayload:
|
||||
if gctx != nil {
|
||||
messageId = atomic.AddInt64(&gctx.messagesReceived, 1)
|
||||
c.rpcRequestSize.Record(wctx, int64(rs.Length), metric.WithAttributes(metricAttrs...))
|
||||
c.rpcRequestSize.Record(ctx, int64(rs.Length), metric.WithAttributeSet(attribute.NewSet(metricAttrs...)))
|
||||
}
|
||||
|
||||
if c.ReceivedEvent {
|
||||
@@ -166,7 +167,7 @@ func (c *config) handleRPC(ctx context.Context, rs stats.RPCStats) {
|
||||
case *stats.OutPayload:
|
||||
if gctx != nil {
|
||||
messageId = atomic.AddInt64(&gctx.messagesSent, 1)
|
||||
c.rpcResponseSize.Record(wctx, int64(rs.Length), metric.WithAttributes(metricAttrs...))
|
||||
c.rpcResponseSize.Record(ctx, int64(rs.Length), metric.WithAttributeSet(attribute.NewSet(metricAttrs...)))
|
||||
}
|
||||
|
||||
if c.SentEvent {
|
||||
@@ -180,12 +181,21 @@ func (c *config) handleRPC(ctx context.Context, rs stats.RPCStats) {
|
||||
)
|
||||
}
|
||||
case *stats.OutTrailer:
|
||||
case *stats.OutHeader:
|
||||
if p, ok := peer.FromContext(ctx); ok {
|
||||
span.SetAttributes(peerAttr(p.Addr.String())...)
|
||||
}
|
||||
case *stats.End:
|
||||
var rpcStatusAttr attribute.KeyValue
|
||||
|
||||
if rs.Error != nil {
|
||||
s, _ := status.FromError(rs.Error)
|
||||
span.SetStatus(codes.Error, s.Message())
|
||||
if isServer {
|
||||
statusCode, msg := serverStatus(s)
|
||||
span.SetStatus(statusCode, msg)
|
||||
} else {
|
||||
span.SetStatus(codes.Error, s.Message())
|
||||
}
|
||||
rpcStatusAttr = semconv.RPCGRPCStatusCodeKey.Int(int(s.Code()))
|
||||
} else {
|
||||
rpcStatusAttr = semconv.RPCGRPCStatusCodeKey.Int(int(grpc_codes.OK))
|
||||
@@ -194,45 +204,19 @@ func (c *config) handleRPC(ctx context.Context, rs stats.RPCStats) {
|
||||
span.End()
|
||||
|
||||
metricAttrs = append(metricAttrs, rpcStatusAttr)
|
||||
// Allocate vararg slice once.
|
||||
recordOpts := []metric.RecordOption{metric.WithAttributeSet(attribute.NewSet(metricAttrs...))}
|
||||
|
||||
// Use floating point division here for higher precision (instead of Millisecond method).
|
||||
// Measure right before calling Record() to capture as much elapsed time as possible.
|
||||
elapsedTime := float64(rs.EndTime.Sub(rs.BeginTime)) / float64(time.Millisecond)
|
||||
|
||||
c.rpcDuration.Record(wctx, elapsedTime, metric.WithAttributes(metricAttrs...))
|
||||
c.rpcRequestsPerRPC.Record(wctx, atomic.LoadInt64(&gctx.messagesReceived), metric.WithAttributes(metricAttrs...))
|
||||
c.rpcResponsesPerRPC.Record(wctx, atomic.LoadInt64(&gctx.messagesSent), metric.WithAttributes(metricAttrs...))
|
||||
c.rpcDuration.Record(ctx, elapsedTime, recordOpts...)
|
||||
if gctx != nil {
|
||||
c.rpcRequestsPerRPC.Record(ctx, atomic.LoadInt64(&gctx.messagesReceived), recordOpts...)
|
||||
c.rpcResponsesPerRPC.Record(ctx, atomic.LoadInt64(&gctx.messagesSent), recordOpts...)
|
||||
}
|
||||
default:
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
func withoutCancel(parent context.Context) context.Context {
|
||||
if parent == nil {
|
||||
panic("cannot create context from nil parent")
|
||||
}
|
||||
return withoutCancelCtx{parent}
|
||||
}
|
||||
|
||||
type withoutCancelCtx struct {
|
||||
c context.Context
|
||||
}
|
||||
|
||||
func (withoutCancelCtx) Deadline() (deadline time.Time, ok bool) {
|
||||
return
|
||||
}
|
||||
|
||||
func (withoutCancelCtx) Done() <-chan struct{} {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (withoutCancelCtx) Err() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (w withoutCancelCtx) Value(key any) any {
|
||||
return w.c.Value(key)
|
||||
}
|
||||
|
||||
func (w withoutCancelCtx) String() string {
|
||||
return "withoutCancel"
|
||||
}
|
||||
|
@@ -1,22 +1,11 @@
|
||||
// Copyright The OpenTelemetry Authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package otelgrpc // import "go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc"
|
||||
|
||||
// Version is the current release version of the gRPC instrumentation.
|
||||
func Version() string {
|
||||
return "0.46.1"
|
||||
return "0.56.0"
|
||||
// This string is updated by the pre_release.sh script during release
|
||||
}
|
||||
|
||||
|
@@ -1,16 +1,5 @@
|
||||
// Copyright The OpenTelemetry Authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package otelhttptrace // import "go.opentelemetry.io/contrib/instrumentation/net/http/httptrace/otelhttptrace"
|
||||
|
||||
|
@@ -1,16 +1,5 @@
|
||||
// Copyright The OpenTelemetry Authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package otelhttptrace // import "go.opentelemetry.io/contrib/instrumentation/net/http/httptrace/otelhttptrace"
|
||||
|
||||
@@ -25,7 +14,7 @@ import (
|
||||
"go.opentelemetry.io/otel"
|
||||
"go.opentelemetry.io/otel/attribute"
|
||||
"go.opentelemetry.io/otel/codes"
|
||||
semconv "go.opentelemetry.io/otel/semconv/v1.17.0"
|
||||
semconv "go.opentelemetry.io/otel/semconv/v1.20.0"
|
||||
"go.opentelemetry.io/otel/trace"
|
||||
)
|
||||
|
||||
@@ -226,6 +215,10 @@ func (ct *clientTracer) start(hook, spanName string, attrs ...attribute.KeyValue
|
||||
|
||||
func (ct *clientTracer) end(hook string, err error, attrs ...attribute.KeyValue) {
|
||||
if !ct.useSpans {
|
||||
// sometimes end may be called without previous start
|
||||
if ct.root == nil {
|
||||
ct.root = trace.SpanFromContext(ct.Context)
|
||||
}
|
||||
if err != nil {
|
||||
attrs = append(attrs, attribute.String(hook+".error", err.Error()))
|
||||
}
|
||||
|
@@ -1,16 +1,5 @@
|
||||
// Copyright The OpenTelemetry Authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package otelhttptrace // import "go.opentelemetry.io/contrib/instrumentation/net/http/httptrace/otelhttptrace"
|
||||
|
||||
@@ -23,7 +12,7 @@ import (
|
||||
"go.opentelemetry.io/otel/attribute"
|
||||
"go.opentelemetry.io/otel/baggage"
|
||||
"go.opentelemetry.io/otel/propagation"
|
||||
semconv "go.opentelemetry.io/otel/semconv/v1.17.0"
|
||||
semconv "go.opentelemetry.io/otel/semconv/v1.20.0"
|
||||
"go.opentelemetry.io/otel/trace"
|
||||
)
|
||||
|
||||
|
@@ -1,16 +1,5 @@
|
||||
// Copyright The OpenTelemetry Authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package semconvutil // import "go.opentelemetry.io/contrib/instrumentation/net/http/httptrace/otelhttptrace/internal/semconvutil"
|
||||
|
||||
|
@@ -2,18 +2,7 @@
|
||||
// source: internal/shared/semconvutil/httpconv.go.tmpl
|
||||
|
||||
// Copyright The OpenTelemetry Authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package semconvutil // import "go.opentelemetry.io/contrib/instrumentation/net/http/httptrace/otelhttptrace/internal/semconvutil"
|
||||
|
||||
@@ -24,7 +13,7 @@ import (
|
||||
|
||||
"go.opentelemetry.io/otel/attribute"
|
||||
"go.opentelemetry.io/otel/codes"
|
||||
semconv "go.opentelemetry.io/otel/semconv/v1.17.0"
|
||||
semconv "go.opentelemetry.io/otel/semconv/v1.20.0"
|
||||
)
|
||||
|
||||
// HTTPClientResponse returns trace attributes for an HTTP response received by a
|
||||
@@ -43,14 +32,22 @@ func HTTPClientResponse(resp *http.Response) []attribute.KeyValue {
|
||||
}
|
||||
|
||||
// HTTPClientRequest returns trace attributes for an HTTP request made by a client.
|
||||
// The following attributes are always returned: "http.url", "http.flavor",
|
||||
// "http.method", "net.peer.name". The following attributes are returned if the
|
||||
// related values are defined in req: "net.peer.port", "http.user_agent",
|
||||
// "http.request_content_length", "enduser.id".
|
||||
// The following attributes are always returned: "http.url", "http.method",
|
||||
// "net.peer.name". The following attributes are returned if the related values
|
||||
// are defined in req: "net.peer.port", "user_agent.original",
|
||||
// "http.request_content_length".
|
||||
func HTTPClientRequest(req *http.Request) []attribute.KeyValue {
|
||||
return hc.ClientRequest(req)
|
||||
}
|
||||
|
||||
// HTTPClientRequestMetrics returns metric attributes for an HTTP request made by a client.
|
||||
// The following attributes are always returned: "http.method", "net.peer.name".
|
||||
// The following attributes are returned if the
|
||||
// related values are defined in req: "net.peer.port".
|
||||
func HTTPClientRequestMetrics(req *http.Request) []attribute.KeyValue {
|
||||
return hc.ClientRequestMetrics(req)
|
||||
}
|
||||
|
||||
// HTTPClientStatus returns a span status code and message for an HTTP status code
|
||||
// value received by a client.
|
||||
func HTTPClientStatus(code int) (codes.Code, string) {
|
||||
@@ -75,10 +72,9 @@ func HTTPClientStatus(code int) (codes.Code, string) {
|
||||
// The req Host will be used to determine the server instead.
|
||||
//
|
||||
// The following attributes are always returned: "http.method", "http.scheme",
|
||||
// "http.flavor", "http.target", "net.host.name". The following attributes are
|
||||
// returned if they related values are defined in req: "net.host.port",
|
||||
// "net.sock.peer.addr", "net.sock.peer.port", "http.user_agent", "enduser.id",
|
||||
// "http.client_ip".
|
||||
// "http.target", "net.host.name". The following attributes are returned if
|
||||
// they related values are defined in req: "net.host.port", "net.sock.peer.addr",
|
||||
// "net.sock.peer.port", "user_agent.original", "http.client_ip".
|
||||
func HTTPServerRequest(server string, req *http.Request) []attribute.KeyValue {
|
||||
return hc.ServerRequest(server, req)
|
||||
}
|
||||
@@ -101,8 +97,8 @@ func HTTPServerRequest(server string, req *http.Request) []attribute.KeyValue {
|
||||
// The req Host will be used to determine the server instead.
|
||||
//
|
||||
// The following attributes are always returned: "http.method", "http.scheme",
|
||||
// "http.flavor", "net.host.name". The following attributes are
|
||||
// returned if they related values are defined in req: "net.host.port".
|
||||
// "net.host.name". The following attributes are returned if they related
|
||||
// values are defined in req: "net.host.port".
|
||||
func HTTPServerRequestMetrics(server string, req *http.Request) []attribute.KeyValue {
|
||||
return hc.ServerRequestMetrics(server, req)
|
||||
}
|
||||
@@ -114,44 +110,12 @@ func HTTPServerStatus(code int) (codes.Code, string) {
|
||||
return hc.ServerStatus(code)
|
||||
}
|
||||
|
||||
// HTTPRequestHeader returns the contents of h as attributes.
|
||||
//
|
||||
// Instrumentation should require an explicit configuration of which headers to
|
||||
// captured and then prune what they pass here. Including all headers can be a
|
||||
// security risk - explicit configuration helps avoid leaking sensitive
|
||||
// information.
|
||||
//
|
||||
// The User-Agent header is already captured in the http.user_agent attribute
|
||||
// from ClientRequest and ServerRequest. Instrumentation may provide an option
|
||||
// to capture that header here even though it is not recommended. Otherwise,
|
||||
// instrumentation should filter that out of what is passed.
|
||||
func HTTPRequestHeader(h http.Header) []attribute.KeyValue {
|
||||
return hc.RequestHeader(h)
|
||||
}
|
||||
|
||||
// HTTPResponseHeader returns the contents of h as attributes.
|
||||
//
|
||||
// Instrumentation should require an explicit configuration of which headers to
|
||||
// captured and then prune what they pass here. Including all headers can be a
|
||||
// security risk - explicit configuration helps avoid leaking sensitive
|
||||
// information.
|
||||
//
|
||||
// The User-Agent header is already captured in the http.user_agent attribute
|
||||
// from ClientRequest and ServerRequest. Instrumentation may provide an option
|
||||
// to capture that header here even though it is not recommended. Otherwise,
|
||||
// instrumentation should filter that out of what is passed.
|
||||
func HTTPResponseHeader(h http.Header) []attribute.KeyValue {
|
||||
return hc.ResponseHeader(h)
|
||||
}
|
||||
|
||||
// httpConv are the HTTP semantic convention attributes defined for a version
|
||||
// of the OpenTelemetry specification.
|
||||
type httpConv struct {
|
||||
NetConv *netConv
|
||||
|
||||
EnduserIDKey attribute.Key
|
||||
HTTPClientIPKey attribute.Key
|
||||
HTTPFlavorKey attribute.Key
|
||||
HTTPMethodKey attribute.Key
|
||||
HTTPRequestContentLengthKey attribute.Key
|
||||
HTTPResponseContentLengthKey attribute.Key
|
||||
@@ -161,15 +125,13 @@ type httpConv struct {
|
||||
HTTPStatusCodeKey attribute.Key
|
||||
HTTPTargetKey attribute.Key
|
||||
HTTPURLKey attribute.Key
|
||||
HTTPUserAgentKey attribute.Key
|
||||
UserAgentOriginalKey attribute.Key
|
||||
}
|
||||
|
||||
var hc = &httpConv{
|
||||
NetConv: nc,
|
||||
|
||||
EnduserIDKey: semconv.EnduserIDKey,
|
||||
HTTPClientIPKey: semconv.HTTPClientIPKey,
|
||||
HTTPFlavorKey: semconv.HTTPFlavorKey,
|
||||
HTTPMethodKey: semconv.HTTPMethodKey,
|
||||
HTTPRequestContentLengthKey: semconv.HTTPRequestContentLengthKey,
|
||||
HTTPResponseContentLengthKey: semconv.HTTPResponseContentLengthKey,
|
||||
@@ -179,7 +141,7 @@ var hc = &httpConv{
|
||||
HTTPStatusCodeKey: semconv.HTTPStatusCodeKey,
|
||||
HTTPTargetKey: semconv.HTTPTargetKey,
|
||||
HTTPURLKey: semconv.HTTPURLKey,
|
||||
HTTPUserAgentKey: semconv.HTTPUserAgentKey,
|
||||
UserAgentOriginalKey: semconv.UserAgentOriginalKey,
|
||||
}
|
||||
|
||||
// ClientResponse returns attributes for an HTTP response received by a client
|
||||
@@ -193,6 +155,10 @@ var hc = &httpConv{
|
||||
//
|
||||
// append(ClientResponse(resp), ClientRequest(resp.Request)...)
|
||||
func (c *httpConv) ClientResponse(resp *http.Response) []attribute.KeyValue {
|
||||
/* The following semantic conventions are returned if present:
|
||||
http.status_code int
|
||||
http.response_content_length int
|
||||
*/
|
||||
var n int
|
||||
if resp.StatusCode > 0 {
|
||||
n++
|
||||
@@ -212,11 +178,31 @@ func (c *httpConv) ClientResponse(resp *http.Response) []attribute.KeyValue {
|
||||
}
|
||||
|
||||
// ClientRequest returns attributes for an HTTP request made by a client. The
|
||||
// following attributes are always returned: "http.url", "http.flavor",
|
||||
// "http.method", "net.peer.name". The following attributes are returned if the
|
||||
// related values are defined in req: "net.peer.port", "http.user_agent",
|
||||
// "http.request_content_length", "enduser.id".
|
||||
// following attributes are always returned: "http.url", "http.method",
|
||||
// "net.peer.name". The following attributes are returned if the related values
|
||||
// are defined in req: "net.peer.port", "user_agent.original",
|
||||
// "http.request_content_length", "user_agent.original".
|
||||
func (c *httpConv) ClientRequest(req *http.Request) []attribute.KeyValue {
|
||||
/* The following semantic conventions are returned if present:
|
||||
http.method string
|
||||
user_agent.original string
|
||||
http.url string
|
||||
net.peer.name string
|
||||
net.peer.port int
|
||||
http.request_content_length int
|
||||
*/
|
||||
|
||||
/* The following semantic conventions are not returned:
|
||||
http.status_code This requires the response. See ClientResponse.
|
||||
http.response_content_length This requires the response. See ClientResponse.
|
||||
net.sock.family This requires the socket used.
|
||||
net.sock.peer.addr This requires the socket used.
|
||||
net.sock.peer.name This requires the socket used.
|
||||
net.sock.peer.port This requires the socket used.
|
||||
http.resend_count This is something outside of a single request.
|
||||
net.protocol.name The value is the Request is ignored, and the go client will always use "http".
|
||||
net.protocol.version The value in the Request is ignored, and the go client will always use 1.1 or 2.0.
|
||||
*/
|
||||
n := 3 // URL, peer name, proto, and method.
|
||||
var h string
|
||||
if req.URL != nil {
|
||||
@@ -234,14 +220,10 @@ func (c *httpConv) ClientRequest(req *http.Request) []attribute.KeyValue {
|
||||
if req.ContentLength > 0 {
|
||||
n++
|
||||
}
|
||||
userID, _, hasUserID := req.BasicAuth()
|
||||
if hasUserID {
|
||||
n++
|
||||
}
|
||||
|
||||
attrs := make([]attribute.KeyValue, 0, n)
|
||||
|
||||
attrs = append(attrs, c.method(req.Method))
|
||||
attrs = append(attrs, c.flavor(req.Proto))
|
||||
|
||||
var u string
|
||||
if req.URL != nil {
|
||||
@@ -260,15 +242,43 @@ func (c *httpConv) ClientRequest(req *http.Request) []attribute.KeyValue {
|
||||
}
|
||||
|
||||
if useragent != "" {
|
||||
attrs = append(attrs, c.HTTPUserAgentKey.String(useragent))
|
||||
attrs = append(attrs, c.UserAgentOriginalKey.String(useragent))
|
||||
}
|
||||
|
||||
if l := req.ContentLength; l > 0 {
|
||||
attrs = append(attrs, c.HTTPRequestContentLengthKey.Int64(l))
|
||||
}
|
||||
|
||||
if hasUserID {
|
||||
attrs = append(attrs, c.EnduserIDKey.String(userID))
|
||||
return attrs
|
||||
}
|
||||
|
||||
// ClientRequestMetrics returns metric attributes for an HTTP request made by a client. The
|
||||
// following attributes are always returned: "http.method", "net.peer.name".
|
||||
// The following attributes are returned if the related values
|
||||
// are defined in req: "net.peer.port".
|
||||
func (c *httpConv) ClientRequestMetrics(req *http.Request) []attribute.KeyValue {
|
||||
/* The following semantic conventions are returned if present:
|
||||
http.method string
|
||||
net.peer.name string
|
||||
net.peer.port int
|
||||
*/
|
||||
|
||||
n := 2 // method, peer name.
|
||||
var h string
|
||||
if req.URL != nil {
|
||||
h = req.URL.Host
|
||||
}
|
||||
peer, p := firstHostPort(h, req.Header.Get("Host"))
|
||||
port := requiredHTTPPort(req.URL != nil && req.URL.Scheme == "https", p)
|
||||
if port > 0 {
|
||||
n++
|
||||
}
|
||||
|
||||
attrs := make([]attribute.KeyValue, 0, n)
|
||||
attrs = append(attrs, c.method(req.Method), c.NetConv.PeerName(peer))
|
||||
|
||||
if port > 0 {
|
||||
attrs = append(attrs, c.NetConv.PeerPort(port))
|
||||
}
|
||||
|
||||
return attrs
|
||||
@@ -291,18 +301,35 @@ func (c *httpConv) ClientRequest(req *http.Request) []attribute.KeyValue {
|
||||
// The req Host will be used to determine the server instead.
|
||||
//
|
||||
// The following attributes are always returned: "http.method", "http.scheme",
|
||||
// "http.flavor", "http.target", "net.host.name". The following attributes are
|
||||
// returned if they related values are defined in req: "net.host.port",
|
||||
// "net.sock.peer.addr", "net.sock.peer.port", "http.user_agent", "enduser.id",
|
||||
// "http.client_ip".
|
||||
// "http.target", "net.host.name". The following attributes are returned if they
|
||||
// related values are defined in req: "net.host.port", "net.sock.peer.addr",
|
||||
// "net.sock.peer.port", "user_agent.original", "http.client_ip",
|
||||
// "net.protocol.name", "net.protocol.version".
|
||||
func (c *httpConv) ServerRequest(server string, req *http.Request) []attribute.KeyValue {
|
||||
// TODO: This currently does not add the specification required
|
||||
// `http.target` attribute. It has too high of a cardinality to safely be
|
||||
// added. An alternate should be added, or this comment removed, when it is
|
||||
// addressed by the specification. If it is ultimately decided to continue
|
||||
// not including the attribute, the HTTPTargetKey field of the httpConv
|
||||
// should be removed as well.
|
||||
/* The following semantic conventions are returned if present:
|
||||
http.method string
|
||||
http.scheme string
|
||||
net.host.name string
|
||||
net.host.port int
|
||||
net.sock.peer.addr string
|
||||
net.sock.peer.port int
|
||||
user_agent.original string
|
||||
http.client_ip string
|
||||
net.protocol.name string Note: not set if the value is "http".
|
||||
net.protocol.version string
|
||||
http.target string Note: doesn't include the query parameter.
|
||||
*/
|
||||
|
||||
/* The following semantic conventions are not returned:
|
||||
http.status_code This requires the response.
|
||||
http.request_content_length This requires the len() of body, which can mutate it.
|
||||
http.response_content_length This requires the response.
|
||||
http.route This is not available.
|
||||
net.sock.peer.name This would require a DNS lookup.
|
||||
net.sock.host.addr The request doesn't have access to the underlying socket.
|
||||
net.sock.host.port The request doesn't have access to the underlying socket.
|
||||
|
||||
*/
|
||||
n := 4 // Method, scheme, proto, and host name.
|
||||
var host string
|
||||
var p int
|
||||
@@ -330,19 +357,31 @@ func (c *httpConv) ServerRequest(server string, req *http.Request) []attribute.K
|
||||
if useragent != "" {
|
||||
n++
|
||||
}
|
||||
userID, _, hasUserID := req.BasicAuth()
|
||||
if hasUserID {
|
||||
n++
|
||||
}
|
||||
|
||||
clientIP := serverClientIP(req.Header.Get("X-Forwarded-For"))
|
||||
if clientIP != "" {
|
||||
n++
|
||||
}
|
||||
|
||||
var target string
|
||||
if req.URL != nil {
|
||||
target = req.URL.Path
|
||||
if target != "" {
|
||||
n++
|
||||
}
|
||||
}
|
||||
protoName, protoVersion := netProtocol(req.Proto)
|
||||
if protoName != "" && protoName != "http" {
|
||||
n++
|
||||
}
|
||||
if protoVersion != "" {
|
||||
n++
|
||||
}
|
||||
|
||||
attrs := make([]attribute.KeyValue, 0, n)
|
||||
|
||||
attrs = append(attrs, c.method(req.Method))
|
||||
attrs = append(attrs, c.scheme(req.TLS != nil))
|
||||
attrs = append(attrs, c.flavor(req.Proto))
|
||||
attrs = append(attrs, c.NetConv.HostName(host))
|
||||
|
||||
if hostPort > 0 {
|
||||
@@ -359,17 +398,24 @@ func (c *httpConv) ServerRequest(server string, req *http.Request) []attribute.K
|
||||
}
|
||||
|
||||
if useragent != "" {
|
||||
attrs = append(attrs, c.HTTPUserAgentKey.String(useragent))
|
||||
}
|
||||
|
||||
if hasUserID {
|
||||
attrs = append(attrs, c.EnduserIDKey.String(userID))
|
||||
attrs = append(attrs, c.UserAgentOriginalKey.String(useragent))
|
||||
}
|
||||
|
||||
if clientIP != "" {
|
||||
attrs = append(attrs, c.HTTPClientIPKey.String(clientIP))
|
||||
}
|
||||
|
||||
if target != "" {
|
||||
attrs = append(attrs, c.HTTPTargetKey.String(target))
|
||||
}
|
||||
|
||||
if protoName != "" && protoName != "http" {
|
||||
attrs = append(attrs, c.NetConv.NetProtocolName.String(protoName))
|
||||
}
|
||||
if protoVersion != "" {
|
||||
attrs = append(attrs, c.NetConv.NetProtocolVersion.String(protoVersion))
|
||||
}
|
||||
|
||||
return attrs
|
||||
}
|
||||
|
||||
@@ -391,17 +437,21 @@ func (c *httpConv) ServerRequest(server string, req *http.Request) []attribute.K
|
||||
// The req Host will be used to determine the server instead.
|
||||
//
|
||||
// The following attributes are always returned: "http.method", "http.scheme",
|
||||
// "http.flavor", "net.host.name". The following attributes are
|
||||
// returned if they related values are defined in req: "net.host.port".
|
||||
// "net.host.name". The following attributes are returned if they related
|
||||
// values are defined in req: "net.host.port".
|
||||
func (c *httpConv) ServerRequestMetrics(server string, req *http.Request) []attribute.KeyValue {
|
||||
// TODO: This currently does not add the specification required
|
||||
// `http.target` attribute. It has too high of a cardinality to safely be
|
||||
// added. An alternate should be added, or this comment removed, when it is
|
||||
// addressed by the specification. If it is ultimately decided to continue
|
||||
// not including the attribute, the HTTPTargetKey field of the httpConv
|
||||
// should be removed as well.
|
||||
/* The following semantic conventions are returned if present:
|
||||
http.scheme string
|
||||
http.route string
|
||||
http.method string
|
||||
http.status_code int
|
||||
net.host.name string
|
||||
net.host.port int
|
||||
net.protocol.name string Note: not set if the value is "http".
|
||||
net.protocol.version string
|
||||
*/
|
||||
|
||||
n := 4 // Method, scheme, proto, and host name.
|
||||
n := 3 // Method, scheme, and host name.
|
||||
var host string
|
||||
var p int
|
||||
if server == "" {
|
||||
@@ -417,16 +467,29 @@ func (c *httpConv) ServerRequestMetrics(server string, req *http.Request) []attr
|
||||
if hostPort > 0 {
|
||||
n++
|
||||
}
|
||||
protoName, protoVersion := netProtocol(req.Proto)
|
||||
if protoName != "" {
|
||||
n++
|
||||
}
|
||||
if protoVersion != "" {
|
||||
n++
|
||||
}
|
||||
|
||||
attrs := make([]attribute.KeyValue, 0, n)
|
||||
|
||||
attrs = append(attrs, c.methodMetric(req.Method))
|
||||
attrs = append(attrs, c.scheme(req.TLS != nil))
|
||||
attrs = append(attrs, c.flavor(req.Proto))
|
||||
attrs = append(attrs, c.NetConv.HostName(host))
|
||||
|
||||
if hostPort > 0 {
|
||||
attrs = append(attrs, c.NetConv.HostPort(hostPort))
|
||||
}
|
||||
if protoName != "" {
|
||||
attrs = append(attrs, c.NetConv.NetProtocolName.String(protoName))
|
||||
}
|
||||
if protoVersion != "" {
|
||||
attrs = append(attrs, c.NetConv.NetProtocolVersion.String(protoVersion))
|
||||
}
|
||||
|
||||
return attrs
|
||||
}
|
||||
@@ -455,21 +518,6 @@ func (c *httpConv) scheme(https bool) attribute.KeyValue { // nolint:revive
|
||||
return c.HTTPSchemeHTTP
|
||||
}
|
||||
|
||||
func (c *httpConv) flavor(proto string) attribute.KeyValue {
|
||||
switch proto {
|
||||
case "HTTP/1.0":
|
||||
return c.HTTPFlavorKey.String("1.0")
|
||||
case "HTTP/1.1":
|
||||
return c.HTTPFlavorKey.String("1.1")
|
||||
case "HTTP/2":
|
||||
return c.HTTPFlavorKey.String("2.0")
|
||||
case "HTTP/3":
|
||||
return c.HTTPFlavorKey.String("3.0")
|
||||
default:
|
||||
return c.HTTPFlavorKey.String(proto)
|
||||
}
|
||||
}
|
||||
|
||||
func serverClientIP(xForwardedFor string) string {
|
||||
if idx := strings.Index(xForwardedFor, ","); idx >= 0 {
|
||||
xForwardedFor = xForwardedFor[:idx]
|
||||
@@ -501,31 +549,6 @@ func firstHostPort(source ...string) (host string, port int) {
|
||||
return
|
||||
}
|
||||
|
||||
// RequestHeader returns the contents of h as OpenTelemetry attributes.
|
||||
func (c *httpConv) RequestHeader(h http.Header) []attribute.KeyValue {
|
||||
return c.header("http.request.header", h)
|
||||
}
|
||||
|
||||
// ResponseHeader returns the contents of h as OpenTelemetry attributes.
|
||||
func (c *httpConv) ResponseHeader(h http.Header) []attribute.KeyValue {
|
||||
return c.header("http.response.header", h)
|
||||
}
|
||||
|
||||
func (c *httpConv) header(prefix string, h http.Header) []attribute.KeyValue {
|
||||
key := func(k string) attribute.Key {
|
||||
k = strings.ToLower(k)
|
||||
k = strings.ReplaceAll(k, "-", "_")
|
||||
k = fmt.Sprintf("%s.%s", prefix, k)
|
||||
return attribute.Key(k)
|
||||
}
|
||||
|
||||
attrs := make([]attribute.KeyValue, 0, len(h))
|
||||
for k, v := range h {
|
||||
attrs = append(attrs, key(k).StringSlice(v))
|
||||
}
|
||||
return attrs
|
||||
}
|
||||
|
||||
// ClientStatus returns a span status code and message for an HTTP status code
|
||||
// value received by a client.
|
||||
func (c *httpConv) ClientStatus(code int) (codes.Code, string) {
|
||||
|
@@ -2,17 +2,7 @@
|
||||
// source: internal/shared/semconvutil/netconv.go.tmpl
|
||||
|
||||
// Copyright The OpenTelemetry Authors
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package semconvutil // import "go.opentelemetry.io/contrib/instrumentation/net/http/httptrace/otelhttptrace/internal/semconvutil"
|
||||
|
||||
@@ -22,7 +12,7 @@ import (
|
||||
"strings"
|
||||
|
||||
"go.opentelemetry.io/otel/attribute"
|
||||
semconv "go.opentelemetry.io/otel/semconv/v1.17.0"
|
||||
semconv "go.opentelemetry.io/otel/semconv/v1.20.0"
|
||||
)
|
||||
|
||||
// NetTransport returns a trace attribute describing the transport protocol of the
|
||||
@@ -32,24 +22,6 @@ func NetTransport(network string) attribute.KeyValue {
|
||||
return nc.Transport(network)
|
||||
}
|
||||
|
||||
// NetClient returns trace attributes for a client network connection to address.
|
||||
// See net.Dial for information about acceptable address values, address should
|
||||
// be the same as the one used to create conn. If conn is nil, only network
|
||||
// peer attributes will be returned that describe address. Otherwise, the
|
||||
// socket level information about conn will also be included.
|
||||
func NetClient(address string, conn net.Conn) []attribute.KeyValue {
|
||||
return nc.Client(address, conn)
|
||||
}
|
||||
|
||||
// NetServer returns trace attributes for a network listener listening at address.
|
||||
// See net.Listen for information about acceptable address values, address
|
||||
// should be the same as the one used to create ln. If ln is nil, only network
|
||||
// host attributes will be returned that describe address. Otherwise, the
|
||||
// socket level information about ln will also be included.
|
||||
func NetServer(address string, ln net.Listener) []attribute.KeyValue {
|
||||
return nc.Server(address, ln)
|
||||
}
|
||||
|
||||
// netConv are the network semantic convention attributes defined for a version
|
||||
// of the OpenTelemetry specification.
|
||||
type netConv struct {
|
||||
@@ -57,6 +29,8 @@ type netConv struct {
|
||||
NetHostPortKey attribute.Key
|
||||
NetPeerNameKey attribute.Key
|
||||
NetPeerPortKey attribute.Key
|
||||
NetProtocolName attribute.Key
|
||||
NetProtocolVersion attribute.Key
|
||||
NetSockFamilyKey attribute.Key
|
||||
NetSockPeerAddrKey attribute.Key
|
||||
NetSockPeerPortKey attribute.Key
|
||||
@@ -73,6 +47,8 @@ var nc = &netConv{
|
||||
NetHostPortKey: semconv.NetHostPortKey,
|
||||
NetPeerNameKey: semconv.NetPeerNameKey,
|
||||
NetPeerPortKey: semconv.NetPeerPortKey,
|
||||
NetProtocolName: semconv.NetProtocolNameKey,
|
||||
NetProtocolVersion: semconv.NetProtocolVersionKey,
|
||||
NetSockFamilyKey: semconv.NetSockFamilyKey,
|
||||
NetSockPeerAddrKey: semconv.NetSockPeerAddrKey,
|
||||
NetSockPeerPortKey: semconv.NetSockPeerPortKey,
|
||||
@@ -116,57 +92,11 @@ func (c *netConv) Host(address string) []attribute.KeyValue {
|
||||
attrs := make([]attribute.KeyValue, 0, n)
|
||||
attrs = append(attrs, c.HostName(h))
|
||||
if p > 0 {
|
||||
attrs = append(attrs, c.HostPort(int(p)))
|
||||
attrs = append(attrs, c.HostPort(p))
|
||||
}
|
||||
return attrs
|
||||
}
|
||||
|
||||
// Server returns attributes for a network listener listening at address. See
|
||||
// net.Listen for information about acceptable address values, address should
|
||||
// be the same as the one used to create ln. If ln is nil, only network host
|
||||
// attributes will be returned that describe address. Otherwise, the socket
|
||||
// level information about ln will also be included.
|
||||
func (c *netConv) Server(address string, ln net.Listener) []attribute.KeyValue {
|
||||
if ln == nil {
|
||||
return c.Host(address)
|
||||
}
|
||||
|
||||
lAddr := ln.Addr()
|
||||
if lAddr == nil {
|
||||
return c.Host(address)
|
||||
}
|
||||
|
||||
hostName, hostPort := splitHostPort(address)
|
||||
sockHostAddr, sockHostPort := splitHostPort(lAddr.String())
|
||||
network := lAddr.Network()
|
||||
sockFamily := family(network, sockHostAddr)
|
||||
|
||||
n := nonZeroStr(hostName, network, sockHostAddr, sockFamily)
|
||||
n += positiveInt(hostPort, sockHostPort)
|
||||
attr := make([]attribute.KeyValue, 0, n)
|
||||
if hostName != "" {
|
||||
attr = append(attr, c.HostName(hostName))
|
||||
if hostPort > 0 {
|
||||
// Only if net.host.name is set should net.host.port be.
|
||||
attr = append(attr, c.HostPort(hostPort))
|
||||
}
|
||||
}
|
||||
if network != "" {
|
||||
attr = append(attr, c.Transport(network))
|
||||
}
|
||||
if sockFamily != "" {
|
||||
attr = append(attr, c.NetSockFamilyKey.String(sockFamily))
|
||||
}
|
||||
if sockHostAddr != "" {
|
||||
attr = append(attr, c.NetSockHostAddrKey.String(sockHostAddr))
|
||||
if sockHostPort > 0 {
|
||||
// Only if net.sock.host.addr is set should net.sock.host.port be.
|
||||
attr = append(attr, c.NetSockHostPortKey.Int(sockHostPort))
|
||||
}
|
||||
}
|
||||
return attr
|
||||
}
|
||||
|
||||
func (c *netConv) HostName(name string) attribute.KeyValue {
|
||||
return c.NetHostNameKey.String(name)
|
||||
}
|
||||
@@ -175,85 +105,6 @@ func (c *netConv) HostPort(port int) attribute.KeyValue {
|
||||
return c.NetHostPortKey.Int(port)
|
||||
}
|
||||
|
||||
// Client returns attributes for a client network connection to address. See
|
||||
// net.Dial for information about acceptable address values, address should be
|
||||
// the same as the one used to create conn. If conn is nil, only network peer
|
||||
// attributes will be returned that describe address. Otherwise, the socket
|
||||
// level information about conn will also be included.
|
||||
func (c *netConv) Client(address string, conn net.Conn) []attribute.KeyValue {
|
||||
if conn == nil {
|
||||
return c.Peer(address)
|
||||
}
|
||||
|
||||
lAddr, rAddr := conn.LocalAddr(), conn.RemoteAddr()
|
||||
|
||||
var network string
|
||||
switch {
|
||||
case lAddr != nil:
|
||||
network = lAddr.Network()
|
||||
case rAddr != nil:
|
||||
network = rAddr.Network()
|
||||
default:
|
||||
return c.Peer(address)
|
||||
}
|
||||
|
||||
peerName, peerPort := splitHostPort(address)
|
||||
var (
|
||||
sockFamily string
|
||||
sockPeerAddr string
|
||||
sockPeerPort int
|
||||
sockHostAddr string
|
||||
sockHostPort int
|
||||
)
|
||||
|
||||
if lAddr != nil {
|
||||
sockHostAddr, sockHostPort = splitHostPort(lAddr.String())
|
||||
}
|
||||
|
||||
if rAddr != nil {
|
||||
sockPeerAddr, sockPeerPort = splitHostPort(rAddr.String())
|
||||
}
|
||||
|
||||
switch {
|
||||
case sockHostAddr != "":
|
||||
sockFamily = family(network, sockHostAddr)
|
||||
case sockPeerAddr != "":
|
||||
sockFamily = family(network, sockPeerAddr)
|
||||
}
|
||||
|
||||
n := nonZeroStr(peerName, network, sockPeerAddr, sockHostAddr, sockFamily)
|
||||
n += positiveInt(peerPort, sockPeerPort, sockHostPort)
|
||||
attr := make([]attribute.KeyValue, 0, n)
|
||||
if peerName != "" {
|
||||
attr = append(attr, c.PeerName(peerName))
|
||||
if peerPort > 0 {
|
||||
// Only if net.peer.name is set should net.peer.port be.
|
||||
attr = append(attr, c.PeerPort(peerPort))
|
||||
}
|
||||
}
|
||||
if network != "" {
|
||||
attr = append(attr, c.Transport(network))
|
||||
}
|
||||
if sockFamily != "" {
|
||||
attr = append(attr, c.NetSockFamilyKey.String(sockFamily))
|
||||
}
|
||||
if sockPeerAddr != "" {
|
||||
attr = append(attr, c.NetSockPeerAddrKey.String(sockPeerAddr))
|
||||
if sockPeerPort > 0 {
|
||||
// Only if net.sock.peer.addr is set should net.sock.peer.port be.
|
||||
attr = append(attr, c.NetSockPeerPortKey.Int(sockPeerPort))
|
||||
}
|
||||
}
|
||||
if sockHostAddr != "" {
|
||||
attr = append(attr, c.NetSockHostAddrKey.String(sockHostAddr))
|
||||
if sockHostPort > 0 {
|
||||
// Only if net.sock.host.addr is set should net.sock.host.port be.
|
||||
attr = append(attr, c.NetSockHostPortKey.Int(sockHostPort))
|
||||
}
|
||||
}
|
||||
return attr
|
||||
}
|
||||
|
||||
func family(network, address string) string {
|
||||
switch network {
|
||||
case "unix", "unixgram", "unixpacket":
|
||||
@@ -269,26 +120,6 @@ func family(network, address string) string {
|
||||
return ""
|
||||
}
|
||||
|
||||
func nonZeroStr(strs ...string) int {
|
||||
var n int
|
||||
for _, str := range strs {
|
||||
if str != "" {
|
||||
n++
|
||||
}
|
||||
}
|
||||
return n
|
||||
}
|
||||
|
||||
func positiveInt(ints ...int) int {
|
||||
var n int
|
||||
for _, i := range ints {
|
||||
if i > 0 {
|
||||
n++
|
||||
}
|
||||
}
|
||||
return n
|
||||
}
|
||||
|
||||
// Peer returns attributes for a network peer address.
|
||||
func (c *netConv) Peer(address string) []attribute.KeyValue {
|
||||
h, p := splitHostPort(address)
|
||||
@@ -307,7 +138,7 @@ func (c *netConv) Peer(address string) []attribute.KeyValue {
|
||||
attrs := make([]attribute.KeyValue, 0, n)
|
||||
attrs = append(attrs, c.PeerName(h))
|
||||
if p > 0 {
|
||||
attrs = append(attrs, c.PeerPort(int(p)))
|
||||
attrs = append(attrs, c.PeerPort(p))
|
||||
}
|
||||
return attrs
|
||||
}
|
||||
@@ -364,5 +195,11 @@ func splitHostPort(hostport string) (host string, port int) {
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
return host, int(p)
|
||||
return host, int(p) // nolint: gosec // Bitsize checked to be 16 above.
|
||||
}
|
||||
|
||||
func netProtocol(proto string) (name string, version string) {
|
||||
name, version, _ = strings.Cut(proto, "/")
|
||||
name = strings.ToLower(name)
|
||||
return name, version
|
||||
}
|
||||
|
@@ -1,22 +1,11 @@
|
||||
// Copyright The OpenTelemetry Authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package otelhttptrace // import "go.opentelemetry.io/contrib/instrumentation/net/http/httptrace/otelhttptrace"
|
||||
|
||||
// Version is the current release version of the httptrace instrumentation.
|
||||
func Version() string {
|
||||
return "0.46.1"
|
||||
return "0.56.0"
|
||||
// This string is updated by the pre_release.sh script during release
|
||||
}
|
||||
|
||||
|
14
vendor/go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/common.go
generated
vendored
14
vendor/go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/common.go
generated
vendored
@@ -18,20 +18,6 @@ const (
|
||||
WriteErrorKey = attribute.Key("http.write_error") // if an error occurred while writing a reply, the string of the error (io.EOF is not recorded)
|
||||
)
|
||||
|
||||
// Server HTTP metrics.
|
||||
const (
|
||||
serverRequestSize = "http.server.request.size" // Incoming request bytes total
|
||||
serverResponseSize = "http.server.response.size" // Incoming response bytes total
|
||||
serverDuration = "http.server.duration" // Incoming end to end duration, milliseconds
|
||||
)
|
||||
|
||||
// Client HTTP metrics.
|
||||
const (
|
||||
clientRequestSize = "http.client.request.size" // Outgoing request bytes total
|
||||
clientResponseSize = "http.client.response.size" // Outgoing response bytes total
|
||||
clientDuration = "http.client.duration" // Outgoing end to end duration, milliseconds
|
||||
)
|
||||
|
||||
// Filter is a predicate used to determine whether a given http.request should
|
||||
// be traced. A Filter must return true if the request should be traced.
|
||||
type Filter func(*http.Request) bool
|
||||
|
15
vendor/go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/config.go
generated
vendored
15
vendor/go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/config.go
generated
vendored
@@ -8,6 +8,8 @@ import (
|
||||
"net/http"
|
||||
"net/http/httptrace"
|
||||
|
||||
"go.opentelemetry.io/otel/attribute"
|
||||
|
||||
"go.opentelemetry.io/otel"
|
||||
"go.opentelemetry.io/otel/metric"
|
||||
"go.opentelemetry.io/otel/propagation"
|
||||
@@ -33,8 +35,9 @@ type config struct {
|
||||
SpanNameFormatter func(string, *http.Request) string
|
||||
ClientTrace func(context.Context) *httptrace.ClientTrace
|
||||
|
||||
TracerProvider trace.TracerProvider
|
||||
MeterProvider metric.MeterProvider
|
||||
TracerProvider trace.TracerProvider
|
||||
MeterProvider metric.MeterProvider
|
||||
MetricAttributesFn func(*http.Request) []attribute.KeyValue
|
||||
}
|
||||
|
||||
// Option interface used for setting optional config properties.
|
||||
@@ -194,3 +197,11 @@ func WithServerName(server string) Option {
|
||||
c.ServerName = server
|
||||
})
|
||||
}
|
||||
|
||||
// WithMetricAttributesFn returns an Option to set a function that maps an HTTP request to a slice of attribute.KeyValue.
|
||||
// These attributes will be included in metrics for every request.
|
||||
func WithMetricAttributesFn(metricAttributesFn func(r *http.Request) []attribute.KeyValue) Option {
|
||||
return optionFunc(func(c *config) {
|
||||
c.MetricAttributesFn = metricAttributesFn
|
||||
})
|
||||
}
|
||||
|
103
vendor/go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/handler.go
generated
vendored
103
vendor/go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/handler.go
generated
vendored
@@ -9,11 +9,9 @@ import (
|
||||
|
||||
"github.com/felixge/httpsnoop"
|
||||
|
||||
"go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/internal/request"
|
||||
"go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/internal/semconv"
|
||||
"go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/internal/semconvutil"
|
||||
"go.opentelemetry.io/otel"
|
||||
"go.opentelemetry.io/otel/attribute"
|
||||
"go.opentelemetry.io/otel/metric"
|
||||
"go.opentelemetry.io/otel/propagation"
|
||||
"go.opentelemetry.io/otel/trace"
|
||||
)
|
||||
@@ -24,7 +22,6 @@ type middleware struct {
|
||||
server string
|
||||
|
||||
tracer trace.Tracer
|
||||
meter metric.Meter
|
||||
propagators propagation.TextMapPropagator
|
||||
spanStartOptions []trace.SpanStartOption
|
||||
readEvent bool
|
||||
@@ -34,10 +31,7 @@ type middleware struct {
|
||||
publicEndpoint bool
|
||||
publicEndpointFn func(*http.Request) bool
|
||||
|
||||
traceSemconv semconv.HTTPServer
|
||||
requestBytesCounter metric.Int64Counter
|
||||
responseBytesCounter metric.Int64Counter
|
||||
serverLatencyMeasure metric.Float64Histogram
|
||||
semconv semconv.HTTPServer
|
||||
}
|
||||
|
||||
func defaultHandlerFormatter(operation string, _ *http.Request) string {
|
||||
@@ -56,8 +50,6 @@ func NewHandler(handler http.Handler, operation string, opts ...Option) http.Han
|
||||
func NewMiddleware(operation string, opts ...Option) func(http.Handler) http.Handler {
|
||||
h := middleware{
|
||||
operation: operation,
|
||||
|
||||
traceSemconv: semconv.NewHTTPServer(),
|
||||
}
|
||||
|
||||
defaultOpts := []Option{
|
||||
@@ -67,7 +59,6 @@ func NewMiddleware(operation string, opts ...Option) func(http.Handler) http.Han
|
||||
|
||||
c := newConfig(append(defaultOpts, opts...)...)
|
||||
h.configure(c)
|
||||
h.createMeasures()
|
||||
|
||||
return func(next http.Handler) http.Handler {
|
||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
@@ -78,7 +69,6 @@ func NewMiddleware(operation string, opts ...Option) func(http.Handler) http.Han
|
||||
|
||||
func (h *middleware) configure(c *config) {
|
||||
h.tracer = c.Tracer
|
||||
h.meter = c.Meter
|
||||
h.propagators = c.Propagators
|
||||
h.spanStartOptions = c.SpanStartOptions
|
||||
h.readEvent = c.ReadEvent
|
||||
@@ -88,36 +78,7 @@ func (h *middleware) configure(c *config) {
|
||||
h.publicEndpoint = c.PublicEndpoint
|
||||
h.publicEndpointFn = c.PublicEndpointFn
|
||||
h.server = c.ServerName
|
||||
}
|
||||
|
||||
func handleErr(err error) {
|
||||
if err != nil {
|
||||
otel.Handle(err)
|
||||
}
|
||||
}
|
||||
|
||||
func (h *middleware) createMeasures() {
|
||||
var err error
|
||||
h.requestBytesCounter, err = h.meter.Int64Counter(
|
||||
serverRequestSize,
|
||||
metric.WithUnit("By"),
|
||||
metric.WithDescription("Measures the size of HTTP request messages."),
|
||||
)
|
||||
handleErr(err)
|
||||
|
||||
h.responseBytesCounter, err = h.meter.Int64Counter(
|
||||
serverResponseSize,
|
||||
metric.WithUnit("By"),
|
||||
metric.WithDescription("Measures the size of HTTP response messages."),
|
||||
)
|
||||
handleErr(err)
|
||||
|
||||
h.serverLatencyMeasure, err = h.meter.Float64Histogram(
|
||||
serverDuration,
|
||||
metric.WithUnit("ms"),
|
||||
metric.WithDescription("Measures the duration of inbound HTTP requests."),
|
||||
)
|
||||
handleErr(err)
|
||||
h.semconv = semconv.NewHTTPServer(c.Meter)
|
||||
}
|
||||
|
||||
// serveHTTP sets up tracing and calls the given next http.Handler with the span
|
||||
@@ -134,7 +95,7 @@ func (h *middleware) serveHTTP(w http.ResponseWriter, r *http.Request, next http
|
||||
|
||||
ctx := h.propagators.Extract(r.Context(), propagation.HeaderCarrier(r.Header))
|
||||
opts := []trace.SpanStartOption{
|
||||
trace.WithAttributes(h.traceSemconv.RequestTraceAttrs(h.server, r)...),
|
||||
trace.WithAttributes(h.semconv.RequestTraceAttrs(h.server, r)...),
|
||||
}
|
||||
|
||||
opts = append(opts, h.spanStartOptions...)
|
||||
@@ -166,14 +127,12 @@ func (h *middleware) serveHTTP(w http.ResponseWriter, r *http.Request, next http
|
||||
}
|
||||
}
|
||||
|
||||
var bw bodyWrapper
|
||||
// if request body is nil or NoBody, we don't want to mutate the body as it
|
||||
// will affect the identity of it in an unforeseeable way because we assert
|
||||
// ReadCloser fulfills a certain interface and it is indeed nil or NoBody.
|
||||
bw := request.NewBodyWrapper(r.Body, readRecordFunc)
|
||||
if r.Body != nil && r.Body != http.NoBody {
|
||||
bw.ReadCloser = r.Body
|
||||
bw.record = readRecordFunc
|
||||
r.Body = &bw
|
||||
r.Body = bw
|
||||
}
|
||||
|
||||
writeRecordFunc := func(int64) {}
|
||||
@@ -183,13 +142,7 @@ func (h *middleware) serveHTTP(w http.ResponseWriter, r *http.Request, next http
|
||||
}
|
||||
}
|
||||
|
||||
rww := &respWriterWrapper{
|
||||
ResponseWriter: w,
|
||||
record: writeRecordFunc,
|
||||
ctx: ctx,
|
||||
props: h.propagators,
|
||||
statusCode: http.StatusOK, // default status code in case the Handler doesn't write anything
|
||||
}
|
||||
rww := request.NewRespWriterWrapper(w, writeRecordFunc)
|
||||
|
||||
// Wrap w to use our ResponseWriter methods while also exposing
|
||||
// other interfaces that w may implement (http.CloseNotifier,
|
||||
@@ -217,35 +170,39 @@ func (h *middleware) serveHTTP(w http.ResponseWriter, r *http.Request, next http
|
||||
|
||||
next.ServeHTTP(w, r.WithContext(ctx))
|
||||
|
||||
span.SetStatus(semconv.ServerStatus(rww.statusCode))
|
||||
span.SetAttributes(h.traceSemconv.ResponseTraceAttrs(semconv.ResponseTelemetry{
|
||||
StatusCode: rww.statusCode,
|
||||
ReadBytes: bw.read.Load(),
|
||||
ReadError: bw.err,
|
||||
WriteBytes: rww.written,
|
||||
WriteError: rww.err,
|
||||
statusCode := rww.StatusCode()
|
||||
bytesWritten := rww.BytesWritten()
|
||||
span.SetStatus(h.semconv.Status(statusCode))
|
||||
span.SetAttributes(h.semconv.ResponseTraceAttrs(semconv.ResponseTelemetry{
|
||||
StatusCode: statusCode,
|
||||
ReadBytes: bw.BytesRead(),
|
||||
ReadError: bw.Error(),
|
||||
WriteBytes: bytesWritten,
|
||||
WriteError: rww.Error(),
|
||||
})...)
|
||||
|
||||
// Add metrics
|
||||
attributes := append(labeler.Get(), semconvutil.HTTPServerRequestMetrics(h.server, r)...)
|
||||
if rww.statusCode > 0 {
|
||||
attributes = append(attributes, semconv.HTTPStatusCode(rww.statusCode))
|
||||
}
|
||||
o := metric.WithAttributeSet(attribute.NewSet(attributes...))
|
||||
addOpts := []metric.AddOption{o} // Allocate vararg slice once.
|
||||
h.requestBytesCounter.Add(ctx, bw.read.Load(), addOpts...)
|
||||
h.responseBytesCounter.Add(ctx, rww.written, addOpts...)
|
||||
|
||||
// Use floating point division here for higher precision (instead of Millisecond method).
|
||||
elapsedTime := float64(time.Since(requestStartTime)) / float64(time.Millisecond)
|
||||
|
||||
h.serverLatencyMeasure.Record(ctx, elapsedTime, o)
|
||||
h.semconv.RecordMetrics(ctx, semconv.ServerMetricData{
|
||||
ServerName: h.server,
|
||||
ResponseSize: bytesWritten,
|
||||
MetricAttributes: semconv.MetricAttributes{
|
||||
Req: r,
|
||||
StatusCode: statusCode,
|
||||
AdditionalAttributes: labeler.Get(),
|
||||
},
|
||||
MetricData: semconv.MetricData{
|
||||
RequestSize: bw.BytesRead(),
|
||||
ElapsedTime: elapsedTime,
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
// WithRouteTag annotates spans and metrics with the provided route name
|
||||
// with HTTP route attribute.
|
||||
func WithRouteTag(route string, h http.Handler) http.Handler {
|
||||
attr := semconv.NewHTTPServer().Route(route)
|
||||
attr := semconv.NewHTTPServer(nil).Route(route)
|
||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
span := trace.SpanFromContext(r.Context())
|
||||
span.SetAttributes(attr)
|
||||
|
75
vendor/go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/internal/request/body_wrapper.go
generated
vendored
Normal file
75
vendor/go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/internal/request/body_wrapper.go
generated
vendored
Normal file
@@ -0,0 +1,75 @@
|
||||
// Copyright The OpenTelemetry Authors
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package request // import "go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/internal/request"
|
||||
|
||||
import (
|
||||
"io"
|
||||
"sync"
|
||||
)
|
||||
|
||||
var _ io.ReadCloser = &BodyWrapper{}
|
||||
|
||||
// BodyWrapper wraps a http.Request.Body (an io.ReadCloser) to track the number
|
||||
// of bytes read and the last error.
|
||||
type BodyWrapper struct {
|
||||
io.ReadCloser
|
||||
OnRead func(n int64) // must not be nil
|
||||
|
||||
mu sync.Mutex
|
||||
read int64
|
||||
err error
|
||||
}
|
||||
|
||||
// NewBodyWrapper creates a new BodyWrapper.
|
||||
//
|
||||
// The onRead attribute is a callback that will be called every time the data
|
||||
// is read, with the number of bytes being read.
|
||||
func NewBodyWrapper(body io.ReadCloser, onRead func(int64)) *BodyWrapper {
|
||||
return &BodyWrapper{
|
||||
ReadCloser: body,
|
||||
OnRead: onRead,
|
||||
}
|
||||
}
|
||||
|
||||
// Read reads the data from the io.ReadCloser, and stores the number of bytes
|
||||
// read and the error.
|
||||
func (w *BodyWrapper) Read(b []byte) (int, error) {
|
||||
n, err := w.ReadCloser.Read(b)
|
||||
n1 := int64(n)
|
||||
|
||||
w.updateReadData(n1, err)
|
||||
w.OnRead(n1)
|
||||
return n, err
|
||||
}
|
||||
|
||||
func (w *BodyWrapper) updateReadData(n int64, err error) {
|
||||
w.mu.Lock()
|
||||
defer w.mu.Unlock()
|
||||
|
||||
w.read += n
|
||||
if err != nil {
|
||||
w.err = err
|
||||
}
|
||||
}
|
||||
|
||||
// Closes closes the io.ReadCloser.
|
||||
func (w *BodyWrapper) Close() error {
|
||||
return w.ReadCloser.Close()
|
||||
}
|
||||
|
||||
// BytesRead returns the number of bytes read up to this point.
|
||||
func (w *BodyWrapper) BytesRead() int64 {
|
||||
w.mu.Lock()
|
||||
defer w.mu.Unlock()
|
||||
|
||||
return w.read
|
||||
}
|
||||
|
||||
// Error returns the last error.
|
||||
func (w *BodyWrapper) Error() error {
|
||||
w.mu.Lock()
|
||||
defer w.mu.Unlock()
|
||||
|
||||
return w.err
|
||||
}
|
119
vendor/go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/internal/request/resp_writer_wrapper.go
generated
vendored
Normal file
119
vendor/go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/internal/request/resp_writer_wrapper.go
generated
vendored
Normal file
@@ -0,0 +1,119 @@
|
||||
// Copyright The OpenTelemetry Authors
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package request // import "go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/internal/request"
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"sync"
|
||||
)
|
||||
|
||||
var _ http.ResponseWriter = &RespWriterWrapper{}
|
||||
|
||||
// RespWriterWrapper wraps a http.ResponseWriter in order to track the number of
|
||||
// bytes written, the last error, and to catch the first written statusCode.
|
||||
// TODO: The wrapped http.ResponseWriter doesn't implement any of the optional
|
||||
// types (http.Hijacker, http.Pusher, http.CloseNotifier, etc)
|
||||
// that may be useful when using it in real life situations.
|
||||
type RespWriterWrapper struct {
|
||||
http.ResponseWriter
|
||||
OnWrite func(n int64) // must not be nil
|
||||
|
||||
mu sync.RWMutex
|
||||
written int64
|
||||
statusCode int
|
||||
err error
|
||||
wroteHeader bool
|
||||
}
|
||||
|
||||
// NewRespWriterWrapper creates a new RespWriterWrapper.
|
||||
//
|
||||
// The onWrite attribute is a callback that will be called every time the data
|
||||
// is written, with the number of bytes that were written.
|
||||
func NewRespWriterWrapper(w http.ResponseWriter, onWrite func(int64)) *RespWriterWrapper {
|
||||
return &RespWriterWrapper{
|
||||
ResponseWriter: w,
|
||||
OnWrite: onWrite,
|
||||
statusCode: http.StatusOK, // default status code in case the Handler doesn't write anything
|
||||
}
|
||||
}
|
||||
|
||||
// Write writes the bytes array into the [ResponseWriter], and tracks the
|
||||
// number of bytes written and last error.
|
||||
func (w *RespWriterWrapper) Write(p []byte) (int, error) {
|
||||
w.mu.Lock()
|
||||
defer w.mu.Unlock()
|
||||
|
||||
if !w.wroteHeader {
|
||||
w.writeHeader(http.StatusOK)
|
||||
}
|
||||
|
||||
n, err := w.ResponseWriter.Write(p)
|
||||
n1 := int64(n)
|
||||
w.OnWrite(n1)
|
||||
w.written += n1
|
||||
w.err = err
|
||||
return n, err
|
||||
}
|
||||
|
||||
// WriteHeader persists initial statusCode for span attribution.
|
||||
// All calls to WriteHeader will be propagated to the underlying ResponseWriter
|
||||
// and will persist the statusCode from the first call.
|
||||
// Blocking consecutive calls to WriteHeader alters expected behavior and will
|
||||
// remove warning logs from net/http where developers will notice incorrect handler implementations.
|
||||
func (w *RespWriterWrapper) WriteHeader(statusCode int) {
|
||||
w.mu.Lock()
|
||||
defer w.mu.Unlock()
|
||||
|
||||
w.writeHeader(statusCode)
|
||||
}
|
||||
|
||||
// writeHeader persists the status code for span attribution, and propagates
|
||||
// the call to the underlying ResponseWriter.
|
||||
// It does not acquire a lock, and therefore assumes that is being handled by a
|
||||
// parent method.
|
||||
func (w *RespWriterWrapper) writeHeader(statusCode int) {
|
||||
if !w.wroteHeader {
|
||||
w.wroteHeader = true
|
||||
w.statusCode = statusCode
|
||||
}
|
||||
w.ResponseWriter.WriteHeader(statusCode)
|
||||
}
|
||||
|
||||
// Flush implements [http.Flusher].
|
||||
func (w *RespWriterWrapper) Flush() {
|
||||
w.mu.Lock()
|
||||
defer w.mu.Unlock()
|
||||
|
||||
if !w.wroteHeader {
|
||||
w.writeHeader(http.StatusOK)
|
||||
}
|
||||
|
||||
if f, ok := w.ResponseWriter.(http.Flusher); ok {
|
||||
f.Flush()
|
||||
}
|
||||
}
|
||||
|
||||
// BytesWritten returns the number of bytes written.
|
||||
func (w *RespWriterWrapper) BytesWritten() int64 {
|
||||
w.mu.RLock()
|
||||
defer w.mu.RUnlock()
|
||||
|
||||
return w.written
|
||||
}
|
||||
|
||||
// BytesWritten returns the HTTP status code that was sent.
|
||||
func (w *RespWriterWrapper) StatusCode() int {
|
||||
w.mu.RLock()
|
||||
defer w.mu.RUnlock()
|
||||
|
||||
return w.statusCode
|
||||
}
|
||||
|
||||
// Error returns the last error.
|
||||
func (w *RespWriterWrapper) Error() error {
|
||||
w.mu.RLock()
|
||||
defer w.mu.RUnlock()
|
||||
|
||||
return w.err
|
||||
}
|
159
vendor/go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/internal/semconv/env.go
generated
vendored
159
vendor/go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/internal/semconv/env.go
generated
vendored
@@ -4,6 +4,7 @@
|
||||
package semconv // import "go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/internal/semconv"
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"os"
|
||||
@@ -11,6 +12,7 @@ import (
|
||||
|
||||
"go.opentelemetry.io/otel/attribute"
|
||||
"go.opentelemetry.io/otel/codes"
|
||||
"go.opentelemetry.io/otel/metric"
|
||||
)
|
||||
|
||||
type ResponseTelemetry struct {
|
||||
@@ -23,6 +25,11 @@ type ResponseTelemetry struct {
|
||||
|
||||
type HTTPServer struct {
|
||||
duplicate bool
|
||||
|
||||
// Old metrics
|
||||
requestBytesCounter metric.Int64Counter
|
||||
responseBytesCounter metric.Int64Counter
|
||||
serverLatencyMeasure metric.Float64Histogram
|
||||
}
|
||||
|
||||
// RequestTraceAttrs returns trace attributes for an HTTP request received by a
|
||||
@@ -63,15 +70,10 @@ func (s HTTPServer) Route(route string) attribute.KeyValue {
|
||||
return oldHTTPServer{}.Route(route)
|
||||
}
|
||||
|
||||
func NewHTTPServer() HTTPServer {
|
||||
env := strings.ToLower(os.Getenv("OTEL_HTTP_CLIENT_COMPATIBILITY_MODE"))
|
||||
return HTTPServer{duplicate: env == "http/dup"}
|
||||
}
|
||||
|
||||
// ServerStatus returns a span status code and message for an HTTP status code
|
||||
// Status returns a span status code and message for an HTTP status code
|
||||
// value returned by a server. Status codes in the 400-499 range are not
|
||||
// returned as errors.
|
||||
func ServerStatus(code int) (codes.Code, string) {
|
||||
func (s HTTPServer) Status(code int) (codes.Code, string) {
|
||||
if code < 100 || code >= 600 {
|
||||
return codes.Error, fmt.Sprintf("Invalid HTTP status code %d", code)
|
||||
}
|
||||
@@ -80,3 +82,146 @@ func ServerStatus(code int) (codes.Code, string) {
|
||||
}
|
||||
return codes.Unset, ""
|
||||
}
|
||||
|
||||
type ServerMetricData struct {
|
||||
ServerName string
|
||||
ResponseSize int64
|
||||
|
||||
MetricData
|
||||
MetricAttributes
|
||||
}
|
||||
|
||||
type MetricAttributes struct {
|
||||
Req *http.Request
|
||||
StatusCode int
|
||||
AdditionalAttributes []attribute.KeyValue
|
||||
}
|
||||
|
||||
type MetricData struct {
|
||||
RequestSize int64
|
||||
ElapsedTime float64
|
||||
}
|
||||
|
||||
func (s HTTPServer) RecordMetrics(ctx context.Context, md ServerMetricData) {
|
||||
if s.requestBytesCounter == nil || s.responseBytesCounter == nil || s.serverLatencyMeasure == nil {
|
||||
// This will happen if an HTTPServer{} is used insted of NewHTTPServer.
|
||||
return
|
||||
}
|
||||
|
||||
attributes := oldHTTPServer{}.MetricAttributes(md.ServerName, md.Req, md.StatusCode, md.AdditionalAttributes)
|
||||
o := metric.WithAttributeSet(attribute.NewSet(attributes...))
|
||||
addOpts := []metric.AddOption{o}
|
||||
s.requestBytesCounter.Add(ctx, md.RequestSize, addOpts...)
|
||||
s.responseBytesCounter.Add(ctx, md.ResponseSize, addOpts...)
|
||||
s.serverLatencyMeasure.Record(ctx, md.ElapsedTime, o)
|
||||
|
||||
// TODO: Duplicate Metrics
|
||||
}
|
||||
|
||||
func NewHTTPServer(meter metric.Meter) HTTPServer {
|
||||
env := strings.ToLower(os.Getenv("OTEL_SEMCONV_STABILITY_OPT_IN"))
|
||||
duplicate := env == "http/dup"
|
||||
server := HTTPServer{
|
||||
duplicate: duplicate,
|
||||
}
|
||||
server.requestBytesCounter, server.responseBytesCounter, server.serverLatencyMeasure = oldHTTPServer{}.createMeasures(meter)
|
||||
return server
|
||||
}
|
||||
|
||||
type HTTPClient struct {
|
||||
duplicate bool
|
||||
|
||||
// old metrics
|
||||
requestBytesCounter metric.Int64Counter
|
||||
responseBytesCounter metric.Int64Counter
|
||||
latencyMeasure metric.Float64Histogram
|
||||
}
|
||||
|
||||
func NewHTTPClient(meter metric.Meter) HTTPClient {
|
||||
env := strings.ToLower(os.Getenv("OTEL_SEMCONV_STABILITY_OPT_IN"))
|
||||
client := HTTPClient{
|
||||
duplicate: env == "http/dup",
|
||||
}
|
||||
client.requestBytesCounter, client.responseBytesCounter, client.latencyMeasure = oldHTTPClient{}.createMeasures(meter)
|
||||
return client
|
||||
}
|
||||
|
||||
// RequestTraceAttrs returns attributes for an HTTP request made by a client.
|
||||
func (c HTTPClient) RequestTraceAttrs(req *http.Request) []attribute.KeyValue {
|
||||
if c.duplicate {
|
||||
return append(oldHTTPClient{}.RequestTraceAttrs(req), newHTTPClient{}.RequestTraceAttrs(req)...)
|
||||
}
|
||||
return oldHTTPClient{}.RequestTraceAttrs(req)
|
||||
}
|
||||
|
||||
// ResponseTraceAttrs returns metric attributes for an HTTP request made by a client.
|
||||
func (c HTTPClient) ResponseTraceAttrs(resp *http.Response) []attribute.KeyValue {
|
||||
if c.duplicate {
|
||||
return append(oldHTTPClient{}.ResponseTraceAttrs(resp), newHTTPClient{}.ResponseTraceAttrs(resp)...)
|
||||
}
|
||||
|
||||
return oldHTTPClient{}.ResponseTraceAttrs(resp)
|
||||
}
|
||||
|
||||
func (c HTTPClient) Status(code int) (codes.Code, string) {
|
||||
if code < 100 || code >= 600 {
|
||||
return codes.Error, fmt.Sprintf("Invalid HTTP status code %d", code)
|
||||
}
|
||||
if code >= 400 {
|
||||
return codes.Error, ""
|
||||
}
|
||||
return codes.Unset, ""
|
||||
}
|
||||
|
||||
func (c HTTPClient) ErrorType(err error) attribute.KeyValue {
|
||||
if c.duplicate {
|
||||
return newHTTPClient{}.ErrorType(err)
|
||||
}
|
||||
|
||||
return attribute.KeyValue{}
|
||||
}
|
||||
|
||||
type MetricOpts struct {
|
||||
measurement metric.MeasurementOption
|
||||
addOptions metric.AddOption
|
||||
}
|
||||
|
||||
func (o MetricOpts) MeasurementOption() metric.MeasurementOption {
|
||||
return o.measurement
|
||||
}
|
||||
|
||||
func (o MetricOpts) AddOptions() metric.AddOption {
|
||||
return o.addOptions
|
||||
}
|
||||
|
||||
func (c HTTPClient) MetricOptions(ma MetricAttributes) MetricOpts {
|
||||
attributes := oldHTTPClient{}.MetricAttributes(ma.Req, ma.StatusCode, ma.AdditionalAttributes)
|
||||
// TODO: Duplicate Metrics
|
||||
set := metric.WithAttributeSet(attribute.NewSet(attributes...))
|
||||
return MetricOpts{
|
||||
measurement: set,
|
||||
addOptions: set,
|
||||
}
|
||||
}
|
||||
|
||||
func (s HTTPClient) RecordMetrics(ctx context.Context, md MetricData, opts MetricOpts) {
|
||||
if s.requestBytesCounter == nil || s.latencyMeasure == nil {
|
||||
// This will happen if an HTTPClient{} is used insted of NewHTTPClient().
|
||||
return
|
||||
}
|
||||
|
||||
s.requestBytesCounter.Add(ctx, md.RequestSize, opts.AddOptions())
|
||||
s.latencyMeasure.Record(ctx, md.ElapsedTime, opts.MeasurementOption())
|
||||
|
||||
// TODO: Duplicate Metrics
|
||||
}
|
||||
|
||||
func (s HTTPClient) RecordResponseSize(ctx context.Context, responseData int64, opts metric.AddOption) {
|
||||
if s.responseBytesCounter == nil {
|
||||
// This will happen if an HTTPClient{} is used insted of NewHTTPClient().
|
||||
return
|
||||
}
|
||||
|
||||
s.responseBytesCounter.Add(ctx, responseData, opts)
|
||||
// TODO: Duplicate Metrics
|
||||
}
|
||||
|
@@ -4,11 +4,14 @@
|
||||
package semconv // import "go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/internal/semconv"
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
"reflect"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"go.opentelemetry.io/otel/attribute"
|
||||
semconvNew "go.opentelemetry.io/otel/semconv/v1.24.0"
|
||||
semconvNew "go.opentelemetry.io/otel/semconv/v1.26.0"
|
||||
)
|
||||
|
||||
type newHTTPServer struct{}
|
||||
@@ -195,3 +198,151 @@ func (n newHTTPServer) ResponseTraceAttrs(resp ResponseTelemetry) []attribute.Ke
|
||||
func (n newHTTPServer) Route(route string) attribute.KeyValue {
|
||||
return semconvNew.HTTPRoute(route)
|
||||
}
|
||||
|
||||
type newHTTPClient struct{}
|
||||
|
||||
// RequestTraceAttrs returns trace attributes for an HTTP request made by a client.
|
||||
func (n newHTTPClient) RequestTraceAttrs(req *http.Request) []attribute.KeyValue {
|
||||
/*
|
||||
below attributes are returned:
|
||||
- http.request.method
|
||||
- http.request.method.original
|
||||
- url.full
|
||||
- server.address
|
||||
- server.port
|
||||
- network.protocol.name
|
||||
- network.protocol.version
|
||||
*/
|
||||
numOfAttributes := 3 // URL, server address, proto, and method.
|
||||
|
||||
var urlHost string
|
||||
if req.URL != nil {
|
||||
urlHost = req.URL.Host
|
||||
}
|
||||
var requestHost string
|
||||
var requestPort int
|
||||
for _, hostport := range []string{urlHost, req.Header.Get("Host")} {
|
||||
requestHost, requestPort = splitHostPort(hostport)
|
||||
if requestHost != "" || requestPort > 0 {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
eligiblePort := requiredHTTPPort(req.URL != nil && req.URL.Scheme == "https", requestPort)
|
||||
if eligiblePort > 0 {
|
||||
numOfAttributes++
|
||||
}
|
||||
useragent := req.UserAgent()
|
||||
if useragent != "" {
|
||||
numOfAttributes++
|
||||
}
|
||||
|
||||
protoName, protoVersion := netProtocol(req.Proto)
|
||||
if protoName != "" && protoName != "http" {
|
||||
numOfAttributes++
|
||||
}
|
||||
if protoVersion != "" {
|
||||
numOfAttributes++
|
||||
}
|
||||
|
||||
method, originalMethod := n.method(req.Method)
|
||||
if originalMethod != (attribute.KeyValue{}) {
|
||||
numOfAttributes++
|
||||
}
|
||||
|
||||
attrs := make([]attribute.KeyValue, 0, numOfAttributes)
|
||||
|
||||
attrs = append(attrs, method)
|
||||
if originalMethod != (attribute.KeyValue{}) {
|
||||
attrs = append(attrs, originalMethod)
|
||||
}
|
||||
|
||||
var u string
|
||||
if req.URL != nil {
|
||||
// Remove any username/password info that may be in the URL.
|
||||
userinfo := req.URL.User
|
||||
req.URL.User = nil
|
||||
u = req.URL.String()
|
||||
// Restore any username/password info that was removed.
|
||||
req.URL.User = userinfo
|
||||
}
|
||||
attrs = append(attrs, semconvNew.URLFull(u))
|
||||
|
||||
attrs = append(attrs, semconvNew.ServerAddress(requestHost))
|
||||
if eligiblePort > 0 {
|
||||
attrs = append(attrs, semconvNew.ServerPort(eligiblePort))
|
||||
}
|
||||
|
||||
if protoName != "" && protoName != "http" {
|
||||
attrs = append(attrs, semconvNew.NetworkProtocolName(protoName))
|
||||
}
|
||||
if protoVersion != "" {
|
||||
attrs = append(attrs, semconvNew.NetworkProtocolVersion(protoVersion))
|
||||
}
|
||||
|
||||
return attrs
|
||||
}
|
||||
|
||||
// ResponseTraceAttrs returns trace attributes for an HTTP response made by a client.
|
||||
func (n newHTTPClient) ResponseTraceAttrs(resp *http.Response) []attribute.KeyValue {
|
||||
/*
|
||||
below attributes are returned:
|
||||
- http.response.status_code
|
||||
- error.type
|
||||
*/
|
||||
var count int
|
||||
if resp.StatusCode > 0 {
|
||||
count++
|
||||
}
|
||||
|
||||
if isErrorStatusCode(resp.StatusCode) {
|
||||
count++
|
||||
}
|
||||
|
||||
attrs := make([]attribute.KeyValue, 0, count)
|
||||
if resp.StatusCode > 0 {
|
||||
attrs = append(attrs, semconvNew.HTTPResponseStatusCode(resp.StatusCode))
|
||||
}
|
||||
|
||||
if isErrorStatusCode(resp.StatusCode) {
|
||||
errorType := strconv.Itoa(resp.StatusCode)
|
||||
attrs = append(attrs, semconvNew.ErrorTypeKey.String(errorType))
|
||||
}
|
||||
return attrs
|
||||
}
|
||||
|
||||
func (n newHTTPClient) ErrorType(err error) attribute.KeyValue {
|
||||
t := reflect.TypeOf(err)
|
||||
var value string
|
||||
if t.PkgPath() == "" && t.Name() == "" {
|
||||
// Likely a builtin type.
|
||||
value = t.String()
|
||||
} else {
|
||||
value = fmt.Sprintf("%s.%s", t.PkgPath(), t.Name())
|
||||
}
|
||||
|
||||
if value == "" {
|
||||
return semconvNew.ErrorTypeOther
|
||||
}
|
||||
|
||||
return semconvNew.ErrorTypeKey.String(value)
|
||||
}
|
||||
|
||||
func (n newHTTPClient) method(method string) (attribute.KeyValue, attribute.KeyValue) {
|
||||
if method == "" {
|
||||
return semconvNew.HTTPRequestMethodGet, attribute.KeyValue{}
|
||||
}
|
||||
if attr, ok := methodLookup[method]; ok {
|
||||
return attr, attribute.KeyValue{}
|
||||
}
|
||||
|
||||
orig := semconvNew.HTTPRequestMethodOriginal(method)
|
||||
if attr, ok := methodLookup[strings.ToUpper(method)]; ok {
|
||||
return attr, orig
|
||||
}
|
||||
return semconvNew.HTTPRequestMethodGet, orig
|
||||
}
|
||||
|
||||
func isErrorStatusCode(code int) bool {
|
||||
return code >= 400 || code < 100
|
||||
}
|
@@ -9,8 +9,9 @@ import (
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"go.opentelemetry.io/otel"
|
||||
"go.opentelemetry.io/otel/attribute"
|
||||
semconvNew "go.opentelemetry.io/otel/semconv/v1.24.0"
|
||||
semconvNew "go.opentelemetry.io/otel/semconv/v1.26.0"
|
||||
)
|
||||
|
||||
// splitHostPort splits a network address hostport of the form "host",
|
||||
@@ -49,7 +50,7 @@ func splitHostPort(hostport string) (host string, port int) {
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
return host, int(p)
|
||||
return host, int(p) // nolint: gosec // Byte size checked 16 above.
|
||||
}
|
||||
|
||||
func requiredHTTPPort(https bool, port int) int { // nolint:revive
|
||||
@@ -89,3 +90,9 @@ var methodLookup = map[string]attribute.KeyValue{
|
||||
http.MethodPut: semconvNew.HTTPRequestMethodPut,
|
||||
http.MethodTrace: semconvNew.HTTPRequestMethodTrace,
|
||||
}
|
||||
|
||||
func handleErr(err error) {
|
||||
if err != nil {
|
||||
otel.Handle(err)
|
||||
}
|
||||
}
|
||||
|
@@ -7,9 +7,13 @@ import (
|
||||
"errors"
|
||||
"io"
|
||||
"net/http"
|
||||
"slices"
|
||||
"strings"
|
||||
|
||||
"go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/internal/semconvutil"
|
||||
"go.opentelemetry.io/otel/attribute"
|
||||
"go.opentelemetry.io/otel/metric"
|
||||
"go.opentelemetry.io/otel/metric/noop"
|
||||
semconv "go.opentelemetry.io/otel/semconv/v1.20.0"
|
||||
)
|
||||
|
||||
@@ -72,3 +76,199 @@ func (o oldHTTPServer) Route(route string) attribute.KeyValue {
|
||||
func HTTPStatusCode(status int) attribute.KeyValue {
|
||||
return semconv.HTTPStatusCode(status)
|
||||
}
|
||||
|
||||
// Server HTTP metrics.
|
||||
const (
|
||||
serverRequestSize = "http.server.request.size" // Incoming request bytes total
|
||||
serverResponseSize = "http.server.response.size" // Incoming response bytes total
|
||||
serverDuration = "http.server.duration" // Incoming end to end duration, milliseconds
|
||||
)
|
||||
|
||||
func (h oldHTTPServer) createMeasures(meter metric.Meter) (metric.Int64Counter, metric.Int64Counter, metric.Float64Histogram) {
|
||||
if meter == nil {
|
||||
return noop.Int64Counter{}, noop.Int64Counter{}, noop.Float64Histogram{}
|
||||
}
|
||||
var err error
|
||||
requestBytesCounter, err := meter.Int64Counter(
|
||||
serverRequestSize,
|
||||
metric.WithUnit("By"),
|
||||
metric.WithDescription("Measures the size of HTTP request messages."),
|
||||
)
|
||||
handleErr(err)
|
||||
|
||||
responseBytesCounter, err := meter.Int64Counter(
|
||||
serverResponseSize,
|
||||
metric.WithUnit("By"),
|
||||
metric.WithDescription("Measures the size of HTTP response messages."),
|
||||
)
|
||||
handleErr(err)
|
||||
|
||||
serverLatencyMeasure, err := meter.Float64Histogram(
|
||||
serverDuration,
|
||||
metric.WithUnit("ms"),
|
||||
metric.WithDescription("Measures the duration of inbound HTTP requests."),
|
||||
)
|
||||
handleErr(err)
|
||||
|
||||
return requestBytesCounter, responseBytesCounter, serverLatencyMeasure
|
||||
}
|
||||
|
||||
func (o oldHTTPServer) MetricAttributes(server string, req *http.Request, statusCode int, additionalAttributes []attribute.KeyValue) []attribute.KeyValue {
|
||||
n := len(additionalAttributes) + 3
|
||||
var host string
|
||||
var p int
|
||||
if server == "" {
|
||||
host, p = splitHostPort(req.Host)
|
||||
} else {
|
||||
// Prioritize the primary server name.
|
||||
host, p = splitHostPort(server)
|
||||
if p < 0 {
|
||||
_, p = splitHostPort(req.Host)
|
||||
}
|
||||
}
|
||||
hostPort := requiredHTTPPort(req.TLS != nil, p)
|
||||
if hostPort > 0 {
|
||||
n++
|
||||
}
|
||||
protoName, protoVersion := netProtocol(req.Proto)
|
||||
if protoName != "" {
|
||||
n++
|
||||
}
|
||||
if protoVersion != "" {
|
||||
n++
|
||||
}
|
||||
|
||||
if statusCode > 0 {
|
||||
n++
|
||||
}
|
||||
|
||||
attributes := slices.Grow(additionalAttributes, n)
|
||||
attributes = append(attributes,
|
||||
standardizeHTTPMethodMetric(req.Method),
|
||||
o.scheme(req.TLS != nil),
|
||||
semconv.NetHostName(host))
|
||||
|
||||
if hostPort > 0 {
|
||||
attributes = append(attributes, semconv.NetHostPort(hostPort))
|
||||
}
|
||||
if protoName != "" {
|
||||
attributes = append(attributes, semconv.NetProtocolName(protoName))
|
||||
}
|
||||
if protoVersion != "" {
|
||||
attributes = append(attributes, semconv.NetProtocolVersion(protoVersion))
|
||||
}
|
||||
|
||||
if statusCode > 0 {
|
||||
attributes = append(attributes, semconv.HTTPStatusCode(statusCode))
|
||||
}
|
||||
return attributes
|
||||
}
|
||||
|
||||
func (o oldHTTPServer) scheme(https bool) attribute.KeyValue { // nolint:revive
|
||||
if https {
|
||||
return semconv.HTTPSchemeHTTPS
|
||||
}
|
||||
return semconv.HTTPSchemeHTTP
|
||||
}
|
||||
|
||||
type oldHTTPClient struct{}
|
||||
|
||||
func (o oldHTTPClient) RequestTraceAttrs(req *http.Request) []attribute.KeyValue {
|
||||
return semconvutil.HTTPClientRequest(req)
|
||||
}
|
||||
|
||||
func (o oldHTTPClient) ResponseTraceAttrs(resp *http.Response) []attribute.KeyValue {
|
||||
return semconvutil.HTTPClientResponse(resp)
|
||||
}
|
||||
|
||||
func (o oldHTTPClient) MetricAttributes(req *http.Request, statusCode int, additionalAttributes []attribute.KeyValue) []attribute.KeyValue {
|
||||
/* The following semantic conventions are returned if present:
|
||||
http.method string
|
||||
http.status_code int
|
||||
net.peer.name string
|
||||
net.peer.port int
|
||||
*/
|
||||
|
||||
n := 2 // method, peer name.
|
||||
var h string
|
||||
if req.URL != nil {
|
||||
h = req.URL.Host
|
||||
}
|
||||
var requestHost string
|
||||
var requestPort int
|
||||
for _, hostport := range []string{h, req.Header.Get("Host")} {
|
||||
requestHost, requestPort = splitHostPort(hostport)
|
||||
if requestHost != "" || requestPort > 0 {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
port := requiredHTTPPort(req.URL != nil && req.URL.Scheme == "https", requestPort)
|
||||
if port > 0 {
|
||||
n++
|
||||
}
|
||||
|
||||
if statusCode > 0 {
|
||||
n++
|
||||
}
|
||||
|
||||
attributes := slices.Grow(additionalAttributes, n)
|
||||
attributes = append(attributes,
|
||||
standardizeHTTPMethodMetric(req.Method),
|
||||
semconv.NetPeerName(requestHost),
|
||||
)
|
||||
|
||||
if port > 0 {
|
||||
attributes = append(attributes, semconv.NetPeerPort(port))
|
||||
}
|
||||
|
||||
if statusCode > 0 {
|
||||
attributes = append(attributes, semconv.HTTPStatusCode(statusCode))
|
||||
}
|
||||
return attributes
|
||||
}
|
||||
|
||||
// Client HTTP metrics.
|
||||
const (
|
||||
clientRequestSize = "http.client.request.size" // Incoming request bytes total
|
||||
clientResponseSize = "http.client.response.size" // Incoming response bytes total
|
||||
clientDuration = "http.client.duration" // Incoming end to end duration, milliseconds
|
||||
)
|
||||
|
||||
func (o oldHTTPClient) createMeasures(meter metric.Meter) (metric.Int64Counter, metric.Int64Counter, metric.Float64Histogram) {
|
||||
if meter == nil {
|
||||
return noop.Int64Counter{}, noop.Int64Counter{}, noop.Float64Histogram{}
|
||||
}
|
||||
requestBytesCounter, err := meter.Int64Counter(
|
||||
clientRequestSize,
|
||||
metric.WithUnit("By"),
|
||||
metric.WithDescription("Measures the size of HTTP request messages."),
|
||||
)
|
||||
handleErr(err)
|
||||
|
||||
responseBytesCounter, err := meter.Int64Counter(
|
||||
clientResponseSize,
|
||||
metric.WithUnit("By"),
|
||||
metric.WithDescription("Measures the size of HTTP response messages."),
|
||||
)
|
||||
handleErr(err)
|
||||
|
||||
latencyMeasure, err := meter.Float64Histogram(
|
||||
clientDuration,
|
||||
metric.WithUnit("ms"),
|
||||
metric.WithDescription("Measures the duration of outbound HTTP requests."),
|
||||
)
|
||||
handleErr(err)
|
||||
|
||||
return requestBytesCounter, responseBytesCounter, latencyMeasure
|
||||
}
|
||||
|
||||
func standardizeHTTPMethodMetric(method string) attribute.KeyValue {
|
||||
method = strings.ToUpper(method)
|
||||
switch method {
|
||||
case http.MethodConnect, http.MethodDelete, http.MethodGet, http.MethodHead, http.MethodOptions, http.MethodPatch, http.MethodPost, http.MethodPut, http.MethodTrace:
|
||||
default:
|
||||
method = "_OTHER"
|
||||
}
|
||||
return semconv.HTTPMethod(method)
|
||||
}
|
||||
|
@@ -195,7 +195,7 @@ func splitHostPort(hostport string) (host string, port int) {
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
return host, int(p)
|
||||
return host, int(p) // nolint: gosec // Bitsize checked to be 16 above.
|
||||
}
|
||||
|
||||
func netProtocol(proto string) (name string, version string) {
|
||||
|
106
vendor/go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/transport.go
generated
vendored
106
vendor/go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/transport.go
generated
vendored
@@ -11,13 +11,13 @@ import (
|
||||
"sync/atomic"
|
||||
"time"
|
||||
|
||||
"go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/internal/semconvutil"
|
||||
"go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/internal/request"
|
||||
"go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/internal/semconv"
|
||||
"go.opentelemetry.io/otel"
|
||||
"go.opentelemetry.io/otel/attribute"
|
||||
"go.opentelemetry.io/otel/codes"
|
||||
"go.opentelemetry.io/otel/metric"
|
||||
"go.opentelemetry.io/otel/propagation"
|
||||
semconv "go.opentelemetry.io/otel/semconv/v1.20.0"
|
||||
|
||||
"go.opentelemetry.io/otel/trace"
|
||||
)
|
||||
|
||||
@@ -26,17 +26,15 @@ import (
|
||||
type Transport struct {
|
||||
rt http.RoundTripper
|
||||
|
||||
tracer trace.Tracer
|
||||
meter metric.Meter
|
||||
propagators propagation.TextMapPropagator
|
||||
spanStartOptions []trace.SpanStartOption
|
||||
filters []Filter
|
||||
spanNameFormatter func(string, *http.Request) string
|
||||
clientTrace func(context.Context) *httptrace.ClientTrace
|
||||
tracer trace.Tracer
|
||||
propagators propagation.TextMapPropagator
|
||||
spanStartOptions []trace.SpanStartOption
|
||||
filters []Filter
|
||||
spanNameFormatter func(string, *http.Request) string
|
||||
clientTrace func(context.Context) *httptrace.ClientTrace
|
||||
metricAttributesFn func(*http.Request) []attribute.KeyValue
|
||||
|
||||
requestBytesCounter metric.Int64Counter
|
||||
responseBytesCounter metric.Int64Counter
|
||||
latencyMeasure metric.Float64Histogram
|
||||
semconv semconv.HTTPClient
|
||||
}
|
||||
|
||||
var _ http.RoundTripper = &Transport{}
|
||||
@@ -63,43 +61,19 @@ func NewTransport(base http.RoundTripper, opts ...Option) *Transport {
|
||||
|
||||
c := newConfig(append(defaultOpts, opts...)...)
|
||||
t.applyConfig(c)
|
||||
t.createMeasures()
|
||||
|
||||
return &t
|
||||
}
|
||||
|
||||
func (t *Transport) applyConfig(c *config) {
|
||||
t.tracer = c.Tracer
|
||||
t.meter = c.Meter
|
||||
t.propagators = c.Propagators
|
||||
t.spanStartOptions = c.SpanStartOptions
|
||||
t.filters = c.Filters
|
||||
t.spanNameFormatter = c.SpanNameFormatter
|
||||
t.clientTrace = c.ClientTrace
|
||||
}
|
||||
|
||||
func (t *Transport) createMeasures() {
|
||||
var err error
|
||||
t.requestBytesCounter, err = t.meter.Int64Counter(
|
||||
clientRequestSize,
|
||||
metric.WithUnit("By"),
|
||||
metric.WithDescription("Measures the size of HTTP request messages."),
|
||||
)
|
||||
handleErr(err)
|
||||
|
||||
t.responseBytesCounter, err = t.meter.Int64Counter(
|
||||
clientResponseSize,
|
||||
metric.WithUnit("By"),
|
||||
metric.WithDescription("Measures the size of HTTP response messages."),
|
||||
)
|
||||
handleErr(err)
|
||||
|
||||
t.latencyMeasure, err = t.meter.Float64Histogram(
|
||||
clientDuration,
|
||||
metric.WithUnit("ms"),
|
||||
metric.WithDescription("Measures the duration of outbound HTTP requests."),
|
||||
)
|
||||
handleErr(err)
|
||||
t.semconv = semconv.NewHTTPClient(c.Meter)
|
||||
t.metricAttributesFn = c.MetricAttributesFn
|
||||
}
|
||||
|
||||
func defaultTransportFormatter(_ string, r *http.Request) string {
|
||||
@@ -143,54 +117,68 @@ func (t *Transport) RoundTrip(r *http.Request) (*http.Response, error) {
|
||||
|
||||
r = r.Clone(ctx) // According to RoundTripper spec, we shouldn't modify the origin request.
|
||||
|
||||
// use a body wrapper to determine the request size
|
||||
var bw bodyWrapper
|
||||
// if request body is nil or NoBody, we don't want to mutate the body as it
|
||||
// will affect the identity of it in an unforeseeable way because we assert
|
||||
// ReadCloser fulfills a certain interface and it is indeed nil or NoBody.
|
||||
bw := request.NewBodyWrapper(r.Body, func(int64) {})
|
||||
if r.Body != nil && r.Body != http.NoBody {
|
||||
bw.ReadCloser = r.Body
|
||||
// noop to prevent nil panic. not using this record fun yet.
|
||||
bw.record = func(int64) {}
|
||||
r.Body = &bw
|
||||
r.Body = bw
|
||||
}
|
||||
|
||||
span.SetAttributes(semconvutil.HTTPClientRequest(r)...)
|
||||
span.SetAttributes(t.semconv.RequestTraceAttrs(r)...)
|
||||
t.propagators.Inject(ctx, propagation.HeaderCarrier(r.Header))
|
||||
|
||||
res, err := t.rt.RoundTrip(r)
|
||||
if err != nil {
|
||||
span.RecordError(err)
|
||||
// set error type attribute if the error is part of the predefined
|
||||
// error types.
|
||||
// otherwise, record it as an exception
|
||||
if errType := t.semconv.ErrorType(err); errType.Valid() {
|
||||
span.SetAttributes(errType)
|
||||
} else {
|
||||
span.RecordError(err)
|
||||
}
|
||||
|
||||
span.SetStatus(codes.Error, err.Error())
|
||||
span.End()
|
||||
return res, err
|
||||
}
|
||||
|
||||
// metrics
|
||||
metricAttrs := append(labeler.Get(), semconvutil.HTTPClientRequestMetrics(r)...)
|
||||
if res.StatusCode > 0 {
|
||||
metricAttrs = append(metricAttrs, semconv.HTTPStatusCode(res.StatusCode))
|
||||
}
|
||||
o := metric.WithAttributeSet(attribute.NewSet(metricAttrs...))
|
||||
addOpts := []metric.AddOption{o} // Allocate vararg slice once.
|
||||
t.requestBytesCounter.Add(ctx, bw.read.Load(), addOpts...)
|
||||
metricOpts := t.semconv.MetricOptions(semconv.MetricAttributes{
|
||||
Req: r,
|
||||
StatusCode: res.StatusCode,
|
||||
AdditionalAttributes: append(labeler.Get(), t.metricAttributesFromRequest(r)...),
|
||||
})
|
||||
|
||||
// For handling response bytes we leverage a callback when the client reads the http response
|
||||
readRecordFunc := func(n int64) {
|
||||
t.responseBytesCounter.Add(ctx, n, addOpts...)
|
||||
t.semconv.RecordResponseSize(ctx, n, metricOpts.AddOptions())
|
||||
}
|
||||
|
||||
// traces
|
||||
span.SetAttributes(semconvutil.HTTPClientResponse(res)...)
|
||||
span.SetStatus(semconvutil.HTTPClientStatus(res.StatusCode))
|
||||
span.SetAttributes(t.semconv.ResponseTraceAttrs(res)...)
|
||||
span.SetStatus(t.semconv.Status(res.StatusCode))
|
||||
|
||||
res.Body = newWrappedBody(span, readRecordFunc, res.Body)
|
||||
|
||||
// Use floating point division here for higher precision (instead of Millisecond method).
|
||||
elapsedTime := float64(time.Since(requestStartTime)) / float64(time.Millisecond)
|
||||
|
||||
t.latencyMeasure.Record(ctx, elapsedTime, o)
|
||||
t.semconv.RecordMetrics(ctx, semconv.MetricData{
|
||||
RequestSize: bw.BytesRead(),
|
||||
ElapsedTime: elapsedTime,
|
||||
}, metricOpts)
|
||||
|
||||
return res, err
|
||||
return res, nil
|
||||
}
|
||||
|
||||
func (t *Transport) metricAttributesFromRequest(r *http.Request) []attribute.KeyValue {
|
||||
var attributeForRequest []attribute.KeyValue
|
||||
if t.metricAttributesFn != nil {
|
||||
attributeForRequest = t.metricAttributesFn(r)
|
||||
}
|
||||
return attributeForRequest
|
||||
}
|
||||
|
||||
// newWrappedBody returns a new and appropriately scoped *wrappedBody as an
|
||||
|
2
vendor/go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/version.go
generated
vendored
2
vendor/go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/version.go
generated
vendored
@@ -5,7 +5,7 @@ package otelhttp // import "go.opentelemetry.io/contrib/instrumentation/net/http
|
||||
|
||||
// Version is the current release version of the otelhttp instrumentation.
|
||||
func Version() string {
|
||||
return "0.53.0"
|
||||
return "0.56.0"
|
||||
// This string is updated by the pre_release.sh script during release
|
||||
}
|
||||
|
||||
|
99
vendor/go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/wrap.go
generated
vendored
99
vendor/go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/wrap.go
generated
vendored
@@ -1,99 +0,0 @@
|
||||
// Copyright The OpenTelemetry Authors
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package otelhttp // import "go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp"
|
||||
|
||||
import (
|
||||
"context"
|
||||
"io"
|
||||
"net/http"
|
||||
"sync/atomic"
|
||||
|
||||
"go.opentelemetry.io/otel/propagation"
|
||||
)
|
||||
|
||||
var _ io.ReadCloser = &bodyWrapper{}
|
||||
|
||||
// bodyWrapper wraps a http.Request.Body (an io.ReadCloser) to track the number
|
||||
// of bytes read and the last error.
|
||||
type bodyWrapper struct {
|
||||
io.ReadCloser
|
||||
record func(n int64) // must not be nil
|
||||
|
||||
read atomic.Int64
|
||||
err error
|
||||
}
|
||||
|
||||
func (w *bodyWrapper) Read(b []byte) (int, error) {
|
||||
n, err := w.ReadCloser.Read(b)
|
||||
n1 := int64(n)
|
||||
w.read.Add(n1)
|
||||
w.err = err
|
||||
w.record(n1)
|
||||
return n, err
|
||||
}
|
||||
|
||||
func (w *bodyWrapper) Close() error {
|
||||
return w.ReadCloser.Close()
|
||||
}
|
||||
|
||||
var _ http.ResponseWriter = &respWriterWrapper{}
|
||||
|
||||
// respWriterWrapper wraps a http.ResponseWriter in order to track the number of
|
||||
// bytes written, the last error, and to catch the first written statusCode.
|
||||
// TODO: The wrapped http.ResponseWriter doesn't implement any of the optional
|
||||
// types (http.Hijacker, http.Pusher, http.CloseNotifier, http.Flusher, etc)
|
||||
// that may be useful when using it in real life situations.
|
||||
type respWriterWrapper struct {
|
||||
http.ResponseWriter
|
||||
record func(n int64) // must not be nil
|
||||
|
||||
// used to inject the header
|
||||
ctx context.Context
|
||||
|
||||
props propagation.TextMapPropagator
|
||||
|
||||
written int64
|
||||
statusCode int
|
||||
err error
|
||||
wroteHeader bool
|
||||
}
|
||||
|
||||
func (w *respWriterWrapper) Header() http.Header {
|
||||
return w.ResponseWriter.Header()
|
||||
}
|
||||
|
||||
func (w *respWriterWrapper) Write(p []byte) (int, error) {
|
||||
if !w.wroteHeader {
|
||||
w.WriteHeader(http.StatusOK)
|
||||
}
|
||||
n, err := w.ResponseWriter.Write(p)
|
||||
n1 := int64(n)
|
||||
w.record(n1)
|
||||
w.written += n1
|
||||
w.err = err
|
||||
return n, err
|
||||
}
|
||||
|
||||
// WriteHeader persists initial statusCode for span attribution.
|
||||
// All calls to WriteHeader will be propagated to the underlying ResponseWriter
|
||||
// and will persist the statusCode from the first call.
|
||||
// Blocking consecutive calls to WriteHeader alters expected behavior and will
|
||||
// remove warning logs from net/http where developers will notice incorrect handler implementations.
|
||||
func (w *respWriterWrapper) WriteHeader(statusCode int) {
|
||||
if !w.wroteHeader {
|
||||
w.wroteHeader = true
|
||||
w.statusCode = statusCode
|
||||
}
|
||||
w.ResponseWriter.WriteHeader(statusCode)
|
||||
}
|
||||
|
||||
func (w *respWriterWrapper) Flush() {
|
||||
if !w.wroteHeader {
|
||||
w.WriteHeader(http.StatusOK)
|
||||
}
|
||||
|
||||
if f, ok := w.ResponseWriter.(http.Flusher); ok {
|
||||
f.Flush()
|
||||
}
|
||||
}
|
13
vendor/go.opentelemetry.io/otel/.golangci.yml
generated
vendored
13
vendor/go.opentelemetry.io/otel/.golangci.yml
generated
vendored
@@ -9,6 +9,8 @@ linters:
|
||||
disable-all: true
|
||||
# Specifically enable linters we want to use.
|
||||
enable:
|
||||
- asasalint
|
||||
- bodyclose
|
||||
- depguard
|
||||
- errcheck
|
||||
- errorlint
|
||||
@@ -23,6 +25,7 @@ linters:
|
||||
- revive
|
||||
- staticcheck
|
||||
- tenv
|
||||
- testifylint
|
||||
- typecheck
|
||||
- unconvert
|
||||
- unused
|
||||
@@ -62,12 +65,12 @@ issues:
|
||||
- path: _test\.go
|
||||
linters:
|
||||
- gosec
|
||||
# Igonoring gosec G404: Use of weak random number generator (math/rand instead of crypto/rand)
|
||||
# Ignoring gosec G404: Use of weak random number generator (math/rand instead of crypto/rand)
|
||||
# as we commonly use it in tests and examples.
|
||||
- text: "G404:"
|
||||
linters:
|
||||
- gosec
|
||||
# Igonoring gosec G402: TLS MinVersion too low
|
||||
# Ignoring gosec G402: TLS MinVersion too low
|
||||
# as the https://pkg.go.dev/crypto/tls#Config handles MinVersion default well.
|
||||
- text: "G402: TLS MinVersion too low."
|
||||
linters:
|
||||
@@ -300,3 +303,9 @@ linters-settings:
|
||||
# https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#waitgroup-by-value
|
||||
- name: waitgroup-by-value
|
||||
disabled: false
|
||||
testifylint:
|
||||
enable-all: true
|
||||
disable:
|
||||
- float-compare
|
||||
- go-require
|
||||
- require-error
|
||||
|
121
vendor/go.opentelemetry.io/otel/CHANGELOG.md
generated
vendored
121
vendor/go.opentelemetry.io/otel/CHANGELOG.md
generated
vendored
@@ -8,6 +8,112 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm
|
||||
|
||||
## [Unreleased]
|
||||
|
||||
<!-- Released section -->
|
||||
<!-- Don't change this section unless doing release -->
|
||||
|
||||
## [1.31.0/0.53.0/0.7.0/0.0.10] 2024-10-11
|
||||
|
||||
### Added
|
||||
|
||||
- Add `go.opentelemetry.io/otel/sdk/metric/exemplar` package which includes `Exemplar`, `Filter`, `TraceBasedFilter`, `AlwaysOnFilter`, `HistogramReservoir`, `FixedSizeReservoir`, `Reservoir`, `Value` and `ValueType` types. These will be used for configuring the exemplar reservoir for the metrics sdk. (#5747, #5862)
|
||||
- Add `WithExportBufferSize` option to log batch processor.(#5877)
|
||||
|
||||
### Changed
|
||||
|
||||
- Enable exemplars by default in `go.opentelemetry.io/otel/sdk/metric`. Exemplars can be disabled by setting `OTEL_METRICS_EXEMPLAR_FILTER=always_off` (#5778)
|
||||
- `Logger.Enabled` in `go.opentelemetry.io/otel/log` now accepts a newly introduced `EnabledParameters` type instead of `Record`. (#5791)
|
||||
- `FilterProcessor.Enabled` in `go.opentelemetry.io/otel/sdk/log/internal/x` now accepts `EnabledParameters` instead of `Record`. (#5791)
|
||||
- The `Record` type in `go.opentelemetry.io/otel/log` is no longer comparable. (#5847)
|
||||
- Performance improvements for the trace SDK `SetAttributes` method in `Span`. (#5864)
|
||||
- Reduce memory allocations for the `Event` and `Link` lists in `Span`. (#5858)
|
||||
- Performance improvements for the trace SDK `AddEvent`, `AddLink`, `RecordError` and `End` methods in `Span`. (#5874)
|
||||
|
||||
### Deprecated
|
||||
|
||||
- Deprecate all examples under `go.opentelemetry.io/otel/example` as they are moved to [Contrib repository](https://github.com/open-telemetry/opentelemetry-go-contrib/tree/main/examples). (#5854)
|
||||
|
||||
### Fixed
|
||||
|
||||
- The race condition for multiple `FixedSize` exemplar reservoirs identified in #5814 is resolved. (#5819)
|
||||
- Fix log records duplication in case of heterogeneous resource attributes by correctly mapping each log record to it's resource and scope. (#5803)
|
||||
- Fix timer channel drain to avoid hanging on Go 1.23. (#5868)
|
||||
- Fix delegation for global meter providers, and panic when calling otel.SetMeterProvider. (#5827)
|
||||
- Change the `reflect.TypeOf` to use a nil pointer to not allocate on the heap unless necessary. (#5827)
|
||||
|
||||
## [1.30.0/0.52.0/0.6.0/0.0.9] 2024-09-09
|
||||
|
||||
### Added
|
||||
|
||||
- Support `OTEL_EXPORTER_OTLP_LOGS_INSECURE` and `OTEL_EXPORTER_OTLP_INSECURE` environments in `go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploggrpc`. (#5739)
|
||||
- The `WithResource` option for `NewMeterProvider` now merges the provided resources with the ones from environment variables. (#5773)
|
||||
- The `WithResource` option for `NewLoggerProvider` now merges the provided resources with the ones from environment variables. (#5773)
|
||||
- Add UTF-8 support to `go.opentelemetry.io/otel/exporters/prometheus`. (#5755)
|
||||
|
||||
### Fixed
|
||||
|
||||
- Fix memory leak in the global `MeterProvider` when identical instruments are repeatedly created. (#5754)
|
||||
- Fix panic on instruments creation when setting meter provider. (#5758)
|
||||
- Fix an issue where `SetMeterProvider` in `go.opentelemetry.io/otel` might miss the delegation for instruments and registries. (#5780)
|
||||
|
||||
### Removed
|
||||
|
||||
- Drop support for [Go 1.21]. (#5736, #5740, #5800)
|
||||
|
||||
## [1.29.0/0.51.0/0.5.0] 2024-08-23
|
||||
|
||||
This release is the last to support [Go 1.21].
|
||||
The next release will require at least [Go 1.22].
|
||||
|
||||
### Added
|
||||
|
||||
- Add MacOS ARM64 platform to the compatibility testing suite. (#5577)
|
||||
- Add `InstrumentationScope` field to `SpanStub` in `go.opentelemetry.io/otel/sdk/trace/tracetest`, as a replacement for the deprecated `InstrumentationLibrary`. (#5627)
|
||||
- Make the initial release of `go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploggrpc`.
|
||||
This new module contains an OTLP exporter that transmits log telemetry using gRPC.
|
||||
This module is unstable and breaking changes may be introduced.
|
||||
See our [versioning policy](VERSIONING.md) for more information about these stability guarantees. (#5629)
|
||||
- Add `Walk` function to `TraceState` in `go.opentelemetry.io/otel/trace` to iterate all the key-value pairs. (#5651)
|
||||
- Bridge the trace state in `go.opentelemetry.io/otel/bridge/opencensus`. (#5651)
|
||||
- Zero value of `SimpleProcessor` in `go.opentelemetry.io/otel/sdk/log` no longer panics. (#5665)
|
||||
- The `FilterProcessor` interface type is added in `go.opentelemetry.io/otel/sdk/log/internal/x`.
|
||||
This is an optional and experimental interface that log `Processor`s can implement to instruct the `Logger` if a `Record` will be processed or not.
|
||||
It replaces the existing `Enabled` method that is removed from the `Processor` interface itself.
|
||||
It does not fall within the scope of the OpenTelemetry Go versioning and stability [policy](./VERSIONING.md) and it may be changed in backwards incompatible ways or removed in feature releases. (#5692)
|
||||
- Support [Go 1.23]. (#5720)
|
||||
|
||||
### Changed
|
||||
|
||||
- `NewMemberRaw`, `NewKeyProperty` and `NewKeyValuePropertyRaw` in `go.opentelemetry.io/otel/baggage` allow UTF-8 string in key. (#5132)
|
||||
- `Processor.OnEmit` in `go.opentelemetry.io/otel/sdk/log` now accepts a pointer to `Record` instead of a value so that the record modifications done in a processor are propagated to subsequent registered processors. (#5636)
|
||||
- `SimpleProcessor.Enabled` in `go.opentelemetry.io/otel/sdk/log` now returns `false` if the exporter is `nil`. (#5665)
|
||||
- Update the concurrency requirements of `Exporter` in `go.opentelemetry.io/otel/sdk/log`. (#5666)
|
||||
- `SimpleProcessor` in `go.opentelemetry.io/otel/sdk/log` synchronizes `OnEmit` calls. (#5666)
|
||||
- The `Processor` interface in `go.opentelemetry.io/otel/sdk/log` no longer includes the `Enabled` method.
|
||||
See the `FilterProcessor` interface type added in `go.opentelemetry.io/otel/sdk/log/internal/x` to continue providing this functionality. (#5692)
|
||||
- The `SimpleProcessor` type in `go.opentelemetry.io/otel/sdk/log` is no longer comparable. (#5693)
|
||||
- The `BatchProcessor` type in `go.opentelemetry.io/otel/sdk/log` is no longer comparable. (#5693)
|
||||
|
||||
### Fixed
|
||||
|
||||
- Correct comments for the priority of the `WithEndpoint` and `WithEndpointURL` options and their corresponding environment variables in `go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp`. (#5584)
|
||||
- Pass the underlying error rather than a generic retry-able failure in `go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp`, `go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploghttp` and `go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp`. (#5541)
|
||||
- Correct the `Tracer`, `Meter`, and `Logger` names used in `go.opentelemetry.io/otel/example/dice`. (#5612)
|
||||
- Correct the `Tracer` names used in `go.opentelemetry.io/otel/example/namedtracer`. (#5612)
|
||||
- Correct the `Tracer` name used in `go.opentelemetry.io/otel/example/opencensus`. (#5612)
|
||||
- Correct the `Tracer` and `Meter` names used in `go.opentelemetry.io/otel/example/otel-collector`. (#5612)
|
||||
- Correct the `Tracer` names used in `go.opentelemetry.io/otel/example/passthrough`. (#5612)
|
||||
- Correct the `Meter` name used in `go.opentelemetry.io/otel/example/prometheus`. (#5612)
|
||||
- Correct the `Tracer` names used in `go.opentelemetry.io/otel/example/zipkin`. (#5612)
|
||||
- Correct comments for the priority of the `WithEndpoint` and `WithEndpointURL` options and their corresponding environment variables in `go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc` and `go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp`. (#5641)
|
||||
- Correct comments for the priority of the `WithEndpoint` and `WithEndpointURL` options and their corresponding environment variables in `go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploghttp`. (#5650)
|
||||
- Stop percent encoding header environment variables in `go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc`, `go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp`, `go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc` and `go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp` (#5705)
|
||||
- Remove invalid environment variable header keys in `go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc`, `go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp`, `go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc` and `go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp` (#5705)
|
||||
|
||||
### Removed
|
||||
|
||||
- The `Enabled` method of the `SimpleProcessor` in `go.opentelemetry.io/otel/sdk/log` is removed. (#5692)
|
||||
- The `Enabled` method of the `BatchProcessor` in `go.opentelemetry.io/otel/sdk/log` is removed. (#5692)
|
||||
|
||||
## [1.28.0/0.50.0/0.4.0] 2024-07-02
|
||||
|
||||
### Added
|
||||
@@ -49,6 +155,7 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm
|
||||
- Fix stale timestamps reported by the last-value aggregation. (#5517)
|
||||
- Indicate the `Exporter` in `go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploghttp` must be created by the `New` method. (#5521)
|
||||
- Improved performance in all `{Bool,Int64,Float64,String}SliceValue` functions of `go.opentelemetry.io/attributes` by reducing the number of allocations. (#5549)
|
||||
- Replace invalid percent-encoded octet sequences with replacement char in `go.opentelemetry.io/otel/baggage`. (#5528)
|
||||
|
||||
## [1.27.0/0.49.0/0.3.0] 2024-05-21
|
||||
|
||||
@@ -175,7 +282,7 @@ The next release will require at least [Go 1.21].
|
||||
This module includes OpenTelemetry Go's implementation of the Logs Bridge API.
|
||||
This module is in an alpha state, it is subject to breaking changes.
|
||||
See our [versioning policy](./VERSIONING.md) for more info. (#4961)
|
||||
- ARM64 platform to the compatibility testing suite. (#4994)
|
||||
- Add ARM64 platform to the compatibility testing suite. (#4994)
|
||||
|
||||
### Fixed
|
||||
|
||||
@@ -1836,7 +1943,7 @@ with major version 0.
|
||||
- Setting error status while recording error with Span from oteltest package. (#1729)
|
||||
- The concept of a remote and local Span stored in a context is unified to just the current Span.
|
||||
Because of this `"go.opentelemetry.io/otel/trace".RemoteSpanContextFromContext` is removed as it is no longer needed.
|
||||
Instead, `"go.opentelemetry.io/otel/trace".SpanContextFromContex` can be used to return the current Span.
|
||||
Instead, `"go.opentelemetry.io/otel/trace".SpanContextFromContext` can be used to return the current Span.
|
||||
If needed, that Span's `SpanContext.IsRemote()` can then be used to determine if it is remote or not. (#1731)
|
||||
- The `HasRemoteParent` field of the `"go.opentelemetry.io/otel/sdk/trace".SamplingParameters` is removed.
|
||||
This field is redundant to the information returned from the `Remote` method of the `SpanContext` held in the `ParentContext` field. (#1749)
|
||||
@@ -2410,7 +2517,7 @@ This release migrates the default OpenTelemetry SDK into its own Go module, deco
|
||||
- Prometheus exporter will not apply stale updates or forget inactive metrics. (#903)
|
||||
- Add test for api.standard `HTTPClientAttributesFromHTTPRequest`. (#905)
|
||||
- Bump github.com/golangci/golangci-lint from 1.27.0 to 1.28.1 in /tools. (#901, #913)
|
||||
- Update otel-colector example to use the v0.5.0 collector. (#915)
|
||||
- Update otel-collector example to use the v0.5.0 collector. (#915)
|
||||
- The `grpctrace` instrumentation uses a span name conforming to the OpenTelemetry semantic conventions (does not contain a leading slash (`/`)). (#922)
|
||||
- The `grpctrace` instrumentation includes an `rpc.method` attribute now set to the gRPC method name. (#900, #922)
|
||||
- The `grpctrace` instrumentation `rpc.service` attribute now contains the package name if one exists.
|
||||
@@ -3003,7 +3110,10 @@ It contains api and sdk for trace and meter.
|
||||
- CircleCI build CI manifest files.
|
||||
- CODEOWNERS file to track owners of this project.
|
||||
|
||||
[Unreleased]: https://github.com/open-telemetry/opentelemetry-go/compare/v1.28.0...HEAD
|
||||
[Unreleased]: https://github.com/open-telemetry/opentelemetry-go/compare/v1.31.0...HEAD
|
||||
[1.31.0/0.53.0/0.7.0/0.0.10]: https://github.com/open-telemetry/opentelemetry-go/releases/tag/v1.31.0
|
||||
[1.30.0/0.52.0/0.6.0/0.0.9]: https://github.com/open-telemetry/opentelemetry-go/releases/tag/v1.30.0
|
||||
[1.29.0/0.51.0/0.5.0]: https://github.com/open-telemetry/opentelemetry-go/releases/tag/v1.29.0
|
||||
[1.28.0/0.50.0/0.4.0]: https://github.com/open-telemetry/opentelemetry-go/releases/tag/v1.28.0
|
||||
[1.27.0/0.49.0/0.3.0]: https://github.com/open-telemetry/opentelemetry-go/releases/tag/v1.27.0
|
||||
[1.26.0/0.48.0/0.2.0-alpha]: https://github.com/open-telemetry/opentelemetry-go/releases/tag/v1.26.0
|
||||
@@ -3086,6 +3196,9 @@ It contains api and sdk for trace and meter.
|
||||
[0.1.1]: https://github.com/open-telemetry/opentelemetry-go/releases/tag/v0.1.1
|
||||
[0.1.0]: https://github.com/open-telemetry/opentelemetry-go/releases/tag/v0.1.0
|
||||
|
||||
<!-- Released section ended -->
|
||||
|
||||
[Go 1.23]: https://go.dev/doc/go1.23
|
||||
[Go 1.22]: https://go.dev/doc/go1.22
|
||||
[Go 1.21]: https://go.dev/doc/go1.21
|
||||
[Go 1.20]: https://go.dev/doc/go1.20
|
||||
|
6
vendor/go.opentelemetry.io/otel/CODEOWNERS
generated
vendored
6
vendor/go.opentelemetry.io/otel/CODEOWNERS
generated
vendored
@@ -5,13 +5,13 @@
|
||||
#####################################################
|
||||
#
|
||||
# Learn about membership in OpenTelemetry community:
|
||||
# https://github.com/open-telemetry/community/blob/main/community-membership.md
|
||||
# https://github.com/open-telemetry/community/blob/main/guides/contributor/membership.md
|
||||
#
|
||||
#
|
||||
# Learn about CODEOWNERS file format:
|
||||
# https://help.github.com/en/articles/about-code-owners
|
||||
#
|
||||
|
||||
* @MrAlias @XSAM @dashpole @MadVikingGod @pellared @hanyuancheung @dmathieu
|
||||
* @MrAlias @XSAM @dashpole @pellared @dmathieu
|
||||
|
||||
CODEOWNERS @MrAlias @MadVikingGod @pellared @dashpole @XSAM @dmathieu
|
||||
CODEOWNERS @MrAlias @pellared @dashpole @XSAM @dmathieu
|
||||
|
18
vendor/go.opentelemetry.io/otel/CONTRIBUTING.md
generated
vendored
18
vendor/go.opentelemetry.io/otel/CONTRIBUTING.md
generated
vendored
@@ -578,7 +578,10 @@ See also:
|
||||
The tests should never leak goroutines.
|
||||
|
||||
Use the term `ConcurrentSafe` in the test name when it aims to verify the
|
||||
absence of race conditions.
|
||||
absence of race conditions. The top-level tests with this term will be run
|
||||
many times in the `test-concurrent-safe` CI job to increase the chance of
|
||||
catching concurrency issues. This does not apply to subtests when this term
|
||||
is not in their root name.
|
||||
|
||||
### Internal packages
|
||||
|
||||
@@ -628,11 +631,8 @@ should be canceled.
|
||||
|
||||
### Approvers
|
||||
|
||||
- [Chester Cheung](https://github.com/hanyuancheung), Tencent
|
||||
|
||||
### Maintainers
|
||||
|
||||
- [Aaron Clawson](https://github.com/MadVikingGod), LightStep
|
||||
- [Damien Mathieu](https://github.com/dmathieu), Elastic
|
||||
- [David Ashpole](https://github.com/dashpole), Google
|
||||
- [Robert Pająk](https://github.com/pellared), Splunk
|
||||
@@ -641,16 +641,18 @@ should be canceled.
|
||||
|
||||
### Emeritus
|
||||
|
||||
- [Liz Fong-Jones](https://github.com/lizthegrey), Honeycomb
|
||||
- [Aaron Clawson](https://github.com/MadVikingGod), LightStep
|
||||
- [Anthony Mirabella](https://github.com/Aneurysm9), AWS
|
||||
- [Chester Cheung](https://github.com/hanyuancheung), Tencent
|
||||
- [Evan Torrie](https://github.com/evantorrie), Yahoo
|
||||
- [Gustavo Silva Paiva](https://github.com/paivagustavo), LightStep
|
||||
- [Josh MacDonald](https://github.com/jmacd), LightStep
|
||||
- [Anthony Mirabella](https://github.com/Aneurysm9), AWS
|
||||
- [Evan Torrie](https://github.com/evantorrie), Yahoo
|
||||
- [Liz Fong-Jones](https://github.com/lizthegrey), Honeycomb
|
||||
|
||||
### Become an Approver or a Maintainer
|
||||
|
||||
See the [community membership document in OpenTelemetry community
|
||||
repo](https://github.com/open-telemetry/community/blob/main/community-membership.md).
|
||||
repo](https://github.com/open-telemetry/community/blob/main/guides/contributor/membership.md).
|
||||
|
||||
[Approver]: #approvers
|
||||
[Maintainer]: #maintainers
|
||||
|
22
vendor/go.opentelemetry.io/otel/Makefile
generated
vendored
22
vendor/go.opentelemetry.io/otel/Makefile
generated
vendored
@@ -54,9 +54,6 @@ $(TOOLS)/stringer: PACKAGE=golang.org/x/tools/cmd/stringer
|
||||
PORTO = $(TOOLS)/porto
|
||||
$(TOOLS)/porto: PACKAGE=github.com/jcchavezs/porto/cmd/porto
|
||||
|
||||
GOJQ = $(TOOLS)/gojq
|
||||
$(TOOLS)/gojq: PACKAGE=github.com/itchyny/gojq/cmd/gojq
|
||||
|
||||
GOTMPL = $(TOOLS)/gotmpl
|
||||
$(GOTMPL): PACKAGE=go.opentelemetry.io/build-tools/gotmpl
|
||||
|
||||
@@ -67,7 +64,7 @@ GOVULNCHECK = $(TOOLS)/govulncheck
|
||||
$(TOOLS)/govulncheck: PACKAGE=golang.org/x/vuln/cmd/govulncheck
|
||||
|
||||
.PHONY: tools
|
||||
tools: $(CROSSLINK) $(GOLANGCI_LINT) $(MISSPELL) $(GOCOVMERGE) $(STRINGER) $(PORTO) $(GOJQ) $(SEMCONVGEN) $(MULTIMOD) $(SEMCONVKIT) $(GOTMPL) $(GORELEASE)
|
||||
tools: $(CROSSLINK) $(GOLANGCI_LINT) $(MISSPELL) $(GOCOVMERGE) $(STRINGER) $(PORTO) $(SEMCONVGEN) $(MULTIMOD) $(SEMCONVKIT) $(GOTMPL) $(GORELEASE)
|
||||
|
||||
# Virtualized python tools via docker
|
||||
|
||||
@@ -145,12 +142,14 @@ build-tests/%:
|
||||
|
||||
# Tests
|
||||
|
||||
TEST_TARGETS := test-default test-bench test-short test-verbose test-race
|
||||
TEST_TARGETS := test-default test-bench test-short test-verbose test-race test-concurrent-safe
|
||||
.PHONY: $(TEST_TARGETS) test
|
||||
test-default test-race: ARGS=-race
|
||||
test-bench: ARGS=-run=xxxxxMatchNothingxxxxx -test.benchtime=1ms -bench=.
|
||||
test-short: ARGS=-short
|
||||
test-verbose: ARGS=-v -race
|
||||
test-concurrent-safe: ARGS=-run=ConcurrentSafe -count=100 -race
|
||||
test-concurrent-safe: TIMEOUT=120
|
||||
$(TEST_TARGETS): test
|
||||
test: $(OTEL_GO_MOD_DIRS:%=test/%)
|
||||
test/%: DIR=$*
|
||||
@@ -178,17 +177,14 @@ test-coverage: $(GOCOVMERGE)
|
||||
done; \
|
||||
$(GOCOVMERGE) $$(find . -name coverage.out) > coverage.txt
|
||||
|
||||
# Adding a directory will include all benchmarks in that directory if a filter is not specified.
|
||||
BENCHMARK_TARGETS := sdk/trace
|
||||
.PHONY: benchmark
|
||||
benchmark: $(BENCHMARK_TARGETS:%=benchmark/%)
|
||||
BENCHMARK_FILTER = .
|
||||
# You can override the filter for a particular directory by adding a rule here.
|
||||
benchmark/sdk/trace: BENCHMARK_FILTER = SpanWithAttributes_8/AlwaysSample
|
||||
benchmark: $(OTEL_GO_MOD_DIRS:%=benchmark/%)
|
||||
benchmark/%:
|
||||
@echo "$(GO) test -timeout $(TIMEOUT)s -run=xxxxxMatchNothingxxxxx -bench=$(BENCHMARK_FILTER) $*..." \
|
||||
@echo "$(GO) test -run=xxxxxMatchNothingxxxxx -bench=. $*..." \
|
||||
&& cd $* \
|
||||
$(foreach filter, $(BENCHMARK_FILTER), && $(GO) test -timeout $(TIMEOUT)s -run=xxxxxMatchNothingxxxxx -bench=$(filter))
|
||||
&& $(GO) list ./... \
|
||||
| grep -v third_party \
|
||||
| xargs $(GO) test -run=xxxxxMatchNothingxxxxx -bench=.
|
||||
|
||||
.PHONY: golangci-lint golangci-lint-fix
|
||||
golangci-lint-fix: ARGS=--fix
|
||||
|
34
vendor/go.opentelemetry.io/otel/README.md
generated
vendored
34
vendor/go.opentelemetry.io/otel/README.md
generated
vendored
@@ -47,20 +47,22 @@ stop ensuring compatibility with these versions in the following manner:
|
||||
|
||||
Currently, this project supports the following environments.
|
||||
|
||||
| OS | Go Version | Architecture |
|
||||
|---------|------------|--------------|
|
||||
| Ubuntu | 1.22 | amd64 |
|
||||
| Ubuntu | 1.21 | amd64 |
|
||||
| Ubuntu | 1.22 | 386 |
|
||||
| Ubuntu | 1.21 | 386 |
|
||||
| Linux | 1.22 | arm64 |
|
||||
| Linux | 1.21 | arm64 |
|
||||
| MacOS | 1.22 | amd64 |
|
||||
| MacOS | 1.21 | amd64 |
|
||||
| Windows | 1.22 | amd64 |
|
||||
| Windows | 1.21 | amd64 |
|
||||
| Windows | 1.22 | 386 |
|
||||
| Windows | 1.21 | 386 |
|
||||
| OS | Go Version | Architecture |
|
||||
|----------|------------|--------------|
|
||||
| Ubuntu | 1.23 | amd64 |
|
||||
| Ubuntu | 1.22 | amd64 |
|
||||
| Ubuntu | 1.23 | 386 |
|
||||
| Ubuntu | 1.22 | 386 |
|
||||
| Linux | 1.23 | arm64 |
|
||||
| Linux | 1.22 | arm64 |
|
||||
| macOS 13 | 1.23 | amd64 |
|
||||
| macOS 13 | 1.22 | amd64 |
|
||||
| macOS | 1.23 | arm64 |
|
||||
| macOS | 1.22 | arm64 |
|
||||
| Windows | 1.23 | amd64 |
|
||||
| Windows | 1.22 | amd64 |
|
||||
| Windows | 1.23 | 386 |
|
||||
| Windows | 1.22 | 386 |
|
||||
|
||||
While this project should work for other systems, no compatibility guarantees
|
||||
are made for those systems currently.
|
||||
@@ -87,8 +89,8 @@ If you need to extend the telemetry an instrumentation library provides or want
|
||||
to build your own instrumentation for your application directly you will need
|
||||
to use the
|
||||
[Go otel](https://pkg.go.dev/go.opentelemetry.io/otel)
|
||||
package. The included [examples](./example/) are a good way to see some
|
||||
practical uses of this process.
|
||||
package. The [examples](https://github.com/open-telemetry/opentelemetry-go-contrib/tree/main/examples)
|
||||
are a good way to see some practical uses of this process.
|
||||
|
||||
### Export
|
||||
|
||||
|
12
vendor/go.opentelemetry.io/otel/RELEASING.md
generated
vendored
12
vendor/go.opentelemetry.io/otel/RELEASING.md
generated
vendored
@@ -69,6 +69,7 @@ Update go.mod for submodules to depend on the new release which will happen in t
|
||||
```
|
||||
|
||||
- Move all the `Unreleased` changes into a new section following the title scheme (`[<new tag>] - <date of release>`).
|
||||
- Make sure the new section is under the comment for released section, like `<!-- Released section -->`, so it is protected from being overwritten in the future.
|
||||
- Update all the appropriate links at the bottom.
|
||||
|
||||
4. Push the changes to upstream and create a Pull Request on GitHub.
|
||||
@@ -110,17 +111,6 @@ It is critical you make sure the version you push upstream is correct.
|
||||
Finally create a Release for the new `<new tag>` on GitHub.
|
||||
The release body should include all the release notes from the Changelog for this release.
|
||||
|
||||
## Verify Examples
|
||||
|
||||
After releasing verify that examples build outside of the repository.
|
||||
|
||||
```
|
||||
./verify_examples.sh
|
||||
```
|
||||
|
||||
The script copies examples into a different directory removes any `replace` declarations in `go.mod` and builds them.
|
||||
This ensures they build with the published release, not the local copy.
|
||||
|
||||
## Post-Release
|
||||
|
||||
### Contrib Repository
|
||||
|
40
vendor/go.opentelemetry.io/otel/attribute/set.go
generated
vendored
40
vendor/go.opentelemetry.io/otel/attribute/set.go
generated
vendored
@@ -347,45 +347,25 @@ func computeDistinct(kvs []KeyValue) Distinct {
|
||||
func computeDistinctFixed(kvs []KeyValue) interface{} {
|
||||
switch len(kvs) {
|
||||
case 1:
|
||||
ptr := new([1]KeyValue)
|
||||
copy((*ptr)[:], kvs)
|
||||
return *ptr
|
||||
return [1]KeyValue(kvs)
|
||||
case 2:
|
||||
ptr := new([2]KeyValue)
|
||||
copy((*ptr)[:], kvs)
|
||||
return *ptr
|
||||
return [2]KeyValue(kvs)
|
||||
case 3:
|
||||
ptr := new([3]KeyValue)
|
||||
copy((*ptr)[:], kvs)
|
||||
return *ptr
|
||||
return [3]KeyValue(kvs)
|
||||
case 4:
|
||||
ptr := new([4]KeyValue)
|
||||
copy((*ptr)[:], kvs)
|
||||
return *ptr
|
||||
return [4]KeyValue(kvs)
|
||||
case 5:
|
||||
ptr := new([5]KeyValue)
|
||||
copy((*ptr)[:], kvs)
|
||||
return *ptr
|
||||
return [5]KeyValue(kvs)
|
||||
case 6:
|
||||
ptr := new([6]KeyValue)
|
||||
copy((*ptr)[:], kvs)
|
||||
return *ptr
|
||||
return [6]KeyValue(kvs)
|
||||
case 7:
|
||||
ptr := new([7]KeyValue)
|
||||
copy((*ptr)[:], kvs)
|
||||
return *ptr
|
||||
return [7]KeyValue(kvs)
|
||||
case 8:
|
||||
ptr := new([8]KeyValue)
|
||||
copy((*ptr)[:], kvs)
|
||||
return *ptr
|
||||
return [8]KeyValue(kvs)
|
||||
case 9:
|
||||
ptr := new([9]KeyValue)
|
||||
copy((*ptr)[:], kvs)
|
||||
return *ptr
|
||||
return [9]KeyValue(kvs)
|
||||
case 10:
|
||||
ptr := new([10]KeyValue)
|
||||
copy((*ptr)[:], kvs)
|
||||
return *ptr
|
||||
return [10]KeyValue(kvs)
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
|
150
vendor/go.opentelemetry.io/otel/baggage/baggage.go
generated
vendored
150
vendor/go.opentelemetry.io/otel/baggage/baggage.go
generated
vendored
@@ -44,9 +44,15 @@ type Property struct {
|
||||
|
||||
// NewKeyProperty returns a new Property for key.
|
||||
//
|
||||
// The passed key must be valid, non-empty UTF-8 string.
|
||||
// If key is invalid, an error will be returned.
|
||||
// However, the specific Propagators that are used to transmit baggage entries across
|
||||
// component boundaries may impose their own restrictions on Property key.
|
||||
// For example, the W3C Baggage specification restricts the Property keys to strings that
|
||||
// satisfy the token definition from RFC7230, Section 3.2.6.
|
||||
// For maximum compatibility, alphanumeric value are strongly recommended to be used as Property key.
|
||||
func NewKeyProperty(key string) (Property, error) {
|
||||
if !validateKey(key) {
|
||||
if !validateBaggageName(key) {
|
||||
return newInvalidProperty(), fmt.Errorf("%w: %q", errInvalidKey, key)
|
||||
}
|
||||
|
||||
@@ -62,6 +68,10 @@ func NewKeyProperty(key string) (Property, error) {
|
||||
// Notice: Consider using [NewKeyValuePropertyRaw] instead
|
||||
// that does not require percent-encoding of the value.
|
||||
func NewKeyValueProperty(key, value string) (Property, error) {
|
||||
if !validateKey(key) {
|
||||
return newInvalidProperty(), fmt.Errorf("%w: %q", errInvalidKey, key)
|
||||
}
|
||||
|
||||
if !validateValue(value) {
|
||||
return newInvalidProperty(), fmt.Errorf("%w: %q", errInvalidValue, value)
|
||||
}
|
||||
@@ -74,11 +84,20 @@ func NewKeyValueProperty(key, value string) (Property, error) {
|
||||
|
||||
// NewKeyValuePropertyRaw returns a new Property for key with value.
|
||||
//
|
||||
// The passed key must be compliant with W3C Baggage specification.
|
||||
// The passed key must be valid, non-empty UTF-8 string.
|
||||
// The passed value must be valid UTF-8 string.
|
||||
// However, the specific Propagators that are used to transmit baggage entries across
|
||||
// component boundaries may impose their own restrictions on Property key.
|
||||
// For example, the W3C Baggage specification restricts the Property keys to strings that
|
||||
// satisfy the token definition from RFC7230, Section 3.2.6.
|
||||
// For maximum compatibility, alphanumeric value are strongly recommended to be used as Property key.
|
||||
func NewKeyValuePropertyRaw(key, value string) (Property, error) {
|
||||
if !validateKey(key) {
|
||||
if !validateBaggageName(key) {
|
||||
return newInvalidProperty(), fmt.Errorf("%w: %q", errInvalidKey, key)
|
||||
}
|
||||
if !validateBaggageValue(value) {
|
||||
return newInvalidProperty(), fmt.Errorf("%w: %q", errInvalidValue, value)
|
||||
}
|
||||
|
||||
p := Property{
|
||||
key: key,
|
||||
@@ -115,12 +134,15 @@ func (p Property) validate() error {
|
||||
return fmt.Errorf("invalid property: %w", err)
|
||||
}
|
||||
|
||||
if !validateKey(p.key) {
|
||||
if !validateBaggageName(p.key) {
|
||||
return errFunc(fmt.Errorf("%w: %q", errInvalidKey, p.key))
|
||||
}
|
||||
if !p.hasValue && p.value != "" {
|
||||
return errFunc(errors.New("inconsistent value"))
|
||||
}
|
||||
if p.hasValue && !validateBaggageValue(p.value) {
|
||||
return errFunc(fmt.Errorf("%w: %q", errInvalidValue, p.value))
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -138,7 +160,15 @@ func (p Property) Value() (string, bool) {
|
||||
|
||||
// String encodes Property into a header string compliant with the W3C Baggage
|
||||
// specification.
|
||||
// It would return empty string if the key is invalid with the W3C Baggage
|
||||
// specification. This could happen for a UTF-8 key, as it may contain
|
||||
// invalid characters.
|
||||
func (p Property) String() string {
|
||||
// W3C Baggage specification does not allow percent-encoded keys.
|
||||
if !validateKey(p.key) {
|
||||
return ""
|
||||
}
|
||||
|
||||
if p.hasValue {
|
||||
return fmt.Sprintf("%s%s%v", p.key, keyValueDelimiter, valueEscape(p.value))
|
||||
}
|
||||
@@ -203,9 +233,14 @@ func (p properties) validate() error {
|
||||
// String encodes properties into a header string compliant with the W3C Baggage
|
||||
// specification.
|
||||
func (p properties) String() string {
|
||||
props := make([]string, len(p))
|
||||
for i, prop := range p {
|
||||
props[i] = prop.String()
|
||||
props := make([]string, 0, len(p))
|
||||
for _, prop := range p {
|
||||
s := prop.String()
|
||||
|
||||
// Ignored empty properties.
|
||||
if s != "" {
|
||||
props = append(props, s)
|
||||
}
|
||||
}
|
||||
return strings.Join(props, propertyDelimiter)
|
||||
}
|
||||
@@ -230,6 +265,10 @@ type Member struct {
|
||||
// Notice: Consider using [NewMemberRaw] instead
|
||||
// that does not require percent-encoding of the value.
|
||||
func NewMember(key, value string, props ...Property) (Member, error) {
|
||||
if !validateKey(key) {
|
||||
return newInvalidMember(), fmt.Errorf("%w: %q", errInvalidKey, key)
|
||||
}
|
||||
|
||||
if !validateValue(value) {
|
||||
return newInvalidMember(), fmt.Errorf("%w: %q", errInvalidValue, value)
|
||||
}
|
||||
@@ -242,7 +281,13 @@ func NewMember(key, value string, props ...Property) (Member, error) {
|
||||
|
||||
// NewMemberRaw returns a new Member from the passed arguments.
|
||||
//
|
||||
// The passed key must be compliant with W3C Baggage specification.
|
||||
// The passed key must be valid, non-empty UTF-8 string.
|
||||
// The passed value must be valid UTF-8 string.
|
||||
// However, the specific Propagators that are used to transmit baggage entries across
|
||||
// component boundaries may impose their own restrictions on baggage key.
|
||||
// For example, the W3C Baggage specification restricts the baggage keys to strings that
|
||||
// satisfy the token definition from RFC7230, Section 3.2.6.
|
||||
// For maximum compatibility, alphanumeric value are strongly recommended to be used as baggage key.
|
||||
func NewMemberRaw(key, value string, props ...Property) (Member, error) {
|
||||
m := Member{
|
||||
key: key,
|
||||
@@ -294,19 +339,45 @@ func parseMember(member string) (Member, error) {
|
||||
return newInvalidMember(), fmt.Errorf("%w: %q", errInvalidKey, key)
|
||||
}
|
||||
|
||||
val := strings.TrimSpace(v)
|
||||
if !validateValue(val) {
|
||||
rawVal := strings.TrimSpace(v)
|
||||
if !validateValue(rawVal) {
|
||||
return newInvalidMember(), fmt.Errorf("%w: %q", errInvalidValue, v)
|
||||
}
|
||||
|
||||
// Decode a percent-encoded value.
|
||||
value, err := url.PathUnescape(val)
|
||||
unescapeVal, err := url.PathUnescape(rawVal)
|
||||
if err != nil {
|
||||
return newInvalidMember(), fmt.Errorf("%w: %w", errInvalidValue, err)
|
||||
}
|
||||
|
||||
value := replaceInvalidUTF8Sequences(len(rawVal), unescapeVal)
|
||||
return Member{key: key, value: value, properties: props, hasData: true}, nil
|
||||
}
|
||||
|
||||
// replaceInvalidUTF8Sequences replaces invalid UTF-8 sequences with '<27>'.
|
||||
func replaceInvalidUTF8Sequences(cap int, unescapeVal string) string {
|
||||
if utf8.ValidString(unescapeVal) {
|
||||
return unescapeVal
|
||||
}
|
||||
// W3C baggage spec:
|
||||
// https://github.com/w3c/baggage/blob/8c215efbeebd3fa4b1aceb937a747e56444f22f3/baggage/HTTP_HEADER_FORMAT.md?plain=1#L69
|
||||
|
||||
var b strings.Builder
|
||||
b.Grow(cap)
|
||||
for i := 0; i < len(unescapeVal); {
|
||||
r, size := utf8.DecodeRuneInString(unescapeVal[i:])
|
||||
if r == utf8.RuneError && size == 1 {
|
||||
// Invalid UTF-8 sequence found, replace it with '<27>'
|
||||
_, _ = b.WriteString("<22>")
|
||||
} else {
|
||||
_, _ = b.WriteRune(r)
|
||||
}
|
||||
i += size
|
||||
}
|
||||
|
||||
return b.String()
|
||||
}
|
||||
|
||||
// validate ensures m conforms to the W3C Baggage specification.
|
||||
// A key must be an ASCII string, returning an error otherwise.
|
||||
func (m Member) validate() error {
|
||||
@@ -314,9 +385,12 @@ func (m Member) validate() error {
|
||||
return fmt.Errorf("%w: %q", errInvalidMember, m)
|
||||
}
|
||||
|
||||
if !validateKey(m.key) {
|
||||
if !validateBaggageName(m.key) {
|
||||
return fmt.Errorf("%w: %q", errInvalidKey, m.key)
|
||||
}
|
||||
if !validateBaggageValue(m.value) {
|
||||
return fmt.Errorf("%w: %q", errInvalidValue, m.value)
|
||||
}
|
||||
return m.properties.validate()
|
||||
}
|
||||
|
||||
@@ -331,10 +405,15 @@ func (m Member) Properties() []Property { return m.properties.Copy() }
|
||||
|
||||
// String encodes Member into a header string compliant with the W3C Baggage
|
||||
// specification.
|
||||
// It would return empty string if the key is invalid with the W3C Baggage
|
||||
// specification. This could happen for a UTF-8 key, as it may contain
|
||||
// invalid characters.
|
||||
func (m Member) String() string {
|
||||
// A key is just an ASCII string. A value is restricted to be
|
||||
// US-ASCII characters excluding CTLs, whitespace,
|
||||
// DQUOTE, comma, semicolon, and backslash.
|
||||
// W3C Baggage specification does not allow percent-encoded keys.
|
||||
if !validateKey(m.key) {
|
||||
return ""
|
||||
}
|
||||
|
||||
s := m.key + keyValueDelimiter + valueEscape(m.value)
|
||||
if len(m.properties) > 0 {
|
||||
s += propertyDelimiter + m.properties.String()
|
||||
@@ -448,7 +527,7 @@ func (b Baggage) Member(key string) Member {
|
||||
}
|
||||
|
||||
// Members returns all the baggage list-members.
|
||||
// The order of the returned list-members does not have significance.
|
||||
// The order of the returned list-members is not significant.
|
||||
//
|
||||
// The returned members are not validated, as we assume the validation happened
|
||||
// when they were added to the Baggage.
|
||||
@@ -469,8 +548,8 @@ func (b Baggage) Members() []Member {
|
||||
return members
|
||||
}
|
||||
|
||||
// SetMember returns a copy the Baggage with the member included. If the
|
||||
// baggage contains a Member with the same key the existing Member is
|
||||
// SetMember returns a copy of the Baggage with the member included. If the
|
||||
// baggage contains a Member with the same key, the existing Member is
|
||||
// replaced.
|
||||
//
|
||||
// If member is invalid according to the W3C Baggage specification, an error
|
||||
@@ -528,14 +607,22 @@ func (b Baggage) Len() int {
|
||||
|
||||
// String encodes Baggage into a header string compliant with the W3C Baggage
|
||||
// specification.
|
||||
// It would ignore members where the member key is invalid with the W3C Baggage
|
||||
// specification. This could happen for a UTF-8 key, as it may contain
|
||||
// invalid characters.
|
||||
func (b Baggage) String() string {
|
||||
members := make([]string, 0, len(b.list))
|
||||
for k, v := range b.list {
|
||||
members = append(members, Member{
|
||||
s := Member{
|
||||
key: k,
|
||||
value: v.Value,
|
||||
properties: fromInternalProperties(v.Properties),
|
||||
}.String())
|
||||
}.String()
|
||||
|
||||
// Ignored empty members.
|
||||
if s != "" {
|
||||
members = append(members, s)
|
||||
}
|
||||
}
|
||||
return strings.Join(members, listDelimiter)
|
||||
}
|
||||
@@ -607,10 +694,12 @@ func parsePropertyInternal(s string) (p Property, ok bool) {
|
||||
}
|
||||
|
||||
// Decode a percent-encoded value.
|
||||
value, err := url.PathUnescape(s[valueStart:valueEnd])
|
||||
rawVal := s[valueStart:valueEnd]
|
||||
unescapeVal, err := url.PathUnescape(rawVal)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
value := replaceInvalidUTF8Sequences(len(rawVal), unescapeVal)
|
||||
|
||||
ok = true
|
||||
p.key = s[keyStart:keyEnd]
|
||||
@@ -720,6 +809,24 @@ var safeKeyCharset = [utf8.RuneSelf]bool{
|
||||
'~': true,
|
||||
}
|
||||
|
||||
// validateBaggageName checks if the string is a valid OpenTelemetry Baggage name.
|
||||
// Baggage name is a valid, non-empty UTF-8 string.
|
||||
func validateBaggageName(s string) bool {
|
||||
if len(s) == 0 {
|
||||
return false
|
||||
}
|
||||
|
||||
return utf8.ValidString(s)
|
||||
}
|
||||
|
||||
// validateBaggageValue checks if the string is a valid OpenTelemetry Baggage value.
|
||||
// Baggage value is a valid UTF-8 strings.
|
||||
// Empty string is also a valid UTF-8 string.
|
||||
func validateBaggageValue(s string) bool {
|
||||
return utf8.ValidString(s)
|
||||
}
|
||||
|
||||
// validateKey checks if the string is a valid W3C Baggage key.
|
||||
func validateKey(s string) bool {
|
||||
if len(s) == 0 {
|
||||
return false
|
||||
@@ -738,6 +845,7 @@ func validateKeyChar(c int32) bool {
|
||||
return c >= 0 && c < int32(utf8.RuneSelf) && safeKeyCharset[c]
|
||||
}
|
||||
|
||||
// validateValue checks if the string is a valid W3C Baggage value.
|
||||
func validateValue(s string) bool {
|
||||
for _, c := range s {
|
||||
if !validateValueChar(c) {
|
||||
|
2
vendor/go.opentelemetry.io/otel/codes/codes.go
generated
vendored
2
vendor/go.opentelemetry.io/otel/codes/codes.go
generated
vendored
@@ -83,7 +83,7 @@ func (c *Code) UnmarshalJSON(b []byte) error {
|
||||
return fmt.Errorf("invalid code: %q", ci)
|
||||
}
|
||||
|
||||
*c = Code(ci)
|
||||
*c = Code(ci) // nolint: gosec // Bit size of 32 check above.
|
||||
return nil
|
||||
}
|
||||
return fmt.Errorf("invalid code: %q", string(b))
|
||||
|
2
vendor/go.opentelemetry.io/otel/doc.go
generated
vendored
2
vendor/go.opentelemetry.io/otel/doc.go
generated
vendored
@@ -17,6 +17,8 @@ To read more about tracing, see go.opentelemetry.io/otel/trace.
|
||||
|
||||
To read more about metrics, see go.opentelemetry.io/otel/metric.
|
||||
|
||||
To read more about logs, see go.opentelemetry.io/otel/log.
|
||||
|
||||
To read more about propagation, see go.opentelemetry.io/otel/propagation and
|
||||
go.opentelemetry.io/otel/baggage.
|
||||
*/
|
||||
|
3
vendor/go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc/README.md
generated
vendored
Normal file
3
vendor/go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc/README.md
generated
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
# OTLP Metric gRPC Exporter
|
||||
|
||||
[](https://pkg.go.dev/go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc)
|
17
vendor/go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc/client.go
generated
vendored
17
vendor/go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc/client.go
generated
vendored
@@ -1,16 +1,5 @@
|
||||
// Copyright The OpenTelemetry Authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package otlpmetricgrpc // import "go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc"
|
||||
|
||||
@@ -47,7 +36,7 @@ type client struct {
|
||||
}
|
||||
|
||||
// newClient creates a new gRPC metric client.
|
||||
func newClient(ctx context.Context, cfg oconf.Config) (*client, error) {
|
||||
func newClient(_ context.Context, cfg oconf.Config) (*client, error) {
|
||||
c := &client{
|
||||
exportTimeout: cfg.Metrics.Timeout,
|
||||
requestFunc: cfg.RetryConfig.RequestFunc(retryable),
|
||||
@@ -65,7 +54,7 @@ func newClient(ctx context.Context, cfg oconf.Config) (*client, error) {
|
||||
dialOpts := []grpc.DialOption{grpc.WithUserAgent(userAgent)}
|
||||
dialOpts = append(dialOpts, cfg.DialOptions...)
|
||||
|
||||
conn, err := grpc.DialContext(ctx, cfg.Metrics.Endpoint, dialOpts...)
|
||||
conn, err := grpc.NewClient(cfg.Metrics.Endpoint, dialOpts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
44
vendor/go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc/config.go
generated
vendored
44
vendor/go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc/config.go
generated
vendored
@@ -1,16 +1,5 @@
|
||||
// Copyright The OpenTelemetry Authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package otlpmetricgrpc // import "go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc"
|
||||
|
||||
@@ -77,8 +66,12 @@ func WithInsecure() Option {
|
||||
//
|
||||
// If the OTEL_EXPORTER_OTLP_ENDPOINT or OTEL_EXPORTER_OTLP_METRICS_ENDPOINT
|
||||
// environment variable is set, and this option is not passed, that variable
|
||||
// value will be used. If both are set, OTEL_EXPORTER_OTLP_METRICS_ENDPOINT
|
||||
// will take precedence.
|
||||
// value will be used. If both environment variables are set,
|
||||
// OTEL_EXPORTER_OTLP_METRICS_ENDPOINT will take precedence. If an environment
|
||||
// variable is set, and this option is passed, this option will take precedence.
|
||||
//
|
||||
// If both this option and WithEndpointURL are used, the last used option will
|
||||
// take precedence.
|
||||
//
|
||||
// By default, if an environment variable is not set, and this option is not
|
||||
// passed, "localhost:4317" will be used.
|
||||
@@ -88,6 +81,27 @@ func WithEndpoint(endpoint string) Option {
|
||||
return wrappedOption{oconf.WithEndpoint(endpoint)}
|
||||
}
|
||||
|
||||
// WithEndpointURL sets the target endpoint URL the Exporter will connect to.
|
||||
//
|
||||
// If the OTEL_EXPORTER_OTLP_ENDPOINT or OTEL_EXPORTER_OTLP_METRICS_ENDPOINT
|
||||
// environment variable is set, and this option is not passed, that variable
|
||||
// value will be used. If both environment variables are set,
|
||||
// OTEL_EXPORTER_OTLP_METRICS_ENDPOINT will take precedence. If an environment
|
||||
// variable is set, and this option is passed, this option will take precedence.
|
||||
//
|
||||
// If both this option and WithEndpoint are used, the last used option will
|
||||
// take precedence.
|
||||
//
|
||||
// If an invalid URL is provided, the default value will be kept.
|
||||
//
|
||||
// By default, if an environment variable is not set, and this option is not
|
||||
// passed, "localhost:4317" will be used.
|
||||
//
|
||||
// This option has no effect if WithGRPCConn is used.
|
||||
func WithEndpointURL(u string) Option {
|
||||
return wrappedOption{oconf.WithEndpointURL(u)}
|
||||
}
|
||||
|
||||
// WithReconnectionPeriod set the minimum amount of time between connection
|
||||
// attempts to the target endpoint.
|
||||
//
|
||||
@@ -173,6 +187,8 @@ func WithServiceConfig(serviceConfig string) Option {
|
||||
// gRPC connection. The options here are appended to the internal grpc.DialOptions
|
||||
// used so they will take precedence over any other internal grpc.DialOptions
|
||||
// they might conflict with.
|
||||
// The [grpc.WithBlock], [grpc.WithTimeout], and [grpc.WithReturnConnectionError]
|
||||
// grpc.DialOptions are ignored.
|
||||
//
|
||||
// This option has no effect if WithGRPCConn is used.
|
||||
func WithDialOption(opts ...grpc.DialOption) Option {
|
||||
|
26
vendor/go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc/doc.go
generated
vendored
26
vendor/go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc/doc.go
generated
vendored
@@ -1,16 +1,5 @@
|
||||
// Copyright The OpenTelemetry Authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
/*
|
||||
Package otlpmetricgrpc provides an OTLP metrics exporter using gRPC.
|
||||
@@ -23,12 +12,11 @@ The environment variables described below can be used for configuration.
|
||||
OTEL_EXPORTER_OTLP_ENDPOINT, OTEL_EXPORTER_OTLP_METRICS_ENDPOINT (default: "https://localhost:4317") -
|
||||
target to which the exporter sends telemetry.
|
||||
The target syntax is defined in https://github.com/grpc/grpc/blob/master/doc/naming.md.
|
||||
The value must contain a host.
|
||||
The value may additionally a port, a scheme, and a path.
|
||||
The value accepts "http" and "https" scheme.
|
||||
The value must contain a scheme ("http" or "https") and host.
|
||||
The value may additionally contain a port, and a path.
|
||||
The value should not contain a query string or fragment.
|
||||
OTEL_EXPORTER_OTLP_METRICS_ENDPOINT takes precedence over OTEL_EXPORTER_OTLP_ENDPOINT.
|
||||
The configuration can be overridden by [WithEndpoint], [WithInsecure], [WithGRPCConn] options.
|
||||
The configuration can be overridden by [WithEndpoint], [WithEndpointURL], [WithInsecure], and [WithGRPCConn] options.
|
||||
|
||||
OTEL_EXPORTER_OTLP_INSECURE, OTEL_EXPORTER_OTLP_METRICS_INSECURE (default: "false") -
|
||||
setting "true" disables client transport security for the exporter's gRPC connection.
|
||||
@@ -40,7 +28,7 @@ The configuration can be overridden by [WithInsecure], [WithGRPCConn] options.
|
||||
|
||||
OTEL_EXPORTER_OTLP_HEADERS, OTEL_EXPORTER_OTLP_METRICS_HEADERS (default: none) -
|
||||
key-value pairs used as gRPC metadata associated with gRPC requests.
|
||||
The value is expected to be represented in a format matching to the [W3C Baggage HTTP Header Content Format],
|
||||
The value is expected to be represented in a format matching the [W3C Baggage HTTP Header Content Format],
|
||||
except that additional semi-colon delimited metadata is not supported.
|
||||
Example value: "key1=value1,key2=value2".
|
||||
OTEL_EXPORTER_OTLP_METRICS_HEADERS takes precedence over OTEL_EXPORTER_OTLP_HEADERS.
|
||||
@@ -63,12 +51,12 @@ OTEL_EXPORTER_OTLP_METRICS_CERTIFICATE takes precedence over OTEL_EXPORTER_OTLP_
|
||||
The configuration can be overridden by [WithTLSCredentials], [WithGRPCConn] options.
|
||||
|
||||
OTEL_EXPORTER_OTLP_CLIENT_CERTIFICATE, OTEL_EXPORTER_OTLP_METRICS_CLIENT_CERTIFICATE (default: none) -
|
||||
the filepath to the client certificate/chain trust for clients private key to use in mTLS communication in PEM format.
|
||||
the filepath to the client certificate/chain trust for client's private key to use in mTLS communication in PEM format.
|
||||
OTEL_EXPORTER_OTLP_METRICS_CLIENT_CERTIFICATE takes precedence over OTEL_EXPORTER_OTLP_CLIENT_CERTIFICATE.
|
||||
The configuration can be overridden by [WithTLSCredentials], [WithGRPCConn] options.
|
||||
|
||||
OTEL_EXPORTER_OTLP_CLIENT_KEY, OTEL_EXPORTER_OTLP_METRICS_CLIENT_KEY (default: none) -
|
||||
the filepath to the clients private key to use in mTLS communication in PEM format.
|
||||
the filepath to the client's private key to use in mTLS communication in PEM format.
|
||||
OTEL_EXPORTER_OTLP_METRICS_CLIENT_KEY takes precedence over OTEL_EXPORTER_OTLP_CLIENT_KEY.
|
||||
The configuration can be overridden by [WithTLSCredentials], [WithGRPCConn] option.
|
||||
|
||||
|
15
vendor/go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc/exporter.go
generated
vendored
15
vendor/go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc/exporter.go
generated
vendored
@@ -1,16 +1,5 @@
|
||||
// Copyright The OpenTelemetry Authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package otlpmetricgrpc // import "go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc"
|
||||
|
||||
@@ -90,7 +79,7 @@ func (e *Exporter) Export(ctx context.Context, rm *metricdata.ResourceMetrics) e
|
||||
return fmt.Errorf("failed to upload metrics: %w", upErr)
|
||||
}
|
||||
// Merge the two errors.
|
||||
return fmt.Errorf("failed to upload incomplete metrics (%s): %w", err, upErr)
|
||||
return fmt.Errorf("failed to upload incomplete metrics (%w): %w", err, upErr)
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
@@ -2,18 +2,7 @@
|
||||
// source: internal/shared/otlp/envconfig/envconfig.go.tmpl
|
||||
|
||||
// Copyright The OpenTelemetry Authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package envconfig // import "go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc/internal/envconfig"
|
||||
|
||||
@@ -26,6 +15,7 @@ import (
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
"unicode"
|
||||
|
||||
"go.opentelemetry.io/otel/internal/global"
|
||||
)
|
||||
@@ -174,12 +164,16 @@ func stringToHeader(value string) map[string]string {
|
||||
global.Error(errors.New("missing '="), "parse headers", "input", header)
|
||||
continue
|
||||
}
|
||||
name, err := url.PathUnescape(n)
|
||||
if err != nil {
|
||||
global.Error(err, "escape header key", "key", n)
|
||||
|
||||
trimmedName := strings.TrimSpace(n)
|
||||
|
||||
// Validate the key.
|
||||
if !isValidHeaderKey(trimmedName) {
|
||||
global.Error(errors.New("invalid header key"), "parse headers", "key", trimmedName)
|
||||
continue
|
||||
}
|
||||
trimmedName := strings.TrimSpace(name)
|
||||
|
||||
// Only decode the value.
|
||||
value, err := url.PathUnescape(v)
|
||||
if err != nil {
|
||||
global.Error(err, "escape header value", "value", v)
|
||||
@@ -200,3 +194,22 @@ func createCertPool(certBytes []byte) (*x509.CertPool, error) {
|
||||
}
|
||||
return cp, nil
|
||||
}
|
||||
|
||||
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 == '~')
|
||||
}
|
||||
|
13
vendor/go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc/internal/gen.go
generated
vendored
13
vendor/go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc/internal/gen.go
generated
vendored
@@ -1,16 +1,5 @@
|
||||
// Copyright The OpenTelemetry Authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package internal // import "go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc/internal"
|
||||
|
||||
|
@@ -2,18 +2,7 @@
|
||||
// source: internal/shared/otlp/otlpmetric/oconf/envconfig.go.tmpl
|
||||
|
||||
// Copyright The OpenTelemetry Authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package oconf // import "go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc/internal/oconf"
|
||||
|
||||
|
@@ -2,24 +2,15 @@
|
||||
// source: internal/shared/otlp/otlpmetric/oconf/options.go.tmpl
|
||||
|
||||
// Copyright The OpenTelemetry Authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package oconf // import "go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc/internal/oconf"
|
||||
|
||||
import (
|
||||
"crypto/tls"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"path"
|
||||
"strings"
|
||||
"time"
|
||||
@@ -31,6 +22,7 @@ import (
|
||||
"google.golang.org/grpc/encoding/gzip"
|
||||
|
||||
"go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc/internal/retry"
|
||||
"go.opentelemetry.io/otel/internal/global"
|
||||
"go.opentelemetry.io/otel/sdk/metric"
|
||||
)
|
||||
|
||||
@@ -51,6 +43,10 @@ const (
|
||||
)
|
||||
|
||||
type (
|
||||
// HTTPTransportProxyFunc is a function that resolves which URL to use as proxy for a given request.
|
||||
// This type is compatible with `http.Transport.Proxy` and can be used to set a custom proxy function to the OTLP HTTP client.
|
||||
HTTPTransportProxyFunc func(*http.Request) (*url.URL, error)
|
||||
|
||||
SignalConfig struct {
|
||||
Endpoint string
|
||||
Insecure bool
|
||||
@@ -65,6 +61,8 @@ type (
|
||||
|
||||
TemporalitySelector metric.TemporalitySelector
|
||||
AggregationSelector metric.AggregationSelector
|
||||
|
||||
Proxy HTTPTransportProxyFunc
|
||||
}
|
||||
|
||||
Config struct {
|
||||
@@ -141,7 +139,7 @@ func NewGRPCConfig(opts ...GRPCOption) Config {
|
||||
if cfg.ServiceConfig != "" {
|
||||
cfg.DialOptions = append(cfg.DialOptions, grpc.WithDefaultServiceConfig(cfg.ServiceConfig))
|
||||
}
|
||||
// Priroritize GRPCCredentials over Insecure (passing both is an error).
|
||||
// Prioritize GRPCCredentials over Insecure (passing both is an error).
|
||||
if cfg.Metrics.GRPCCredentials != nil {
|
||||
cfg.DialOptions = append(cfg.DialOptions, grpc.WithTransportCredentials(cfg.Metrics.GRPCCredentials))
|
||||
} else if cfg.Metrics.Insecure {
|
||||
@@ -279,6 +277,24 @@ func WithEndpoint(endpoint string) GenericOption {
|
||||
})
|
||||
}
|
||||
|
||||
func WithEndpointURL(v string) GenericOption {
|
||||
return newGenericOption(func(cfg Config) Config {
|
||||
u, err := url.Parse(v)
|
||||
if err != nil {
|
||||
global.Error(err, "otlpmetric: parse endpoint url", "url", v)
|
||||
return cfg
|
||||
}
|
||||
|
||||
cfg.Metrics.Endpoint = u.Host
|
||||
cfg.Metrics.URLPath = u.Path
|
||||
if u.Scheme != "https" {
|
||||
cfg.Metrics.Insecure = true
|
||||
}
|
||||
|
||||
return cfg
|
||||
})
|
||||
}
|
||||
|
||||
func WithCompression(compression Compression) GenericOption {
|
||||
return newGenericOption(func(cfg Config) Config {
|
||||
cfg.Metrics.Compression = compression
|
||||
@@ -351,3 +367,10 @@ func WithAggregationSelector(selector metric.AggregationSelector) GenericOption
|
||||
return cfg
|
||||
})
|
||||
}
|
||||
|
||||
func WithProxy(pf HTTPTransportProxyFunc) GenericOption {
|
||||
return newGenericOption(func(cfg Config) Config {
|
||||
cfg.Metrics.Proxy = pf
|
||||
return cfg
|
||||
})
|
||||
}
|
||||
|
@@ -2,18 +2,7 @@
|
||||
// source: internal/shared/otlp/otlpmetric/oconf/optiontypes.go.tmpl
|
||||
|
||||
// Copyright The OpenTelemetry Authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package oconf // import "go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc/internal/oconf"
|
||||
|
||||
|
@@ -2,18 +2,7 @@
|
||||
// source: internal/shared/otlp/otlpmetric/oconf/tls.go.tmpl
|
||||
|
||||
// Copyright The OpenTelemetry Authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package oconf // import "go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc/internal/oconf"
|
||||
|
||||
@@ -25,7 +14,7 @@ import (
|
||||
)
|
||||
|
||||
// ReadTLSConfigFromFile reads a PEM certificate file and creates
|
||||
// a tls.Config that will use this certifate to verify a server certificate.
|
||||
// a tls.Config that will use this certificate to verify a server certificate.
|
||||
func ReadTLSConfigFromFile(path string) (*tls.Config, error) {
|
||||
b, err := os.ReadFile(path)
|
||||
if err != nil {
|
||||
|
@@ -2,18 +2,7 @@
|
||||
// source: internal/shared/otlp/partialsuccess.go
|
||||
|
||||
// Copyright The OpenTelemetry Authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package internal // import "go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc/internal"
|
||||
|
||||
|
@@ -2,18 +2,7 @@
|
||||
// source: internal/shared/otlp/retry/retry.go.tmpl
|
||||
|
||||
// Copyright The OpenTelemetry Authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
// Package retry provides request retry functionality that can perform
|
||||
// configurable exponential backoff for transient errors and honor any
|
||||
@@ -123,7 +112,7 @@ func (c Config) RequestFunc(evaluate EvaluateFunc) RequestFunc {
|
||||
}
|
||||
|
||||
if ctxErr := waitFunc(ctx, delay); ctxErr != nil {
|
||||
return fmt.Errorf("%w: %s", ctxErr, err)
|
||||
return fmt.Errorf("%w: %w", ctxErr, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -2,18 +2,7 @@
|
||||
// source: internal/shared/otlp/otlpmetric/transform/attribute.go.tmpl
|
||||
|
||||
// Copyright The OpenTelemetry Authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package transform // import "go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc/internal/transform"
|
||||
|
||||
|
@@ -2,18 +2,7 @@
|
||||
// source: internal/shared/otlp/otlpmetric/transform/error.go.tmpl
|
||||
|
||||
// Copyright The OpenTelemetry Authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package transform // import "go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc/internal/transform"
|
||||
|
||||
@@ -69,7 +58,7 @@ func (e *multiErr) append(err error) {
|
||||
// Do not use errors.As here, this should only be flattened one layer. If
|
||||
// there is a *multiErr several steps down the chain, all the errors above
|
||||
// it will be discarded if errors.As is used instead.
|
||||
switch other := err.(type) {
|
||||
switch other := err.(type) { //nolint:errorlint
|
||||
case *multiErr:
|
||||
// Flatten err errors into e.
|
||||
e.errs = append(e.errs, other.errs...)
|
||||
|
@@ -2,18 +2,7 @@
|
||||
// source: internal/shared/otlp/otlpmetric/transform/metricdata.go.tmpl
|
||||
|
||||
// Copyright The OpenTelemetry Authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
// Package transform provides transformation functionality from the
|
||||
// sdk/metric/metricdata data-types into OTLP data-types.
|
||||
@@ -90,7 +79,7 @@ func metric(m metricdata.Metrics) (*mpb.Metric, error) {
|
||||
out := &mpb.Metric{
|
||||
Name: m.Name,
|
||||
Description: m.Description,
|
||||
Unit: string(m.Unit),
|
||||
Unit: m.Unit,
|
||||
}
|
||||
switch a := m.Data.(type) {
|
||||
case metricdata.Gauge[int64]:
|
||||
@@ -109,6 +98,8 @@ func metric(m metricdata.Metrics) (*mpb.Metric, error) {
|
||||
out.Data, err = ExponentialHistogram(a)
|
||||
case metricdata.ExponentialHistogram[float64]:
|
||||
out.Data, err = ExponentialHistogram(a)
|
||||
case metricdata.Summary:
|
||||
out.Data = Summary(a)
|
||||
default:
|
||||
return out, fmt.Errorf("%w: %T", errUnknownAggregation, a)
|
||||
}
|
||||
@@ -148,6 +139,7 @@ func DataPoints[N int64 | float64](dPts []metricdata.DataPoint[N]) []*mpb.Number
|
||||
Attributes: AttrIter(dPt.Attributes.Iter()),
|
||||
StartTimeUnixNano: timeUnixNano(dPt.StartTime),
|
||||
TimeUnixNano: timeUnixNano(dPt.Time),
|
||||
Exemplars: Exemplars(dPt.Exemplars),
|
||||
}
|
||||
switch v := any(dPt.Value).(type) {
|
||||
case int64:
|
||||
@@ -193,6 +185,7 @@ func HistogramDataPoints[N int64 | float64](dPts []metricdata.HistogramDataPoint
|
||||
Sum: &sum,
|
||||
BucketCounts: dPt.BucketCounts,
|
||||
ExplicitBounds: dPt.Bounds,
|
||||
Exemplars: Exemplars(dPt.Exemplars),
|
||||
}
|
||||
if v, ok := dPt.Min.Value(); ok {
|
||||
vF64 := float64(v)
|
||||
@@ -236,6 +229,7 @@ func ExponentialHistogramDataPoints[N int64 | float64](dPts []metricdata.Exponen
|
||||
Sum: &sum,
|
||||
Scale: dPt.Scale,
|
||||
ZeroCount: dPt.ZeroCount,
|
||||
Exemplars: Exemplars(dPt.Exemplars),
|
||||
|
||||
Positive: ExponentialHistogramDataPointBuckets(dPt.PositiveBucket),
|
||||
Negative: ExponentialHistogramDataPointBuckets(dPt.NegativeBucket),
|
||||
@@ -285,8 +279,71 @@ func Temporality(t metricdata.Temporality) (mpb.AggregationTemporality, error) {
|
||||
// timeUnixNano on the zero Time returns 0.
|
||||
// The result does not depend on the location associated with t.
|
||||
func timeUnixNano(t time.Time) uint64 {
|
||||
if t.IsZero() {
|
||||
return 0
|
||||
}
|
||||
return uint64(t.UnixNano())
|
||||
return uint64(max(0, t.UnixNano())) // nolint:gosec // Overflow checked.
|
||||
}
|
||||
|
||||
// Exemplars returns a slice of OTLP Exemplars generated from exemplars.
|
||||
func Exemplars[N int64 | float64](exemplars []metricdata.Exemplar[N]) []*mpb.Exemplar {
|
||||
out := make([]*mpb.Exemplar, 0, len(exemplars))
|
||||
for _, exemplar := range exemplars {
|
||||
e := &mpb.Exemplar{
|
||||
FilteredAttributes: KeyValues(exemplar.FilteredAttributes),
|
||||
TimeUnixNano: timeUnixNano(exemplar.Time),
|
||||
SpanId: exemplar.SpanID,
|
||||
TraceId: exemplar.TraceID,
|
||||
}
|
||||
switch v := any(exemplar.Value).(type) {
|
||||
case int64:
|
||||
e.Value = &mpb.Exemplar_AsInt{
|
||||
AsInt: v,
|
||||
}
|
||||
case float64:
|
||||
e.Value = &mpb.Exemplar_AsDouble{
|
||||
AsDouble: v,
|
||||
}
|
||||
}
|
||||
out = append(out, e)
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
||||
// Summary returns an OTLP Metric_Summary generated from s.
|
||||
func Summary(s metricdata.Summary) *mpb.Metric_Summary {
|
||||
return &mpb.Metric_Summary{
|
||||
Summary: &mpb.Summary{
|
||||
DataPoints: SummaryDataPoints(s.DataPoints),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
// SummaryDataPoints returns a slice of OTLP SummaryDataPoint generated from
|
||||
// dPts.
|
||||
func SummaryDataPoints(dPts []metricdata.SummaryDataPoint) []*mpb.SummaryDataPoint {
|
||||
out := make([]*mpb.SummaryDataPoint, 0, len(dPts))
|
||||
for _, dPt := range dPts {
|
||||
sdp := &mpb.SummaryDataPoint{
|
||||
Attributes: AttrIter(dPt.Attributes.Iter()),
|
||||
StartTimeUnixNano: timeUnixNano(dPt.StartTime),
|
||||
TimeUnixNano: timeUnixNano(dPt.Time),
|
||||
Count: dPt.Count,
|
||||
Sum: dPt.Sum,
|
||||
QuantileValues: QuantileValues(dPt.QuantileValues),
|
||||
}
|
||||
out = append(out, sdp)
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
||||
// QuantileValues returns a slice of OTLP SummaryDataPoint_ValueAtQuantile
|
||||
// generated from quantiles.
|
||||
func QuantileValues(quantiles []metricdata.QuantileValue) []*mpb.SummaryDataPoint_ValueAtQuantile {
|
||||
out := make([]*mpb.SummaryDataPoint_ValueAtQuantile, 0, len(quantiles))
|
||||
for _, q := range quantiles {
|
||||
quantile := &mpb.SummaryDataPoint_ValueAtQuantile{
|
||||
Quantile: q.Quantile,
|
||||
Value: q.Value,
|
||||
}
|
||||
out = append(out, quantile)
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
15
vendor/go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc/version.go
generated
vendored
15
vendor/go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc/version.go
generated
vendored
@@ -1,20 +1,9 @@
|
||||
// Copyright The OpenTelemetry Authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package otlpmetricgrpc // import "go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc"
|
||||
|
||||
// Version is the current release version of the OpenTelemetry OTLP over gRPC metrics exporter in use.
|
||||
func Version() string {
|
||||
return "0.44.0"
|
||||
return "1.31.0"
|
||||
}
|
||||
|
3
vendor/go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp/README.md
generated
vendored
Normal file
3
vendor/go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp/README.md
generated
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
# OTLP Metric HTTP Exporter
|
||||
|
||||
[](https://pkg.go.dev/go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp)
|
86
vendor/go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp/client.go
generated
vendored
86
vendor/go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp/client.go
generated
vendored
@@ -1,16 +1,5 @@
|
||||
// Copyright The OpenTelemetry Authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package otlpmetrichttp // import "go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp"
|
||||
|
||||
@@ -25,6 +14,7 @@ import (
|
||||
"net/http"
|
||||
"net/url"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
@@ -69,10 +59,17 @@ func newClient(cfg oconf.Config) (*client, error) {
|
||||
Transport: ourTransport,
|
||||
Timeout: cfg.Metrics.Timeout,
|
||||
}
|
||||
if cfg.Metrics.TLSCfg != nil {
|
||||
transport := ourTransport.Clone()
|
||||
transport.TLSClientConfig = cfg.Metrics.TLSCfg
|
||||
httpClient.Transport = transport
|
||||
|
||||
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
|
||||
}
|
||||
}
|
||||
|
||||
u := &url.URL{
|
||||
@@ -150,7 +147,7 @@ func (c *client) UploadMetrics(ctx context.Context, protoMetrics *metricpb.Resou
|
||||
resp, err := c.httpClient.Do(request.Request)
|
||||
var urlErr *url.Error
|
||||
if errors.As(err, &urlErr) && urlErr.Temporary() {
|
||||
return newResponseError(http.Header{})
|
||||
return newResponseError(http.Header{}, err)
|
||||
}
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -191,13 +188,25 @@ func (c *client) UploadMetrics(ctx context.Context, protoMetrics *metricpb.Resou
|
||||
sc == http.StatusServiceUnavailable,
|
||||
sc == http.StatusGatewayTimeout:
|
||||
// Retry-able failure.
|
||||
rErr = newResponseError(resp.Header)
|
||||
rErr = newResponseError(resp.Header, nil)
|
||||
|
||||
// Going to retry, drain the body to reuse the connection.
|
||||
if _, err := io.Copy(io.Discard, resp.Body); err != nil {
|
||||
// server may return a message with the response
|
||||
// body, so we read it to include in the error
|
||||
// message to be returned. It will help in
|
||||
// debugging the actual issue.
|
||||
var respData bytes.Buffer
|
||||
if _, err := io.Copy(&respData, resp.Body); err != nil {
|
||||
_ = resp.Body.Close()
|
||||
return err
|
||||
}
|
||||
|
||||
// overwrite the error message with the response body
|
||||
// if it is not empty
|
||||
if respStr := strings.TrimSpace(respData.String()); respStr != "" {
|
||||
// Include response for context.
|
||||
e := errors.New(respStr)
|
||||
rErr = newResponseError(resp.Header, e)
|
||||
}
|
||||
default:
|
||||
rErr = fmt.Errorf("failed to send metrics to %s: %s", request.URL, resp.Status)
|
||||
}
|
||||
@@ -238,7 +247,7 @@ func (c *client) newRequest(ctx context.Context, body []byte) (request, error) {
|
||||
if _, err := gz.Write(body); err != nil {
|
||||
return req, err
|
||||
}
|
||||
// Close needs to be called to ensure body if fully written.
|
||||
// Close needs to be called to ensure body is fully written.
|
||||
if err := gz.Close(); err != nil {
|
||||
return req, err
|
||||
}
|
||||
@@ -273,24 +282,50 @@ func (r *request) reset(ctx context.Context) {
|
||||
// retryableError represents a request failure that can be retried.
|
||||
type retryableError struct {
|
||||
throttle int64
|
||||
err error
|
||||
}
|
||||
|
||||
// newResponseError returns a retryableError and will extract any explicit
|
||||
// throttle delay contained in headers.
|
||||
func newResponseError(header http.Header) error {
|
||||
// throttle delay contained in headers. The returned error wraps wrapped
|
||||
// if it is not nil.
|
||||
func newResponseError(header http.Header, wrapped error) error {
|
||||
var rErr retryableError
|
||||
if v := header.Get("Retry-After"); v != "" {
|
||||
if t, err := strconv.ParseInt(v, 10, 64); err == nil {
|
||||
rErr.throttle = t
|
||||
}
|
||||
}
|
||||
|
||||
rErr.err = wrapped
|
||||
return rErr
|
||||
}
|
||||
|
||||
func (e retryableError) Error() string {
|
||||
if e.err != nil {
|
||||
return fmt.Sprintf("retry-able request failure: %s", e.err.Error())
|
||||
}
|
||||
|
||||
return "retry-able request failure"
|
||||
}
|
||||
|
||||
func (e retryableError) Unwrap() error {
|
||||
return e.err
|
||||
}
|
||||
|
||||
func (e retryableError) As(target interface{}) bool {
|
||||
if e.err == nil {
|
||||
return false
|
||||
}
|
||||
|
||||
switch v := target.(type) {
|
||||
case **retryableError:
|
||||
*v = &e
|
||||
return true
|
||||
default:
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
// evaluate returns if err is retry-able. If it is and it includes an explicit
|
||||
// throttling delay, that delay is also returned.
|
||||
func evaluate(err error) (bool, time.Duration) {
|
||||
@@ -298,7 +333,10 @@ func evaluate(err error) (bool, time.Duration) {
|
||||
return false, 0
|
||||
}
|
||||
|
||||
rErr, ok := err.(retryableError)
|
||||
// Do not use errors.As here, this should only be flattened one layer. If
|
||||
// there are several chained errors, all the errors above it will be
|
||||
// discarded if errors.As is used instead.
|
||||
rErr, ok := err.(retryableError) //nolint:errorlint
|
||||
if !ok {
|
||||
return false, 0
|
||||
}
|
||||
|
53
vendor/go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp/config.go
generated
vendored
53
vendor/go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp/config.go
generated
vendored
@@ -1,21 +1,12 @@
|
||||
// Copyright The OpenTelemetry Authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package otlpmetrichttp // import "go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp"
|
||||
|
||||
import (
|
||||
"crypto/tls"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"time"
|
||||
|
||||
"go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp/internal/oconf"
|
||||
@@ -27,6 +18,11 @@ import (
|
||||
// collector.
|
||||
type Compression oconf.Compression
|
||||
|
||||
// HTTPTransportProxyFunc is a function that resolves which URL to use as proxy for a given request.
|
||||
// This type is compatible with http.Transport.Proxy and can be used to set a custom proxy function
|
||||
// to the OTLP HTTP client.
|
||||
type HTTPTransportProxyFunc func(*http.Request) (*url.URL, error)
|
||||
|
||||
const (
|
||||
// NoCompression tells the driver to send payloads without
|
||||
// compression.
|
||||
@@ -67,8 +63,9 @@ func (w wrappedOption) applyHTTPOption(cfg oconf.Config) oconf.Config {
|
||||
//
|
||||
// If the OTEL_EXPORTER_OTLP_ENDPOINT or OTEL_EXPORTER_OTLP_METRICS_ENDPOINT
|
||||
// environment variable is set, and this option is not passed, that variable
|
||||
// value will be used. If both are set, OTEL_EXPORTER_OTLP_METRICS_ENDPOINT
|
||||
// will take precedence.
|
||||
// value will be used. If both environment variables are set,
|
||||
// OTEL_EXPORTER_OTLP_METRICS_ENDPOINT will take precedence. If an environment
|
||||
// variable is set, and this option is passed, this option will take precedence.
|
||||
//
|
||||
// By default, if an environment variable is not set, and this option is not
|
||||
// passed, "localhost:4318" will be used.
|
||||
@@ -76,6 +73,27 @@ func WithEndpoint(endpoint string) Option {
|
||||
return wrappedOption{oconf.WithEndpoint(endpoint)}
|
||||
}
|
||||
|
||||
// WithEndpointURL sets the target endpoint URL the Exporter will connect to.
|
||||
//
|
||||
// If the OTEL_EXPORTER_OTLP_ENDPOINT or OTEL_EXPORTER_OTLP_METRICS_ENDPOINT
|
||||
// environment variable is set, and this option is not passed, that variable
|
||||
// value will be used. If both environment variables are set,
|
||||
// OTEL_EXPORTER_OTLP_METRICS_ENDPOINT will take precedence. If an environment
|
||||
// variable is set, and this option is passed, this option will take precedence.
|
||||
//
|
||||
// If both this option and WithEndpoint are used, the last used option will
|
||||
// take precedence.
|
||||
//
|
||||
// If an invalid URL is provided, the default value will be kept.
|
||||
//
|
||||
// By default, if an environment variable is not set, and this option is not
|
||||
// passed, "localhost:4318" will be used.
|
||||
//
|
||||
// This option has no effect if WithGRPCConn is used.
|
||||
func WithEndpointURL(u string) Option {
|
||||
return wrappedOption{oconf.WithEndpointURL(u)}
|
||||
}
|
||||
|
||||
// WithCompression sets the compression strategy the Exporter will use to
|
||||
// compress the HTTP body.
|
||||
//
|
||||
@@ -197,3 +215,10 @@ func WithTemporalitySelector(selector metric.TemporalitySelector) Option {
|
||||
func WithAggregationSelector(selector metric.AggregationSelector) Option {
|
||||
return wrappedOption{oconf.WithAggregationSelector(selector)}
|
||||
}
|
||||
|
||||
// WithProxy sets the Proxy function the client will use to determine the
|
||||
// proxy to use for an HTTP request. If this option is not used, the client
|
||||
// will use [http.ProxyFromEnvironment].
|
||||
func WithProxy(pf HTTPTransportProxyFunc) Option {
|
||||
return wrappedOption{oconf.WithProxy(oconf.HTTPTransportProxyFunc(pf))}
|
||||
}
|
||||
|
23
vendor/go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp/doc.go
generated
vendored
23
vendor/go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp/doc.go
generated
vendored
@@ -1,16 +1,5 @@
|
||||
// Copyright The OpenTelemetry Authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
/*
|
||||
Package otlpmetrichttp provides an OTLP metrics exporter using HTTP with protobuf payloads.
|
||||
@@ -26,18 +15,18 @@ The value must contain a scheme ("http" or "https") and host.
|
||||
The value may additionally contain a port and a path.
|
||||
The value should not contain a query string or fragment.
|
||||
The configuration can be overridden by OTEL_EXPORTER_OTLP_METRICS_ENDPOINT
|
||||
environment variable and by [WithEndpoint], [WithInsecure] options.
|
||||
environment variable and by [WithEndpoint], [WithEndpointURL], and [WithInsecure] options.
|
||||
|
||||
OTEL_EXPORTER_OTLP_METRICS_ENDPOINT (default: "https://localhost:4318/v1/metrics") -
|
||||
target URL to which the exporter sends telemetry.
|
||||
The value must contain a scheme ("http" or "https") and host.
|
||||
The value may additionally contain a port and a path.
|
||||
The value should not contain a query string or fragment.
|
||||
The configuration can be overridden by [WithEndpoint], [WitnInsecure], [WithURLPath] options.
|
||||
The configuration can be overridden by [WithEndpoint], [WithEndpointURL], [WithInsecure], and [WithURLPath] options.
|
||||
|
||||
OTEL_EXPORTER_OTLP_HEADERS, OTEL_EXPORTER_OTLP_METRICS_HEADERS (default: none) -
|
||||
key-value pairs used as headers associated with HTTP requests.
|
||||
The value is expected to be represented in a format matching to the [W3C Baggage HTTP Header Content Format],
|
||||
The value is expected to be represented in a format matching the [W3C Baggage HTTP Header Content Format],
|
||||
except that additional semi-colon delimited metadata is not supported.
|
||||
Example value: "key1=value1,key2=value2".
|
||||
OTEL_EXPORTER_OTLP_METRICS_HEADERS takes precedence over OTEL_EXPORTER_OTLP_HEADERS.
|
||||
@@ -60,12 +49,12 @@ OTEL_EXPORTER_OTLP_METRICS_CERTIFICATE takes precedence over OTEL_EXPORTER_OTLP_
|
||||
The configuration can be overridden by [WithTLSClientConfig] option.
|
||||
|
||||
OTEL_EXPORTER_OTLP_CLIENT_CERTIFICATE, OTEL_EXPORTER_OTLP_METRICS_CLIENT_CERTIFICATE (default: none) -
|
||||
filepath to the client certificate/chain trust for clients private key to use in mTLS communication in PEM format.
|
||||
filepath to the client certificate/chain trust for client's private key to use in mTLS communication in PEM format.
|
||||
OTEL_EXPORTER_OTLP_METRICS_CLIENT_CERTIFICATE takes precedence over OTEL_EXPORTER_OTLP_CLIENT_CERTIFICATE.
|
||||
The configuration can be overridden by [WithTLSClientConfig] option.
|
||||
|
||||
OTEL_EXPORTER_OTLP_CLIENT_KEY, OTEL_EXPORTER_OTLP_METRICS_CLIENT_KEY (default: none) -
|
||||
filepath to the clients private key to use in mTLS communication in PEM format.
|
||||
filepath to the client's private key to use in mTLS communication in PEM format.
|
||||
OTEL_EXPORTER_OTLP_METRICS_CLIENT_KEY takes precedence over OTEL_EXPORTER_OTLP_CLIENT_KEY.
|
||||
The configuration can be overridden by [WithTLSClientConfig] option.
|
||||
|
||||
|
15
vendor/go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp/exporter.go
generated
vendored
15
vendor/go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp/exporter.go
generated
vendored
@@ -1,16 +1,5 @@
|
||||
// Copyright The OpenTelemetry Authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package otlpmetrichttp // import "go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp"
|
||||
|
||||
@@ -90,7 +79,7 @@ func (e *Exporter) Export(ctx context.Context, rm *metricdata.ResourceMetrics) e
|
||||
return fmt.Errorf("failed to upload metrics: %w", upErr)
|
||||
}
|
||||
// Merge the two errors.
|
||||
return fmt.Errorf("failed to upload incomplete metrics (%s): %w", err, upErr)
|
||||
return fmt.Errorf("failed to upload incomplete metrics (%w): %w", err, upErr)
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
@@ -2,18 +2,7 @@
|
||||
// source: internal/shared/otlp/envconfig/envconfig.go.tmpl
|
||||
|
||||
// Copyright The OpenTelemetry Authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package envconfig // import "go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp/internal/envconfig"
|
||||
|
||||
@@ -26,6 +15,7 @@ import (
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
"unicode"
|
||||
|
||||
"go.opentelemetry.io/otel/internal/global"
|
||||
)
|
||||
@@ -174,12 +164,16 @@ func stringToHeader(value string) map[string]string {
|
||||
global.Error(errors.New("missing '="), "parse headers", "input", header)
|
||||
continue
|
||||
}
|
||||
name, err := url.PathUnescape(n)
|
||||
if err != nil {
|
||||
global.Error(err, "escape header key", "key", n)
|
||||
|
||||
trimmedName := strings.TrimSpace(n)
|
||||
|
||||
// Validate the key.
|
||||
if !isValidHeaderKey(trimmedName) {
|
||||
global.Error(errors.New("invalid header key"), "parse headers", "key", trimmedName)
|
||||
continue
|
||||
}
|
||||
trimmedName := strings.TrimSpace(name)
|
||||
|
||||
// Only decode the value.
|
||||
value, err := url.PathUnescape(v)
|
||||
if err != nil {
|
||||
global.Error(err, "escape header value", "value", v)
|
||||
@@ -200,3 +194,22 @@ func createCertPool(certBytes []byte) (*x509.CertPool, error) {
|
||||
}
|
||||
return cp, nil
|
||||
}
|
||||
|
||||
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 == '~')
|
||||
}
|
||||
|
13
vendor/go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp/internal/gen.go
generated
vendored
13
vendor/go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp/internal/gen.go
generated
vendored
@@ -1,16 +1,5 @@
|
||||
// Copyright The OpenTelemetry Authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package internal // import "go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp/internal"
|
||||
|
||||
|
@@ -2,18 +2,7 @@
|
||||
// source: internal/shared/otlp/otlpmetric/oconf/envconfig.go.tmpl
|
||||
|
||||
// Copyright The OpenTelemetry Authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package oconf // import "go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp/internal/oconf"
|
||||
|
||||
|
@@ -2,24 +2,15 @@
|
||||
// source: internal/shared/otlp/otlpmetric/oconf/options.go.tmpl
|
||||
|
||||
// Copyright The OpenTelemetry Authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package oconf // import "go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp/internal/oconf"
|
||||
|
||||
import (
|
||||
"crypto/tls"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"path"
|
||||
"strings"
|
||||
"time"
|
||||
@@ -31,6 +22,7 @@ import (
|
||||
"google.golang.org/grpc/encoding/gzip"
|
||||
|
||||
"go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp/internal/retry"
|
||||
"go.opentelemetry.io/otel/internal/global"
|
||||
"go.opentelemetry.io/otel/sdk/metric"
|
||||
)
|
||||
|
||||
@@ -51,6 +43,10 @@ const (
|
||||
)
|
||||
|
||||
type (
|
||||
// HTTPTransportProxyFunc is a function that resolves which URL to use as proxy for a given request.
|
||||
// This type is compatible with `http.Transport.Proxy` and can be used to set a custom proxy function to the OTLP HTTP client.
|
||||
HTTPTransportProxyFunc func(*http.Request) (*url.URL, error)
|
||||
|
||||
SignalConfig struct {
|
||||
Endpoint string
|
||||
Insecure bool
|
||||
@@ -65,6 +61,8 @@ type (
|
||||
|
||||
TemporalitySelector metric.TemporalitySelector
|
||||
AggregationSelector metric.AggregationSelector
|
||||
|
||||
Proxy HTTPTransportProxyFunc
|
||||
}
|
||||
|
||||
Config struct {
|
||||
@@ -141,7 +139,7 @@ func NewGRPCConfig(opts ...GRPCOption) Config {
|
||||
if cfg.ServiceConfig != "" {
|
||||
cfg.DialOptions = append(cfg.DialOptions, grpc.WithDefaultServiceConfig(cfg.ServiceConfig))
|
||||
}
|
||||
// Priroritize GRPCCredentials over Insecure (passing both is an error).
|
||||
// Prioritize GRPCCredentials over Insecure (passing both is an error).
|
||||
if cfg.Metrics.GRPCCredentials != nil {
|
||||
cfg.DialOptions = append(cfg.DialOptions, grpc.WithTransportCredentials(cfg.Metrics.GRPCCredentials))
|
||||
} else if cfg.Metrics.Insecure {
|
||||
@@ -279,6 +277,24 @@ func WithEndpoint(endpoint string) GenericOption {
|
||||
})
|
||||
}
|
||||
|
||||
func WithEndpointURL(v string) GenericOption {
|
||||
return newGenericOption(func(cfg Config) Config {
|
||||
u, err := url.Parse(v)
|
||||
if err != nil {
|
||||
global.Error(err, "otlpmetric: parse endpoint url", "url", v)
|
||||
return cfg
|
||||
}
|
||||
|
||||
cfg.Metrics.Endpoint = u.Host
|
||||
cfg.Metrics.URLPath = u.Path
|
||||
if u.Scheme != "https" {
|
||||
cfg.Metrics.Insecure = true
|
||||
}
|
||||
|
||||
return cfg
|
||||
})
|
||||
}
|
||||
|
||||
func WithCompression(compression Compression) GenericOption {
|
||||
return newGenericOption(func(cfg Config) Config {
|
||||
cfg.Metrics.Compression = compression
|
||||
@@ -351,3 +367,10 @@ func WithAggregationSelector(selector metric.AggregationSelector) GenericOption
|
||||
return cfg
|
||||
})
|
||||
}
|
||||
|
||||
func WithProxy(pf HTTPTransportProxyFunc) GenericOption {
|
||||
return newGenericOption(func(cfg Config) Config {
|
||||
cfg.Metrics.Proxy = pf
|
||||
return cfg
|
||||
})
|
||||
}
|
||||
|
@@ -2,18 +2,7 @@
|
||||
// source: internal/shared/otlp/otlpmetric/oconf/optiontypes.go.tmpl
|
||||
|
||||
// Copyright The OpenTelemetry Authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package oconf // import "go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp/internal/oconf"
|
||||
|
||||
|
@@ -2,18 +2,7 @@
|
||||
// source: internal/shared/otlp/otlpmetric/oconf/tls.go.tmpl
|
||||
|
||||
// Copyright The OpenTelemetry Authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package oconf // import "go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp/internal/oconf"
|
||||
|
||||
@@ -25,7 +14,7 @@ import (
|
||||
)
|
||||
|
||||
// ReadTLSConfigFromFile reads a PEM certificate file and creates
|
||||
// a tls.Config that will use this certifate to verify a server certificate.
|
||||
// a tls.Config that will use this certificate to verify a server certificate.
|
||||
func ReadTLSConfigFromFile(path string) (*tls.Config, error) {
|
||||
b, err := os.ReadFile(path)
|
||||
if err != nil {
|
||||
|
@@ -2,18 +2,7 @@
|
||||
// source: internal/shared/otlp/partialsuccess.go
|
||||
|
||||
// Copyright The OpenTelemetry Authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package internal // import "go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp/internal"
|
||||
|
||||
|
@@ -2,18 +2,7 @@
|
||||
// source: internal/shared/otlp/retry/retry.go.tmpl
|
||||
|
||||
// Copyright The OpenTelemetry Authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
// Package retry provides request retry functionality that can perform
|
||||
// configurable exponential backoff for transient errors and honor any
|
||||
@@ -123,7 +112,7 @@ func (c Config) RequestFunc(evaluate EvaluateFunc) RequestFunc {
|
||||
}
|
||||
|
||||
if ctxErr := waitFunc(ctx, delay); ctxErr != nil {
|
||||
return fmt.Errorf("%w: %s", ctxErr, err)
|
||||
return fmt.Errorf("%w: %w", ctxErr, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -2,18 +2,7 @@
|
||||
// source: internal/shared/otlp/otlpmetric/transform/attribute.go.tmpl
|
||||
|
||||
// Copyright The OpenTelemetry Authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package transform // import "go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp/internal/transform"
|
||||
|
||||
|
@@ -2,18 +2,7 @@
|
||||
// source: internal/shared/otlp/otlpmetric/transform/error.go.tmpl
|
||||
|
||||
// Copyright The OpenTelemetry Authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package transform // import "go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp/internal/transform"
|
||||
|
||||
@@ -69,7 +58,7 @@ func (e *multiErr) append(err error) {
|
||||
// Do not use errors.As here, this should only be flattened one layer. If
|
||||
// there is a *multiErr several steps down the chain, all the errors above
|
||||
// it will be discarded if errors.As is used instead.
|
||||
switch other := err.(type) {
|
||||
switch other := err.(type) { //nolint:errorlint
|
||||
case *multiErr:
|
||||
// Flatten err errors into e.
|
||||
e.errs = append(e.errs, other.errs...)
|
||||
|
@@ -2,18 +2,7 @@
|
||||
// source: internal/shared/otlp/otlpmetric/transform/metricdata.go.tmpl
|
||||
|
||||
// Copyright The OpenTelemetry Authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
// Package transform provides transformation functionality from the
|
||||
// sdk/metric/metricdata data-types into OTLP data-types.
|
||||
@@ -90,7 +79,7 @@ func metric(m metricdata.Metrics) (*mpb.Metric, error) {
|
||||
out := &mpb.Metric{
|
||||
Name: m.Name,
|
||||
Description: m.Description,
|
||||
Unit: string(m.Unit),
|
||||
Unit: m.Unit,
|
||||
}
|
||||
switch a := m.Data.(type) {
|
||||
case metricdata.Gauge[int64]:
|
||||
@@ -109,6 +98,8 @@ func metric(m metricdata.Metrics) (*mpb.Metric, error) {
|
||||
out.Data, err = ExponentialHistogram(a)
|
||||
case metricdata.ExponentialHistogram[float64]:
|
||||
out.Data, err = ExponentialHistogram(a)
|
||||
case metricdata.Summary:
|
||||
out.Data = Summary(a)
|
||||
default:
|
||||
return out, fmt.Errorf("%w: %T", errUnknownAggregation, a)
|
||||
}
|
||||
@@ -148,6 +139,7 @@ func DataPoints[N int64 | float64](dPts []metricdata.DataPoint[N]) []*mpb.Number
|
||||
Attributes: AttrIter(dPt.Attributes.Iter()),
|
||||
StartTimeUnixNano: timeUnixNano(dPt.StartTime),
|
||||
TimeUnixNano: timeUnixNano(dPt.Time),
|
||||
Exemplars: Exemplars(dPt.Exemplars),
|
||||
}
|
||||
switch v := any(dPt.Value).(type) {
|
||||
case int64:
|
||||
@@ -193,6 +185,7 @@ func HistogramDataPoints[N int64 | float64](dPts []metricdata.HistogramDataPoint
|
||||
Sum: &sum,
|
||||
BucketCounts: dPt.BucketCounts,
|
||||
ExplicitBounds: dPt.Bounds,
|
||||
Exemplars: Exemplars(dPt.Exemplars),
|
||||
}
|
||||
if v, ok := dPt.Min.Value(); ok {
|
||||
vF64 := float64(v)
|
||||
@@ -236,6 +229,7 @@ func ExponentialHistogramDataPoints[N int64 | float64](dPts []metricdata.Exponen
|
||||
Sum: &sum,
|
||||
Scale: dPt.Scale,
|
||||
ZeroCount: dPt.ZeroCount,
|
||||
Exemplars: Exemplars(dPt.Exemplars),
|
||||
|
||||
Positive: ExponentialHistogramDataPointBuckets(dPt.PositiveBucket),
|
||||
Negative: ExponentialHistogramDataPointBuckets(dPt.NegativeBucket),
|
||||
@@ -285,8 +279,71 @@ func Temporality(t metricdata.Temporality) (mpb.AggregationTemporality, error) {
|
||||
// timeUnixNano on the zero Time returns 0.
|
||||
// The result does not depend on the location associated with t.
|
||||
func timeUnixNano(t time.Time) uint64 {
|
||||
if t.IsZero() {
|
||||
return 0
|
||||
}
|
||||
return uint64(t.UnixNano())
|
||||
return uint64(max(0, t.UnixNano())) // nolint:gosec // Overflow checked.
|
||||
}
|
||||
|
||||
// Exemplars returns a slice of OTLP Exemplars generated from exemplars.
|
||||
func Exemplars[N int64 | float64](exemplars []metricdata.Exemplar[N]) []*mpb.Exemplar {
|
||||
out := make([]*mpb.Exemplar, 0, len(exemplars))
|
||||
for _, exemplar := range exemplars {
|
||||
e := &mpb.Exemplar{
|
||||
FilteredAttributes: KeyValues(exemplar.FilteredAttributes),
|
||||
TimeUnixNano: timeUnixNano(exemplar.Time),
|
||||
SpanId: exemplar.SpanID,
|
||||
TraceId: exemplar.TraceID,
|
||||
}
|
||||
switch v := any(exemplar.Value).(type) {
|
||||
case int64:
|
||||
e.Value = &mpb.Exemplar_AsInt{
|
||||
AsInt: v,
|
||||
}
|
||||
case float64:
|
||||
e.Value = &mpb.Exemplar_AsDouble{
|
||||
AsDouble: v,
|
||||
}
|
||||
}
|
||||
out = append(out, e)
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
||||
// Summary returns an OTLP Metric_Summary generated from s.
|
||||
func Summary(s metricdata.Summary) *mpb.Metric_Summary {
|
||||
return &mpb.Metric_Summary{
|
||||
Summary: &mpb.Summary{
|
||||
DataPoints: SummaryDataPoints(s.DataPoints),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
// SummaryDataPoints returns a slice of OTLP SummaryDataPoint generated from
|
||||
// dPts.
|
||||
func SummaryDataPoints(dPts []metricdata.SummaryDataPoint) []*mpb.SummaryDataPoint {
|
||||
out := make([]*mpb.SummaryDataPoint, 0, len(dPts))
|
||||
for _, dPt := range dPts {
|
||||
sdp := &mpb.SummaryDataPoint{
|
||||
Attributes: AttrIter(dPt.Attributes.Iter()),
|
||||
StartTimeUnixNano: timeUnixNano(dPt.StartTime),
|
||||
TimeUnixNano: timeUnixNano(dPt.Time),
|
||||
Count: dPt.Count,
|
||||
Sum: dPt.Sum,
|
||||
QuantileValues: QuantileValues(dPt.QuantileValues),
|
||||
}
|
||||
out = append(out, sdp)
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
||||
// QuantileValues returns a slice of OTLP SummaryDataPoint_ValueAtQuantile
|
||||
// generated from quantiles.
|
||||
func QuantileValues(quantiles []metricdata.QuantileValue) []*mpb.SummaryDataPoint_ValueAtQuantile {
|
||||
out := make([]*mpb.SummaryDataPoint_ValueAtQuantile, 0, len(quantiles))
|
||||
for _, q := range quantiles {
|
||||
quantile := &mpb.SummaryDataPoint_ValueAtQuantile{
|
||||
Quantile: q.Quantile,
|
||||
Value: q.Value,
|
||||
}
|
||||
out = append(out, quantile)
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
15
vendor/go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp/version.go
generated
vendored
15
vendor/go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp/version.go
generated
vendored
@@ -1,20 +1,9 @@
|
||||
// Copyright The OpenTelemetry Authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package otlpmetrichttp // import "go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp"
|
||||
|
||||
// Version is the current release version of the OpenTelemetry OTLP over HTTP/protobuf metrics exporter in use.
|
||||
func Version() string {
|
||||
return "0.44.0"
|
||||
return "1.31.0"
|
||||
}
|
||||
|
30
vendor/go.opentelemetry.io/otel/exporters/otlp/otlptrace/internal/tracetransform/span.go
generated
vendored
30
vendor/go.opentelemetry.io/otel/exporters/otlp/otlptrace/internal/tracetransform/span.go
generated
vendored
@@ -4,6 +4,8 @@
|
||||
package tracetransform // import "go.opentelemetry.io/otel/exporters/otlp/otlptrace/internal/tracetransform"
|
||||
|
||||
import (
|
||||
"math"
|
||||
|
||||
"go.opentelemetry.io/otel/attribute"
|
||||
"go.opentelemetry.io/otel/codes"
|
||||
"go.opentelemetry.io/otel/sdk/instrumentation"
|
||||
@@ -95,16 +97,16 @@ func span(sd tracesdk.ReadOnlySpan) *tracepb.Span {
|
||||
SpanId: sid[:],
|
||||
TraceState: sd.SpanContext().TraceState().String(),
|
||||
Status: status(sd.Status().Code, sd.Status().Description),
|
||||
StartTimeUnixNano: uint64(sd.StartTime().UnixNano()),
|
||||
EndTimeUnixNano: uint64(sd.EndTime().UnixNano()),
|
||||
StartTimeUnixNano: uint64(max(0, sd.StartTime().UnixNano())), // nolint:gosec // Overflow checked.
|
||||
EndTimeUnixNano: uint64(max(0, sd.EndTime().UnixNano())), // nolint:gosec // Overflow checked.
|
||||
Links: links(sd.Links()),
|
||||
Kind: spanKind(sd.SpanKind()),
|
||||
Name: sd.Name(),
|
||||
Attributes: KeyValues(sd.Attributes()),
|
||||
Events: spanEvents(sd.Events()),
|
||||
DroppedAttributesCount: uint32(sd.DroppedAttributes()),
|
||||
DroppedEventsCount: uint32(sd.DroppedEvents()),
|
||||
DroppedLinksCount: uint32(sd.DroppedLinks()),
|
||||
DroppedAttributesCount: clampUint32(sd.DroppedAttributes()),
|
||||
DroppedEventsCount: clampUint32(sd.DroppedEvents()),
|
||||
DroppedLinksCount: clampUint32(sd.DroppedLinks()),
|
||||
}
|
||||
|
||||
if psid := sd.Parent().SpanID(); psid.IsValid() {
|
||||
@@ -115,6 +117,16 @@ func span(sd tracesdk.ReadOnlySpan) *tracepb.Span {
|
||||
return s
|
||||
}
|
||||
|
||||
func clampUint32(v int) uint32 {
|
||||
if v < 0 {
|
||||
return 0
|
||||
}
|
||||
if int64(v) > math.MaxUint32 {
|
||||
return math.MaxUint32
|
||||
}
|
||||
return uint32(v) // nolint: gosec // Overflow/Underflow checked.
|
||||
}
|
||||
|
||||
// status transform a span code and message into an OTLP span status.
|
||||
func status(status codes.Code, message string) *tracepb.Status {
|
||||
var c tracepb.Status_StatusCode
|
||||
@@ -153,7 +165,7 @@ func links(links []tracesdk.Link) []*tracepb.Span_Link {
|
||||
TraceId: tid[:],
|
||||
SpanId: sid[:],
|
||||
Attributes: KeyValues(otLink.Attributes),
|
||||
DroppedAttributesCount: uint32(otLink.DroppedAttributeCount),
|
||||
DroppedAttributesCount: clampUint32(otLink.DroppedAttributeCount),
|
||||
Flags: flags,
|
||||
})
|
||||
}
|
||||
@@ -166,7 +178,7 @@ func buildSpanFlags(sc trace.SpanContext) uint32 {
|
||||
flags |= tracepb.SpanFlags_SPAN_FLAGS_CONTEXT_IS_REMOTE_MASK
|
||||
}
|
||||
|
||||
return uint32(flags)
|
||||
return uint32(flags) // nolint:gosec // Flags is a bitmask and can't be negative
|
||||
}
|
||||
|
||||
// spanEvents transforms span Events to an OTLP span events.
|
||||
@@ -180,9 +192,9 @@ func spanEvents(es []tracesdk.Event) []*tracepb.Span_Event {
|
||||
for i := 0; i < len(es); i++ {
|
||||
events[i] = &tracepb.Span_Event{
|
||||
Name: es[i].Name,
|
||||
TimeUnixNano: uint64(es[i].Time.UnixNano()),
|
||||
TimeUnixNano: uint64(max(0, es[i].Time.UnixNano())), // nolint:gosec // Overflow checked.
|
||||
Attributes: KeyValues(es[i].Attributes),
|
||||
DroppedAttributesCount: uint32(es[i].DroppedAttributeCount),
|
||||
DroppedAttributesCount: clampUint32(es[i].DroppedAttributeCount),
|
||||
}
|
||||
}
|
||||
return events
|
||||
|
5
vendor/go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc/doc.go
generated
vendored
5
vendor/go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc/doc.go
generated
vendored
@@ -12,9 +12,8 @@ The environment variables described below can be used for configuration.
|
||||
OTEL_EXPORTER_OTLP_ENDPOINT, OTEL_EXPORTER_OTLP_TRACES_ENDPOINT (default: "https://localhost:4317") -
|
||||
target to which the exporter sends telemetry.
|
||||
The target syntax is defined in https://github.com/grpc/grpc/blob/master/doc/naming.md.
|
||||
The value must contain a host.
|
||||
The value may additionally a port, a scheme, and a path.
|
||||
The value accepts "http" and "https" scheme.
|
||||
The value must contain a scheme ("http" or "https") and host.
|
||||
The value may additionally contain a port, and a path.
|
||||
The value should not contain a query string or fragment.
|
||||
OTEL_EXPORTER_OTLP_TRACES_ENDPOINT takes precedence over OTEL_EXPORTER_OTLP_ENDPOINT.
|
||||
The configuration can be overridden by [WithEndpoint], [WithEndpointURL], [WithInsecure], and [WithGRPCConn] options.
|
||||
|
@@ -15,6 +15,7 @@ import (
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
"unicode"
|
||||
|
||||
"go.opentelemetry.io/otel/internal/global"
|
||||
)
|
||||
@@ -163,12 +164,16 @@ func stringToHeader(value string) map[string]string {
|
||||
global.Error(errors.New("missing '="), "parse headers", "input", header)
|
||||
continue
|
||||
}
|
||||
name, err := url.PathUnescape(n)
|
||||
if err != nil {
|
||||
global.Error(err, "escape header key", "key", n)
|
||||
|
||||
trimmedName := strings.TrimSpace(n)
|
||||
|
||||
// Validate the key.
|
||||
if !isValidHeaderKey(trimmedName) {
|
||||
global.Error(errors.New("invalid header key"), "parse headers", "key", trimmedName)
|
||||
continue
|
||||
}
|
||||
trimmedName := strings.TrimSpace(name)
|
||||
|
||||
// Only decode the value.
|
||||
value, err := url.PathUnescape(v)
|
||||
if err != nil {
|
||||
global.Error(err, "escape header value", "value", v)
|
||||
@@ -189,3 +194,22 @@ func createCertPool(certBytes []byte) (*x509.CertPool, error) {
|
||||
}
|
||||
return cp, nil
|
||||
}
|
||||
|
||||
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 == '~')
|
||||
}
|
||||
|
@@ -125,7 +125,7 @@ func NewGRPCConfig(opts ...GRPCOption) Config {
|
||||
if cfg.ServiceConfig != "" {
|
||||
cfg.DialOptions = append(cfg.DialOptions, grpc.WithDefaultServiceConfig(cfg.ServiceConfig))
|
||||
}
|
||||
// Priroritize GRPCCredentials over Insecure (passing both is an error).
|
||||
// Prioritize GRPCCredentials over Insecure (passing both is an error).
|
||||
if cfg.Traces.GRPCCredentials != nil {
|
||||
cfg.DialOptions = append(cfg.DialOptions, grpc.WithTransportCredentials(cfg.Traces.GRPCCredentials))
|
||||
} else if cfg.Traces.Insecure {
|
||||
|
57
vendor/go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp/client.go
generated
vendored
57
vendor/go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp/client.go
generated
vendored
@@ -14,6 +14,7 @@ import (
|
||||
"net/http"
|
||||
"net/url"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
@@ -151,7 +152,7 @@ func (d *client) UploadTraces(ctx context.Context, protoSpans []*tracepb.Resourc
|
||||
resp, err := d.client.Do(request.Request)
|
||||
var urlErr *url.Error
|
||||
if errors.As(err, &urlErr) && urlErr.Temporary() {
|
||||
return newResponseError(http.Header{})
|
||||
return newResponseError(http.Header{}, err)
|
||||
}
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -198,11 +199,27 @@ func (d *client) UploadTraces(ctx context.Context, protoSpans []*tracepb.Resourc
|
||||
sc == http.StatusBadGateway,
|
||||
sc == http.StatusServiceUnavailable,
|
||||
sc == http.StatusGatewayTimeout:
|
||||
// Retry-able failures. Drain the body to reuse the connection.
|
||||
if _, err := io.Copy(io.Discard, resp.Body); err != nil {
|
||||
otel.Handle(err)
|
||||
// Retry-able failures.
|
||||
rErr := newResponseError(resp.Header, nil)
|
||||
|
||||
// server may return a message with the response
|
||||
// body, so we read it to include in the error
|
||||
// message to be returned. It will help in
|
||||
// debugging the actual issue.
|
||||
var respData bytes.Buffer
|
||||
if _, err := io.Copy(&respData, resp.Body); err != nil {
|
||||
_ = resp.Body.Close()
|
||||
return err
|
||||
}
|
||||
return newResponseError(resp.Header)
|
||||
|
||||
// overwrite the error message with the response body
|
||||
// if it is not empty
|
||||
if respStr := strings.TrimSpace(respData.String()); respStr != "" {
|
||||
// Include response for context.
|
||||
e := errors.New(respStr)
|
||||
rErr = newResponseError(resp.Header, e)
|
||||
}
|
||||
return rErr
|
||||
default:
|
||||
return fmt.Errorf("failed to send to %s: %s", request.URL, resp.Status)
|
||||
}
|
||||
@@ -291,24 +308,50 @@ func (r *request) reset(ctx context.Context) {
|
||||
// retryableError represents a request failure that can be retried.
|
||||
type retryableError struct {
|
||||
throttle int64
|
||||
err error
|
||||
}
|
||||
|
||||
// newResponseError returns a retryableError and will extract any explicit
|
||||
// throttle delay contained in headers.
|
||||
func newResponseError(header http.Header) error {
|
||||
// throttle delay contained in headers. The returned error wraps wrapped
|
||||
// if it is not nil.
|
||||
func newResponseError(header http.Header, wrapped error) error {
|
||||
var rErr retryableError
|
||||
if s, ok := header["Retry-After"]; ok {
|
||||
if t, err := strconv.ParseInt(s[0], 10, 64); err == nil {
|
||||
rErr.throttle = t
|
||||
}
|
||||
}
|
||||
|
||||
rErr.err = wrapped
|
||||
return rErr
|
||||
}
|
||||
|
||||
func (e retryableError) Error() string {
|
||||
if e.err != nil {
|
||||
return fmt.Sprintf("retry-able request failure: %s", e.err.Error())
|
||||
}
|
||||
|
||||
return "retry-able request failure"
|
||||
}
|
||||
|
||||
func (e retryableError) Unwrap() error {
|
||||
return e.err
|
||||
}
|
||||
|
||||
func (e retryableError) As(target interface{}) bool {
|
||||
if e.err == nil {
|
||||
return false
|
||||
}
|
||||
|
||||
switch v := target.(type) {
|
||||
case **retryableError:
|
||||
*v = &e
|
||||
return true
|
||||
default:
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
// evaluate returns if err is retry-able. If it is and it includes an explicit
|
||||
// throttling delay, that delay is also returned.
|
||||
func evaluate(err error) (bool, time.Duration) {
|
||||
|
2
vendor/go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp/doc.go
generated
vendored
2
vendor/go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp/doc.go
generated
vendored
@@ -22,7 +22,7 @@ target URL to which the exporter sends telemetry.
|
||||
The value must contain a scheme ("http" or "https") and host.
|
||||
The value may additionally contain a port and a path.
|
||||
The value should not contain a query string or fragment.
|
||||
The configuration can be overridden by [WithEndpoint], [WithEndpointURL], [WitnInsecure], and [WithURLPath] options.
|
||||
The configuration can be overridden by [WithEndpoint], [WithEndpointURL], [WithInsecure], and [WithURLPath] options.
|
||||
|
||||
OTEL_EXPORTER_OTLP_HEADERS, OTEL_EXPORTER_OTLP_TRACES_HEADERS (default: none) -
|
||||
key-value pairs used as headers associated with HTTP requests.
|
||||
|
@@ -15,6 +15,7 @@ import (
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
"unicode"
|
||||
|
||||
"go.opentelemetry.io/otel/internal/global"
|
||||
)
|
||||
@@ -163,12 +164,16 @@ func stringToHeader(value string) map[string]string {
|
||||
global.Error(errors.New("missing '="), "parse headers", "input", header)
|
||||
continue
|
||||
}
|
||||
name, err := url.PathUnescape(n)
|
||||
if err != nil {
|
||||
global.Error(err, "escape header key", "key", n)
|
||||
|
||||
trimmedName := strings.TrimSpace(n)
|
||||
|
||||
// Validate the key.
|
||||
if !isValidHeaderKey(trimmedName) {
|
||||
global.Error(errors.New("invalid header key"), "parse headers", "key", trimmedName)
|
||||
continue
|
||||
}
|
||||
trimmedName := strings.TrimSpace(name)
|
||||
|
||||
// Only decode the value.
|
||||
value, err := url.PathUnescape(v)
|
||||
if err != nil {
|
||||
global.Error(err, "escape header value", "value", v)
|
||||
@@ -189,3 +194,22 @@ func createCertPool(certBytes []byte) (*x509.CertPool, error) {
|
||||
}
|
||||
return cp, nil
|
||||
}
|
||||
|
||||
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 == '~')
|
||||
}
|
||||
|
@@ -125,7 +125,7 @@ func NewGRPCConfig(opts ...GRPCOption) Config {
|
||||
if cfg.ServiceConfig != "" {
|
||||
cfg.DialOptions = append(cfg.DialOptions, grpc.WithDefaultServiceConfig(cfg.ServiceConfig))
|
||||
}
|
||||
// Priroritize GRPCCredentials over Insecure (passing both is an error).
|
||||
// Prioritize GRPCCredentials over Insecure (passing both is an error).
|
||||
if cfg.Traces.GRPCCredentials != nil {
|
||||
cfg.DialOptions = append(cfg.DialOptions, grpc.WithTransportCredentials(cfg.Traces.GRPCCredentials))
|
||||
} else if cfg.Traces.Insecure {
|
||||
|
11
vendor/go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp/options.go
generated
vendored
11
vendor/go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp/options.go
generated
vendored
@@ -62,8 +62,10 @@ func (w wrappedOption) applyHTTPOption(cfg otlpconfig.Config) otlpconfig.Config
|
||||
//
|
||||
// If the OTEL_EXPORTER_OTLP_ENDPOINT or OTEL_EXPORTER_OTLP_TRACES_ENDPOINT
|
||||
// environment variable is set, and this option is not passed, that variable
|
||||
// value will be used. If both are set, OTEL_EXPORTER_OTLP_TRACES_ENDPOINT
|
||||
// will take precedence. Note, both environment variables include the full
|
||||
// value will be used. If both environment variables are set,
|
||||
// OTEL_EXPORTER_OTLP_TRACES_ENDPOINT will take precedence. If an environment
|
||||
// variable is set, and this option is passed, this option will take precedence.
|
||||
// Note, both environment variables include the full
|
||||
// scheme and path, while WithEndpoint sets only the host and port.
|
||||
//
|
||||
// If both this option and WithEndpointURL are used, the last used option will
|
||||
@@ -82,8 +84,9 @@ func WithEndpoint(endpoint string) Option {
|
||||
//
|
||||
// If the OTEL_EXPORTER_OTLP_ENDPOINT or OTEL_EXPORTER_OTLP_TRACES_ENDPOINT
|
||||
// environment variable is set, and this option is not passed, that variable
|
||||
// value will be used. If both are set, OTEL_EXPORTER_OTLP_TRACES_ENDPOINT
|
||||
// will take precedence.
|
||||
// value will be used. If both environment variables are set,
|
||||
// OTEL_EXPORTER_OTLP_TRACES_ENDPOINT will take precedence. If an environment
|
||||
// variable is set, and this option is passed, this option will take precedence.
|
||||
//
|
||||
// If both this option and WithEndpoint are used, the last used option will
|
||||
// take precedence.
|
||||
|
2
vendor/go.opentelemetry.io/otel/exporters/otlp/otlptrace/version.go
generated
vendored
2
vendor/go.opentelemetry.io/otel/exporters/otlp/otlptrace/version.go
generated
vendored
@@ -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.28.0"
|
||||
return "1.31.0"
|
||||
}
|
||||
|
317
vendor/go.opentelemetry.io/otel/internal/global/meter.go
generated
vendored
317
vendor/go.opentelemetry.io/otel/internal/global/meter.go
generated
vendored
@@ -5,8 +5,8 @@ package global // import "go.opentelemetry.io/otel/internal/global"
|
||||
|
||||
import (
|
||||
"container/list"
|
||||
"reflect"
|
||||
"sync"
|
||||
"sync/atomic"
|
||||
|
||||
"go.opentelemetry.io/otel/metric"
|
||||
"go.opentelemetry.io/otel/metric/embedded"
|
||||
@@ -76,7 +76,7 @@ func (p *meterProvider) Meter(name string, opts ...metric.MeterOption) metric.Me
|
||||
return val
|
||||
}
|
||||
|
||||
t := &meter{name: name, opts: opts}
|
||||
t := &meter{name: name, opts: opts, instruments: make(map[instID]delegatedInstrument)}
|
||||
p.meters[key] = t
|
||||
return t
|
||||
}
|
||||
@@ -92,17 +92,29 @@ type meter struct {
|
||||
opts []metric.MeterOption
|
||||
|
||||
mtx sync.Mutex
|
||||
instruments []delegatedInstrument
|
||||
instruments map[instID]delegatedInstrument
|
||||
|
||||
registry list.List
|
||||
|
||||
delegate atomic.Value // metric.Meter
|
||||
delegate metric.Meter
|
||||
}
|
||||
|
||||
type delegatedInstrument interface {
|
||||
setDelegate(metric.Meter)
|
||||
}
|
||||
|
||||
// instID are the identifying properties of a instrument.
|
||||
type instID struct {
|
||||
// name is the name of the stream.
|
||||
name string
|
||||
// description is the description of the stream.
|
||||
description string
|
||||
// kind defines the functional group of the instrument.
|
||||
kind reflect.Type
|
||||
// unit is the unit of the stream.
|
||||
unit string
|
||||
}
|
||||
|
||||
// setDelegate configures m to delegate all Meter functionality to Meters
|
||||
// created by provider.
|
||||
//
|
||||
@@ -110,12 +122,12 @@ type delegatedInstrument interface {
|
||||
//
|
||||
// It is guaranteed by the caller that this happens only once.
|
||||
func (m *meter) setDelegate(provider metric.MeterProvider) {
|
||||
meter := provider.Meter(m.name, m.opts...)
|
||||
m.delegate.Store(meter)
|
||||
|
||||
m.mtx.Lock()
|
||||
defer m.mtx.Unlock()
|
||||
|
||||
meter := provider.Meter(m.name, m.opts...)
|
||||
m.delegate = meter
|
||||
|
||||
for _, inst := range m.instruments {
|
||||
inst.setDelegate(meter)
|
||||
}
|
||||
@@ -133,169 +145,337 @@ func (m *meter) setDelegate(provider metric.MeterProvider) {
|
||||
}
|
||||
|
||||
func (m *meter) Int64Counter(name string, options ...metric.Int64CounterOption) (metric.Int64Counter, error) {
|
||||
if del, ok := m.delegate.Load().(metric.Meter); ok {
|
||||
return del.Int64Counter(name, options...)
|
||||
}
|
||||
m.mtx.Lock()
|
||||
defer m.mtx.Unlock()
|
||||
|
||||
if m.delegate != nil {
|
||||
return m.delegate.Int64Counter(name, options...)
|
||||
}
|
||||
|
||||
cfg := metric.NewInt64CounterConfig(options...)
|
||||
id := instID{
|
||||
name: name,
|
||||
kind: reflect.TypeOf((*siCounter)(nil)),
|
||||
description: cfg.Description(),
|
||||
unit: cfg.Unit(),
|
||||
}
|
||||
if f, ok := m.instruments[id]; ok {
|
||||
return f.(metric.Int64Counter), nil
|
||||
}
|
||||
i := &siCounter{name: name, opts: options}
|
||||
m.instruments = append(m.instruments, i)
|
||||
m.instruments[id] = i
|
||||
return i, nil
|
||||
}
|
||||
|
||||
func (m *meter) Int64UpDownCounter(name string, options ...metric.Int64UpDownCounterOption) (metric.Int64UpDownCounter, error) {
|
||||
if del, ok := m.delegate.Load().(metric.Meter); ok {
|
||||
return del.Int64UpDownCounter(name, options...)
|
||||
}
|
||||
m.mtx.Lock()
|
||||
defer m.mtx.Unlock()
|
||||
|
||||
if m.delegate != nil {
|
||||
return m.delegate.Int64UpDownCounter(name, options...)
|
||||
}
|
||||
|
||||
cfg := metric.NewInt64UpDownCounterConfig(options...)
|
||||
id := instID{
|
||||
name: name,
|
||||
kind: reflect.TypeOf((*siUpDownCounter)(nil)),
|
||||
description: cfg.Description(),
|
||||
unit: cfg.Unit(),
|
||||
}
|
||||
if f, ok := m.instruments[id]; ok {
|
||||
return f.(metric.Int64UpDownCounter), nil
|
||||
}
|
||||
i := &siUpDownCounter{name: name, opts: options}
|
||||
m.instruments = append(m.instruments, i)
|
||||
m.instruments[id] = i
|
||||
return i, nil
|
||||
}
|
||||
|
||||
func (m *meter) Int64Histogram(name string, options ...metric.Int64HistogramOption) (metric.Int64Histogram, error) {
|
||||
if del, ok := m.delegate.Load().(metric.Meter); ok {
|
||||
return del.Int64Histogram(name, options...)
|
||||
}
|
||||
m.mtx.Lock()
|
||||
defer m.mtx.Unlock()
|
||||
|
||||
if m.delegate != nil {
|
||||
return m.delegate.Int64Histogram(name, options...)
|
||||
}
|
||||
|
||||
cfg := metric.NewInt64HistogramConfig(options...)
|
||||
id := instID{
|
||||
name: name,
|
||||
kind: reflect.TypeOf((*siHistogram)(nil)),
|
||||
description: cfg.Description(),
|
||||
unit: cfg.Unit(),
|
||||
}
|
||||
if f, ok := m.instruments[id]; ok {
|
||||
return f.(metric.Int64Histogram), nil
|
||||
}
|
||||
i := &siHistogram{name: name, opts: options}
|
||||
m.instruments = append(m.instruments, i)
|
||||
m.instruments[id] = i
|
||||
return i, nil
|
||||
}
|
||||
|
||||
func (m *meter) Int64Gauge(name string, options ...metric.Int64GaugeOption) (metric.Int64Gauge, error) {
|
||||
if del, ok := m.delegate.Load().(metric.Meter); ok {
|
||||
return del.Int64Gauge(name, options...)
|
||||
}
|
||||
m.mtx.Lock()
|
||||
defer m.mtx.Unlock()
|
||||
|
||||
if m.delegate != nil {
|
||||
return m.delegate.Int64Gauge(name, options...)
|
||||
}
|
||||
|
||||
cfg := metric.NewInt64GaugeConfig(options...)
|
||||
id := instID{
|
||||
name: name,
|
||||
kind: reflect.TypeOf((*siGauge)(nil)),
|
||||
description: cfg.Description(),
|
||||
unit: cfg.Unit(),
|
||||
}
|
||||
if f, ok := m.instruments[id]; ok {
|
||||
return f.(metric.Int64Gauge), nil
|
||||
}
|
||||
i := &siGauge{name: name, opts: options}
|
||||
m.instruments = append(m.instruments, i)
|
||||
m.instruments[id] = i
|
||||
return i, nil
|
||||
}
|
||||
|
||||
func (m *meter) Int64ObservableCounter(name string, options ...metric.Int64ObservableCounterOption) (metric.Int64ObservableCounter, error) {
|
||||
if del, ok := m.delegate.Load().(metric.Meter); ok {
|
||||
return del.Int64ObservableCounter(name, options...)
|
||||
}
|
||||
m.mtx.Lock()
|
||||
defer m.mtx.Unlock()
|
||||
|
||||
if m.delegate != nil {
|
||||
return m.delegate.Int64ObservableCounter(name, options...)
|
||||
}
|
||||
|
||||
cfg := metric.NewInt64ObservableCounterConfig(options...)
|
||||
id := instID{
|
||||
name: name,
|
||||
kind: reflect.TypeOf((*aiCounter)(nil)),
|
||||
description: cfg.Description(),
|
||||
unit: cfg.Unit(),
|
||||
}
|
||||
if f, ok := m.instruments[id]; ok {
|
||||
return f.(metric.Int64ObservableCounter), nil
|
||||
}
|
||||
i := &aiCounter{name: name, opts: options}
|
||||
m.instruments = append(m.instruments, i)
|
||||
m.instruments[id] = i
|
||||
return i, nil
|
||||
}
|
||||
|
||||
func (m *meter) Int64ObservableUpDownCounter(name string, options ...metric.Int64ObservableUpDownCounterOption) (metric.Int64ObservableUpDownCounter, error) {
|
||||
if del, ok := m.delegate.Load().(metric.Meter); ok {
|
||||
return del.Int64ObservableUpDownCounter(name, options...)
|
||||
}
|
||||
m.mtx.Lock()
|
||||
defer m.mtx.Unlock()
|
||||
|
||||
if m.delegate != nil {
|
||||
return m.delegate.Int64ObservableUpDownCounter(name, options...)
|
||||
}
|
||||
|
||||
cfg := metric.NewInt64ObservableUpDownCounterConfig(options...)
|
||||
id := instID{
|
||||
name: name,
|
||||
kind: reflect.TypeOf((*aiUpDownCounter)(nil)),
|
||||
description: cfg.Description(),
|
||||
unit: cfg.Unit(),
|
||||
}
|
||||
if f, ok := m.instruments[id]; ok {
|
||||
return f.(metric.Int64ObservableUpDownCounter), nil
|
||||
}
|
||||
i := &aiUpDownCounter{name: name, opts: options}
|
||||
m.instruments = append(m.instruments, i)
|
||||
m.instruments[id] = i
|
||||
return i, nil
|
||||
}
|
||||
|
||||
func (m *meter) Int64ObservableGauge(name string, options ...metric.Int64ObservableGaugeOption) (metric.Int64ObservableGauge, error) {
|
||||
if del, ok := m.delegate.Load().(metric.Meter); ok {
|
||||
return del.Int64ObservableGauge(name, options...)
|
||||
}
|
||||
m.mtx.Lock()
|
||||
defer m.mtx.Unlock()
|
||||
|
||||
if m.delegate != nil {
|
||||
return m.delegate.Int64ObservableGauge(name, options...)
|
||||
}
|
||||
|
||||
cfg := metric.NewInt64ObservableGaugeConfig(options...)
|
||||
id := instID{
|
||||
name: name,
|
||||
kind: reflect.TypeOf((*aiGauge)(nil)),
|
||||
description: cfg.Description(),
|
||||
unit: cfg.Unit(),
|
||||
}
|
||||
if f, ok := m.instruments[id]; ok {
|
||||
return f.(metric.Int64ObservableGauge), nil
|
||||
}
|
||||
i := &aiGauge{name: name, opts: options}
|
||||
m.instruments = append(m.instruments, i)
|
||||
m.instruments[id] = i
|
||||
return i, nil
|
||||
}
|
||||
|
||||
func (m *meter) Float64Counter(name string, options ...metric.Float64CounterOption) (metric.Float64Counter, error) {
|
||||
if del, ok := m.delegate.Load().(metric.Meter); ok {
|
||||
return del.Float64Counter(name, options...)
|
||||
}
|
||||
m.mtx.Lock()
|
||||
defer m.mtx.Unlock()
|
||||
|
||||
if m.delegate != nil {
|
||||
return m.delegate.Float64Counter(name, options...)
|
||||
}
|
||||
|
||||
cfg := metric.NewFloat64CounterConfig(options...)
|
||||
id := instID{
|
||||
name: name,
|
||||
kind: reflect.TypeOf((*sfCounter)(nil)),
|
||||
description: cfg.Description(),
|
||||
unit: cfg.Unit(),
|
||||
}
|
||||
if f, ok := m.instruments[id]; ok {
|
||||
return f.(metric.Float64Counter), nil
|
||||
}
|
||||
i := &sfCounter{name: name, opts: options}
|
||||
m.instruments = append(m.instruments, i)
|
||||
m.instruments[id] = i
|
||||
return i, nil
|
||||
}
|
||||
|
||||
func (m *meter) Float64UpDownCounter(name string, options ...metric.Float64UpDownCounterOption) (metric.Float64UpDownCounter, error) {
|
||||
if del, ok := m.delegate.Load().(metric.Meter); ok {
|
||||
return del.Float64UpDownCounter(name, options...)
|
||||
}
|
||||
m.mtx.Lock()
|
||||
defer m.mtx.Unlock()
|
||||
|
||||
if m.delegate != nil {
|
||||
return m.delegate.Float64UpDownCounter(name, options...)
|
||||
}
|
||||
|
||||
cfg := metric.NewFloat64UpDownCounterConfig(options...)
|
||||
id := instID{
|
||||
name: name,
|
||||
kind: reflect.TypeOf((*sfUpDownCounter)(nil)),
|
||||
description: cfg.Description(),
|
||||
unit: cfg.Unit(),
|
||||
}
|
||||
if f, ok := m.instruments[id]; ok {
|
||||
return f.(metric.Float64UpDownCounter), nil
|
||||
}
|
||||
i := &sfUpDownCounter{name: name, opts: options}
|
||||
m.instruments = append(m.instruments, i)
|
||||
m.instruments[id] = i
|
||||
return i, nil
|
||||
}
|
||||
|
||||
func (m *meter) Float64Histogram(name string, options ...metric.Float64HistogramOption) (metric.Float64Histogram, error) {
|
||||
if del, ok := m.delegate.Load().(metric.Meter); ok {
|
||||
return del.Float64Histogram(name, options...)
|
||||
}
|
||||
m.mtx.Lock()
|
||||
defer m.mtx.Unlock()
|
||||
|
||||
if m.delegate != nil {
|
||||
return m.delegate.Float64Histogram(name, options...)
|
||||
}
|
||||
|
||||
cfg := metric.NewFloat64HistogramConfig(options...)
|
||||
id := instID{
|
||||
name: name,
|
||||
kind: reflect.TypeOf((*sfHistogram)(nil)),
|
||||
description: cfg.Description(),
|
||||
unit: cfg.Unit(),
|
||||
}
|
||||
if f, ok := m.instruments[id]; ok {
|
||||
return f.(metric.Float64Histogram), nil
|
||||
}
|
||||
i := &sfHistogram{name: name, opts: options}
|
||||
m.instruments = append(m.instruments, i)
|
||||
m.instruments[id] = i
|
||||
return i, nil
|
||||
}
|
||||
|
||||
func (m *meter) Float64Gauge(name string, options ...metric.Float64GaugeOption) (metric.Float64Gauge, error) {
|
||||
if del, ok := m.delegate.Load().(metric.Meter); ok {
|
||||
return del.Float64Gauge(name, options...)
|
||||
}
|
||||
m.mtx.Lock()
|
||||
defer m.mtx.Unlock()
|
||||
|
||||
if m.delegate != nil {
|
||||
return m.delegate.Float64Gauge(name, options...)
|
||||
}
|
||||
|
||||
cfg := metric.NewFloat64GaugeConfig(options...)
|
||||
id := instID{
|
||||
name: name,
|
||||
kind: reflect.TypeOf((*sfGauge)(nil)),
|
||||
description: cfg.Description(),
|
||||
unit: cfg.Unit(),
|
||||
}
|
||||
if f, ok := m.instruments[id]; ok {
|
||||
return f.(metric.Float64Gauge), nil
|
||||
}
|
||||
i := &sfGauge{name: name, opts: options}
|
||||
m.instruments = append(m.instruments, i)
|
||||
m.instruments[id] = i
|
||||
return i, nil
|
||||
}
|
||||
|
||||
func (m *meter) Float64ObservableCounter(name string, options ...metric.Float64ObservableCounterOption) (metric.Float64ObservableCounter, error) {
|
||||
if del, ok := m.delegate.Load().(metric.Meter); ok {
|
||||
return del.Float64ObservableCounter(name, options...)
|
||||
}
|
||||
m.mtx.Lock()
|
||||
defer m.mtx.Unlock()
|
||||
|
||||
if m.delegate != nil {
|
||||
return m.delegate.Float64ObservableCounter(name, options...)
|
||||
}
|
||||
|
||||
cfg := metric.NewFloat64ObservableCounterConfig(options...)
|
||||
id := instID{
|
||||
name: name,
|
||||
kind: reflect.TypeOf((*afCounter)(nil)),
|
||||
description: cfg.Description(),
|
||||
unit: cfg.Unit(),
|
||||
}
|
||||
if f, ok := m.instruments[id]; ok {
|
||||
return f.(metric.Float64ObservableCounter), nil
|
||||
}
|
||||
i := &afCounter{name: name, opts: options}
|
||||
m.instruments = append(m.instruments, i)
|
||||
m.instruments[id] = i
|
||||
return i, nil
|
||||
}
|
||||
|
||||
func (m *meter) Float64ObservableUpDownCounter(name string, options ...metric.Float64ObservableUpDownCounterOption) (metric.Float64ObservableUpDownCounter, error) {
|
||||
if del, ok := m.delegate.Load().(metric.Meter); ok {
|
||||
return del.Float64ObservableUpDownCounter(name, options...)
|
||||
}
|
||||
m.mtx.Lock()
|
||||
defer m.mtx.Unlock()
|
||||
|
||||
if m.delegate != nil {
|
||||
return m.delegate.Float64ObservableUpDownCounter(name, options...)
|
||||
}
|
||||
|
||||
cfg := metric.NewFloat64ObservableUpDownCounterConfig(options...)
|
||||
id := instID{
|
||||
name: name,
|
||||
kind: reflect.TypeOf((*afUpDownCounter)(nil)),
|
||||
description: cfg.Description(),
|
||||
unit: cfg.Unit(),
|
||||
}
|
||||
if f, ok := m.instruments[id]; ok {
|
||||
return f.(metric.Float64ObservableUpDownCounter), nil
|
||||
}
|
||||
i := &afUpDownCounter{name: name, opts: options}
|
||||
m.instruments = append(m.instruments, i)
|
||||
m.instruments[id] = i
|
||||
return i, nil
|
||||
}
|
||||
|
||||
func (m *meter) Float64ObservableGauge(name string, options ...metric.Float64ObservableGaugeOption) (metric.Float64ObservableGauge, error) {
|
||||
if del, ok := m.delegate.Load().(metric.Meter); ok {
|
||||
return del.Float64ObservableGauge(name, options...)
|
||||
}
|
||||
m.mtx.Lock()
|
||||
defer m.mtx.Unlock()
|
||||
|
||||
if m.delegate != nil {
|
||||
return m.delegate.Float64ObservableGauge(name, options...)
|
||||
}
|
||||
|
||||
cfg := metric.NewFloat64ObservableGaugeConfig(options...)
|
||||
id := instID{
|
||||
name: name,
|
||||
kind: reflect.TypeOf((*afGauge)(nil)),
|
||||
description: cfg.Description(),
|
||||
unit: cfg.Unit(),
|
||||
}
|
||||
if f, ok := m.instruments[id]; ok {
|
||||
return f.(metric.Float64ObservableGauge), nil
|
||||
}
|
||||
i := &afGauge{name: name, opts: options}
|
||||
m.instruments = append(m.instruments, i)
|
||||
m.instruments[id] = i
|
||||
return i, nil
|
||||
}
|
||||
|
||||
// RegisterCallback captures the function that will be called during Collect.
|
||||
func (m *meter) RegisterCallback(f metric.Callback, insts ...metric.Observable) (metric.Registration, error) {
|
||||
if del, ok := m.delegate.Load().(metric.Meter); ok {
|
||||
insts = unwrapInstruments(insts)
|
||||
return del.RegisterCallback(f, insts...)
|
||||
}
|
||||
|
||||
m.mtx.Lock()
|
||||
defer m.mtx.Unlock()
|
||||
|
||||
if m.delegate != nil {
|
||||
insts = unwrapInstruments(insts)
|
||||
return m.delegate.RegisterCallback(f, insts...)
|
||||
}
|
||||
|
||||
reg := ®istration{instruments: insts, function: f}
|
||||
e := m.registry.PushBack(reg)
|
||||
reg.unreg = func() error {
|
||||
@@ -349,6 +529,7 @@ func (c *registration) setDelegate(m metric.Meter) {
|
||||
reg, err := m.RegisterCallback(c.function, insts...)
|
||||
if err != nil {
|
||||
GetErrorHandler().Handle(err)
|
||||
return
|
||||
}
|
||||
|
||||
c.unreg = reg.Unregister
|
||||
|
12
vendor/go.opentelemetry.io/otel/internal/rawhelpers.go
generated
vendored
12
vendor/go.opentelemetry.io/otel/internal/rawhelpers.go
generated
vendored
@@ -20,11 +20,13 @@ func RawToBool(r uint64) bool {
|
||||
}
|
||||
|
||||
func Int64ToRaw(i int64) uint64 {
|
||||
return uint64(i)
|
||||
// Assumes original was a valid int64 (overflow not checked).
|
||||
return uint64(i) // nolint: gosec
|
||||
}
|
||||
|
||||
func RawToInt64(r uint64) int64 {
|
||||
return int64(r)
|
||||
// Assumes original was a valid int64 (overflow not checked).
|
||||
return int64(r) // nolint: gosec
|
||||
}
|
||||
|
||||
func Float64ToRaw(f float64) uint64 {
|
||||
@@ -36,9 +38,11 @@ func RawToFloat64(r uint64) float64 {
|
||||
}
|
||||
|
||||
func RawPtrToFloat64Ptr(r *uint64) *float64 {
|
||||
return (*float64)(unsafe.Pointer(r))
|
||||
// Assumes original was a valid *float64 (overflow not checked).
|
||||
return (*float64)(unsafe.Pointer(r)) // nolint: gosec
|
||||
}
|
||||
|
||||
func RawPtrToInt64Ptr(r *uint64) *int64 {
|
||||
return (*int64)(unsafe.Pointer(r))
|
||||
// Assumes original was a valid *int64 (overflow not checked).
|
||||
return (*int64)(unsafe.Pointer(r)) // nolint: gosec
|
||||
}
|
||||
|
2
vendor/go.opentelemetry.io/otel/metric/asyncfloat64.go
generated
vendored
2
vendor/go.opentelemetry.io/otel/metric/asyncfloat64.go
generated
vendored
@@ -213,7 +213,7 @@ type Float64Observer interface {
|
||||
}
|
||||
|
||||
// Float64Callback is a function registered with a Meter that makes
|
||||
// observations for a Float64Observerable instrument it is registered with.
|
||||
// observations for a Float64Observable instrument it is registered with.
|
||||
// Calls to the Float64Observer record measurement values for the
|
||||
// Float64Observable.
|
||||
//
|
||||
|
2
vendor/go.opentelemetry.io/otel/metric/asyncint64.go
generated
vendored
2
vendor/go.opentelemetry.io/otel/metric/asyncint64.go
generated
vendored
@@ -212,7 +212,7 @@ type Int64Observer interface {
|
||||
}
|
||||
|
||||
// Int64Callback is a function registered with a Meter that makes observations
|
||||
// for an Int64Observerable instrument it is registered with. Calls to the
|
||||
// for an Int64Observable instrument it is registered with. Calls to the
|
||||
// Int64Observer record measurement values for the Int64Observable.
|
||||
//
|
||||
// The function needs to complete in a finite amount of time and the deadline
|
||||
|
2
vendor/go.opentelemetry.io/otel/metric/instrument.go
generated
vendored
2
vendor/go.opentelemetry.io/otel/metric/instrument.go
generated
vendored
@@ -351,7 +351,7 @@ func WithAttributeSet(attributes attribute.Set) MeasurementOption {
|
||||
//
|
||||
// cp := make([]attribute.KeyValue, len(attributes))
|
||||
// copy(cp, attributes)
|
||||
// WithAttributes(attribute.NewSet(cp...))
|
||||
// WithAttributeSet(attribute.NewSet(cp...))
|
||||
//
|
||||
// [attribute.NewSet] may modify the passed attributes so this will make a copy
|
||||
// of attributes before creating a set in order to ensure this function is
|
||||
|
13
vendor/go.opentelemetry.io/otel/metric/meter.go
generated
vendored
13
vendor/go.opentelemetry.io/otel/metric/meter.go
generated
vendored
@@ -52,6 +52,7 @@ type Meter interface {
|
||||
// See the Instrument Name section of the package documentation for more
|
||||
// information.
|
||||
Int64Counter(name string, options ...Int64CounterOption) (Int64Counter, error)
|
||||
|
||||
// Int64UpDownCounter returns a new Int64UpDownCounter instrument
|
||||
// identified by name and configured with options. The instrument is used
|
||||
// to synchronously record int64 measurements during a computational
|
||||
@@ -61,6 +62,7 @@ type Meter interface {
|
||||
// See the Instrument Name section of the package documentation for more
|
||||
// information.
|
||||
Int64UpDownCounter(name string, options ...Int64UpDownCounterOption) (Int64UpDownCounter, error)
|
||||
|
||||
// Int64Histogram returns a new Int64Histogram instrument identified by
|
||||
// name and configured with options. The instrument is used to
|
||||
// synchronously record the distribution of int64 measurements during a
|
||||
@@ -70,6 +72,7 @@ type Meter interface {
|
||||
// See the Instrument Name section of the package documentation for more
|
||||
// information.
|
||||
Int64Histogram(name string, options ...Int64HistogramOption) (Int64Histogram, error)
|
||||
|
||||
// Int64Gauge returns a new Int64Gauge instrument identified by name and
|
||||
// configured with options. The instrument is used to synchronously record
|
||||
// instantaneous int64 measurements during a computational operation.
|
||||
@@ -78,6 +81,7 @@ type Meter interface {
|
||||
// See the Instrument Name section of the package documentation for more
|
||||
// information.
|
||||
Int64Gauge(name string, options ...Int64GaugeOption) (Int64Gauge, error)
|
||||
|
||||
// Int64ObservableCounter returns a new Int64ObservableCounter identified
|
||||
// by name and configured with options. The instrument is used to
|
||||
// asynchronously record increasing int64 measurements once per a
|
||||
@@ -92,6 +96,7 @@ type Meter interface {
|
||||
// See the Instrument Name section of the package documentation for more
|
||||
// information.
|
||||
Int64ObservableCounter(name string, options ...Int64ObservableCounterOption) (Int64ObservableCounter, error)
|
||||
|
||||
// Int64ObservableUpDownCounter returns a new Int64ObservableUpDownCounter
|
||||
// instrument identified by name and configured with options. The
|
||||
// instrument is used to asynchronously record int64 measurements once per
|
||||
@@ -106,6 +111,7 @@ type Meter interface {
|
||||
// See the Instrument Name section of the package documentation for more
|
||||
// information.
|
||||
Int64ObservableUpDownCounter(name string, options ...Int64ObservableUpDownCounterOption) (Int64ObservableUpDownCounter, error)
|
||||
|
||||
// Int64ObservableGauge returns a new Int64ObservableGauge instrument
|
||||
// identified by name and configured with options. The instrument is used
|
||||
// to asynchronously record instantaneous int64 measurements once per a
|
||||
@@ -130,6 +136,7 @@ type Meter interface {
|
||||
// See the Instrument Name section of the package documentation for more
|
||||
// information.
|
||||
Float64Counter(name string, options ...Float64CounterOption) (Float64Counter, error)
|
||||
|
||||
// Float64UpDownCounter returns a new Float64UpDownCounter instrument
|
||||
// identified by name and configured with options. The instrument is used
|
||||
// to synchronously record float64 measurements during a computational
|
||||
@@ -139,6 +146,7 @@ type Meter interface {
|
||||
// See the Instrument Name section of the package documentation for more
|
||||
// information.
|
||||
Float64UpDownCounter(name string, options ...Float64UpDownCounterOption) (Float64UpDownCounter, error)
|
||||
|
||||
// Float64Histogram returns a new Float64Histogram instrument identified by
|
||||
// name and configured with options. The instrument is used to
|
||||
// synchronously record the distribution of float64 measurements during a
|
||||
@@ -148,6 +156,7 @@ type Meter interface {
|
||||
// See the Instrument Name section of the package documentation for more
|
||||
// information.
|
||||
Float64Histogram(name string, options ...Float64HistogramOption) (Float64Histogram, error)
|
||||
|
||||
// Float64Gauge returns a new Float64Gauge instrument identified by name and
|
||||
// configured with options. The instrument is used to synchronously record
|
||||
// instantaneous float64 measurements during a computational operation.
|
||||
@@ -156,6 +165,7 @@ type Meter interface {
|
||||
// See the Instrument Name section of the package documentation for more
|
||||
// information.
|
||||
Float64Gauge(name string, options ...Float64GaugeOption) (Float64Gauge, error)
|
||||
|
||||
// Float64ObservableCounter returns a new Float64ObservableCounter
|
||||
// instrument identified by name and configured with options. The
|
||||
// instrument is used to asynchronously record increasing float64
|
||||
@@ -170,6 +180,7 @@ type Meter interface {
|
||||
// See the Instrument Name section of the package documentation for more
|
||||
// information.
|
||||
Float64ObservableCounter(name string, options ...Float64ObservableCounterOption) (Float64ObservableCounter, error)
|
||||
|
||||
// Float64ObservableUpDownCounter returns a new
|
||||
// Float64ObservableUpDownCounter instrument identified by name and
|
||||
// configured with options. The instrument is used to asynchronously record
|
||||
@@ -184,6 +195,7 @@ type Meter interface {
|
||||
// See the Instrument Name section of the package documentation for more
|
||||
// information.
|
||||
Float64ObservableUpDownCounter(name string, options ...Float64ObservableUpDownCounterOption) (Float64ObservableUpDownCounter, error)
|
||||
|
||||
// Float64ObservableGauge returns a new Float64ObservableGauge instrument
|
||||
// identified by name and configured with options. The instrument is used
|
||||
// to asynchronously record instantaneous float64 measurements once per a
|
||||
@@ -242,6 +254,7 @@ type Observer interface {
|
||||
|
||||
// ObserveFloat64 records the float64 value for obsrv.
|
||||
ObserveFloat64(obsrv Float64Observable, value float64, opts ...ObserveOption)
|
||||
|
||||
// ObserveInt64 records the int64 value for obsrv.
|
||||
ObserveInt64(obsrv Int64Observable, value int64, opts ...ObserveOption)
|
||||
}
|
||||
|
8
vendor/go.opentelemetry.io/otel/renovate.json
generated
vendored
8
vendor/go.opentelemetry.io/otel/renovate.json
generated
vendored
@@ -19,6 +19,14 @@
|
||||
"matchManagers": ["gomod"],
|
||||
"matchDepTypes": ["indirect"],
|
||||
"enabled": false
|
||||
},
|
||||
{
|
||||
"matchPackageNames": ["google.golang.org/genproto/googleapis/**"],
|
||||
"groupName": "googleapis"
|
||||
},
|
||||
{
|
||||
"matchPackageNames": ["golang.org/x/**"],
|
||||
"groupName": "golang.org/x"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
3
vendor/go.opentelemetry.io/otel/sdk/instrumentation/library.go
generated
vendored
3
vendor/go.opentelemetry.io/otel/sdk/instrumentation/library.go
generated
vendored
@@ -4,5 +4,6 @@
|
||||
package instrumentation // import "go.opentelemetry.io/otel/sdk/instrumentation"
|
||||
|
||||
// Library represents the instrumentation library.
|
||||
// Deprecated: please use Scope instead.
|
||||
//
|
||||
// Deprecated: use [Scope] instead.
|
||||
type Library = Scope
|
||||
|
7
vendor/go.opentelemetry.io/otel/sdk/metric/config.go
generated
vendored
7
vendor/go.opentelemetry.io/otel/sdk/metric/config.go
generated
vendored
@@ -8,6 +8,7 @@ import (
|
||||
"fmt"
|
||||
"sync"
|
||||
|
||||
"go.opentelemetry.io/otel"
|
||||
"go.opentelemetry.io/otel/sdk/resource"
|
||||
)
|
||||
|
||||
@@ -103,7 +104,11 @@ func (o optionFunc) apply(conf config) config {
|
||||
// go.opentelemetry.io/otel/sdk/resource package will be used.
|
||||
func WithResource(res *resource.Resource) Option {
|
||||
return optionFunc(func(conf config) config {
|
||||
conf.res = res
|
||||
var err error
|
||||
conf.res, err = resource.Merge(resource.Environment(), res)
|
||||
if err != nil {
|
||||
otel.Handle(err)
|
||||
}
|
||||
return conf
|
||||
})
|
||||
}
|
||||
|
8
vendor/go.opentelemetry.io/otel/sdk/metric/doc.go
generated
vendored
8
vendor/go.opentelemetry.io/otel/sdk/metric/doc.go
generated
vendored
@@ -31,6 +31,14 @@
|
||||
// is being run on. That way when multiple instances of the code are collected
|
||||
// at a single endpoint their origin is decipherable.
|
||||
//
|
||||
// To avoid leaking memory, the SDK returns the same instrument for calls to
|
||||
// create new instruments with the same Name, Unit, and Description.
|
||||
// Importantly, callbacks provided using metric.WithFloat64Callback or
|
||||
// metric.WithInt64Callback will only apply for the first instrument created
|
||||
// with a given Name, Unit, and Description. Instead, use
|
||||
// Meter.RegisterCallback and Registration.Unregister to add and remove
|
||||
// callbacks without leaking memory.
|
||||
//
|
||||
// See [go.opentelemetry.io/otel/metric] for more information about
|
||||
// the metric API.
|
||||
//
|
||||
|
21
vendor/go.opentelemetry.io/otel/sdk/metric/exemplar.go
generated
vendored
21
vendor/go.opentelemetry.io/otel/sdk/metric/exemplar.go
generated
vendored
@@ -8,8 +8,8 @@ import (
|
||||
"runtime"
|
||||
"slices"
|
||||
|
||||
"go.opentelemetry.io/otel/sdk/metric/internal/exemplar"
|
||||
"go.opentelemetry.io/otel/sdk/metric/internal/x"
|
||||
"go.opentelemetry.io/otel/sdk/metric/exemplar"
|
||||
"go.opentelemetry.io/otel/sdk/metric/internal/aggregate"
|
||||
)
|
||||
|
||||
// reservoirFunc returns the appropriately configured exemplar reservoir
|
||||
@@ -19,10 +19,7 @@ import (
|
||||
// Note: This will only return non-nil values when the experimental exemplar
|
||||
// feature is enabled and the OTEL_METRICS_EXEMPLAR_FILTER environment variable
|
||||
// is not set to always_off.
|
||||
func reservoirFunc[N int64 | float64](agg Aggregation) func() exemplar.FilteredReservoir[N] {
|
||||
if !x.Exemplars.Enabled() {
|
||||
return nil
|
||||
}
|
||||
func reservoirFunc[N int64 | float64](agg Aggregation) func() aggregate.FilteredExemplarReservoir[N] {
|
||||
// https://github.com/open-telemetry/opentelemetry-specification/blob/d4b241f451674e8f611bb589477680341006ad2b/specification/configuration/sdk-environment-variables.md#exemplar
|
||||
const filterEnvKey = "OTEL_METRICS_EXEMPLAR_FILTER"
|
||||
|
||||
@@ -32,11 +29,11 @@ func reservoirFunc[N int64 | float64](agg Aggregation) func() exemplar.FilteredR
|
||||
case "always_on":
|
||||
filter = exemplar.AlwaysOnFilter
|
||||
case "always_off":
|
||||
return exemplar.Drop
|
||||
return aggregate.DropReservoir
|
||||
case "trace_based":
|
||||
fallthrough
|
||||
default:
|
||||
filter = exemplar.SampledFilter
|
||||
filter = exemplar.TraceBasedFilter
|
||||
}
|
||||
|
||||
// https://github.com/open-telemetry/opentelemetry-specification/blob/d4b241f451674e8f611bb589477680341006ad2b/specification/metrics/sdk.md#exemplar-defaults
|
||||
@@ -45,9 +42,9 @@ func reservoirFunc[N int64 | float64](agg Aggregation) func() exemplar.FilteredR
|
||||
a, ok := agg.(AggregationExplicitBucketHistogram)
|
||||
if ok && len(a.Boundaries) > 0 {
|
||||
cp := slices.Clone(a.Boundaries)
|
||||
return func() exemplar.FilteredReservoir[N] {
|
||||
return func() aggregate.FilteredExemplarReservoir[N] {
|
||||
bounds := cp
|
||||
return exemplar.NewFilteredReservoir[N](filter, exemplar.Histogram(bounds))
|
||||
return aggregate.NewFilteredExemplarReservoir[N](filter, exemplar.NewHistogramReservoir(bounds))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -75,7 +72,7 @@ func reservoirFunc[N int64 | float64](agg Aggregation) func() exemplar.FilteredR
|
||||
}
|
||||
}
|
||||
|
||||
return func() exemplar.FilteredReservoir[N] {
|
||||
return exemplar.NewFilteredReservoir[N](filter, exemplar.FixedSize(n))
|
||||
return func() aggregate.FilteredExemplarReservoir[N] {
|
||||
return aggregate.NewFilteredExemplarReservoir[N](filter, exemplar.NewFixedSizeReservoir(n))
|
||||
}
|
||||
}
|
||||
|
3
vendor/go.opentelemetry.io/otel/sdk/metric/exemplar/README.md
generated
vendored
Normal file
3
vendor/go.opentelemetry.io/otel/sdk/metric/exemplar/README.md
generated
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
# Metric SDK Exemplars
|
||||
|
||||
[](https://pkg.go.dev/go.opentelemetry.io/otel/sdk/metric/exemplar)
|
@@ -3,4 +3,4 @@
|
||||
|
||||
// Package exemplar provides an implementation of the OpenTelemetry exemplar
|
||||
// reservoir to be used in metric collection pipelines.
|
||||
package exemplar // import "go.opentelemetry.io/otel/sdk/metric/internal/exemplar"
|
||||
package exemplar // import "go.opentelemetry.io/otel/sdk/metric/exemplar"
|
@@ -1,7 +1,7 @@
|
||||
// Copyright The OpenTelemetry Authors
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package exemplar // import "go.opentelemetry.io/otel/sdk/metric/internal/exemplar"
|
||||
package exemplar // import "go.opentelemetry.io/otel/sdk/metric/exemplar"
|
||||
|
||||
import (
|
||||
"time"
|
@@ -1,7 +1,7 @@
|
||||
// Copyright The OpenTelemetry Authors
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package exemplar // import "go.opentelemetry.io/otel/sdk/metric/internal/exemplar"
|
||||
package exemplar // import "go.opentelemetry.io/otel/sdk/metric/exemplar"
|
||||
|
||||
import (
|
||||
"context"
|
||||
@@ -16,10 +16,10 @@ import (
|
||||
// Reservoir in making a sampling decision.
|
||||
type Filter func(context.Context) bool
|
||||
|
||||
// SampledFilter is a [Filter] that will only offer measurements
|
||||
// TraceBasedFilter is a [Filter] that will only offer measurements
|
||||
// if the passed context associated with the measurement contains a sampled
|
||||
// [go.opentelemetry.io/otel/trace.SpanContext].
|
||||
func SampledFilter(ctx context.Context) bool {
|
||||
func TraceBasedFilter(ctx context.Context) bool {
|
||||
return trace.SpanContextFromContext(ctx).IsSampled()
|
||||
}
|
||||
|
@@ -1,31 +1,62 @@
|
||||
// Copyright The OpenTelemetry Authors
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package exemplar // import "go.opentelemetry.io/otel/sdk/metric/internal/exemplar"
|
||||
package exemplar // import "go.opentelemetry.io/otel/sdk/metric/exemplar"
|
||||
|
||||
import (
|
||||
"context"
|
||||
"math"
|
||||
"math/rand"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"go.opentelemetry.io/otel/attribute"
|
||||
)
|
||||
|
||||
var (
|
||||
// NewFixedSizeReservoir returns a [FixedSizeReservoir] that samples at most
|
||||
// k exemplars. If there are k or less measurements made, the Reservoir will
|
||||
// sample each one. If there are more than k, the Reservoir will then randomly
|
||||
// sample all additional measurement with a decreasing probability.
|
||||
func NewFixedSizeReservoir(k int) *FixedSizeReservoir {
|
||||
return newFixedSizeReservoir(newStorage(k))
|
||||
}
|
||||
|
||||
var _ Reservoir = &FixedSizeReservoir{}
|
||||
|
||||
// FixedSizeReservoir is a [Reservoir] that samples at most k exemplars. If
|
||||
// there are k or less measurements made, the Reservoir will sample each one.
|
||||
// If there are more than k, the Reservoir will then randomly sample all
|
||||
// additional measurement with a decreasing probability.
|
||||
type FixedSizeReservoir struct {
|
||||
*storage
|
||||
|
||||
// count is the number of measurement seen.
|
||||
count int64
|
||||
// next is the next count that will store a measurement at a random index
|
||||
// once the reservoir has been filled.
|
||||
next int64
|
||||
// w is the largest random number in a distribution that is used to compute
|
||||
// the next next.
|
||||
w float64
|
||||
|
||||
// rng is used to make sampling decisions.
|
||||
//
|
||||
// Do not use crypto/rand. There is no reason for the decrease in performance
|
||||
// given this is not a security sensitive decision.
|
||||
rng = rand.New(rand.NewSource(time.Now().UnixNano()))
|
||||
// Ensure concurrent safe accecess to rng and its underlying source.
|
||||
rngMu sync.Mutex
|
||||
)
|
||||
rng *rand.Rand
|
||||
}
|
||||
|
||||
// random returns, as a float64, a uniform pseudo-random number in the open
|
||||
// interval (0.0,1.0).
|
||||
func random() float64 {
|
||||
func newFixedSizeReservoir(s *storage) *FixedSizeReservoir {
|
||||
r := &FixedSizeReservoir{
|
||||
storage: s,
|
||||
rng: rand.New(rand.NewSource(time.Now().UnixNano())),
|
||||
}
|
||||
r.reset()
|
||||
return r
|
||||
}
|
||||
|
||||
// randomFloat64 returns, as a float64, a uniform pseudo-random number in the
|
||||
// open interval (0.0,1.0).
|
||||
func (r *FixedSizeReservoir) randomFloat64() float64 {
|
||||
// TODO: This does not return a uniform number. rng.Float64 returns a
|
||||
// uniformly random int in [0,2^53) that is divided by 2^53. Meaning it
|
||||
// returns multiples of 2^-53, and not all floating point numbers between 0
|
||||
@@ -43,40 +74,25 @@ func random() float64 {
|
||||
//
|
||||
// There are likely many other methods to explore here as well.
|
||||
|
||||
rngMu.Lock()
|
||||
defer rngMu.Unlock()
|
||||
|
||||
f := rng.Float64()
|
||||
f := r.rng.Float64()
|
||||
for f == 0 {
|
||||
f = rng.Float64()
|
||||
f = r.rng.Float64()
|
||||
}
|
||||
return f
|
||||
}
|
||||
|
||||
// FixedSize returns a [Reservoir] that samples at most k exemplars. If there
|
||||
// are k or less measurements made, the Reservoir will sample each one. If
|
||||
// there are more than k, the Reservoir will then randomly sample all
|
||||
// additional measurement with a decreasing probability.
|
||||
func FixedSize(k int) Reservoir {
|
||||
r := &randRes{storage: newStorage(k)}
|
||||
r.reset()
|
||||
return r
|
||||
}
|
||||
|
||||
type randRes struct {
|
||||
*storage
|
||||
|
||||
// count is the number of measurement seen.
|
||||
count int64
|
||||
// next is the next count that will store a measurement at a random index
|
||||
// once the reservoir has been filled.
|
||||
next int64
|
||||
// w is the largest random number in a distribution that is used to compute
|
||||
// the next next.
|
||||
w float64
|
||||
}
|
||||
|
||||
func (r *randRes) Offer(ctx context.Context, t time.Time, n Value, a []attribute.KeyValue) {
|
||||
// Offer accepts the parameters associated with a measurement. The
|
||||
// parameters will be stored as an exemplar if the Reservoir decides to
|
||||
// sample the measurement.
|
||||
//
|
||||
// The passed ctx needs to contain any baggage or span that were active
|
||||
// when the measurement was made. This information may be used by the
|
||||
// Reservoir in making a sampling decision.
|
||||
//
|
||||
// The time t is the time when the measurement was made. The v and a
|
||||
// parameters are the value and dropped (filtered) attributes of the
|
||||
// measurement respectively.
|
||||
func (r *FixedSizeReservoir) Offer(ctx context.Context, t time.Time, n Value, a []attribute.KeyValue) {
|
||||
// The following algorithm is "Algorithm L" from Li, Kim-Hung (4 December
|
||||
// 1994). "Reservoir-Sampling Algorithms of Time Complexity
|
||||
// O(n(1+log(N/n)))". ACM Transactions on Mathematical Software. 20 (4):
|
||||
@@ -123,7 +139,7 @@ func (r *randRes) Offer(ctx context.Context, t time.Time, n Value, a []attribute
|
||||
} else {
|
||||
if r.count == r.next {
|
||||
// Overwrite a random existing measurement with the one offered.
|
||||
idx := int(rng.Int63n(int64(cap(r.store))))
|
||||
idx := int(r.rng.Int63n(int64(cap(r.store))))
|
||||
r.store[idx] = newMeasurement(ctx, t, n, a)
|
||||
r.advance()
|
||||
}
|
||||
@@ -132,7 +148,7 @@ func (r *randRes) Offer(ctx context.Context, t time.Time, n Value, a []attribute
|
||||
}
|
||||
|
||||
// reset resets r to the initial state.
|
||||
func (r *randRes) reset() {
|
||||
func (r *FixedSizeReservoir) reset() {
|
||||
// This resets the number of exemplars known.
|
||||
r.count = 0
|
||||
// Random index inserts should only happen after the storage is full.
|
||||
@@ -147,14 +163,14 @@ func (r *randRes) reset() {
|
||||
// This maps the uniform random number in (0,1) to a geometric distribution
|
||||
// over the same interval. The mean of the distribution is inversely
|
||||
// proportional to the storage capacity.
|
||||
r.w = math.Exp(math.Log(random()) / float64(cap(r.store)))
|
||||
r.w = math.Exp(math.Log(r.randomFloat64()) / float64(cap(r.store)))
|
||||
|
||||
r.advance()
|
||||
}
|
||||
|
||||
// advance updates the count at which the offered measurement will overwrite an
|
||||
// existing exemplar.
|
||||
func (r *randRes) advance() {
|
||||
func (r *FixedSizeReservoir) advance() {
|
||||
// Calculate the next value in the random number series.
|
||||
//
|
||||
// The current value of r.w is based on the max of a distribution of random
|
||||
@@ -167,7 +183,7 @@ func (r *randRes) advance() {
|
||||
// therefore the next r.w will be based on the same distribution (i.e.
|
||||
// `max(u_1,u_2,...,u_k)`). Therefore, we can sample the next r.w by
|
||||
// computing the next random number `u` and take r.w as `w * u^(1/k)`.
|
||||
r.w *= math.Exp(math.Log(random()) / float64(cap(r.store)))
|
||||
r.w *= math.Exp(math.Log(r.randomFloat64()) / float64(cap(r.store)))
|
||||
// Use the new random number in the series to calculate the count of the
|
||||
// next measurement that will be stored.
|
||||
//
|
||||
@@ -178,10 +194,13 @@ func (r *randRes) advance() {
|
||||
//
|
||||
// Important to note, the new r.next will always be at least 1 more than
|
||||
// the last r.next.
|
||||
r.next += int64(math.Log(random())/math.Log(1-r.w)) + 1
|
||||
r.next += int64(math.Log(r.randomFloat64())/math.Log(1-r.w)) + 1
|
||||
}
|
||||
|
||||
func (r *randRes) Collect(dest *[]Exemplar) {
|
||||
// Collect returns all the held exemplars.
|
||||
//
|
||||
// The Reservoir state is preserved after this call.
|
||||
func (r *FixedSizeReservoir) Collect(dest *[]Exemplar) {
|
||||
r.storage.Collect(dest)
|
||||
// Call reset here even though it will reset r.count and restart the random
|
||||
// number series. This will persist any old exemplars as long as no new
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user