Bump sigs.k8s.io/controller-runtime to v0.14.4 (#5507)

* Bump sigs.k8s.io/controller-runtime to v0.14.4

* Update gofmt
This commit is contained in:
hongming
2023-02-08 14:06:15 +08:00
committed by GitHub
parent 129e6fbec3
commit 1c49fcd57e
1404 changed files with 141422 additions and 47769 deletions

View File

@@ -12,7 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
package trace
package trace // import "go.opentelemetry.io/otel/trace"
import (
"time"
@@ -22,110 +22,199 @@ import (
// TracerConfig is a group of options for a Tracer.
type TracerConfig struct {
// InstrumentationVersion is the version of the library providing
// instrumentation.
InstrumentationVersion string
instrumentationVersion string
// Schema URL of the telemetry emitted by the Tracer.
schemaURL string
}
// InstrumentationVersion returns the version of the library providing instrumentation.
func (t *TracerConfig) InstrumentationVersion() string {
return t.instrumentationVersion
}
// SchemaURL returns the Schema URL of the telemetry emitted by the Tracer.
func (t *TracerConfig) SchemaURL() string {
return t.schemaURL
}
// NewTracerConfig applies all the options to a returned TracerConfig.
func NewTracerConfig(options ...TracerOption) *TracerConfig {
config := new(TracerConfig)
func NewTracerConfig(options ...TracerOption) TracerConfig {
var config TracerConfig
for _, option := range options {
option.ApplyTracer(config)
config = option.apply(config)
}
return config
}
// TracerOption applies an option to a TracerConfig.
type TracerOption interface {
ApplyTracer(*TracerConfig)
apply(TracerConfig) TracerConfig
}
// A private method to prevent users implementing the
// interface and so future additions to it will not
// violate compatibility.
private()
type tracerOptionFunc func(TracerConfig) TracerConfig
func (fn tracerOptionFunc) apply(cfg TracerConfig) TracerConfig {
return fn(cfg)
}
// SpanConfig is a group of options for a Span.
type SpanConfig struct {
// Attributes describe the associated qualities of a Span.
Attributes []attribute.KeyValue
// Timestamp is a time in a Span life-cycle.
Timestamp time.Time
// Links are the associations a Span has with other Spans.
Links []Link
// NewRoot identifies a Span as the root Span for a new trace. This is
// commonly used when an existing trace crosses trust boundaries and the
// remote parent span context should be ignored for security.
NewRoot bool
// SpanKind is the role a Span has in a trace.
SpanKind SpanKind
attributes []attribute.KeyValue
timestamp time.Time
links []Link
newRoot bool
spanKind SpanKind
stackTrace bool
}
// NewSpanConfig applies all the options to a returned SpanConfig.
// Attributes describe the associated qualities of a Span.
func (cfg *SpanConfig) Attributes() []attribute.KeyValue {
return cfg.attributes
}
// Timestamp is a time in a Span life-cycle.
func (cfg *SpanConfig) Timestamp() time.Time {
return cfg.timestamp
}
// StackTrace checks whether stack trace capturing is enabled.
func (cfg *SpanConfig) StackTrace() bool {
return cfg.stackTrace
}
// Links are the associations a Span has with other Spans.
func (cfg *SpanConfig) Links() []Link {
return cfg.links
}
// NewRoot identifies a Span as the root Span for a new trace. This is
// commonly used when an existing trace crosses trust boundaries and the
// remote parent span context should be ignored for security.
func (cfg *SpanConfig) NewRoot() bool {
return cfg.newRoot
}
// SpanKind is the role a Span has in a trace.
func (cfg *SpanConfig) SpanKind() SpanKind {
return cfg.spanKind
}
// NewSpanStartConfig applies all the options to a returned SpanConfig.
// No validation is performed on the returned SpanConfig (e.g. no uniqueness
// checking or bounding of data), it is left to the SDK to perform this
// action.
func NewSpanConfig(options ...SpanOption) *SpanConfig {
c := new(SpanConfig)
func NewSpanStartConfig(options ...SpanStartOption) SpanConfig {
var c SpanConfig
for _, option := range options {
option.ApplySpan(c)
c = option.applySpanStart(c)
}
return c
}
// SpanOption applies an option to a SpanConfig.
type SpanOption interface {
ApplySpan(*SpanConfig)
// A private method to prevent users implementing the
// interface and so future additions to it will not
// violate compatibility.
private()
// NewSpanEndConfig applies all the options to a returned SpanConfig.
// No validation is performed on the returned SpanConfig (e.g. no uniqueness
// checking or bounding of data), it is left to the SDK to perform this
// action.
func NewSpanEndConfig(options ...SpanEndOption) SpanConfig {
var c SpanConfig
for _, option := range options {
c = option.applySpanEnd(c)
}
return c
}
// NewEventConfig applies all the EventOptions to a returned SpanConfig. If no
// timestamp option is passed, the returned SpanConfig will have a Timestamp
// SpanStartOption applies an option to a SpanConfig. These options are applicable
// only when the span is created.
type SpanStartOption interface {
applySpanStart(SpanConfig) SpanConfig
}
type spanOptionFunc func(SpanConfig) SpanConfig
func (fn spanOptionFunc) applySpanStart(cfg SpanConfig) SpanConfig {
return fn(cfg)
}
// SpanEndOption applies an option to a SpanConfig. These options are
// applicable only when the span is ended.
type SpanEndOption interface {
applySpanEnd(SpanConfig) SpanConfig
}
// EventConfig is a group of options for an Event.
type EventConfig struct {
attributes []attribute.KeyValue
timestamp time.Time
stackTrace bool
}
// Attributes describe the associated qualities of an Event.
func (cfg *EventConfig) Attributes() []attribute.KeyValue {
return cfg.attributes
}
// Timestamp is a time in an Event life-cycle.
func (cfg *EventConfig) Timestamp() time.Time {
return cfg.timestamp
}
// StackTrace checks whether stack trace capturing is enabled.
func (cfg *EventConfig) StackTrace() bool {
return cfg.stackTrace
}
// NewEventConfig applies all the EventOptions to a returned EventConfig. If no
// timestamp option is passed, the returned EventConfig will have a Timestamp
// set to the call time, otherwise no validation is performed on the returned
// SpanConfig.
func NewEventConfig(options ...EventOption) *SpanConfig {
c := new(SpanConfig)
// EventConfig.
func NewEventConfig(options ...EventOption) EventConfig {
var c EventConfig
for _, option := range options {
option.ApplyEvent(c)
c = option.applyEvent(c)
}
if c.Timestamp.IsZero() {
c.Timestamp = time.Now()
if c.timestamp.IsZero() {
c.timestamp = time.Now()
}
return c
}
// EventOption applies span event options to a SpanConfig.
// EventOption applies span event options to an EventConfig.
type EventOption interface {
ApplyEvent(*SpanConfig)
// A private method to prevent users implementing the
// interface and so future additions to it will not
// violate compatibility.
private()
applyEvent(EventConfig) EventConfig
}
// LifeCycleOption applies span life-cycle options to a SpanConfig. These
// options set values releated to events in a spans life-cycle like starting,
// ending, experiencing an error and other user defined notable events.
type LifeCycleOption interface {
SpanOption
// SpanOption are options that can be used at both the beginning and end of a span.
type SpanOption interface {
SpanStartOption
SpanEndOption
}
// SpanStartEventOption are options that can be used at the start of a span, or with an event.
type SpanStartEventOption interface {
SpanStartOption
EventOption
}
type attributeSpanOption []attribute.KeyValue
func (o attributeSpanOption) ApplySpan(c *SpanConfig) { o.apply(c) }
func (o attributeSpanOption) ApplyEvent(c *SpanConfig) { o.apply(c) }
func (attributeSpanOption) private() {}
func (o attributeSpanOption) apply(c *SpanConfig) {
c.Attributes = append(c.Attributes, []attribute.KeyValue(o)...)
// SpanEndEventOption are options that can be used at the end of a span, or with an event.
type SpanEndEventOption interface {
SpanEndOption
EventOption
}
type attributeOption []attribute.KeyValue
func (o attributeOption) applySpan(c SpanConfig) SpanConfig {
c.attributes = append(c.attributes, []attribute.KeyValue(o)...)
return c
}
func (o attributeOption) applySpanStart(c SpanConfig) SpanConfig { return o.applySpan(c) }
func (o attributeOption) applyEvent(c EventConfig) EventConfig {
c.attributes = append(c.attributes, []attribute.KeyValue(o)...)
return c
}
var _ SpanStartEventOption = attributeOption{}
// WithAttributes adds the attributes related to a span life-cycle event.
// These attributes are used to describe the work a Span represents when this
// option is provided to a Span's start or end events. Otherwise, these
@@ -135,71 +224,93 @@ func (o attributeSpanOption) apply(c *SpanConfig) {
// If multiple of these options are passed the attributes of each successive
// option will extend the attributes instead of overwriting. There is no
// guarantee of uniqueness in the resulting attributes.
func WithAttributes(attributes ...attribute.KeyValue) LifeCycleOption {
return attributeSpanOption(attributes)
func WithAttributes(attributes ...attribute.KeyValue) SpanStartEventOption {
return attributeOption(attributes)
}
type timestampSpanOption time.Time
func (o timestampSpanOption) ApplySpan(c *SpanConfig) { o.apply(c) }
func (o timestampSpanOption) ApplyEvent(c *SpanConfig) { o.apply(c) }
func (timestampSpanOption) private() {}
func (o timestampSpanOption) apply(c *SpanConfig) { c.Timestamp = time.Time(o) }
// WithTimestamp sets the time of a Span life-cycle moment (e.g. started,
// stopped, errored).
func WithTimestamp(t time.Time) LifeCycleOption {
return timestampSpanOption(t)
// SpanEventOption are options that can be used with an event or a span.
type SpanEventOption interface {
SpanOption
EventOption
}
type linksSpanOption []Link
type timestampOption time.Time
func (o linksSpanOption) ApplySpan(c *SpanConfig) { c.Links = append(c.Links, []Link(o)...) }
func (linksSpanOption) private() {}
func (o timestampOption) applySpan(c SpanConfig) SpanConfig {
c.timestamp = time.Time(o)
return c
}
func (o timestampOption) applySpanStart(c SpanConfig) SpanConfig { return o.applySpan(c) }
func (o timestampOption) applySpanEnd(c SpanConfig) SpanConfig { return o.applySpan(c) }
func (o timestampOption) applyEvent(c EventConfig) EventConfig {
c.timestamp = time.Time(o)
return c
}
var _ SpanEventOption = timestampOption{}
// WithTimestamp sets the time of a Span or Event life-cycle moment (e.g.
// started, stopped, errored).
func WithTimestamp(t time.Time) SpanEventOption {
return timestampOption(t)
}
type stackTraceOption bool
func (o stackTraceOption) applyEvent(c EventConfig) EventConfig {
c.stackTrace = bool(o)
return c
}
func (o stackTraceOption) applySpan(c SpanConfig) SpanConfig {
c.stackTrace = bool(o)
return c
}
func (o stackTraceOption) applySpanEnd(c SpanConfig) SpanConfig { return o.applySpan(c) }
// WithStackTrace sets the flag to capture the error with stack trace (e.g. true, false).
func WithStackTrace(b bool) SpanEndEventOption {
return stackTraceOption(b)
}
// WithLinks adds links to a Span. The links are added to the existing Span
// links, i.e. this does not overwrite.
func WithLinks(links ...Link) SpanOption {
return linksSpanOption(links)
// links, i.e. this does not overwrite. Links with invalid span context are ignored.
func WithLinks(links ...Link) SpanStartOption {
return spanOptionFunc(func(cfg SpanConfig) SpanConfig {
cfg.links = append(cfg.links, links...)
return cfg
})
}
type newRootSpanOption bool
func (o newRootSpanOption) ApplySpan(c *SpanConfig) { c.NewRoot = bool(o) }
func (newRootSpanOption) private() {}
// WithNewRoot specifies that the Span should be treated as a root Span. Any
// existing parent span context will be ignored when defining the Span's trace
// identifiers.
func WithNewRoot() SpanOption {
return newRootSpanOption(true)
func WithNewRoot() SpanStartOption {
return spanOptionFunc(func(cfg SpanConfig) SpanConfig {
cfg.newRoot = true
return cfg
})
}
type spanKindSpanOption SpanKind
func (o spanKindSpanOption) ApplySpan(c *SpanConfig) { c.SpanKind = SpanKind(o) }
func (o spanKindSpanOption) private() {}
// WithSpanKind sets the SpanKind of a Span.
func WithSpanKind(kind SpanKind) SpanOption {
return spanKindSpanOption(kind)
}
// InstrumentationOption is an interface for applying instrumentation specific
// options.
type InstrumentationOption interface {
TracerOption
func WithSpanKind(kind SpanKind) SpanStartOption {
return spanOptionFunc(func(cfg SpanConfig) SpanConfig {
cfg.spanKind = kind
return cfg
})
}
// WithInstrumentationVersion sets the instrumentation version.
func WithInstrumentationVersion(version string) InstrumentationOption {
return instrumentationVersionOption(version)
func WithInstrumentationVersion(version string) TracerOption {
return tracerOptionFunc(func(cfg TracerConfig) TracerConfig {
cfg.instrumentationVersion = version
return cfg
})
}
type instrumentationVersionOption string
func (i instrumentationVersionOption) ApplyTracer(config *TracerConfig) {
config.InstrumentationVersion = string(i)
// WithSchemaURL sets the schema URL for the Tracer.
func WithSchemaURL(schemaURL string) TracerOption {
return tracerOptionFunc(func(cfg TracerConfig) TracerConfig {
cfg.schemaURL = schemaURL
return cfg
})
}
func (instrumentationVersionOption) private() {}

View File

@@ -16,10 +16,6 @@
Package trace provides an implementation of the tracing part of the
OpenTelemetry API.
This package is currently in a pre-GA phase. Backwards incompatible changes
may be introduced in subsequent minor version releases as we work to track the
evolving OpenTelemetry specification and user feedback.
To participate in distributed traces a Span needs to be created for the
operation being performed as part of a traced workflow. It its simplest form:

View File

@@ -42,9 +42,14 @@ type noopTracer struct{}
var _ Tracer = noopTracer{}
// Start starts a noop span.
func (t noopTracer) Start(ctx context.Context, name string, _ ...SpanOption) (context.Context, Span) {
span := noopSpan{}
// Start carries forward a non-recording Span, if one is present in the context, otherwise it
// creates a no-op Span.
func (t noopTracer) Start(ctx context.Context, name string, _ ...SpanStartOption) (context.Context, Span) {
span := SpanFromContext(ctx)
if _, ok := span.(nonRecordingSpan); !ok {
// span is likely already a noopSpan, but let's be sure
span = noopSpan{}
}
return ContextWithSpan(ctx, span), span
}
@@ -69,16 +74,16 @@ func (noopSpan) SetError(bool) {}
func (noopSpan) SetAttributes(...attribute.KeyValue) {}
// End does nothing.
func (noopSpan) End(...SpanOption) {}
func (noopSpan) End(...SpanEndOption) {}
// RecordError does nothing.
func (noopSpan) RecordError(error, ...EventOption) {}
// Tracer returns the Tracer that created this Span.
func (noopSpan) Tracer() Tracer { return noopTracer{} }
// AddEvent does nothing.
func (noopSpan) AddEvent(string, ...EventOption) {}
// SetName does nothing.
func (noopSpan) SetName(string) {}
// TracerProvider returns a no-op TracerProvider.
func (noopSpan) TracerProvider() TracerProvider { return noopTracerProvider{} }

View File

@@ -19,9 +19,6 @@ import (
"context"
"encoding/hex"
"encoding/json"
"regexp"
"strings"
"time"
"go.opentelemetry.io/otel/attribute"
"go.opentelemetry.io/otel/codes"
@@ -39,18 +36,6 @@ const (
errInvalidSpanIDLength errorConst = "hex encoded span-id must have length equals to 16"
errNilSpanID errorConst = "span-id can't be all zero"
// based on the W3C Trace Context specification, see https://www.w3.org/TR/trace-context-1/#tracestate-header
traceStateKeyFormat = `[a-z][_0-9a-z\-\*\/]{0,255}`
traceStateKeyFormatWithMultiTenantVendor = `[a-z0-9][_0-9a-z\-\*\/]{0,240}@[a-z][_0-9a-z\-\*\/]{0,13}`
traceStateValueFormat = `[\x20-\x2b\x2d-\x3c\x3e-\x7e]{0,255}[\x21-\x2b\x2d-\x3c\x3e-\x7e]`
traceStateMaxListMembers = 32
errInvalidTraceStateKeyValue errorConst = "provided key or value is not valid according to the" +
" W3C Trace Context specification"
errInvalidTraceStateMembersNumber errorConst = "trace state would exceed the maximum limit of members (32)"
errInvalidTraceStateDuplicate errorConst = "trace state key/value pairs with duplicate keys provided"
)
type errorConst string
@@ -60,7 +45,7 @@ func (e errorConst) Error() string {
}
// TraceID is a unique identity of a trace.
// nolint:golint
// nolint:revive // revive complains about stutter of `trace.TraceID`.
type TraceID [16]byte
var nilTraceID TraceID
@@ -78,7 +63,7 @@ func (t TraceID) MarshalJSON() ([]byte, error) {
return json.Marshal(t.String())
}
// String returns the hex string representation form of a TraceID
// String returns the hex string representation form of a TraceID.
func (t TraceID) String() string {
return hex.EncodeToString(t[:])
}
@@ -101,7 +86,7 @@ func (s SpanID) MarshalJSON() ([]byte, error) {
return json.Marshal(s.String())
}
// String returns the hex string representation form of a SpanID
// String returns the hex string representation form of a SpanID.
func (s SpanID) String() string {
return hex.EncodeToString(s[:])
}
@@ -109,7 +94,7 @@ func (s SpanID) String() string {
// TraceIDFromHex returns a TraceID from a hex string if it is compliant with
// the W3C trace-context specification. See more at
// https://www.w3.org/TR/trace-context/#trace-id
// nolint:golint
// nolint:revive // revive complains about stutter of `trace.TraceIDFromHex`.
func TraceIDFromHex(h string) (TraceID, error) {
t := TraceID{}
if len(h) != 32 {
@@ -166,155 +151,8 @@ func decodeHex(h string, b []byte) error {
return nil
}
// TraceState provides additional vendor-specific trace identification information
// across different distributed tracing systems. It represents an immutable list consisting
// of key/value pairs. There can be a maximum of 32 entries in the list.
//
// Key and value of each list member must be valid according to the W3C Trace Context specification
// (see https://www.w3.org/TR/trace-context-1/#key and https://www.w3.org/TR/trace-context-1/#value
// respectively).
//
// Trace state must be valid according to the W3C Trace Context specification at all times. All
// mutating operations validate their input and, in case of valid parameters, return a new TraceState.
type TraceState struct { //nolint:golint
// TODO @matej-g: Consider implementing this as attribute.Set, see
// comment https://github.com/open-telemetry/opentelemetry-go/pull/1340#discussion_r540599226
kvs []attribute.KeyValue
}
var _ json.Marshaler = TraceState{}
var _ json.Marshaler = SpanContext{}
var keyFormatRegExp = regexp.MustCompile(
`^((` + traceStateKeyFormat + `)|(` + traceStateKeyFormatWithMultiTenantVendor + `))$`,
)
var valueFormatRegExp = regexp.MustCompile(`^(` + traceStateValueFormat + `)$`)
// MarshalJSON implements a custom marshal function to encode trace state.
func (ts TraceState) MarshalJSON() ([]byte, error) {
return json.Marshal(ts.kvs)
}
// String returns trace state as a string valid according to the
// W3C Trace Context specification.
func (ts TraceState) String() string {
var sb strings.Builder
for i, kv := range ts.kvs {
sb.WriteString((string)(kv.Key))
sb.WriteByte('=')
sb.WriteString(kv.Value.Emit())
if i != len(ts.kvs)-1 {
sb.WriteByte(',')
}
}
return sb.String()
}
// Get returns a value for given key from the trace state.
// If no key is found or provided key is invalid, returns an empty value.
func (ts TraceState) Get(key attribute.Key) attribute.Value {
if !isTraceStateKeyValid(key) {
return attribute.Value{}
}
for _, kv := range ts.kvs {
if kv.Key == key {
return kv.Value
}
}
return attribute.Value{}
}
// Insert adds a new key/value, if one doesn't exists; otherwise updates the existing entry.
// The new or updated entry is always inserted at the beginning of the TraceState, i.e.
// on the left side, as per the W3C Trace Context specification requirement.
func (ts TraceState) Insert(entry attribute.KeyValue) (TraceState, error) {
if !isTraceStateKeyValueValid(entry) {
return ts, errInvalidTraceStateKeyValue
}
ckvs := ts.copyKVsAndDeleteEntry(entry.Key)
if len(ckvs)+1 > traceStateMaxListMembers {
return ts, errInvalidTraceStateMembersNumber
}
ckvs = append(ckvs, attribute.KeyValue{})
copy(ckvs[1:], ckvs)
ckvs[0] = entry
return TraceState{ckvs}, nil
}
// Delete removes specified entry from the trace state.
func (ts TraceState) Delete(key attribute.Key) (TraceState, error) {
if !isTraceStateKeyValid(key) {
return ts, errInvalidTraceStateKeyValue
}
return TraceState{ts.copyKVsAndDeleteEntry(key)}, nil
}
// IsEmpty returns true if the TraceState does not contain any entries
func (ts TraceState) IsEmpty() bool {
return len(ts.kvs) == 0
}
func (ts TraceState) copyKVsAndDeleteEntry(key attribute.Key) []attribute.KeyValue {
ckvs := make([]attribute.KeyValue, len(ts.kvs))
copy(ckvs, ts.kvs)
for i, kv := range ts.kvs {
if kv.Key == key {
ckvs = append(ckvs[:i], ckvs[i+1:]...)
break
}
}
return ckvs
}
// TraceStateFromKeyValues is a convenience method to create a new TraceState from
// provided key/value pairs.
func TraceStateFromKeyValues(kvs ...attribute.KeyValue) (TraceState, error) { //nolint:golint
if len(kvs) == 0 {
return TraceState{}, nil
}
if len(kvs) > traceStateMaxListMembers {
return TraceState{}, errInvalidTraceStateMembersNumber
}
km := make(map[attribute.Key]bool)
for _, kv := range kvs {
if !isTraceStateKeyValueValid(kv) {
return TraceState{}, errInvalidTraceStateKeyValue
}
_, ok := km[kv.Key]
if ok {
return TraceState{}, errInvalidTraceStateDuplicate
}
km[kv.Key] = true
}
ckvs := make([]attribute.KeyValue, len(kvs))
copy(ckvs, kvs)
return TraceState{ckvs}, nil
}
func isTraceStateKeyValid(key attribute.Key) bool {
return keyFormatRegExp.MatchString(string(key))
}
func isTraceStateKeyValueValid(kv attribute.KeyValue) bool {
return isTraceStateKeyValid(kv.Key) &&
valueFormatRegExp.MatchString(kv.Value.Emit())
}
// TraceFlags contains flags that can be set on a SpanContext
type TraceFlags byte //nolint:golint
// TraceFlags contains flags that can be set on a SpanContext.
type TraceFlags byte //nolint:revive // revive complains about stutter of `trace.TraceFlags`.
// IsSampled returns if the sampling bit is set in the TraceFlags.
func (tf TraceFlags) IsSampled() bool {
@@ -322,7 +160,7 @@ func (tf TraceFlags) IsSampled() bool {
}
// WithSampled sets the sampling bit in a new copy of the TraceFlags.
func (tf TraceFlags) WithSampled(sampled bool) TraceFlags {
func (tf TraceFlags) WithSampled(sampled bool) TraceFlags { // nolint:revive // sampled is not a control flag.
if sampled {
return tf | FlagsSampled
}
@@ -336,7 +174,7 @@ func (tf TraceFlags) MarshalJSON() ([]byte, error) {
return json.Marshal(tf.String())
}
// String returns the hex string representation form of TraceFlags
// String returns the hex string representation form of TraceFlags.
func (tf TraceFlags) String() string {
return hex.EncodeToString([]byte{byte(tf)}[:])
}
@@ -372,6 +210,8 @@ type SpanContext struct {
remote bool
}
var _ json.Marshaler = SpanContext{}
// IsValid returns if the SpanContext is valid. A valid span context has a
// valid TraceID and SpanID.
func (sc SpanContext) IsValid() bool {
@@ -497,16 +337,14 @@ func (sc SpanContext) MarshalJSON() ([]byte, error) {
// and timed operation of a workflow that is traced. A Tracer is used to
// create a Span and it is then up to the operation the Span represents to
// properly end the Span when the operation itself ends.
//
// Warning: methods may be added to this interface in minor releases.
type Span interface {
// Tracer returns the Tracer that created the Span. Tracer MUST NOT be
// nil.
Tracer() Tracer
// End completes the Span. The Span is considered complete and ready to be
// delivered through the rest of the telemetry pipeline after this method
// is called. Therefore, updates to the Span are not allowed after this
// method has been called.
End(options ...SpanOption)
End(options ...SpanEndOption)
// AddEvent adds an event with the provided name and options.
AddEvent(name string, options ...EventOption)
@@ -516,19 +354,19 @@ type Span interface {
IsRecording() bool
// RecordError will record err as an exception span event for this span. An
// additional call toSetStatus is required if the Status of the Span should
// be set to Error, this method does not change the Span status. If this
// span is not being recorded or err is nil than this method does nothing.
// additional call to SetStatus is required if the Status of the Span should
// be set to Error, as this method does not change the Span status. If this
// span is not being recorded or err is nil then this method does nothing.
RecordError(err error, options ...EventOption)
// SpanContext returns the SpanContext of the Span. The returned
// SpanContext is usable even after the End has been called for the Span.
// SpanContext returns the SpanContext of the Span. The returned SpanContext
// is usable even after the End method has been called for the Span.
SpanContext() SpanContext
// SetStatus sets the status of the Span in the form of a code and a
// message. SetStatus overrides the value of previous calls to SetStatus
// on the Span.
SetStatus(code codes.Code, msg string)
// description, overriding previous values set. The description is only
// included in a status when the code is for an error.
SetStatus(code codes.Code, description string)
// SetName sets the Span name.
SetName(name string)
@@ -537,22 +375,10 @@ type Span interface {
// already exists for an attribute of the Span it will be overwritten with
// the value contained in kv.
SetAttributes(kv ...attribute.KeyValue)
}
// Event is a thing that happened during a Span's lifetime.
type Event struct {
// Name is the name of this event
Name string
// Attributes describe the aspects of the event.
Attributes []attribute.KeyValue
// DroppedAttributeCount is the number of attributes that were not
// recorded due to configured limits being reached.
DroppedAttributeCount int
// Time at which this event was recorded.
Time time.Time
// TracerProvider returns a TracerProvider that can be used to generate
// additional Spans on the same telemetry pipeline as the current Span.
TracerProvider() TracerProvider
}
// Link is the relationship between two Spans. The relationship can be within
@@ -560,26 +386,30 @@ type Event struct {
//
// For example, a Link is used in the following situations:
//
// 1. Batch Processing: A batch of operations may contain operations
// associated with one or more traces/spans. Since there can only be one
// parent SpanContext, a Link is used to keep reference to the
// SpanContext of all operations in the batch.
// 2. Public Endpoint: A SpanContext for an in incoming client request on a
// public endpoint should be considered untrusted. In such a case, a new
// trace with its own identity and sampling decision needs to be created,
// but this new trace needs to be related to the original trace in some
// form. A Link is used to keep reference to the original SpanContext and
// track the relationship.
// 1. Batch Processing: A batch of operations may contain operations
// associated with one or more traces/spans. Since there can only be one
// parent SpanContext, a Link is used to keep reference to the
// SpanContext of all operations in the batch.
// 2. Public Endpoint: A SpanContext for an in incoming client request on a
// public endpoint should be considered untrusted. In such a case, a new
// trace with its own identity and sampling decision needs to be created,
// but this new trace needs to be related to the original trace in some
// form. A Link is used to keep reference to the original SpanContext and
// track the relationship.
type Link struct {
// SpanContext of the linked Span.
SpanContext
SpanContext SpanContext
// Attributes describe the aspects of the link.
Attributes []attribute.KeyValue
}
// DroppedAttributeCount is the number of attributes that were not
// recorded due to configured limits being reached.
DroppedAttributeCount int
// LinkFromContext returns a link encapsulating the SpanContext in the provided ctx.
func LinkFromContext(ctx context.Context, attrs ...attribute.KeyValue) Link {
return Link{
SpanContext: SpanContextFromContext(ctx),
Attributes: attrs,
}
}
// SpanKind is the role a Span plays in a Trace.
@@ -654,20 +484,67 @@ func (sk SpanKind) String() string {
}
// Tracer is the creator of Spans.
//
// Warning: methods may be added to this interface in minor releases.
type Tracer interface {
// Start creates a span.
Start(ctx context.Context, spanName string, opts ...SpanOption) (context.Context, Span)
// Start creates a span and a context.Context containing the newly-created span.
//
// If the context.Context provided in `ctx` contains a Span then the newly-created
// Span will be a child of that span, otherwise it will be a root span. This behavior
// can be overridden by providing `WithNewRoot()` as a SpanOption, causing the
// newly-created Span to be a root span even if `ctx` contains a Span.
//
// When creating a Span it is recommended to provide all known span attributes using
// the `WithAttributes()` SpanOption as samplers will only have access to the
// attributes provided when a Span is created.
//
// Any Span that is created MUST also be ended. This is the responsibility of the user.
// Implementations of this API may leak memory or other resources if Spans are not ended.
Start(ctx context.Context, spanName string, opts ...SpanStartOption) (context.Context, Span)
}
// TracerProvider provides access to instrumentation Tracers.
// TracerProvider provides Tracers that are used by instrumentation code to
// trace computational workflows.
//
// A TracerProvider is the collection destination of all Spans from Tracers it
// provides, it represents a unique telemetry collection pipeline. How that
// pipeline is defined, meaning how those Spans are collected, processed, and
// where they are exported, depends on its implementation. Instrumentation
// authors do not need to define this implementation, rather just use the
// provided Tracers to instrument code.
//
// Commonly, instrumentation code will accept a TracerProvider implementation
// at runtime from its users or it can simply use the globally registered one
// (see https://pkg.go.dev/go.opentelemetry.io/otel#GetTracerProvider).
//
// Warning: methods may be added to this interface in minor releases.
type TracerProvider interface {
// Tracer creates an implementation of the Tracer interface.
// The instrumentationName must be the name of the library providing
// instrumentation. This name may be the same as the instrumented code
// only if that code provides built-in instrumentation. If the
// instrumentationName is empty, then a implementation defined default
// name will be used instead.
// Tracer returns a unique Tracer scoped to be used by instrumentation code
// to trace computational workflows. The scope and identity of that
// instrumentation code is uniquely defined by the name and options passed.
//
// This method must be concurrency safe.
Tracer(instrumentationName string, opts ...TracerOption) Tracer
// The passed name needs to uniquely identify instrumentation code.
// Therefore, it is recommended that name is the Go package name of the
// library providing instrumentation (note: not the code being
// instrumented). Instrumentation libraries can have multiple versions,
// therefore, the WithInstrumentationVersion option should be used to
// distinguish these different codebases. Additionally, instrumentation
// libraries may sometimes use traces to communicate different domains of
// workflow data (i.e. using spans to communicate workflow events only). If
// this is the case, the WithScopeAttributes option should be used to
// uniquely identify Tracers that handle the different domains of workflow
// data.
//
// If the same name and options are passed multiple times, the same Tracer
// will be returned (it is up to the implementation if this will be the
// same underlying instance of that Tracer or not). It is not necessary to
// call this multiple times with the same name and options to get an
// up-to-date Tracer. All implementations will ensure any TracerProvider
// configuration changes are propagated to all provided Tracers.
//
// If name is empty, then an implementation defined default name will be
// used instead.
//
// This method is safe to call concurrently.
Tracer(name string, options ...TracerOption) Tracer
}

212
vendor/go.opentelemetry.io/otel/trace/tracestate.go generated vendored Normal file
View File

@@ -0,0 +1,212 @@
// 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 trace // import "go.opentelemetry.io/otel/trace"
import (
"encoding/json"
"fmt"
"regexp"
"strings"
)
const (
maxListMembers = 32
listDelimiter = ","
// based on the W3C Trace Context specification, see
// https://www.w3.org/TR/trace-context-1/#tracestate-header
noTenantKeyFormat = `[a-z][_0-9a-z\-\*\/]{0,255}`
withTenantKeyFormat = `[a-z0-9][_0-9a-z\-\*\/]{0,240}@[a-z][_0-9a-z\-\*\/]{0,13}`
valueFormat = `[\x20-\x2b\x2d-\x3c\x3e-\x7e]{0,255}[\x21-\x2b\x2d-\x3c\x3e-\x7e]`
errInvalidKey errorConst = "invalid tracestate key"
errInvalidValue errorConst = "invalid tracestate value"
errInvalidMember errorConst = "invalid tracestate list-member"
errMemberNumber errorConst = "too many list-members in tracestate"
errDuplicate errorConst = "duplicate list-member in tracestate"
)
var (
keyRe = regexp.MustCompile(`^((` + noTenantKeyFormat + `)|(` + withTenantKeyFormat + `))$`)
valueRe = regexp.MustCompile(`^(` + valueFormat + `)$`)
memberRe = regexp.MustCompile(`^\s*((` + noTenantKeyFormat + `)|(` + withTenantKeyFormat + `))=(` + valueFormat + `)\s*$`)
)
type member struct {
Key string
Value string
}
func newMember(key, value string) (member, error) {
if !keyRe.MatchString(key) {
return member{}, fmt.Errorf("%w: %s", errInvalidKey, key)
}
if !valueRe.MatchString(value) {
return member{}, fmt.Errorf("%w: %s", errInvalidValue, value)
}
return member{Key: key, Value: value}, nil
}
func parseMember(m string) (member, error) {
matches := memberRe.FindStringSubmatch(m)
if len(matches) != 5 {
return member{}, fmt.Errorf("%w: %s", errInvalidMember, m)
}
return member{
Key: matches[1],
Value: matches[4],
}, nil
}
// String encodes member into a string compliant with the W3C Trace Context
// specification.
func (m member) String() string {
return fmt.Sprintf("%s=%s", m.Key, m.Value)
}
// TraceState provides additional vendor-specific trace identification
// information across different distributed tracing systems. It represents an
// immutable list consisting of key/value pairs, each pair is referred to as a
// list-member.
//
// TraceState conforms to the W3C Trace Context specification
// (https://www.w3.org/TR/trace-context-1). All operations that create or copy
// a TraceState do so by validating all input and will only produce TraceState
// that conform to the specification. Specifically, this means that all
// list-member's key/value pairs are valid, no duplicate list-members exist,
// and the maximum number of list-members (32) is not exceeded.
type TraceState struct { //nolint:revive // revive complains about stutter of `trace.TraceState`
// list is the members in order.
list []member
}
var _ json.Marshaler = TraceState{}
// ParseTraceState attempts to decode a TraceState from the passed
// string. It returns an error if the input is invalid according to the W3C
// Trace Context specification.
func ParseTraceState(tracestate string) (TraceState, error) {
if tracestate == "" {
return TraceState{}, nil
}
wrapErr := func(err error) error {
return fmt.Errorf("failed to parse tracestate: %w", err)
}
var members []member
found := make(map[string]struct{})
for _, memberStr := range strings.Split(tracestate, listDelimiter) {
if len(memberStr) == 0 {
continue
}
m, err := parseMember(memberStr)
if err != nil {
return TraceState{}, wrapErr(err)
}
if _, ok := found[m.Key]; ok {
return TraceState{}, wrapErr(errDuplicate)
}
found[m.Key] = struct{}{}
members = append(members, m)
if n := len(members); n > maxListMembers {
return TraceState{}, wrapErr(errMemberNumber)
}
}
return TraceState{list: members}, nil
}
// MarshalJSON marshals the TraceState into JSON.
func (ts TraceState) MarshalJSON() ([]byte, error) {
return json.Marshal(ts.String())
}
// String encodes the TraceState into a string compliant with the W3C
// Trace Context specification. The returned string will be invalid if the
// TraceState contains any invalid members.
func (ts TraceState) String() string {
members := make([]string, len(ts.list))
for i, m := range ts.list {
members[i] = m.String()
}
return strings.Join(members, listDelimiter)
}
// Get returns the value paired with key from the corresponding TraceState
// list-member if it exists, otherwise an empty string is returned.
func (ts TraceState) Get(key string) string {
for _, member := range ts.list {
if member.Key == key {
return member.Value
}
}
return ""
}
// Insert adds a new list-member defined by the key/value pair to the
// TraceState. If a list-member already exists for the given key, that
// list-member's value is updated. The new or updated list-member is always
// moved to the beginning of the TraceState as specified by the W3C Trace
// Context specification.
//
// If key or value are invalid according to the W3C Trace Context
// specification an error is returned with the original TraceState.
//
// If adding a new list-member means the TraceState would have more members
// then is allowed, the new list-member will be inserted and the right-most
// list-member will be dropped in the returned TraceState.
func (ts TraceState) Insert(key, value string) (TraceState, error) {
m, err := newMember(key, value)
if err != nil {
return ts, err
}
cTS := ts.Delete(key)
if cTS.Len()+1 <= maxListMembers {
cTS.list = append(cTS.list, member{})
}
// When the number of members exceeds capacity, drop the "right-most".
copy(cTS.list[1:], cTS.list)
cTS.list[0] = m
return cTS, nil
}
// Delete returns a copy of the TraceState with the list-member identified by
// key removed.
func (ts TraceState) Delete(key string) TraceState {
members := make([]member, ts.Len())
copy(members, ts.list)
for i, member := range ts.list {
if member.Key == key {
members = append(members[:i], members[i+1:]...)
// TraceState should contain no duplicate members.
break
}
}
return TraceState{list: members}
}
// Len returns the number of list-members in the TraceState.
func (ts TraceState) Len() int {
return len(ts.list)
}