blob: 1869b1a0418eeff435808723e409951eeac007f5 [file] [log] [blame]
Girish Kumar46d7c3a2020-05-18 12:06:33 +00001/*
2 * Copyright 2018-present Open Networking Foundation
3
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7
8 * http://www.apache.org/licenses/LICENSE-2.0
9
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17// File contains utility functions to support Open Tracing in conjunction with
18// Enhanced Logging based on context propagation
19
20package log
21
22import (
23 "context"
24 "errors"
25 "github.com/opentracing/opentracing-go"
26 jtracing "github.com/uber/jaeger-client-go"
27 jcfg "github.com/uber/jaeger-client-go/config"
28 jmetrics "github.com/uber/jaeger-lib/metrics"
29 "io"
30 "os"
31)
32
33// This method will start the Tracing for a component using Component name injected from the Chart
34// The close() method on returned Closer instance should be called in defer mode to gracefully
35// terminate tracing on component shutdown
36func StartTracing() (io.Closer, error) {
37 componentName := os.Getenv("COMPONENT_NAME")
38 if componentName == "" {
39 return nil, errors.New("Unable to retrieve PoD Component Name from Runtime env")
40 }
41
42 // Use basic configuration to start with; will extend later to support dynamic config updates
43 cfg := jcfg.Configuration{}
44
45 jLoggerCfgOption := jcfg.Logger(jtracing.StdLogger)
46 jMetricsFactoryCfgOption := jcfg.Metrics(jmetrics.NullFactory)
47
48 return cfg.InitGlobalTracer(componentName, jLoggerCfgOption, jMetricsFactoryCfgOption)
49}
50
51// Extracts details of Execution Context as log fields from the Tracing Span injected into the
52// context instance. Following log fields are extracted:
53// 1. Operation Name : key as 'op-name' and value as Span operation name
54// 2. Operation Id : key as 'op-id' and value as 64 bit Span Id in hex digits string
55//
56// Additionally, any tags present in Span are also extracted to use as log fields e.g. device-id.
57//
58// If no Span is found associated with context, blank slice is returned without any log fields
59func ExtractContextAttributes(ctx context.Context) []interface{} {
60 attrMap := make(map[string]interface{})
61
62 if ctx != nil {
63 if span := opentracing.SpanFromContext(ctx); span != nil {
64 if jspan, ok := span.(*jtracing.Span); ok {
65 opname := jspan.OperationName()
66 spanid := jspan.SpanContext().SpanID().String()
67
68 attrMap["op-id"] = spanid
69 attrMap["op-name"] = opname
70
71 for k, v := range jspan.Tags() {
72 attrMap[k] = v
73 }
74 }
75 }
76 }
77
78 return serializeMap(attrMap)
79}
80
81// Utility method to convert log Fields into array of interfaces expected by zap logger methods
82func serializeMap(fields Fields) []interface{} {
83 data := make([]interface{}, len(fields)*2)
84 i := 0
85 for k, v := range fields {
86 data[i] = k
87 data[i+1] = v
88 i = i + 2
89 }
90 return data
91}