/
opentelemetry.go
111 lines (89 loc) · 3.06 KB
/
opentelemetry.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
package client
import (
"net/http"
"github.com/go-openapi/runtime"
"github.com/go-openapi/strfmt"
"go.opentelemetry.io/otel"
"go.opentelemetry.io/otel/attribute"
"go.opentelemetry.io/otel/codes"
semconv "go.opentelemetry.io/otel/semconv/v1.12.0"
"go.opentelemetry.io/otel/trace"
)
type openTelemetryTransport struct {
transport runtime.ClientTransport
host string
opts []trace.SpanStartOption
}
func newOpenTelemetryTransport(transport runtime.ClientTransport, host string, opts []trace.SpanStartOption) runtime.ClientTransport {
return &openTelemetryTransport{
transport: transport,
host: host,
opts: opts,
}
}
func (t *openTelemetryTransport) Submit(op *runtime.ClientOperation) (interface{}, error) {
if op.Context == nil {
return t.transport.Submit(op)
}
params := op.Params
reader := op.Reader
var span trace.Span
defer func() {
if span != nil {
span.End()
}
}()
op.Params = runtime.ClientRequestWriterFunc(func(req runtime.ClientRequest, reg strfmt.Registry) error {
span = createOpenTelemetryClientSpan(op, req.GetHeaderParams(), t.host, t.opts)
return params.WriteToRequest(req, reg)
})
op.Reader = runtime.ClientResponseReaderFunc(func(response runtime.ClientResponse, consumer runtime.Consumer) (interface{}, error) {
if span != nil {
statusCode := response.Code()
span.SetAttributes(attribute.Int(string(semconv.HTTPStatusCodeKey), statusCode))
span.SetStatus(semconv.SpanStatusFromHTTPStatusCodeAndSpanKind(statusCode, trace.SpanKindClient))
}
return reader.ReadResponse(response, consumer)
})
submit, err := t.transport.Submit(op)
if err != nil && span != nil {
span.RecordError(err)
span.SetStatus(codes.Error, "")
}
return submit, err
}
func createOpenTelemetryClientSpan(op *runtime.ClientOperation, _ http.Header, host string, opts []trace.SpanStartOption) trace.Span {
ctx := op.Context
span := trace.SpanFromContext(ctx)
if span != nil {
// TODO: Can we get the version number for use with trace.WithInstrumentationVersion?
tracer := otel.GetTracerProvider().Tracer("")
ctx, span = tracer.Start(ctx, operationName(op), opts...)
op.Context = ctx
span.SetAttributes(
attribute.String("net.peer.name", 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()),
//TODO: Figure out the best way to get the scheme?
attribute.String("http.scheme", op.Schemes[0]),
)
return span
}
// if span != nil {
// opts = append(opts, ext.SpanKindRPCClient)
// span, _ = opentracing.StartSpanFromContextWithTracer(
// ctx, span.Tracer(), operationName(op), opts...)
// ext.Component.Set(span, "go-openapi")
// ext.PeerHostname.Set(span, host)
// span.SetTag("http.path", op.PathPattern)
// ext.HTTPMethod.Set(span, op.Method)
// _ = span.Tracer().Inject(
// span.Context(),
// opentracing.HTTPHeaders,
// opentracing.HTTPHeadersCarrier(header))
// return span
// }
return nil
}