From 25bd614fac069da45363e41d6cfcb83a057013ca Mon Sep 17 00:00:00 2001 From: Tigran Najaryan Date: Thu, 6 May 2021 17:29:21 -0400 Subject: [PATCH] [WIP] Add schema URL support to Tracer [Do not merge, this is a draft to get maintainers' feedback] This adds support for schema URL according to the specification: https://github.com/open-telemetry/opentelemetry-specification/pull/1666 (Link to replaced by the link to the spec after that PR is merged) TODO: Populate the schema_url field in the OTLP after this PR https://github.com/open-telemetry/opentelemetry-proto/pull/298 is merged and the field is available in the proto message. This is the first in the series of changes that are necessary to add support for schemas in Go SDK. Subsequent PRs will add support in Meter and Resource. We will also see if we can find a good way to group semantic conventions with the schema version that declares them. --- exporters/otlp/internal/transform/span.go | 2 ++ exporters/otlp/internal/transform/span_test.go | 6 ++++-- exporters/stdout/example_test.go | 1 + exporters/stdout/trace_test.go | 3 ++- sdk/instrumentation/library.go | 2 ++ sdk/trace/provider.go | 5 +++-- sdk/trace/provider_test.go | 12 ++++++++++++ sdk/trace/trace_test.go | 8 +++++--- trace/config.go | 15 +++++++++++++++ trace/config_test.go | 9 +++++++++ 10 files changed, 55 insertions(+), 8 deletions(-) diff --git a/exporters/otlp/internal/transform/span.go b/exporters/otlp/internal/transform/span.go index bcf540e4e435..7bcdeeedfdc1 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 d32fefed14ea..adb52d72dd13 100644 --- a/exporters/otlp/internal/transform/span_test.go +++ b/exporters/otlp/internal/transform/span_test.go @@ -262,8 +262,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", }, } @@ -294,6 +295,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 82da5665bf95..f38a572bb824 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 8b60790dfcb6..2027d9b14f69 100644 --- a/exporters/stdout/trace_test.go +++ b/exporters/stdout/trace_test.go @@ -177,7 +177,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 c897c04de37a..5e54ee484bd4 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 83e1fe5e8d37..ccb3d8d0dab8 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 6a55b50bb2df..e2fce31d7f79 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 a340ddb1baea..826359340f46 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 ea30ee35f153..4447b156e960 100644 --- a/trace/config.go +++ b/trace/config.go @@ -25,6 +25,8 @@ type TracerConfig struct { // InstrumentationVersion is the version of the library providing // instrumentation. InstrumentationVersion string + // SchemaURL of the telemetry emitted by the Tracer. + SchemaURL string } // NewTracerConfig applies all the options to a returned TracerConfig. @@ -203,3 +205,16 @@ func (i instrumentationVersionOption) ApplyTracer(config *TracerConfig) { } func (instrumentationVersionOption) private() {} + +// WithSchemaURL sets the schema URL for Tracer. +func WithSchemaURL(schemaURL string) InstrumentationOption { + return schemaURLOption(schemaURL) +} + +type schemaURLOption string + +func (i schemaURLOption) ApplyTracer(config *TracerConfig) { + config.SchemaURL = string(i) +} + +func (schemaURLOption) private() {} diff --git a/trace/config_test.go b/trace/config_test.go index 9375191c40ac..e8cc623bb8fd 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...)