-
Notifications
You must be signed in to change notification settings - Fork 4.6k
/
helper.go
119 lines (105 loc) · 3.72 KB
/
helper.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
112
113
114
115
116
117
118
119
// Copyright Project Harbor Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package trace
import (
"context"
"fmt"
"net/http"
"go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp"
"go.opentelemetry.io/otel"
"go.opentelemetry.io/otel/codes"
"go.opentelemetry.io/otel/propagation"
oteltrace "go.opentelemetry.io/otel/trace"
)
// GetGlobalTracer returns the global tracer.
func GetGlobalTracer(instrumentationName string, opts ...oteltrace.TracerOption) oteltrace.Tracer {
return otel.GetTracerProvider().Tracer(instrumentationName, opts...)
}
// StartSpan starts a span with the given name.
func StartSpan(ctx context.Context, name string) (context.Context, oteltrace.Span) {
return otel.Tracer("goharbor/harbor/src/lib/trace").Start(ctx, name)
}
// SpanFromHTTPRequest returns the span from the context.
func SpanFromHTTPRequest(req *http.Request) oteltrace.Span {
ctx := req.Context()
return oteltrace.SpanFromContext(ctx)
}
// RecordError records the error in the span from context.
func RecordError(span oteltrace.Span, err error, description string) {
if span == nil {
return
}
span.RecordError(err)
span.SetStatus(codes.Error, description)
}
// HarborSpanNameFormatter common span name formatter in Harbor
func HarborSpanNameFormatter(operation string, r *http.Request) string {
schema := "http"
if r.URL != nil && len(r.URL.Scheme) != 0 {
schema = r.URL.Scheme
}
host := "host_unknown"
if len(r.Host) != 0 {
host = r.Host
}
path := ""
if r.URL != nil && len(r.URL.Path) != 0 {
path = r.URL.Path
}
if len(path) != 0 {
return fmt.Sprintf("%s %s://%s%s", r.Method, schema, host, path)
}
return operation
}
// HarborHTTPTraceOptions common trace options
var HarborHTTPTraceOptions = []otelhttp.Option{
otelhttp.WithTracerProvider(otel.GetTracerProvider()),
otelhttp.WithPropagators(otel.GetTextMapPropagator()),
otelhttp.WithSpanNameFormatter(HarborSpanNameFormatter),
}
// NewHandler returns a handler that wraps the given handler with tracing.
func NewHandler(h http.Handler, operation string) http.Handler {
return otelhttp.NewHandler(h, operation, HarborHTTPTraceOptions...)
}
// StartTrace returns a new span with the given name.
func StartTrace(ctx context.Context, tracerName string, spanName string, opts ...oteltrace.SpanStartOption) (context.Context, oteltrace.Span) {
return otel.Tracer(tracerName).Start(ctx, spanName, opts...)
}
/*
ExractTraceID returns OpenTelemetry Trace ID
If tracing is enabled, the trace middleware already put the Span into request context,
so the func returns the Trace ID form request context
If tracing is NOT enabled, the func returns the Trace ID from the request header (if exists)
If Trace ID is not found, the func returns empty string
*/
func ExractTraceID(r *http.Request) string {
var traceID string
if Enabled() {
sc := oteltrace.SpanContextFromContext(r.Context())
if sc.HasTraceID() {
traceID = sc.TraceID().String()
}
}
if traceID == "" {
if tpHeader := r.Header.Get("traceparent"); tpHeader != "" {
var prop propagation.TraceContext
ctx := prop.Extract(context.Background(), propagation.HeaderCarrier(r.Header))
sc := oteltrace.SpanContextFromContext(ctx)
if sc.HasTraceID() {
traceID = sc.TraceID().String()
}
}
}
return traceID
}