Skip to content

Commit

Permalink
Clean up implementation
Browse files Browse the repository at this point in the history
Signed-off-by: Joseph Woodward <joseph.woodward@xeuse.com>
  • Loading branch information
josephwoodward committed Nov 4, 2022
1 parent 601824c commit f318eb6
Show file tree
Hide file tree
Showing 2 changed files with 53 additions and 50 deletions.
90 changes: 49 additions & 41 deletions client/opentelemetry.go
Expand Up @@ -15,9 +15,14 @@ import (
"go.opentelemetry.io/otel/trace"
)

const (
instrumentationVersion = "1.0.0"
tracerName = "go-openapi"
)

type config struct {
Tracer trace.Tracer
Propagators propagation.TextMapPropagator
Propagator propagation.TextMapPropagator
SpanStartOptions []trace.SpanStartOption
SpanNameFormatter func(*runtime.ClientOperation) string
TracerProvider trace.TracerProvider
Expand Down Expand Up @@ -48,7 +53,7 @@ func WithTracerProvider(provider trace.TracerProvider) OpenTelemetryOpt {
func WithPropagators(ps propagation.TextMapPropagator) OpenTelemetryOpt {
return optionFunc(func(c *config) {
if ps != nil {
c.Propagators = ps
c.Propagator = ps
}
})
}
Expand Down Expand Up @@ -78,50 +83,29 @@ func defaultTransportFormatter(op *runtime.ClientOperation) string {
}

type openTelemetryTransport struct {
transport runtime.ClientTransport
host string
spanStartOptions []trace.SpanStartOption
propagator propagation.TextMapPropagator
provider trace.TracerProvider
tracer trace.Tracer
config *config
}

// newConfig creates a new config struct and applies opts to it.
func newConfig(opts ...OpenTelemetryOpt) *config {
c := &config{
Propagators: otel.GetTextMapPropagator(),
}

for _, opt := range opts {
opt.apply(c)
}

// Tracer is only initialized if manually specified. Otherwise, can be passed with the tracing context.
if c.TracerProvider != nil {
c.Tracer = newTracer(c.TracerProvider)
}

return c
transport runtime.ClientTransport
host string
tracer trace.Tracer
config *config
}

func newOpenTelemetryTransport(transport runtime.ClientTransport, host string, opts []OpenTelemetryOpt) *openTelemetryTransport {
t := &openTelemetryTransport{
transport: transport,
host: host,
provider: otel.GetTracerProvider(),
propagator: otel.GetTextMapPropagator(),
tr := &openTelemetryTransport{
transport: transport,
host: host,
}

defaultOpts := []OpenTelemetryOpt{
WithSpanOptions(trace.WithSpanKind(trace.SpanKindClient)),
WithSpanNameFormatter(defaultTransportFormatter),
WithPropagators(otel.GetTextMapPropagator()),
WithTracerProvider(otel.GetTracerProvider()),
}

c := newConfig(append(defaultOpts, opts...)...)
t.config = c
tr.config = c

return t
return tr
}

func (t *openTelemetryTransport) Submit(op *runtime.ClientOperation) (interface{}, error) {
Expand Down Expand Up @@ -175,30 +159,54 @@ func (t *openTelemetryTransport) newOpenTelemetrySpan(op *runtime.ClientOperatio
}
}

ctx, span := tracer.Start(ctx, t.config.SpanNameFormatter(op), t.spanStartOptions...)
ctx, span := tracer.Start(ctx, t.config.SpanNameFormatter(op), t.config.SpanStartOptions...)

// TODO: Can we get the underlying request so we can wire these bits up easily?
// span.SetAttributes(semconv.HTTPClientAttributesFromHTTPRequest()...)
var scheme string
if len(op.Schemes) == 1 {
if len(op.Schemes) > 0 {
scheme = op.Schemes[0]
}

span.SetAttributes(
attribute.String("net.peer.name", t.host),
// attribute.String("net.peer.port", ""),
attribute.String(string(semconv.HTTPRouteKey), op.PathPattern),
attribute.String(string(semconv.HTTPMethodKey), op.Method),
attribute.String("span.kind", trace.SpanKindClient.String()),
attribute.String("http.scheme", scheme),
)

carrier := propagation.HeaderCarrier(header)
t.propagator.Inject(ctx, carrier)
t.config.Propagator.Inject(ctx, carrier)

return span
}

func newTracer(tp trace.TracerProvider) trace.Tracer {
return tp.Tracer("go-runtime", trace.WithInstrumentationVersion("1.0.0"))
return tp.Tracer(tracerName, trace.WithInstrumentationVersion(version()))
}

func newConfig(opts ...OpenTelemetryOpt) *config {
c := &config{
Propagator: otel.GetTextMapPropagator(),
}

for _, opt := range opts {
opt.apply(c)
}

// Tracer is only initialized if manually specified. Otherwise, can be passed with the tracing context.
if c.TracerProvider != nil {
c.Tracer = newTracer(c.TracerProvider)
}

return c
}

// Version is the current release version of the go-runtime instrumentation.
func version() string {
return instrumentationVersion
}

// SemVersion is the semantic version to be supplied to tracer/meter creation.
func semVersion() string {
return "semver:" + version()
}
13 changes: 4 additions & 9 deletions client/opentelemetry_test.go
Expand Up @@ -90,20 +90,17 @@ func Test_injectOpenTelemetrySpanContext(t *testing.T) {

header := map[string][]string{}
tr := newOpenTelemetryTransport(&mockRuntime{runtime.TestClientRequest{Headers: header}}, "", nil)
tr.propagator = propagation.TraceContext{}
tr.config.Propagator = propagation.TraceContext{}
tr.Submit(operation)

// values are random - just check that something was injected
assert.Len(t, header, 1)
}

func assertOpenTelemetrySubmit(t *testing.T, operation *runtime.ClientOperation, exporter *tracetest.InMemoryExporter, expectedSpanCount int) {
header := map[string][]string{}
r := newOpenTelemetryTransport(&mockRuntime{runtime.TestClientRequest{Headers: header}},
"remote_host",
nil)
tr := newOpenTelemetryTransport(&mockRuntime{runtime.TestClientRequest{Headers: header}}, "remote_host", nil)

_, err := r.Submit(operation)
_, err := tr.Submit(operation)
require.NoError(t, err)

spans := exporter.GetSpans()
Expand All @@ -112,17 +109,15 @@ func assertOpenTelemetrySubmit(t *testing.T, operation *runtime.ClientOperation,
if expectedSpanCount == 1 {
span := spans[0]
assert.Equal(t, "getCluster", span.Name)
assert.Equal(t, "go-openapi", span.InstrumentationLibrary.Name)
assert.Equal(t, span.Status.Code, codes.Error)
assert.Equal(t, []attribute.KeyValue{
// "component": "go-openapi",
attribute.String("net.peer.name", "remote_host"),
attribute.String("http.route", "/kubernetes-clusters/{cluster_id}"),
attribute.String("http.method", "GET"),
attribute.String("span.kind", trace.SpanKindClient.String()),
attribute.String("http.scheme", "https"),
attribute.Int("http.status_code", 490),
// "peer.service": "service",
// "error": true,
}, span.Attributes)
}
}

0 comments on commit f318eb6

Please sign in to comment.