3 // Copyright 2018 Microsoft Corporation
5 // Licensed under the Apache License, Version 2.0 (the "License");
6 // you may not use this file except in compliance with the License.
7 // You may obtain a copy of the License at
9 // http://www.apache.org/licenses/LICENSE-2.0
11 // Unless required by applicable law or agreed to in writing, software
12 // distributed under the License is distributed on an "AS IS" BASIS,
13 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 // See the License for the specific language governing permissions and
15 // limitations under the License.
23 "contrib.go.opencensus.io/exporter/ocagent"
24 "go.opencensus.io/plugin/ochttp"
25 "go.opencensus.io/plugin/ochttp/propagation/tracecontext"
26 "go.opencensus.io/stats/view"
27 "go.opencensus.io/trace"
31 // Transport is the default tracing RoundTripper. The custom options setter will control
32 // if traces are being emitted or not.
33 Transport = &ochttp.Transport{
34 Propagation: &tracecontext.HTTPFormat{},
35 GetStartOptions: getStartOptions,
38 // enabled is the flag for marking if tracing is enabled.
41 // Sampler is the tracing sampler. If tracing is disabled it will never sample. Otherwise
42 // it will be using the parent sampler or the default.
43 sampler = trace.NeverSample()
45 // Views for metric instrumentation.
46 views = map[string]*view.View{}
49 traceExporter trace.Exporter
56 func enableFromEnv() {
57 _, ok := os.LookupEnv("AZURE_SDK_TRACING_ENABLED")
58 _, legacyOk := os.LookupEnv("AZURE_SDK_TRACING_ENABELD")
60 agentEndpoint, ok := os.LookupEnv("OCAGENT_TRACE_EXPORTER_ENDPOINT")
63 EnableWithAIForwarding(agentEndpoint)
70 // IsEnabled returns true if monitoring is enabled for the sdk.
71 func IsEnabled() bool {
75 // Enable will start instrumentation for metrics and traces.
84 // Disable will disable instrumentation for metrics and traces.
87 sampler = trace.NeverSample()
88 if traceExporter != nil {
89 trace.UnregisterExporter(traceExporter)
94 // EnableWithAIForwarding will start instrumentation and will connect to app insights forwarder
95 // exporter making the metrics and traces available in app insights.
96 func EnableWithAIForwarding(agentEndpoint string) (err error) {
102 traceExporter, err := ocagent.NewExporter(ocagent.WithInsecure(), ocagent.WithAddress(agentEndpoint))
106 trace.RegisterExporter(traceExporter)
110 // getStartOptions is the custom options setter for the ochttp package.
111 func getStartOptions(*http.Request) trace.StartOptions {
112 return trace.StartOptions{
117 // initStats registers the views for the http metrics
118 func initStats() (err error) {
119 clientViews := []*view.View{
120 ochttp.ClientCompletedCount,
121 ochttp.ClientRoundtripLatencyDistribution,
122 ochttp.ClientReceivedBytesDistribution,
123 ochttp.ClientSentBytesDistribution,
125 for _, cv := range clientViews {
126 vn := fmt.Sprintf("Azure/go-autorest/tracing-%s", cv.Name)
127 views[vn] = cv.WithName(vn)
128 err = view.Register(views[vn])
136 // disableStats will unregister the previously registered metrics
137 func disableStats() {
138 for _, v := range views {
143 // StartSpan starts a trace span
144 func StartSpan(ctx context.Context, name string) context.Context {
145 ctx, _ = trace.StartSpan(ctx, name, trace.WithSampler(sampler))
149 // EndSpan ends a previously started span stored in the context
150 func EndSpan(ctx context.Context, httpStatusCode int, err error) {
151 span := trace.FromContext(ctx)
158 span.SetStatus(trace.Status{Message: err.Error(), Code: toTraceStatusCode(httpStatusCode)})
163 // toTraceStatusCode converts HTTP Codes to OpenCensus codes as defined
164 // at https://github.com/census-instrumentation/opencensus-specs/blob/master/trace/HTTP.md#status
165 func toTraceStatusCode(httpStatusCode int) int32 {
167 case http.StatusOK <= httpStatusCode && httpStatusCode < http.StatusBadRequest:
168 return trace.StatusCodeOK
169 case httpStatusCode == http.StatusBadRequest:
170 return trace.StatusCodeInvalidArgument
171 case httpStatusCode == http.StatusUnauthorized: // 401 is actually unauthenticated.
172 return trace.StatusCodeUnauthenticated
173 case httpStatusCode == http.StatusForbidden:
174 return trace.StatusCodePermissionDenied
175 case httpStatusCode == http.StatusNotFound:
176 return trace.StatusCodeNotFound
177 case httpStatusCode == http.StatusTooManyRequests:
178 return trace.StatusCodeResourceExhausted
179 case httpStatusCode == 499:
180 return trace.StatusCodeCancelled
181 case httpStatusCode == http.StatusNotImplemented:
182 return trace.StatusCodeUnimplemented
183 case httpStatusCode == http.StatusServiceUnavailable:
184 return trace.StatusCodeUnavailable
185 case httpStatusCode == http.StatusGatewayTimeout:
186 return trace.StatusCodeDeadlineExceeded
188 return trace.StatusCodeUnknown