mirror of
https://github.com/superseriousbusiness/gotosocial.git
synced 2025-12-09 18:28:07 -06:00
[feature] Support OTLP HTTP, drop Jaeger (#2184)
* [feature] Add http trace exporter, drop Jaeger Jaeger supports ingesting traces using the OpenTelemetry gRPC or HTTP methods. The Jaeger project has deprecated the old jaeger transport. * Add support for submitting traces over HTTP * Drop support for the old Jaeger protocol * Upgrade the trace libraries to v1.17 Fixes: #2176 Fixes: #2179
This commit is contained in:
parent
916c6d07ba
commit
14ef098099
199 changed files with 12972 additions and 18581 deletions
61
vendor/go.opentelemetry.io/otel/exporters/otlp/internal/wrappederror.go
generated
vendored
61
vendor/go.opentelemetry.io/otel/exporters/otlp/internal/wrappederror.go
generated
vendored
|
|
@ -1,61 +0,0 @@
|
|||
// 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.
|
||||
|
||||
package internal // import "go.opentelemetry.io/otel/exporters/otlp/internal"
|
||||
|
||||
// ErrorKind is used to identify the kind of export error
|
||||
// being wrapped.
|
||||
type ErrorKind int
|
||||
|
||||
const (
|
||||
// TracesExport indicates the error comes from the OTLP trace exporter.
|
||||
TracesExport ErrorKind = iota
|
||||
)
|
||||
|
||||
// prefix returns a prefix for the Error() string.
|
||||
func (k ErrorKind) prefix() string {
|
||||
switch k {
|
||||
case TracesExport:
|
||||
return "traces export: "
|
||||
default:
|
||||
return "unknown: "
|
||||
}
|
||||
}
|
||||
|
||||
// wrappedExportError wraps an OTLP exporter error with the kind of
|
||||
// signal that produced it.
|
||||
type wrappedExportError struct {
|
||||
wrap error
|
||||
kind ErrorKind
|
||||
}
|
||||
|
||||
// WrapTracesError wraps an error from the OTLP exporter for traces.
|
||||
func WrapTracesError(err error) error {
|
||||
return wrappedExportError{
|
||||
wrap: err,
|
||||
kind: TracesExport,
|
||||
}
|
||||
}
|
||||
|
||||
var _ error = wrappedExportError{}
|
||||
|
||||
// Error attaches a prefix corresponding to the kind of exporter.
|
||||
func (t wrappedExportError) Error() string {
|
||||
return t.kind.prefix() + t.wrap.Error()
|
||||
}
|
||||
|
||||
// Unwrap returns the wrapped error.
|
||||
func (t wrappedExportError) Unwrap() error {
|
||||
return t.wrap
|
||||
}
|
||||
4
vendor/go.opentelemetry.io/otel/exporters/otlp/otlptrace/exporter.go
generated
vendored
4
vendor/go.opentelemetry.io/otel/exporters/otlp/otlptrace/exporter.go
generated
vendored
|
|
@ -17,9 +17,9 @@ package otlptrace // import "go.opentelemetry.io/otel/exporters/otlp/otlptrace"
|
|||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"sync"
|
||||
|
||||
"go.opentelemetry.io/otel/exporters/otlp/internal"
|
||||
"go.opentelemetry.io/otel/exporters/otlp/otlptrace/internal/tracetransform"
|
||||
tracesdk "go.opentelemetry.io/otel/sdk/trace"
|
||||
)
|
||||
|
|
@ -48,7 +48,7 @@ func (e *Exporter) ExportSpans(ctx context.Context, ss []tracesdk.ReadOnlySpan)
|
|||
|
||||
err := e.client.UploadTraces(ctx, protoSpans)
|
||||
if err != nil {
|
||||
return internal.WrapTracesError(err)
|
||||
return fmt.Errorf("traces export: %w", err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
|
|
|||
7
vendor/go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc/client.go
generated
vendored
7
vendor/go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc/client.go
generated
vendored
|
|
@ -27,10 +27,10 @@ import (
|
|||
"google.golang.org/grpc/status"
|
||||
|
||||
"go.opentelemetry.io/otel"
|
||||
"go.opentelemetry.io/otel/exporters/otlp/internal"
|
||||
"go.opentelemetry.io/otel/exporters/otlp/internal/retry"
|
||||
"go.opentelemetry.io/otel/exporters/otlp/otlptrace"
|
||||
"go.opentelemetry.io/otel/exporters/otlp/otlptrace/internal/otlpconfig"
|
||||
"go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc/internal"
|
||||
"go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc/internal/otlpconfig"
|
||||
"go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc/internal/retry"
|
||||
coltracepb "go.opentelemetry.io/proto/otlp/collector/trace/v1"
|
||||
tracepb "go.opentelemetry.io/proto/otlp/trace/v1"
|
||||
)
|
||||
|
|
@ -259,7 +259,6 @@ func (c *client) exportContext(parent context.Context) (context.Context, context
|
|||
// retryable returns if err identifies a request that can be retried and a
|
||||
// duration to wait for if an explicit throttle time is included in err.
|
||||
func retryable(err error) (bool, time.Duration) {
|
||||
//func retryable(err error) (bool, time.Duration) {
|
||||
s := status.Convert(err)
|
||||
switch s.Code() {
|
||||
case codes.Canceled,
|
||||
|
|
|
|||
|
|
@ -1,3 +1,6 @@
|
|||
// Code created by gotmpl. DO NOT MODIFY.
|
||||
// source: internal/shared/otlp/envconfig/envconfig.go.tmpl
|
||||
|
||||
// Copyright The OpenTelemetry Authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
|
|
@ -12,7 +15,7 @@
|
|||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package envconfig // import "go.opentelemetry.io/otel/exporters/otlp/internal/envconfig"
|
||||
package envconfig // import "go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc/internal/envconfig"
|
||||
|
||||
import (
|
||||
"crypto/tls"
|
||||
35
vendor/go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc/internal/gen.go
generated
vendored
Normal file
35
vendor/go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc/internal/gen.go
generated
vendored
Normal file
|
|
@ -0,0 +1,35 @@
|
|||
// 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.
|
||||
|
||||
package internal // import "go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc/internal"
|
||||
|
||||
//go:generate gotmpl --body=../../../../../internal/shared/otlp/partialsuccess.go.tmpl "--data={}" --out=partialsuccess.go
|
||||
//go:generate gotmpl --body=../../../../../internal/shared/otlp/partialsuccess_test.go.tmpl "--data={}" --out=partialsuccess_test.go
|
||||
|
||||
//go:generate gotmpl --body=../../../../../internal/shared/otlp/retry/retry.go.tmpl "--data={}" --out=retry/retry.go
|
||||
//go:generate gotmpl --body=../../../../../internal/shared/otlp/retry/retry_test.go.tmpl "--data={}" --out=retry/retry_test.go
|
||||
|
||||
//go:generate gotmpl --body=../../../../../internal/shared/otlp/envconfig/envconfig.go.tmpl "--data={}" --out=envconfig/envconfig.go
|
||||
//go:generate gotmpl --body=../../../../../internal/shared/otlp/envconfig/envconfig_test.go.tmpl "--data={}" --out=envconfig/envconfig_test.go
|
||||
|
||||
//go:generate gotmpl --body=../../../../../internal/shared/otlp/otlptrace/otlpconfig/envconfig.go.tmpl "--data={\"envconfigImportPath\": \"go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc/internal/envconfig\"}" --out=otlpconfig/envconfig.go
|
||||
//go:generate gotmpl --body=../../../../../internal/shared/otlp/otlptrace/otlpconfig/options.go.tmpl "--data={\"retryImportPath\": \"go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc/internal/retry\"}" --out=otlpconfig/options.go
|
||||
//go:generate gotmpl --body=../../../../../internal/shared/otlp/otlptrace/otlpconfig/options_test.go.tmpl "--data={\"envconfigImportPath\": \"go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc/internal/envconfig\"}" --out=otlpconfig/options_test.go
|
||||
//go:generate gotmpl --body=../../../../../internal/shared/otlp/otlptrace/otlpconfig/optiontypes.go.tmpl "--data={}" --out=otlpconfig/optiontypes.go
|
||||
//go:generate gotmpl --body=../../../../../internal/shared/otlp/otlptrace/otlpconfig/tls.go.tmpl "--data={}" --out=otlpconfig/tls.go
|
||||
|
||||
//go:generate gotmpl --body=../../../../../internal/shared/otlp/otlptrace/otlptracetest/client.go.tmpl "--data={}" --out=otlptracetest/client.go
|
||||
//go:generate gotmpl --body=../../../../../internal/shared/otlp/otlptrace/otlptracetest/collector.go.tmpl "--data={}" --out=otlptracetest/collector.go
|
||||
//go:generate gotmpl --body=../../../../../internal/shared/otlp/otlptrace/otlptracetest/data.go.tmpl "--data={}" --out=otlptracetest/data.go
|
||||
//go:generate gotmpl --body=../../../../../internal/shared/otlp/otlptrace/otlptracetest/otlptest.go.tmpl "--data={}" --out=otlptracetest/otlptest.go
|
||||
|
|
@ -1,3 +1,6 @@
|
|||
// Code created by gotmpl. DO NOT MODIFY.
|
||||
// source: internal/shared/otlp/otlptrace/otlpconfig/envconfig.go.tmpl
|
||||
|
||||
// Copyright The OpenTelemetry Authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
|
|
@ -12,7 +15,7 @@
|
|||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package otlpconfig // import "go.opentelemetry.io/otel/exporters/otlp/otlptrace/internal/otlpconfig"
|
||||
package otlpconfig // import "go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc/internal/otlpconfig"
|
||||
|
||||
import (
|
||||
"crypto/tls"
|
||||
|
|
@ -23,7 +26,7 @@ import (
|
|||
"strings"
|
||||
"time"
|
||||
|
||||
"go.opentelemetry.io/otel/exporters/otlp/internal/envconfig"
|
||||
"go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc/internal/envconfig"
|
||||
)
|
||||
|
||||
// DefaultEnvOptionsReader is the default environments reader.
|
||||
|
|
@ -1,3 +1,6 @@
|
|||
// Code created by gotmpl. DO NOT MODIFY.
|
||||
// source: internal/shared/otlp/otlptrace/otlpconfig/options.go.tmpl
|
||||
|
||||
// Copyright The OpenTelemetry Authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
|
|
@ -12,11 +15,13 @@
|
|||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package otlpconfig // import "go.opentelemetry.io/otel/exporters/otlp/otlptrace/internal/otlpconfig"
|
||||
package otlpconfig // import "go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc/internal/otlpconfig"
|
||||
|
||||
import (
|
||||
"crypto/tls"
|
||||
"fmt"
|
||||
"path"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"google.golang.org/grpc"
|
||||
|
|
@ -25,9 +30,8 @@ import (
|
|||
"google.golang.org/grpc/credentials/insecure"
|
||||
"google.golang.org/grpc/encoding/gzip"
|
||||
|
||||
"go.opentelemetry.io/otel/exporters/otlp/internal"
|
||||
"go.opentelemetry.io/otel/exporters/otlp/internal/retry"
|
||||
otinternal "go.opentelemetry.io/otel/exporters/otlp/otlptrace/internal"
|
||||
"go.opentelemetry.io/otel/exporters/otlp/otlptrace"
|
||||
"go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc/internal/retry"
|
||||
)
|
||||
|
||||
const (
|
||||
|
|
@ -83,13 +87,28 @@ func NewHTTPConfig(opts ...HTTPOption) Config {
|
|||
for _, opt := range opts {
|
||||
cfg = opt.ApplyHTTPOption(cfg)
|
||||
}
|
||||
cfg.Traces.URLPath = internal.CleanPath(cfg.Traces.URLPath, DefaultTracesPath)
|
||||
cfg.Traces.URLPath = cleanPath(cfg.Traces.URLPath, DefaultTracesPath)
|
||||
return cfg
|
||||
}
|
||||
|
||||
// cleanPath returns a path with all spaces trimmed and all redundancies
|
||||
// removed. If urlPath is empty or cleaning it results in an empty string,
|
||||
// defaultPath is returned instead.
|
||||
func cleanPath(urlPath string, defaultPath string) string {
|
||||
tmp := path.Clean(strings.TrimSpace(urlPath))
|
||||
if tmp == "." {
|
||||
return defaultPath
|
||||
}
|
||||
if !path.IsAbs(tmp) {
|
||||
tmp = fmt.Sprintf("/%s", tmp)
|
||||
}
|
||||
return tmp
|
||||
}
|
||||
|
||||
// NewGRPCConfig returns a new Config with all settings applied from opts and
|
||||
// any unset setting using the default gRPC config values.
|
||||
func NewGRPCConfig(opts ...GRPCOption) Config {
|
||||
userAgent := "OTel OTLP Exporter Go/" + otlptrace.Version()
|
||||
cfg := Config{
|
||||
Traces: SignalConfig{
|
||||
Endpoint: fmt.Sprintf("%s:%d", DefaultCollectorHost, DefaultCollectorGRPCPort),
|
||||
|
|
@ -98,7 +117,7 @@ func NewGRPCConfig(opts ...GRPCOption) Config {
|
|||
Timeout: DefaultTimeout,
|
||||
},
|
||||
RetryConfig: retry.DefaultConfig,
|
||||
DialOptions: []grpc.DialOption{grpc.WithUserAgent(otinternal.GetUserAgentHeader())},
|
||||
DialOptions: []grpc.DialOption{grpc.WithUserAgent(userAgent)},
|
||||
}
|
||||
cfg = ApplyGRPCEnvConfigs(cfg)
|
||||
for _, opt := range opts {
|
||||
|
|
@ -1,3 +1,6 @@
|
|||
// Code created by gotmpl. DO NOT MODIFY.
|
||||
// source: internal/shared/otlp/otlptrace/otlpconfig/optiontypes.go.tmpl
|
||||
|
||||
// Copyright The OpenTelemetry Authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
|
|
@ -12,7 +15,7 @@
|
|||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package otlpconfig // import "go.opentelemetry.io/otel/exporters/otlp/otlptrace/internal/otlpconfig"
|
||||
package otlpconfig // import "go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc/internal/otlpconfig"
|
||||
|
||||
const (
|
||||
// DefaultCollectorGRPCPort is the default gRPC port of the collector.
|
||||
|
|
@ -1,3 +1,6 @@
|
|||
// Code created by gotmpl. DO NOT MODIFY.
|
||||
// source: internal/shared/otlp/otlptrace/otlpconfig/tls.go.tmpl
|
||||
|
||||
// Copyright The OpenTelemetry Authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
|
|
@ -12,7 +15,7 @@
|
|||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package otlpconfig // import "go.opentelemetry.io/otel/exporters/otlp/otlptrace/internal/otlpconfig"
|
||||
package otlpconfig // import "go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc/internal/otlpconfig"
|
||||
|
||||
import (
|
||||
"crypto/tls"
|
||||
|
|
@ -1,3 +1,6 @@
|
|||
// Code created by gotmpl. DO NOT MODIFY.
|
||||
// source: internal/shared/otlp/partialsuccess.go
|
||||
|
||||
// Copyright The OpenTelemetry Authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
|
|
@ -12,7 +15,7 @@
|
|||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package internal // import "go.opentelemetry.io/otel/exporters/otlp/internal"
|
||||
package internal // import "go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc/internal"
|
||||
|
||||
import "fmt"
|
||||
|
||||
|
|
@ -1,3 +1,6 @@
|
|||
// Code created by gotmpl. DO NOT MODIFY.
|
||||
// source: internal/shared/otlp/retry/retry.go.tmpl
|
||||
|
||||
// Copyright The OpenTelemetry Authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
|
|
@ -15,7 +18,7 @@
|
|||
// Package retry provides request retry functionality that can perform
|
||||
// configurable exponential backoff for transient errors and honor any
|
||||
// explicit throttle responses received.
|
||||
package retry // import "go.opentelemetry.io/otel/exporters/otlp/internal/retry"
|
||||
package retry // import "go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc/internal/retry"
|
||||
|
||||
import (
|
||||
"context"
|
||||
4
vendor/go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc/options.go
generated
vendored
4
vendor/go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc/options.go
generated
vendored
|
|
@ -22,8 +22,8 @@ import (
|
|||
"google.golang.org/grpc/credentials"
|
||||
|
||||
"go.opentelemetry.io/otel"
|
||||
"go.opentelemetry.io/otel/exporters/otlp/internal/retry"
|
||||
"go.opentelemetry.io/otel/exporters/otlp/otlptrace/internal/otlpconfig"
|
||||
"go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc/internal/otlpconfig"
|
||||
"go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc/internal/retry"
|
||||
)
|
||||
|
||||
// Option applies an option to the gRPC driver.
|
||||
|
|
|
|||
341
vendor/go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp/client.go
generated
vendored
Normal file
341
vendor/go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp/client.go
generated
vendored
Normal file
|
|
@ -0,0 +1,341 @@
|
|||
// 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.
|
||||
|
||||
package otlptracehttp // import "go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp"
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"compress/gzip"
|
||||
"context"
|
||||
"fmt"
|
||||
"io"
|
||||
"net"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"strconv"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"google.golang.org/protobuf/proto"
|
||||
|
||||
"go.opentelemetry.io/otel"
|
||||
"go.opentelemetry.io/otel/exporters/otlp/otlptrace"
|
||||
"go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp/internal"
|
||||
"go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp/internal/otlpconfig"
|
||||
"go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp/internal/retry"
|
||||
coltracepb "go.opentelemetry.io/proto/otlp/collector/trace/v1"
|
||||
tracepb "go.opentelemetry.io/proto/otlp/trace/v1"
|
||||
)
|
||||
|
||||
const contentTypeProto = "application/x-protobuf"
|
||||
|
||||
var gzPool = sync.Pool{
|
||||
New: func() interface{} {
|
||||
w := gzip.NewWriter(io.Discard)
|
||||
return w
|
||||
},
|
||||
}
|
||||
|
||||
// Keep it in sync with golang's DefaultTransport from net/http! We
|
||||
// have our own copy to avoid handling a situation where the
|
||||
// DefaultTransport is overwritten with some different implementation
|
||||
// of http.RoundTripper or it's modified by other package.
|
||||
var ourTransport = &http.Transport{
|
||||
Proxy: http.ProxyFromEnvironment,
|
||||
DialContext: (&net.Dialer{
|
||||
Timeout: 30 * time.Second,
|
||||
KeepAlive: 30 * time.Second,
|
||||
}).DialContext,
|
||||
ForceAttemptHTTP2: true,
|
||||
MaxIdleConns: 100,
|
||||
IdleConnTimeout: 90 * time.Second,
|
||||
TLSHandshakeTimeout: 10 * time.Second,
|
||||
ExpectContinueTimeout: 1 * time.Second,
|
||||
}
|
||||
|
||||
type client struct {
|
||||
name string
|
||||
cfg otlpconfig.SignalConfig
|
||||
generalCfg otlpconfig.Config
|
||||
requestFunc retry.RequestFunc
|
||||
client *http.Client
|
||||
stopCh chan struct{}
|
||||
stopOnce sync.Once
|
||||
}
|
||||
|
||||
var _ otlptrace.Client = (*client)(nil)
|
||||
|
||||
// NewClient creates a new HTTP trace client.
|
||||
func NewClient(opts ...Option) otlptrace.Client {
|
||||
cfg := otlpconfig.NewHTTPConfig(asHTTPOptions(opts)...)
|
||||
|
||||
httpClient := &http.Client{
|
||||
Transport: ourTransport,
|
||||
Timeout: cfg.Traces.Timeout,
|
||||
}
|
||||
if cfg.Traces.TLSCfg != nil {
|
||||
transport := ourTransport.Clone()
|
||||
transport.TLSClientConfig = cfg.Traces.TLSCfg
|
||||
httpClient.Transport = transport
|
||||
}
|
||||
|
||||
stopCh := make(chan struct{})
|
||||
return &client{
|
||||
name: "traces",
|
||||
cfg: cfg.Traces,
|
||||
generalCfg: cfg,
|
||||
requestFunc: cfg.RetryConfig.RequestFunc(evaluate),
|
||||
stopCh: stopCh,
|
||||
client: httpClient,
|
||||
}
|
||||
}
|
||||
|
||||
// Start does nothing in a HTTP client.
|
||||
func (d *client) Start(ctx context.Context) error {
|
||||
// nothing to do
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
return ctx.Err()
|
||||
default:
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Stop shuts down the client and interrupt any in-flight request.
|
||||
func (d *client) Stop(ctx context.Context) error {
|
||||
d.stopOnce.Do(func() {
|
||||
close(d.stopCh)
|
||||
})
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
return ctx.Err()
|
||||
default:
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// UploadTraces sends a batch of spans to the collector.
|
||||
func (d *client) UploadTraces(ctx context.Context, protoSpans []*tracepb.ResourceSpans) error {
|
||||
pbRequest := &coltracepb.ExportTraceServiceRequest{
|
||||
ResourceSpans: protoSpans,
|
||||
}
|
||||
rawRequest, err := proto.Marshal(pbRequest)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
ctx, cancel := d.contextWithStop(ctx)
|
||||
defer cancel()
|
||||
|
||||
request, err := d.newRequest(rawRequest)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return d.requestFunc(ctx, func(ctx context.Context) error {
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
return ctx.Err()
|
||||
default:
|
||||
}
|
||||
|
||||
request.reset(ctx)
|
||||
resp, err := d.client.Do(request.Request)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if resp != nil && resp.Body != nil {
|
||||
defer func() {
|
||||
if err := resp.Body.Close(); err != nil {
|
||||
otel.Handle(err)
|
||||
}
|
||||
}()
|
||||
}
|
||||
|
||||
switch sc := resp.StatusCode; {
|
||||
case sc >= 200 && sc <= 299:
|
||||
// Success, do not retry.
|
||||
// Read the partial success message, if any.
|
||||
var respData bytes.Buffer
|
||||
if _, err := io.Copy(&respData, resp.Body); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if respData.Len() != 0 {
|
||||
var respProto coltracepb.ExportTraceServiceResponse
|
||||
if err := proto.Unmarshal(respData.Bytes(), &respProto); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if respProto.PartialSuccess != nil {
|
||||
msg := respProto.PartialSuccess.GetErrorMessage()
|
||||
n := respProto.PartialSuccess.GetRejectedSpans()
|
||||
if n != 0 || msg != "" {
|
||||
err := internal.TracePartialSuccessError(n, msg)
|
||||
otel.Handle(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
|
||||
case sc == http.StatusTooManyRequests, sc == http.StatusServiceUnavailable:
|
||||
// Retry-able failures. Drain the body to reuse the connection.
|
||||
if _, err := io.Copy(io.Discard, resp.Body); err != nil {
|
||||
otel.Handle(err)
|
||||
}
|
||||
return newResponseError(resp.Header)
|
||||
default:
|
||||
return fmt.Errorf("failed to send to %s: %s", request.URL, resp.Status)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func (d *client) newRequest(body []byte) (request, error) {
|
||||
u := url.URL{Scheme: d.getScheme(), Host: d.cfg.Endpoint, Path: d.cfg.URLPath}
|
||||
r, err := http.NewRequest(http.MethodPost, u.String(), nil)
|
||||
if err != nil {
|
||||
return request{Request: r}, err
|
||||
}
|
||||
|
||||
userAgent := "OTel OTLP Exporter Go/" + otlptrace.Version()
|
||||
r.Header.Set("User-Agent", userAgent)
|
||||
|
||||
for k, v := range d.cfg.Headers {
|
||||
r.Header.Set(k, v)
|
||||
}
|
||||
r.Header.Set("Content-Type", contentTypeProto)
|
||||
|
||||
req := request{Request: r}
|
||||
switch Compression(d.cfg.Compression) {
|
||||
case NoCompression:
|
||||
r.ContentLength = (int64)(len(body))
|
||||
req.bodyReader = bodyReader(body)
|
||||
case GzipCompression:
|
||||
// Ensure the content length is not used.
|
||||
r.ContentLength = -1
|
||||
r.Header.Set("Content-Encoding", "gzip")
|
||||
|
||||
gz := gzPool.Get().(*gzip.Writer)
|
||||
defer gzPool.Put(gz)
|
||||
|
||||
var b bytes.Buffer
|
||||
gz.Reset(&b)
|
||||
|
||||
if _, err := gz.Write(body); err != nil {
|
||||
return req, err
|
||||
}
|
||||
// Close needs to be called to ensure body if fully written.
|
||||
if err := gz.Close(); err != nil {
|
||||
return req, err
|
||||
}
|
||||
|
||||
req.bodyReader = bodyReader(b.Bytes())
|
||||
}
|
||||
|
||||
return req, nil
|
||||
}
|
||||
|
||||
// MarshalLog is the marshaling function used by the logging system to represent this Client.
|
||||
func (d *client) MarshalLog() interface{} {
|
||||
return struct {
|
||||
Type string
|
||||
Endpoint string
|
||||
Insecure bool
|
||||
}{
|
||||
Type: "otlphttphttp",
|
||||
Endpoint: d.cfg.Endpoint,
|
||||
Insecure: d.cfg.Insecure,
|
||||
}
|
||||
}
|
||||
|
||||
// bodyReader returns a closure returning a new reader for buf.
|
||||
func bodyReader(buf []byte) func() io.ReadCloser {
|
||||
return func() io.ReadCloser {
|
||||
return io.NopCloser(bytes.NewReader(buf))
|
||||
}
|
||||
}
|
||||
|
||||
// request wraps an http.Request with a resettable body reader.
|
||||
type request struct {
|
||||
*http.Request
|
||||
|
||||
// bodyReader allows the same body to be used for multiple requests.
|
||||
bodyReader func() io.ReadCloser
|
||||
}
|
||||
|
||||
// reset reinitializes the request Body and uses ctx for the request.
|
||||
func (r *request) reset(ctx context.Context) {
|
||||
r.Body = r.bodyReader()
|
||||
r.Request = r.Request.WithContext(ctx)
|
||||
}
|
||||
|
||||
// retryableError represents a request failure that can be retried.
|
||||
type retryableError struct {
|
||||
throttle int64
|
||||
}
|
||||
|
||||
// newResponseError returns a retryableError and will extract any explicit
|
||||
// throttle delay contained in headers.
|
||||
func newResponseError(header http.Header) 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
|
||||
}
|
||||
}
|
||||
return rErr
|
||||
}
|
||||
|
||||
func (e retryableError) Error() string {
|
||||
return "retry-able request failure"
|
||||
}
|
||||
|
||||
// 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) {
|
||||
if err == nil {
|
||||
return false, 0
|
||||
}
|
||||
|
||||
rErr, ok := err.(retryableError)
|
||||
if !ok {
|
||||
return false, 0
|
||||
}
|
||||
|
||||
return true, time.Duration(rErr.throttle)
|
||||
}
|
||||
|
||||
func (d *client) getScheme() string {
|
||||
if d.cfg.Insecure {
|
||||
return "http"
|
||||
}
|
||||
return "https"
|
||||
}
|
||||
|
||||
func (d *client) contextWithStop(ctx context.Context) (context.Context, context.CancelFunc) {
|
||||
// Unify the parent context Done signal with the client's stop
|
||||
// channel.
|
||||
ctx, cancel := context.WithCancel(ctx)
|
||||
go func(ctx context.Context, cancel context.CancelFunc) {
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
// Nothing to do, either cancelled or deadline
|
||||
// happened.
|
||||
case <-d.stopCh:
|
||||
cancel()
|
||||
}
|
||||
}(ctx, cancel)
|
||||
return ctx, cancel
|
||||
}
|
||||
|
|
@ -12,23 +12,8 @@
|
|||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
// Package internal contains common functionality for all OTLP exporters.
|
||||
package internal // import "go.opentelemetry.io/otel/exporters/otlp/internal"
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"path"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// CleanPath returns a path with all spaces trimmed and all redundancies removed. If urlPath is empty or cleaning it results in an empty string, defaultPath is returned instead.
|
||||
func CleanPath(urlPath string, defaultPath string) string {
|
||||
tmp := path.Clean(strings.TrimSpace(urlPath))
|
||||
if tmp == "." {
|
||||
return defaultPath
|
||||
}
|
||||
if !path.IsAbs(tmp) {
|
||||
tmp = fmt.Sprintf("/%s", tmp)
|
||||
}
|
||||
return tmp
|
||||
}
|
||||
/*
|
||||
Package otlptracehttp a client that sends traces to the collector using HTTP
|
||||
with binary protobuf payloads.
|
||||
*/
|
||||
package otlptracehttp // import "go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp"
|
||||
|
|
@ -12,14 +12,20 @@
|
|||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package internal // import "go.opentelemetry.io/otel/exporters/otlp/otlptrace/internal"
|
||||
package otlptracehttp // import "go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp"
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"go.opentelemetry.io/otel/exporters/otlp/otlptrace"
|
||||
)
|
||||
|
||||
// GetUserAgentHeader returns an OTLP header value form "OTel OTLP Exporter Go/{{ .Version }}"
|
||||
// https://github.com/open-telemetry/opentelemetry-specification/blob/v1.20.0/specification/protocol/exporter.md#user-agent
|
||||
func GetUserAgentHeader() string {
|
||||
return "OTel OTLP Exporter Go/" + otlptrace.Version()
|
||||
// New constructs a new Exporter and starts it.
|
||||
func New(ctx context.Context, opts ...Option) (*otlptrace.Exporter, error) {
|
||||
return otlptrace.New(ctx, NewClient(opts...))
|
||||
}
|
||||
|
||||
// NewUnstarted constructs a new Exporter and does not start it.
|
||||
func NewUnstarted(opts ...Option) *otlptrace.Exporter {
|
||||
return otlptrace.NewUnstarted(NewClient(opts...))
|
||||
}
|
||||
202
vendor/go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp/internal/envconfig/envconfig.go
generated
vendored
Normal file
202
vendor/go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp/internal/envconfig/envconfig.go
generated
vendored
Normal file
|
|
@ -0,0 +1,202 @@
|
|||
// Code created by gotmpl. DO NOT MODIFY.
|
||||
// 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.
|
||||
|
||||
package envconfig // import "go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp/internal/envconfig"
|
||||
|
||||
import (
|
||||
"crypto/tls"
|
||||
"crypto/x509"
|
||||
"errors"
|
||||
"fmt"
|
||||
"net/url"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"go.opentelemetry.io/otel/internal/global"
|
||||
)
|
||||
|
||||
// ConfigFn is the generic function used to set a config.
|
||||
type ConfigFn func(*EnvOptionsReader)
|
||||
|
||||
// EnvOptionsReader reads the required environment variables.
|
||||
type EnvOptionsReader struct {
|
||||
GetEnv func(string) string
|
||||
ReadFile func(string) ([]byte, error)
|
||||
Namespace string
|
||||
}
|
||||
|
||||
// Apply runs every ConfigFn.
|
||||
func (e *EnvOptionsReader) Apply(opts ...ConfigFn) {
|
||||
for _, o := range opts {
|
||||
o(e)
|
||||
}
|
||||
}
|
||||
|
||||
// GetEnvValue gets an OTLP environment variable value of the specified key
|
||||
// using the GetEnv function.
|
||||
// This function prepends the OTLP specified namespace to all key lookups.
|
||||
func (e *EnvOptionsReader) GetEnvValue(key string) (string, bool) {
|
||||
v := strings.TrimSpace(e.GetEnv(keyWithNamespace(e.Namespace, key)))
|
||||
return v, v != ""
|
||||
}
|
||||
|
||||
// WithString retrieves the specified config and passes it to ConfigFn as a string.
|
||||
func WithString(n string, fn func(string)) func(e *EnvOptionsReader) {
|
||||
return func(e *EnvOptionsReader) {
|
||||
if v, ok := e.GetEnvValue(n); ok {
|
||||
fn(v)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// WithBool returns a ConfigFn that reads the environment variable n and if it exists passes its parsed bool value to fn.
|
||||
func WithBool(n string, fn func(bool)) ConfigFn {
|
||||
return func(e *EnvOptionsReader) {
|
||||
if v, ok := e.GetEnvValue(n); ok {
|
||||
b := strings.ToLower(v) == "true"
|
||||
fn(b)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// WithDuration retrieves the specified config and passes it to ConfigFn as a duration.
|
||||
func WithDuration(n string, fn func(time.Duration)) func(e *EnvOptionsReader) {
|
||||
return func(e *EnvOptionsReader) {
|
||||
if v, ok := e.GetEnvValue(n); ok {
|
||||
d, err := strconv.Atoi(v)
|
||||
if err != nil {
|
||||
global.Error(err, "parse duration", "input", v)
|
||||
return
|
||||
}
|
||||
fn(time.Duration(d) * time.Millisecond)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// WithHeaders retrieves the specified config and passes it to ConfigFn as a map of HTTP headers.
|
||||
func WithHeaders(n string, fn func(map[string]string)) func(e *EnvOptionsReader) {
|
||||
return func(e *EnvOptionsReader) {
|
||||
if v, ok := e.GetEnvValue(n); ok {
|
||||
fn(stringToHeader(v))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// WithURL retrieves the specified config and passes it to ConfigFn as a net/url.URL.
|
||||
func WithURL(n string, fn func(*url.URL)) func(e *EnvOptionsReader) {
|
||||
return func(e *EnvOptionsReader) {
|
||||
if v, ok := e.GetEnvValue(n); ok {
|
||||
u, err := url.Parse(v)
|
||||
if err != nil {
|
||||
global.Error(err, "parse url", "input", v)
|
||||
return
|
||||
}
|
||||
fn(u)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// WithCertPool returns a ConfigFn that reads the environment variable n as a filepath to a TLS certificate pool. If it exists, it is parsed as a crypto/x509.CertPool and it is passed to fn.
|
||||
func WithCertPool(n string, fn func(*x509.CertPool)) ConfigFn {
|
||||
return func(e *EnvOptionsReader) {
|
||||
if v, ok := e.GetEnvValue(n); ok {
|
||||
b, err := e.ReadFile(v)
|
||||
if err != nil {
|
||||
global.Error(err, "read tls ca cert file", "file", v)
|
||||
return
|
||||
}
|
||||
c, err := createCertPool(b)
|
||||
if err != nil {
|
||||
global.Error(err, "create tls cert pool")
|
||||
return
|
||||
}
|
||||
fn(c)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// WithClientCert returns a ConfigFn that reads the environment variable nc and nk as filepaths to a client certificate and key pair. If they exists, they are parsed as a crypto/tls.Certificate and it is passed to fn.
|
||||
func WithClientCert(nc, nk string, fn func(tls.Certificate)) ConfigFn {
|
||||
return func(e *EnvOptionsReader) {
|
||||
vc, okc := e.GetEnvValue(nc)
|
||||
vk, okk := e.GetEnvValue(nk)
|
||||
if !okc || !okk {
|
||||
return
|
||||
}
|
||||
cert, err := e.ReadFile(vc)
|
||||
if err != nil {
|
||||
global.Error(err, "read tls client cert", "file", vc)
|
||||
return
|
||||
}
|
||||
key, err := e.ReadFile(vk)
|
||||
if err != nil {
|
||||
global.Error(err, "read tls client key", "file", vk)
|
||||
return
|
||||
}
|
||||
crt, err := tls.X509KeyPair(cert, key)
|
||||
if err != nil {
|
||||
global.Error(err, "create tls client key pair")
|
||||
return
|
||||
}
|
||||
fn(crt)
|
||||
}
|
||||
}
|
||||
|
||||
func keyWithNamespace(ns, key string) string {
|
||||
if ns == "" {
|
||||
return key
|
||||
}
|
||||
return fmt.Sprintf("%s_%s", ns, key)
|
||||
}
|
||||
|
||||
func stringToHeader(value string) map[string]string {
|
||||
headersPairs := strings.Split(value, ",")
|
||||
headers := make(map[string]string)
|
||||
|
||||
for _, header := range headersPairs {
|
||||
n, v, found := strings.Cut(header, "=")
|
||||
if !found {
|
||||
global.Error(errors.New("missing '="), "parse headers", "input", header)
|
||||
continue
|
||||
}
|
||||
name, err := url.QueryUnescape(n)
|
||||
if err != nil {
|
||||
global.Error(err, "escape header key", "key", n)
|
||||
continue
|
||||
}
|
||||
trimmedName := strings.TrimSpace(name)
|
||||
value, err := url.QueryUnescape(v)
|
||||
if err != nil {
|
||||
global.Error(err, "escape header value", "value", v)
|
||||
continue
|
||||
}
|
||||
trimmedValue := strings.TrimSpace(value)
|
||||
|
||||
headers[trimmedName] = trimmedValue
|
||||
}
|
||||
|
||||
return headers
|
||||
}
|
||||
|
||||
func createCertPool(certBytes []byte) (*x509.CertPool, error) {
|
||||
cp := x509.NewCertPool()
|
||||
if ok := cp.AppendCertsFromPEM(certBytes); !ok {
|
||||
return nil, errors.New("failed to append certificate to the cert pool")
|
||||
}
|
||||
return cp, nil
|
||||
}
|
||||
35
vendor/go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp/internal/gen.go
generated
vendored
Normal file
35
vendor/go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp/internal/gen.go
generated
vendored
Normal file
|
|
@ -0,0 +1,35 @@
|
|||
// 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.
|
||||
|
||||
package internal // import "go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp/internal"
|
||||
|
||||
//go:generate gotmpl --body=../../../../../internal/shared/otlp/partialsuccess.go.tmpl "--data={}" --out=partialsuccess.go
|
||||
//go:generate gotmpl --body=../../../../../internal/shared/otlp/partialsuccess_test.go.tmpl "--data={}" --out=partialsuccess_test.go
|
||||
|
||||
//go:generate gotmpl --body=../../../../../internal/shared/otlp/retry/retry.go.tmpl "--data={}" --out=retry/retry.go
|
||||
//go:generate gotmpl --body=../../../../../internal/shared/otlp/retry/retry_test.go.tmpl "--data={}" --out=retry/retry_test.go
|
||||
|
||||
//go:generate gotmpl --body=../../../../../internal/shared/otlp/envconfig/envconfig.go.tmpl "--data={}" --out=envconfig/envconfig.go
|
||||
//go:generate gotmpl --body=../../../../../internal/shared/otlp/envconfig/envconfig_test.go.tmpl "--data={}" --out=envconfig/envconfig_test.go
|
||||
|
||||
//go:generate gotmpl --body=../../../../../internal/shared/otlp/otlptrace/otlpconfig/envconfig.go.tmpl "--data={\"envconfigImportPath\": \"go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp/internal/envconfig\"}" --out=otlpconfig/envconfig.go
|
||||
//go:generate gotmpl --body=../../../../../internal/shared/otlp/otlptrace/otlpconfig/options.go.tmpl "--data={\"retryImportPath\": \"go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp/internal/retry\"}" --out=otlpconfig/options.go
|
||||
//go:generate gotmpl --body=../../../../../internal/shared/otlp/otlptrace/otlpconfig/options_test.go.tmpl "--data={\"envconfigImportPath\": \"go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp/internal/envconfig\"}" --out=otlpconfig/options_test.go
|
||||
//go:generate gotmpl --body=../../../../../internal/shared/otlp/otlptrace/otlpconfig/optiontypes.go.tmpl "--data={}" --out=otlpconfig/optiontypes.go
|
||||
//go:generate gotmpl --body=../../../../../internal/shared/otlp/otlptrace/otlpconfig/tls.go.tmpl "--data={}" --out=otlpconfig/tls.go
|
||||
|
||||
//go:generate gotmpl --body=../../../../../internal/shared/otlp/otlptrace/otlptracetest/client.go.tmpl "--data={}" --out=otlptracetest/client.go
|
||||
//go:generate gotmpl --body=../../../../../internal/shared/otlp/otlptrace/otlptracetest/collector.go.tmpl "--data={}" --out=otlptracetest/collector.go
|
||||
//go:generate gotmpl --body=../../../../../internal/shared/otlp/otlptrace/otlptracetest/data.go.tmpl "--data={}" --out=otlptracetest/data.go
|
||||
//go:generate gotmpl --body=../../../../../internal/shared/otlp/otlptrace/otlptracetest/otlptest.go.tmpl "--data={}" --out=otlptracetest/otlptest.go
|
||||
153
vendor/go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp/internal/otlpconfig/envconfig.go
generated
vendored
Normal file
153
vendor/go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp/internal/otlpconfig/envconfig.go
generated
vendored
Normal file
|
|
@ -0,0 +1,153 @@
|
|||
// Code created by gotmpl. DO NOT MODIFY.
|
||||
// source: internal/shared/otlp/otlptrace/otlpconfig/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.
|
||||
|
||||
package otlpconfig // import "go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp/internal/otlpconfig"
|
||||
|
||||
import (
|
||||
"crypto/tls"
|
||||
"crypto/x509"
|
||||
"net/url"
|
||||
"os"
|
||||
"path"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp/internal/envconfig"
|
||||
)
|
||||
|
||||
// DefaultEnvOptionsReader is the default environments reader.
|
||||
var DefaultEnvOptionsReader = envconfig.EnvOptionsReader{
|
||||
GetEnv: os.Getenv,
|
||||
ReadFile: os.ReadFile,
|
||||
Namespace: "OTEL_EXPORTER_OTLP",
|
||||
}
|
||||
|
||||
// ApplyGRPCEnvConfigs applies the env configurations for gRPC.
|
||||
func ApplyGRPCEnvConfigs(cfg Config) Config {
|
||||
opts := getOptionsFromEnv()
|
||||
for _, opt := range opts {
|
||||
cfg = opt.ApplyGRPCOption(cfg)
|
||||
}
|
||||
return cfg
|
||||
}
|
||||
|
||||
// ApplyHTTPEnvConfigs applies the env configurations for HTTP.
|
||||
func ApplyHTTPEnvConfigs(cfg Config) Config {
|
||||
opts := getOptionsFromEnv()
|
||||
for _, opt := range opts {
|
||||
cfg = opt.ApplyHTTPOption(cfg)
|
||||
}
|
||||
return cfg
|
||||
}
|
||||
|
||||
func getOptionsFromEnv() []GenericOption {
|
||||
opts := []GenericOption{}
|
||||
|
||||
tlsConf := &tls.Config{}
|
||||
DefaultEnvOptionsReader.Apply(
|
||||
envconfig.WithURL("ENDPOINT", func(u *url.URL) {
|
||||
opts = append(opts, withEndpointScheme(u))
|
||||
opts = append(opts, newSplitOption(func(cfg Config) Config {
|
||||
cfg.Traces.Endpoint = u.Host
|
||||
// For OTLP/HTTP endpoint URLs without a per-signal
|
||||
// configuration, the passed endpoint is used as a base URL
|
||||
// and the signals are sent to these paths relative to that.
|
||||
cfg.Traces.URLPath = path.Join(u.Path, DefaultTracesPath)
|
||||
return cfg
|
||||
}, withEndpointForGRPC(u)))
|
||||
}),
|
||||
envconfig.WithURL("TRACES_ENDPOINT", func(u *url.URL) {
|
||||
opts = append(opts, withEndpointScheme(u))
|
||||
opts = append(opts, newSplitOption(func(cfg Config) Config {
|
||||
cfg.Traces.Endpoint = u.Host
|
||||
// For endpoint URLs for OTLP/HTTP per-signal variables, the
|
||||
// URL MUST be used as-is without any modification. The only
|
||||
// exception is that if an URL contains no path part, the root
|
||||
// path / MUST be used.
|
||||
path := u.Path
|
||||
if path == "" {
|
||||
path = "/"
|
||||
}
|
||||
cfg.Traces.URLPath = path
|
||||
return cfg
|
||||
}, withEndpointForGRPC(u)))
|
||||
}),
|
||||
envconfig.WithCertPool("CERTIFICATE", func(p *x509.CertPool) { tlsConf.RootCAs = p }),
|
||||
envconfig.WithCertPool("TRACES_CERTIFICATE", func(p *x509.CertPool) { tlsConf.RootCAs = p }),
|
||||
envconfig.WithClientCert("CLIENT_CERTIFICATE", "CLIENT_KEY", func(c tls.Certificate) { tlsConf.Certificates = []tls.Certificate{c} }),
|
||||
envconfig.WithClientCert("TRACES_CLIENT_CERTIFICATE", "TRACES_CLIENT_KEY", func(c tls.Certificate) { tlsConf.Certificates = []tls.Certificate{c} }),
|
||||
withTLSConfig(tlsConf, func(c *tls.Config) { opts = append(opts, WithTLSClientConfig(c)) }),
|
||||
envconfig.WithBool("INSECURE", func(b bool) { opts = append(opts, withInsecure(b)) }),
|
||||
envconfig.WithBool("TRACES_INSECURE", func(b bool) { opts = append(opts, withInsecure(b)) }),
|
||||
envconfig.WithHeaders("HEADERS", func(h map[string]string) { opts = append(opts, WithHeaders(h)) }),
|
||||
envconfig.WithHeaders("TRACES_HEADERS", func(h map[string]string) { opts = append(opts, WithHeaders(h)) }),
|
||||
WithEnvCompression("COMPRESSION", func(c Compression) { opts = append(opts, WithCompression(c)) }),
|
||||
WithEnvCompression("TRACES_COMPRESSION", func(c Compression) { opts = append(opts, WithCompression(c)) }),
|
||||
envconfig.WithDuration("TIMEOUT", func(d time.Duration) { opts = append(opts, WithTimeout(d)) }),
|
||||
envconfig.WithDuration("TRACES_TIMEOUT", func(d time.Duration) { opts = append(opts, WithTimeout(d)) }),
|
||||
)
|
||||
|
||||
return opts
|
||||
}
|
||||
|
||||
func withEndpointScheme(u *url.URL) GenericOption {
|
||||
switch strings.ToLower(u.Scheme) {
|
||||
case "http", "unix":
|
||||
return WithInsecure()
|
||||
default:
|
||||
return WithSecure()
|
||||
}
|
||||
}
|
||||
|
||||
func withEndpointForGRPC(u *url.URL) func(cfg Config) Config {
|
||||
return func(cfg Config) Config {
|
||||
// For OTLP/gRPC endpoints, this is the target to which the
|
||||
// exporter is going to send telemetry.
|
||||
cfg.Traces.Endpoint = path.Join(u.Host, u.Path)
|
||||
return cfg
|
||||
}
|
||||
}
|
||||
|
||||
// WithEnvCompression retrieves the specified config and passes it to ConfigFn as a Compression.
|
||||
func WithEnvCompression(n string, fn func(Compression)) func(e *envconfig.EnvOptionsReader) {
|
||||
return func(e *envconfig.EnvOptionsReader) {
|
||||
if v, ok := e.GetEnvValue(n); ok {
|
||||
cp := NoCompression
|
||||
if v == "gzip" {
|
||||
cp = GzipCompression
|
||||
}
|
||||
|
||||
fn(cp)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// revive:disable-next-line:flag-parameter
|
||||
func withInsecure(b bool) GenericOption {
|
||||
if b {
|
||||
return WithInsecure()
|
||||
}
|
||||
return WithSecure()
|
||||
}
|
||||
|
||||
func withTLSConfig(c *tls.Config, fn func(*tls.Config)) func(e *envconfig.EnvOptionsReader) {
|
||||
return func(e *envconfig.EnvOptionsReader) {
|
||||
if c.RootCAs != nil || len(c.Certificates) > 0 {
|
||||
fn(c)
|
||||
}
|
||||
}
|
||||
}
|
||||
328
vendor/go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp/internal/otlpconfig/options.go
generated
vendored
Normal file
328
vendor/go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp/internal/otlpconfig/options.go
generated
vendored
Normal file
|
|
@ -0,0 +1,328 @@
|
|||
// Code created by gotmpl. DO NOT MODIFY.
|
||||
// source: internal/shared/otlp/otlptrace/otlpconfig/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.
|
||||
|
||||
package otlpconfig // import "go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp/internal/otlpconfig"
|
||||
|
||||
import (
|
||||
"crypto/tls"
|
||||
"fmt"
|
||||
"path"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"google.golang.org/grpc"
|
||||
"google.golang.org/grpc/backoff"
|
||||
"google.golang.org/grpc/credentials"
|
||||
"google.golang.org/grpc/credentials/insecure"
|
||||
"google.golang.org/grpc/encoding/gzip"
|
||||
|
||||
"go.opentelemetry.io/otel/exporters/otlp/otlptrace"
|
||||
"go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp/internal/retry"
|
||||
)
|
||||
|
||||
const (
|
||||
// DefaultTracesPath is a default URL path for endpoint that
|
||||
// receives spans.
|
||||
DefaultTracesPath string = "/v1/traces"
|
||||
// DefaultTimeout is a default max waiting time for the backend to process
|
||||
// each span batch.
|
||||
DefaultTimeout time.Duration = 10 * time.Second
|
||||
)
|
||||
|
||||
type (
|
||||
SignalConfig struct {
|
||||
Endpoint string
|
||||
Insecure bool
|
||||
TLSCfg *tls.Config
|
||||
Headers map[string]string
|
||||
Compression Compression
|
||||
Timeout time.Duration
|
||||
URLPath string
|
||||
|
||||
// gRPC configurations
|
||||
GRPCCredentials credentials.TransportCredentials
|
||||
}
|
||||
|
||||
Config struct {
|
||||
// Signal specific configurations
|
||||
Traces SignalConfig
|
||||
|
||||
RetryConfig retry.Config
|
||||
|
||||
// gRPC configurations
|
||||
ReconnectionPeriod time.Duration
|
||||
ServiceConfig string
|
||||
DialOptions []grpc.DialOption
|
||||
GRPCConn *grpc.ClientConn
|
||||
}
|
||||
)
|
||||
|
||||
// NewHTTPConfig returns a new Config with all settings applied from opts and
|
||||
// any unset setting using the default HTTP config values.
|
||||
func NewHTTPConfig(opts ...HTTPOption) Config {
|
||||
cfg := Config{
|
||||
Traces: SignalConfig{
|
||||
Endpoint: fmt.Sprintf("%s:%d", DefaultCollectorHost, DefaultCollectorHTTPPort),
|
||||
URLPath: DefaultTracesPath,
|
||||
Compression: NoCompression,
|
||||
Timeout: DefaultTimeout,
|
||||
},
|
||||
RetryConfig: retry.DefaultConfig,
|
||||
}
|
||||
cfg = ApplyHTTPEnvConfigs(cfg)
|
||||
for _, opt := range opts {
|
||||
cfg = opt.ApplyHTTPOption(cfg)
|
||||
}
|
||||
cfg.Traces.URLPath = cleanPath(cfg.Traces.URLPath, DefaultTracesPath)
|
||||
return cfg
|
||||
}
|
||||
|
||||
// cleanPath returns a path with all spaces trimmed and all redundancies
|
||||
// removed. If urlPath is empty or cleaning it results in an empty string,
|
||||
// defaultPath is returned instead.
|
||||
func cleanPath(urlPath string, defaultPath string) string {
|
||||
tmp := path.Clean(strings.TrimSpace(urlPath))
|
||||
if tmp == "." {
|
||||
return defaultPath
|
||||
}
|
||||
if !path.IsAbs(tmp) {
|
||||
tmp = fmt.Sprintf("/%s", tmp)
|
||||
}
|
||||
return tmp
|
||||
}
|
||||
|
||||
// NewGRPCConfig returns a new Config with all settings applied from opts and
|
||||
// any unset setting using the default gRPC config values.
|
||||
func NewGRPCConfig(opts ...GRPCOption) Config {
|
||||
userAgent := "OTel OTLP Exporter Go/" + otlptrace.Version()
|
||||
cfg := Config{
|
||||
Traces: SignalConfig{
|
||||
Endpoint: fmt.Sprintf("%s:%d", DefaultCollectorHost, DefaultCollectorGRPCPort),
|
||||
URLPath: DefaultTracesPath,
|
||||
Compression: NoCompression,
|
||||
Timeout: DefaultTimeout,
|
||||
},
|
||||
RetryConfig: retry.DefaultConfig,
|
||||
DialOptions: []grpc.DialOption{grpc.WithUserAgent(userAgent)},
|
||||
}
|
||||
cfg = ApplyGRPCEnvConfigs(cfg)
|
||||
for _, opt := range opts {
|
||||
cfg = opt.ApplyGRPCOption(cfg)
|
||||
}
|
||||
|
||||
if cfg.ServiceConfig != "" {
|
||||
cfg.DialOptions = append(cfg.DialOptions, grpc.WithDefaultServiceConfig(cfg.ServiceConfig))
|
||||
}
|
||||
// Priroritize 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 {
|
||||
cfg.DialOptions = append(cfg.DialOptions, grpc.WithTransportCredentials(insecure.NewCredentials()))
|
||||
} else {
|
||||
// Default to using the host's root CA.
|
||||
creds := credentials.NewTLS(nil)
|
||||
cfg.Traces.GRPCCredentials = creds
|
||||
cfg.DialOptions = append(cfg.DialOptions, grpc.WithTransportCredentials(creds))
|
||||
}
|
||||
if cfg.Traces.Compression == GzipCompression {
|
||||
cfg.DialOptions = append(cfg.DialOptions, grpc.WithDefaultCallOptions(grpc.UseCompressor(gzip.Name)))
|
||||
}
|
||||
if len(cfg.DialOptions) != 0 {
|
||||
cfg.DialOptions = append(cfg.DialOptions, cfg.DialOptions...)
|
||||
}
|
||||
if cfg.ReconnectionPeriod != 0 {
|
||||
p := grpc.ConnectParams{
|
||||
Backoff: backoff.DefaultConfig,
|
||||
MinConnectTimeout: cfg.ReconnectionPeriod,
|
||||
}
|
||||
cfg.DialOptions = append(cfg.DialOptions, grpc.WithConnectParams(p))
|
||||
}
|
||||
|
||||
return cfg
|
||||
}
|
||||
|
||||
type (
|
||||
// GenericOption applies an option to the HTTP or gRPC driver.
|
||||
GenericOption interface {
|
||||
ApplyHTTPOption(Config) Config
|
||||
ApplyGRPCOption(Config) Config
|
||||
|
||||
// A private method to prevent users implementing the
|
||||
// interface and so future additions to it will not
|
||||
// violate compatibility.
|
||||
private()
|
||||
}
|
||||
|
||||
// HTTPOption applies an option to the HTTP driver.
|
||||
HTTPOption interface {
|
||||
ApplyHTTPOption(Config) Config
|
||||
|
||||
// A private method to prevent users implementing the
|
||||
// interface and so future additions to it will not
|
||||
// violate compatibility.
|
||||
private()
|
||||
}
|
||||
|
||||
// GRPCOption applies an option to the gRPC driver.
|
||||
GRPCOption interface {
|
||||
ApplyGRPCOption(Config) Config
|
||||
|
||||
// A private method to prevent users implementing the
|
||||
// interface and so future additions to it will not
|
||||
// violate compatibility.
|
||||
private()
|
||||
}
|
||||
)
|
||||
|
||||
// genericOption is an option that applies the same logic
|
||||
// for both gRPC and HTTP.
|
||||
type genericOption struct {
|
||||
fn func(Config) Config
|
||||
}
|
||||
|
||||
func (g *genericOption) ApplyGRPCOption(cfg Config) Config {
|
||||
return g.fn(cfg)
|
||||
}
|
||||
|
||||
func (g *genericOption) ApplyHTTPOption(cfg Config) Config {
|
||||
return g.fn(cfg)
|
||||
}
|
||||
|
||||
func (genericOption) private() {}
|
||||
|
||||
func newGenericOption(fn func(cfg Config) Config) GenericOption {
|
||||
return &genericOption{fn: fn}
|
||||
}
|
||||
|
||||
// splitOption is an option that applies different logics
|
||||
// for gRPC and HTTP.
|
||||
type splitOption struct {
|
||||
httpFn func(Config) Config
|
||||
grpcFn func(Config) Config
|
||||
}
|
||||
|
||||
func (g *splitOption) ApplyGRPCOption(cfg Config) Config {
|
||||
return g.grpcFn(cfg)
|
||||
}
|
||||
|
||||
func (g *splitOption) ApplyHTTPOption(cfg Config) Config {
|
||||
return g.httpFn(cfg)
|
||||
}
|
||||
|
||||
func (splitOption) private() {}
|
||||
|
||||
func newSplitOption(httpFn func(cfg Config) Config, grpcFn func(cfg Config) Config) GenericOption {
|
||||
return &splitOption{httpFn: httpFn, grpcFn: grpcFn}
|
||||
}
|
||||
|
||||
// httpOption is an option that is only applied to the HTTP driver.
|
||||
type httpOption struct {
|
||||
fn func(Config) Config
|
||||
}
|
||||
|
||||
func (h *httpOption) ApplyHTTPOption(cfg Config) Config {
|
||||
return h.fn(cfg)
|
||||
}
|
||||
|
||||
func (httpOption) private() {}
|
||||
|
||||
func NewHTTPOption(fn func(cfg Config) Config) HTTPOption {
|
||||
return &httpOption{fn: fn}
|
||||
}
|
||||
|
||||
// grpcOption is an option that is only applied to the gRPC driver.
|
||||
type grpcOption struct {
|
||||
fn func(Config) Config
|
||||
}
|
||||
|
||||
func (h *grpcOption) ApplyGRPCOption(cfg Config) Config {
|
||||
return h.fn(cfg)
|
||||
}
|
||||
|
||||
func (grpcOption) private() {}
|
||||
|
||||
func NewGRPCOption(fn func(cfg Config) Config) GRPCOption {
|
||||
return &grpcOption{fn: fn}
|
||||
}
|
||||
|
||||
// Generic Options
|
||||
|
||||
func WithEndpoint(endpoint string) GenericOption {
|
||||
return newGenericOption(func(cfg Config) Config {
|
||||
cfg.Traces.Endpoint = endpoint
|
||||
return cfg
|
||||
})
|
||||
}
|
||||
|
||||
func WithCompression(compression Compression) GenericOption {
|
||||
return newGenericOption(func(cfg Config) Config {
|
||||
cfg.Traces.Compression = compression
|
||||
return cfg
|
||||
})
|
||||
}
|
||||
|
||||
func WithURLPath(urlPath string) GenericOption {
|
||||
return newGenericOption(func(cfg Config) Config {
|
||||
cfg.Traces.URLPath = urlPath
|
||||
return cfg
|
||||
})
|
||||
}
|
||||
|
||||
func WithRetry(rc retry.Config) GenericOption {
|
||||
return newGenericOption(func(cfg Config) Config {
|
||||
cfg.RetryConfig = rc
|
||||
return cfg
|
||||
})
|
||||
}
|
||||
|
||||
func WithTLSClientConfig(tlsCfg *tls.Config) GenericOption {
|
||||
return newSplitOption(func(cfg Config) Config {
|
||||
cfg.Traces.TLSCfg = tlsCfg.Clone()
|
||||
return cfg
|
||||
}, func(cfg Config) Config {
|
||||
cfg.Traces.GRPCCredentials = credentials.NewTLS(tlsCfg)
|
||||
return cfg
|
||||
})
|
||||
}
|
||||
|
||||
func WithInsecure() GenericOption {
|
||||
return newGenericOption(func(cfg Config) Config {
|
||||
cfg.Traces.Insecure = true
|
||||
return cfg
|
||||
})
|
||||
}
|
||||
|
||||
func WithSecure() GenericOption {
|
||||
return newGenericOption(func(cfg Config) Config {
|
||||
cfg.Traces.Insecure = false
|
||||
return cfg
|
||||
})
|
||||
}
|
||||
|
||||
func WithHeaders(headers map[string]string) GenericOption {
|
||||
return newGenericOption(func(cfg Config) Config {
|
||||
cfg.Traces.Headers = headers
|
||||
return cfg
|
||||
})
|
||||
}
|
||||
|
||||
func WithTimeout(duration time.Duration) GenericOption {
|
||||
return newGenericOption(func(cfg Config) Config {
|
||||
cfg.Traces.Timeout = duration
|
||||
return cfg
|
||||
})
|
||||
}
|
||||
51
vendor/go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp/internal/otlpconfig/optiontypes.go
generated
vendored
Normal file
51
vendor/go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp/internal/otlpconfig/optiontypes.go
generated
vendored
Normal file
|
|
@ -0,0 +1,51 @@
|
|||
// Code created by gotmpl. DO NOT MODIFY.
|
||||
// source: internal/shared/otlp/otlptrace/otlpconfig/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.
|
||||
|
||||
package otlpconfig // import "go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp/internal/otlpconfig"
|
||||
|
||||
const (
|
||||
// DefaultCollectorGRPCPort is the default gRPC port of the collector.
|
||||
DefaultCollectorGRPCPort uint16 = 4317
|
||||
// DefaultCollectorHTTPPort is the default HTTP port of the collector.
|
||||
DefaultCollectorHTTPPort uint16 = 4318
|
||||
// DefaultCollectorHost is the host address the Exporter will attempt
|
||||
// connect to if no collector address is provided.
|
||||
DefaultCollectorHost string = "localhost"
|
||||
)
|
||||
|
||||
// Compression describes the compression used for payloads sent to the
|
||||
// collector.
|
||||
type Compression int
|
||||
|
||||
const (
|
||||
// NoCompression tells the driver to send payloads without
|
||||
// compression.
|
||||
NoCompression Compression = iota
|
||||
// GzipCompression tells the driver to send payloads after
|
||||
// compressing them with gzip.
|
||||
GzipCompression
|
||||
)
|
||||
|
||||
// Marshaler describes the kind of message format sent to the collector.
|
||||
type Marshaler int
|
||||
|
||||
const (
|
||||
// MarshalProto tells the driver to send using the protobuf binary format.
|
||||
MarshalProto Marshaler = iota
|
||||
// MarshalJSON tells the driver to send using json format.
|
||||
MarshalJSON
|
||||
)
|
||||
37
vendor/go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp/internal/otlpconfig/tls.go
generated
vendored
Normal file
37
vendor/go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp/internal/otlpconfig/tls.go
generated
vendored
Normal file
|
|
@ -0,0 +1,37 @@
|
|||
// Code created by gotmpl. DO NOT MODIFY.
|
||||
// source: internal/shared/otlp/otlptrace/otlpconfig/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.
|
||||
|
||||
package otlpconfig // import "go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp/internal/otlpconfig"
|
||||
|
||||
import (
|
||||
"crypto/tls"
|
||||
"crypto/x509"
|
||||
"errors"
|
||||
)
|
||||
|
||||
// CreateTLSConfig creates a tls.Config from a raw certificate bytes
|
||||
// to verify a server certificate.
|
||||
func CreateTLSConfig(certBytes []byte) (*tls.Config, error) {
|
||||
cp := x509.NewCertPool()
|
||||
if ok := cp.AppendCertsFromPEM(certBytes); !ok {
|
||||
return nil, errors.New("failed to append certificate to the cert pool")
|
||||
}
|
||||
|
||||
return &tls.Config{
|
||||
RootCAs: cp,
|
||||
}, nil
|
||||
}
|
||||
67
vendor/go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp/internal/partialsuccess.go
generated
vendored
Normal file
67
vendor/go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp/internal/partialsuccess.go
generated
vendored
Normal file
|
|
@ -0,0 +1,67 @@
|
|||
// Code created by gotmpl. DO NOT MODIFY.
|
||||
// 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.
|
||||
|
||||
package internal // import "go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp/internal"
|
||||
|
||||
import "fmt"
|
||||
|
||||
// PartialSuccess represents the underlying error for all handling
|
||||
// OTLP partial success messages. Use `errors.Is(err,
|
||||
// PartialSuccess{})` to test whether an error passed to the OTel
|
||||
// error handler belongs to this category.
|
||||
type PartialSuccess struct {
|
||||
ErrorMessage string
|
||||
RejectedItems int64
|
||||
RejectedKind string
|
||||
}
|
||||
|
||||
var _ error = PartialSuccess{}
|
||||
|
||||
// Error implements the error interface.
|
||||
func (ps PartialSuccess) Error() string {
|
||||
msg := ps.ErrorMessage
|
||||
if msg == "" {
|
||||
msg = "empty message"
|
||||
}
|
||||
return fmt.Sprintf("OTLP partial success: %s (%d %s rejected)", msg, ps.RejectedItems, ps.RejectedKind)
|
||||
}
|
||||
|
||||
// Is supports the errors.Is() interface.
|
||||
func (ps PartialSuccess) Is(err error) bool {
|
||||
_, ok := err.(PartialSuccess)
|
||||
return ok
|
||||
}
|
||||
|
||||
// TracePartialSuccessError returns an error describing a partial success
|
||||
// response for the trace signal.
|
||||
func TracePartialSuccessError(itemsRejected int64, errorMessage string) error {
|
||||
return PartialSuccess{
|
||||
ErrorMessage: errorMessage,
|
||||
RejectedItems: itemsRejected,
|
||||
RejectedKind: "spans",
|
||||
}
|
||||
}
|
||||
|
||||
// MetricPartialSuccessError returns an error describing a partial success
|
||||
// response for the metric signal.
|
||||
func MetricPartialSuccessError(itemsRejected int64, errorMessage string) error {
|
||||
return PartialSuccess{
|
||||
ErrorMessage: errorMessage,
|
||||
RejectedItems: itemsRejected,
|
||||
RejectedKind: "metric data points",
|
||||
}
|
||||
}
|
||||
156
vendor/go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp/internal/retry/retry.go
generated
vendored
Normal file
156
vendor/go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp/internal/retry/retry.go
generated
vendored
Normal file
|
|
@ -0,0 +1,156 @@
|
|||
// Code created by gotmpl. DO NOT MODIFY.
|
||||
// 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.
|
||||
|
||||
// Package retry provides request retry functionality that can perform
|
||||
// configurable exponential backoff for transient errors and honor any
|
||||
// explicit throttle responses received.
|
||||
package retry // import "go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp/internal/retry"
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/cenkalti/backoff/v4"
|
||||
)
|
||||
|
||||
// DefaultConfig are the recommended defaults to use.
|
||||
var DefaultConfig = Config{
|
||||
Enabled: true,
|
||||
InitialInterval: 5 * time.Second,
|
||||
MaxInterval: 30 * time.Second,
|
||||
MaxElapsedTime: time.Minute,
|
||||
}
|
||||
|
||||
// Config defines configuration for retrying batches in case of export failure
|
||||
// using an exponential backoff.
|
||||
type Config struct {
|
||||
// Enabled indicates whether to not retry sending batches in case of
|
||||
// export failure.
|
||||
Enabled bool
|
||||
// InitialInterval the time to wait after the first failure before
|
||||
// retrying.
|
||||
InitialInterval time.Duration
|
||||
// MaxInterval is the upper bound on backoff interval. Once this value is
|
||||
// reached the delay between consecutive retries will always be
|
||||
// `MaxInterval`.
|
||||
MaxInterval time.Duration
|
||||
// MaxElapsedTime is the maximum amount of time (including retries) spent
|
||||
// trying to send a request/batch. Once this value is reached, the data
|
||||
// is discarded.
|
||||
MaxElapsedTime time.Duration
|
||||
}
|
||||
|
||||
// RequestFunc wraps a request with retry logic.
|
||||
type RequestFunc func(context.Context, func(context.Context) error) error
|
||||
|
||||
// EvaluateFunc returns if an error is retry-able and if an explicit throttle
|
||||
// duration should be honored that was included in the error.
|
||||
//
|
||||
// The function must return true if the error argument is retry-able,
|
||||
// otherwise it must return false for the first return parameter.
|
||||
//
|
||||
// The function must return a non-zero time.Duration if the error contains
|
||||
// explicit throttle duration that should be honored, otherwise it must return
|
||||
// a zero valued time.Duration.
|
||||
type EvaluateFunc func(error) (bool, time.Duration)
|
||||
|
||||
// RequestFunc returns a RequestFunc using the evaluate function to determine
|
||||
// if requests can be retried and based on the exponential backoff
|
||||
// configuration of c.
|
||||
func (c Config) RequestFunc(evaluate EvaluateFunc) RequestFunc {
|
||||
if !c.Enabled {
|
||||
return func(ctx context.Context, fn func(context.Context) error) error {
|
||||
return fn(ctx)
|
||||
}
|
||||
}
|
||||
|
||||
return func(ctx context.Context, fn func(context.Context) error) error {
|
||||
// Do not use NewExponentialBackOff since it calls Reset and the code here
|
||||
// must call Reset after changing the InitialInterval (this saves an
|
||||
// unnecessary call to Now).
|
||||
b := &backoff.ExponentialBackOff{
|
||||
InitialInterval: c.InitialInterval,
|
||||
RandomizationFactor: backoff.DefaultRandomizationFactor,
|
||||
Multiplier: backoff.DefaultMultiplier,
|
||||
MaxInterval: c.MaxInterval,
|
||||
MaxElapsedTime: c.MaxElapsedTime,
|
||||
Stop: backoff.Stop,
|
||||
Clock: backoff.SystemClock,
|
||||
}
|
||||
b.Reset()
|
||||
|
||||
for {
|
||||
err := fn(ctx)
|
||||
if err == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
retryable, throttle := evaluate(err)
|
||||
if !retryable {
|
||||
return err
|
||||
}
|
||||
|
||||
bOff := b.NextBackOff()
|
||||
if bOff == backoff.Stop {
|
||||
return fmt.Errorf("max retry time elapsed: %w", err)
|
||||
}
|
||||
|
||||
// Wait for the greater of the backoff or throttle delay.
|
||||
var delay time.Duration
|
||||
if bOff > throttle {
|
||||
delay = bOff
|
||||
} else {
|
||||
elapsed := b.GetElapsedTime()
|
||||
if b.MaxElapsedTime != 0 && elapsed+throttle > b.MaxElapsedTime {
|
||||
return fmt.Errorf("max retry time would elapse: %w", err)
|
||||
}
|
||||
delay = throttle
|
||||
}
|
||||
|
||||
if ctxErr := waitFunc(ctx, delay); ctxErr != nil {
|
||||
return fmt.Errorf("%w: %s", ctxErr, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Allow override for testing.
|
||||
var waitFunc = wait
|
||||
|
||||
// wait takes the caller's context, and the amount of time to wait. It will
|
||||
// return nil if the timer fires before or at the same time as the context's
|
||||
// deadline. This indicates that the call can be retried.
|
||||
func wait(ctx context.Context, delay time.Duration) error {
|
||||
timer := time.NewTimer(delay)
|
||||
defer timer.Stop()
|
||||
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
// Handle the case where the timer and context deadline end
|
||||
// simultaneously by prioritizing the timer expiration nil value
|
||||
// response.
|
||||
select {
|
||||
case <-timer.C:
|
||||
default:
|
||||
return ctx.Err()
|
||||
}
|
||||
case <-timer.C:
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
116
vendor/go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp/options.go
generated
vendored
Normal file
116
vendor/go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp/options.go
generated
vendored
Normal file
|
|
@ -0,0 +1,116 @@
|
|||
// 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.
|
||||
|
||||
package otlptracehttp // import "go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp"
|
||||
|
||||
import (
|
||||
"crypto/tls"
|
||||
"time"
|
||||
|
||||
"go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp/internal/otlpconfig"
|
||||
"go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp/internal/retry"
|
||||
)
|
||||
|
||||
// Compression describes the compression used for payloads sent to the
|
||||
// collector.
|
||||
type Compression otlpconfig.Compression
|
||||
|
||||
const (
|
||||
// NoCompression tells the driver to send payloads without
|
||||
// compression.
|
||||
NoCompression = Compression(otlpconfig.NoCompression)
|
||||
// GzipCompression tells the driver to send payloads after
|
||||
// compressing them with gzip.
|
||||
GzipCompression = Compression(otlpconfig.GzipCompression)
|
||||
)
|
||||
|
||||
// Option applies an option to the HTTP client.
|
||||
type Option interface {
|
||||
applyHTTPOption(otlpconfig.Config) otlpconfig.Config
|
||||
}
|
||||
|
||||
func asHTTPOptions(opts []Option) []otlpconfig.HTTPOption {
|
||||
converted := make([]otlpconfig.HTTPOption, len(opts))
|
||||
for i, o := range opts {
|
||||
converted[i] = otlpconfig.NewHTTPOption(o.applyHTTPOption)
|
||||
}
|
||||
return converted
|
||||
}
|
||||
|
||||
// RetryConfig defines configuration for retrying batches in case of export
|
||||
// failure using an exponential backoff.
|
||||
type RetryConfig retry.Config
|
||||
|
||||
type wrappedOption struct {
|
||||
otlpconfig.HTTPOption
|
||||
}
|
||||
|
||||
func (w wrappedOption) applyHTTPOption(cfg otlpconfig.Config) otlpconfig.Config {
|
||||
return w.ApplyHTTPOption(cfg)
|
||||
}
|
||||
|
||||
// WithEndpoint allows one to set the address of the collector
|
||||
// endpoint that the driver will use to send spans. If
|
||||
// unset, it will instead try to use
|
||||
// the default endpoint (localhost:4318). Note that the endpoint
|
||||
// must not contain any URL path.
|
||||
func WithEndpoint(endpoint string) Option {
|
||||
return wrappedOption{otlpconfig.WithEndpoint(endpoint)}
|
||||
}
|
||||
|
||||
// WithCompression tells the driver to compress the sent data.
|
||||
func WithCompression(compression Compression) Option {
|
||||
return wrappedOption{otlpconfig.WithCompression(otlpconfig.Compression(compression))}
|
||||
}
|
||||
|
||||
// WithURLPath allows one to override the default URL path used
|
||||
// for sending traces. If unset, default ("/v1/traces") will be used.
|
||||
func WithURLPath(urlPath string) Option {
|
||||
return wrappedOption{otlpconfig.WithURLPath(urlPath)}
|
||||
}
|
||||
|
||||
// WithTLSClientConfig can be used to set up a custom TLS
|
||||
// configuration for the client used to send payloads to the
|
||||
// collector. Use it if you want to use a custom certificate.
|
||||
func WithTLSClientConfig(tlsCfg *tls.Config) Option {
|
||||
return wrappedOption{otlpconfig.WithTLSClientConfig(tlsCfg)}
|
||||
}
|
||||
|
||||
// WithInsecure tells the driver to connect to the collector using the
|
||||
// HTTP scheme, instead of HTTPS.
|
||||
func WithInsecure() Option {
|
||||
return wrappedOption{otlpconfig.WithInsecure()}
|
||||
}
|
||||
|
||||
// WithHeaders allows one to tell the driver to send additional HTTP
|
||||
// headers with the payloads. Specifying headers like Content-Length,
|
||||
// Content-Encoding and Content-Type may result in a broken driver.
|
||||
func WithHeaders(headers map[string]string) Option {
|
||||
return wrappedOption{otlpconfig.WithHeaders(headers)}
|
||||
}
|
||||
|
||||
// WithTimeout tells the driver the max waiting time for the backend to process
|
||||
// each spans batch. If unset, the default will be 10 seconds.
|
||||
func WithTimeout(duration time.Duration) Option {
|
||||
return wrappedOption{otlpconfig.WithTimeout(duration)}
|
||||
}
|
||||
|
||||
// WithRetry configures the retry policy for transient errors that may occurs
|
||||
// when exporting traces. An exponential back-off algorithm is used to ensure
|
||||
// endpoints are not overwhelmed with retries. If unset, the default retry
|
||||
// policy will retry after 5 seconds and increase exponentially after each
|
||||
// error for a total of 1 minute.
|
||||
func WithRetry(rc RetryConfig) Option {
|
||||
return wrappedOption{otlpconfig.WithRetry(retry.Config(rc))}
|
||||
}
|
||||
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
|
|
@ -16,5 +16,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.16.0"
|
||||
return "1.17.0"
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue