diff --git a/CHANGELOG.md b/CHANGELOG.md index 77cf87b1..0078775b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -25,6 +25,7 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm - The `SpanStub` type and its associated functions were added to the `go.opentelemetry.io/otel/sdk/trace/tracetest` package. This type can be used as a testing replacement for the `SpanSnapshot` that was removed from the `go.opentelemetry.io/otel/sdk/trace` package. (#1873) - Adds support for scheme in `OTEL_EXPORTER_OTLP_ENDPOINT` according to the spec. (#1886) +- Adds `trace.WithSchemaURL` option for configuring the tracer with a Schema URL. (#1889) - An example of using OpenTelemetry Go as a trace context forwarder. (#1912) - `ParseTraceState` is added to the `go.opentelemetry.io/otel/trace` package. It can be used to decode a `TraceState` from a `tracestate` header string value. (#1937) diff --git a/exporters/otlp/internal/transform/span.go b/exporters/otlp/internal/transform/span.go index bcf540e4..7bcdeeed 100644 --- a/exporters/otlp/internal/transform/span.go +++ b/exporters/otlp/internal/transform/span.go @@ -61,6 +61,8 @@ func Spans(sdl []tracesdk.ReadOnlySpan) []*tracepb.ResourceSpans { InstrumentationLibrary: instrumentationLibrary(sd.InstrumentationLibrary()), Spans: []*tracepb.Span{}, } + // TODO: set schema_url field of ils when it is available in the proto. + _ = sd.InstrumentationLibrary().SchemaURL } ils.Spans = append(ils.Spans, span(sd)) ilsm[iKey] = ils diff --git a/exporters/otlp/internal/transform/span_test.go b/exporters/otlp/internal/transform/span_test.go index 9fec4f44..74ed36b8 100644 --- a/exporters/otlp/internal/transform/span_test.go +++ b/exporters/otlp/internal/transform/span_test.go @@ -263,8 +263,9 @@ func TestSpanData(t *testing.T) { DroppedLinks: 3, Resource: resource.NewWithAttributes(attribute.String("rk1", "rv1"), attribute.Int64("rk2", 5)), InstrumentationLibrary: instrumentation.Library{ - Name: "go.opentelemetry.io/test/otel", - Version: "v0.0.1", + Name: "go.opentelemetry.io/test/otel", + Version: "v0.0.1", + SchemaURL: "https://opentelemetry.io/schemas/1.2.0", }, } @@ -295,6 +296,7 @@ func TestSpanData(t *testing.T) { assert.Equal(t, got[0].GetResource(), Resource(spanData.Resource)) ilSpans := got[0].GetInstrumentationLibrarySpans() require.Len(t, ilSpans, 1) + // TODO: Add SchemaURL field checking once the field is added to the proto. assert.Equal(t, ilSpans[0].GetInstrumentationLibrary(), instrumentationLibrary(spanData.InstrumentationLibrary)) require.Len(t, ilSpans[0].Spans, 1) actualSpan := ilSpans[0].Spans[0] diff --git a/exporters/stdout/example_test.go b/exporters/stdout/example_test.go index 82da5665..f38a572b 100644 --- a/exporters/stdout/example_test.go +++ b/exporters/stdout/example_test.go @@ -35,6 +35,7 @@ var ( tracer = otel.GetTracerProvider().Tracer( instrumentationName, trace.WithInstrumentationVersion(instrumentationVersion), + trace.WithSchemaURL("https://opentelemetry.io/schemas/1.2.0"), ) meter = global.GetMeterProvider().Meter( diff --git a/exporters/stdout/trace_test.go b/exporters/stdout/trace_test.go index f9cccef9..fea48d65 100644 --- a/exporters/stdout/trace_test.go +++ b/exporters/stdout/trace_test.go @@ -170,7 +170,8 @@ func TestExporter_ExportSpan(t *testing.T) { ], "InstrumentationLibrary": { "Name": "", - "Version": "" + "Version": "", + "SchemaURL": "" } } ] diff --git a/sdk/instrumentation/library.go b/sdk/instrumentation/library.go index c897c04d..5e54ee48 100644 --- a/sdk/instrumentation/library.go +++ b/sdk/instrumentation/library.go @@ -32,4 +32,6 @@ type Library struct { Name string // Version is the version of the instrumentation library. Version string + // SchemaURL of the telemetry emitted by the library. + SchemaURL string } diff --git a/sdk/trace/provider.go b/sdk/trace/provider.go index bc4ba5db..57edf789 100644 --- a/sdk/trace/provider.go +++ b/sdk/trace/provider.go @@ -115,8 +115,9 @@ func (p *TracerProvider) Tracer(name string, opts ...trace.TracerOption) trace.T name = defaultTracerName } il := instrumentation.Library{ - Name: name, - Version: c.InstrumentationVersion(), + Name: name, + Version: c.InstrumentationVersion(), + SchemaURL: c.SchemaURL(), } t, ok := p.namedTracer[il] if !ok { diff --git a/sdk/trace/provider_test.go b/sdk/trace/provider_test.go index 6a55b50b..e2fce31d 100644 --- a/sdk/trace/provider_test.go +++ b/sdk/trace/provider_test.go @@ -20,6 +20,8 @@ import ( "testing" "github.com/stretchr/testify/assert" + + "go.opentelemetry.io/otel/trace" ) type basicSpanProcesor struct { @@ -82,3 +84,13 @@ func TestFailedProcessorShutdownInUnregister(t *testing.T) { err := stp.Shutdown(context.Background()) assert.NoError(t, err) } + +func TestSchemaURL(t *testing.T) { + stp := NewTracerProvider() + schemaURL := "https://opentelemetry.io/schemas/1.2.0" + tracerIface := stp.Tracer("tracername", trace.WithSchemaURL(schemaURL)) + + // Verify that the SchemaURL of the constructed Tracer is correctly populated. + tracerStruct := tracerIface.(*tracer) + assert.EqualValues(t, schemaURL, tracerStruct.instrumentationLibrary.SchemaURL) +} diff --git a/sdk/trace/trace_test.go b/sdk/trace/trace_test.go index b18a9d77..cf055c57 100644 --- a/sdk/trace/trace_test.go +++ b/sdk/trace/trace_test.go @@ -1284,7 +1284,7 @@ func TestWithResource(t *testing.T) { } } -func TestWithInstrumentationVersion(t *testing.T) { +func TestWithInstrumentationVersionAndSchema(t *testing.T) { te := NewTestExporter() tp := NewTracerProvider(WithSyncer(te), WithResource(resource.Empty())) @@ -1293,6 +1293,7 @@ func TestWithInstrumentationVersion(t *testing.T) { _, span := tp.Tracer( "WithInstrumentationVersion", trace.WithInstrumentationVersion("v0.1.0"), + trace.WithSchemaURL("https://opentelemetry.io/schemas/1.2.0"), ).Start(ctx, "span0") got, err := endSpan(te, span) if err != nil { @@ -1308,8 +1309,9 @@ func TestWithInstrumentationVersion(t *testing.T) { name: "span0", spanKind: trace.SpanKindInternal, instrumentationLibrary: instrumentation.Library{ - Name: "WithInstrumentationVersion", - Version: "v0.1.0", + Name: "WithInstrumentationVersion", + Version: "v0.1.0", + SchemaURL: "https://opentelemetry.io/schemas/1.2.0", }, } if diff := cmpDiff(got, want); diff != "" { diff --git a/trace/config.go b/trace/config.go index 4485fb9b..e93511d6 100644 --- a/trace/config.go +++ b/trace/config.go @@ -23,6 +23,8 @@ import ( // TracerConfig is a group of options for a Tracer. type TracerConfig struct { instrumentationVersion string + // Schema URL of the telemetry emitted by the Tracer. + schemaURL string } // InstrumentationVersion returns the version of the library providing instrumentation. @@ -30,6 +32,11 @@ 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) @@ -252,3 +259,10 @@ func WithInstrumentationVersion(version string) TracerOption { cfg.instrumentationVersion = version }) } + +// WithSchemaURL sets the schema URL for the Tracer. +func WithSchemaURL(schemaURL string) TracerOption { + return tracerOptionFunc(func(cfg *TracerConfig) { + cfg.schemaURL = schemaURL + }) +} diff --git a/trace/config_test.go b/trace/config_test.go index 074aa303..3b8c9b18 100644 --- a/trace/config_test.go +++ b/trace/config_test.go @@ -177,6 +177,7 @@ func TestNewSpanConfig(t *testing.T) { func TestTracerConfig(t *testing.T) { v1 := "semver:0.0.1" v2 := "semver:1.0.0" + schemaURL := "https://opentelemetry.io/schemas/1.2.0" tests := []struct { options []TracerOption expected *TracerConfig @@ -204,6 +205,14 @@ func TestTracerConfig(t *testing.T) { instrumentationVersion: v2, }, }, + { + []TracerOption{ + WithSchemaURL(schemaURL), + }, + &TracerConfig{ + schemaURL: schemaURL, + }, + }, } for _, test := range tests { config := NewTracerConfig(test.options...)