...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 package trace
16
17 import (
18 "context"
19 "errors"
20 "fmt"
21 "os"
22 "strings"
23 "sync"
24
25 "go.opencensus.io/trace"
26 "go.opentelemetry.io/otel"
27 "go.opentelemetry.io/otel/attribute"
28 "go.opentelemetry.io/otel/codes"
29 ottrace "go.opentelemetry.io/otel/trace"
30 "google.golang.org/api/googleapi"
31 "google.golang.org/genproto/googleapis/rpc/code"
32 "google.golang.org/grpc/status"
33 )
34
35 const (
36
37
38
39 TelemetryPlatformTracingOpenCensus = "opencensus"
40
41
42
43 TelemetryPlatformTracingOpenTelemetry = "opentelemetry"
44
45
46
47 TelemetryPlatformTracingVar = "GOOGLE_API_GO_EXPERIMENTAL_TELEMETRY_PLATFORM_TRACING"
48
49
50 OpenTelemetryTracerName = "cloud.google.com/go"
51 )
52
53 var (
54
55 openTelemetryTracingEnabledMu = sync.RWMutex{}
56
57
58
59 openTelemetryTracingEnabled bool = strings.EqualFold(strings.TrimSpace(
60 os.Getenv(TelemetryPlatformTracingVar)), TelemetryPlatformTracingOpenTelemetry)
61 )
62
63
64
65 func SetOpenTelemetryTracingEnabledField(enabled bool) {
66 openTelemetryTracingEnabledMu.Lock()
67 defer openTelemetryTracingEnabledMu.Unlock()
68 openTelemetryTracingEnabled = enabled
69 }
70
71
72
73
74 func IsOpenCensusTracingEnabled() bool {
75 return !IsOpenTelemetryTracingEnabled()
76 }
77
78
79
80
81 func IsOpenTelemetryTracingEnabled() bool {
82 openTelemetryTracingEnabledMu.RLock()
83 defer openTelemetryTracingEnabledMu.RUnlock()
84 return openTelemetryTracingEnabled
85 }
86
87
88
89
90
91
92
93
94
95 func StartSpan(ctx context.Context, name string) context.Context {
96 if IsOpenTelemetryTracingEnabled() {
97 ctx, _ = otel.GetTracerProvider().Tracer(OpenTelemetryTracerName).Start(ctx, name)
98 } else {
99 ctx, _ = trace.StartSpan(ctx, name)
100 }
101 return ctx
102 }
103
104
105
106
107
108
109
110
111
112 func EndSpan(ctx context.Context, err error) {
113 if IsOpenTelemetryTracingEnabled() {
114 span := ottrace.SpanFromContext(ctx)
115 if err != nil {
116 span.SetStatus(codes.Error, toOpenTelemetryStatusDescription(err))
117 span.RecordError(err)
118 }
119 span.End()
120 } else {
121 span := trace.FromContext(ctx)
122 if err != nil {
123 span.SetStatus(toStatus(err))
124 }
125 span.End()
126 }
127 }
128
129
130 func toStatus(err error) trace.Status {
131 var err2 *googleapi.Error
132 if ok := errors.As(err, &err2); ok {
133 return trace.Status{Code: httpStatusCodeToOCCode(err2.Code), Message: err2.Message}
134 } else if s, ok := status.FromError(err); ok {
135 return trace.Status{Code: int32(s.Code()), Message: s.Message()}
136 } else {
137 return trace.Status{Code: int32(code.Code_UNKNOWN), Message: err.Error()}
138 }
139 }
140
141
142 func toOpenTelemetryStatusDescription(err error) string {
143 var err2 *googleapi.Error
144 if ok := errors.As(err, &err2); ok {
145 return err2.Message
146 } else if s, ok := status.FromError(err); ok {
147 return s.Message()
148 } else {
149 return err.Error()
150 }
151 }
152
153
154
155 func httpStatusCodeToOCCode(httpStatusCode int) int32 {
156 switch httpStatusCode {
157 case 200:
158 return int32(code.Code_OK)
159 case 499:
160 return int32(code.Code_CANCELLED)
161 case 500:
162 return int32(code.Code_UNKNOWN)
163 case 400:
164 return int32(code.Code_INVALID_ARGUMENT)
165 case 504:
166 return int32(code.Code_DEADLINE_EXCEEDED)
167 case 404:
168 return int32(code.Code_NOT_FOUND)
169 case 409:
170 return int32(code.Code_ALREADY_EXISTS)
171 case 403:
172 return int32(code.Code_PERMISSION_DENIED)
173 case 401:
174 return int32(code.Code_UNAUTHENTICATED)
175 case 429:
176 return int32(code.Code_RESOURCE_EXHAUSTED)
177 case 501:
178 return int32(code.Code_UNIMPLEMENTED)
179 case 503:
180 return int32(code.Code_UNAVAILABLE)
181 default:
182 return int32(code.Code_UNKNOWN)
183 }
184 }
185
186
187
188
189
190
191
192
193
194
195
196
197
198 func TracePrintf(ctx context.Context, attrMap map[string]interface{}, format string, args ...interface{}) {
199 if IsOpenTelemetryTracingEnabled() {
200 attrs := otAttrs(attrMap)
201 ottrace.SpanFromContext(ctx).AddEvent(fmt.Sprintf(format, args...), ottrace.WithAttributes(attrs...))
202 } else {
203 attrs := ocAttrs(attrMap)
204
205
206
207 trace.FromContext(ctx).Annotatef(attrs, format, args...)
208 }
209 }
210
211
212 func ocAttrs(attrMap map[string]interface{}) []trace.Attribute {
213 var attrs []trace.Attribute
214 for k, v := range attrMap {
215 var a trace.Attribute
216 switch v := v.(type) {
217 case string:
218 a = trace.StringAttribute(k, v)
219 case bool:
220 a = trace.BoolAttribute(k, v)
221 case int:
222 a = trace.Int64Attribute(k, int64(v))
223 case int64:
224 a = trace.Int64Attribute(k, v)
225 default:
226 a = trace.StringAttribute(k, fmt.Sprintf("%#v", v))
227 }
228 attrs = append(attrs, a)
229 }
230 return attrs
231 }
232
233
234 func otAttrs(attrMap map[string]interface{}) []attribute.KeyValue {
235 var attrs []attribute.KeyValue
236 for k, v := range attrMap {
237 var a attribute.KeyValue
238 switch v := v.(type) {
239 case string:
240 a = attribute.Key(k).String(v)
241 case bool:
242 a = attribute.Key(k).Bool(v)
243 case int:
244 a = attribute.Key(k).Int(v)
245 case int64:
246 a = attribute.Key(k).Int64(v)
247 default:
248 a = attribute.Key(k).String(fmt.Sprintf("%#v", v))
249 }
250 attrs = append(attrs, a)
251 }
252 return attrs
253 }
254
View as plain text