From 638bbbf2eba753e11229c5593940fc94d1ae3239 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. --- 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...)