/
option.go
141 lines (122 loc) · 4.09 KB
/
option.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
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
// Unless explicitly stated otherwise all files in this repository are licensed
// under the Apache License Version 2.0.
// This product includes software developed at Datadog (https://www.datadoghq.com/).
// Copyright 2016 Datadog, Inc.
package echo
import (
"errors"
"math"
"gopkg.in/DataDog/dd-trace-go.v1/internal"
"gopkg.in/DataDog/dd-trace-go.v1/internal/globalconfig"
"gopkg.in/DataDog/dd-trace-go.v1/internal/namingschema"
"gopkg.in/DataDog/dd-trace-go.v1/internal/normalizer"
"github.com/labstack/echo/v4"
)
const defaultServiceName = "echo"
type config struct {
serviceName string
analyticsRate float64
noDebugStack bool
ignoreRequestFunc IgnoreRequestFunc
isStatusError func(statusCode int) bool
translateError func(err error) (*echo.HTTPError, bool)
headerTags *internal.LockMap
tags map[string]interface{}
}
// Option represents an option that can be passed to Middleware.
type Option func(*config)
// IgnoreRequestFunc determines if tracing will be skipped for a request.
type IgnoreRequestFunc func(c echo.Context) bool
func defaults(cfg *config) {
cfg.serviceName = namingschema.NewDefaultServiceName(defaultServiceName).GetName()
cfg.analyticsRate = math.NaN()
cfg.isStatusError = isServerError
cfg.headerTags = globalconfig.HeaderTagMap()
cfg.tags = make(map[string]interface{})
cfg.translateError = func(err error) (*echo.HTTPError, bool) {
var echoErr *echo.HTTPError
if errors.As(err, &echoErr) {
return echoErr, true
}
return nil, false
}
}
// WithServiceName sets the given service name for the system.
func WithServiceName(name string) Option {
return func(cfg *config) {
cfg.serviceName = name
}
}
// WithAnalytics enables Trace Analytics for all started spans.
func WithAnalytics(on bool) Option {
return func(cfg *config) {
if on {
cfg.analyticsRate = 1.0
} else {
cfg.analyticsRate = math.NaN()
}
}
}
// WithAnalyticsRate sets the sampling rate for Trace Analytics events
// correlated to started spans.
func WithAnalyticsRate(rate float64) Option {
return func(cfg *config) {
if rate >= 0.0 && rate <= 1.0 {
cfg.analyticsRate = rate
} else {
cfg.analyticsRate = math.NaN()
}
}
}
// NoDebugStack prevents stack traces from being attached to spans finishing
// with an error. This is useful in situations where errors are frequent and
// performance is critical.
func NoDebugStack() Option {
return func(cfg *config) {
cfg.noDebugStack = true
}
}
// WithIgnoreRequest sets a function which determines if tracing will be
// skipped for a given request.
func WithIgnoreRequest(ignoreRequestFunc IgnoreRequestFunc) Option {
return func(cfg *config) {
cfg.ignoreRequestFunc = ignoreRequestFunc
}
}
// WithErrorTranslator sets a function to translate Go errors into echo Errors.
// This is used for extracting the HTTP response status code.
func WithErrorTranslator(fn func(err error) (*echo.HTTPError, bool)) Option {
return func(cfg *config) {
cfg.translateError = fn
}
}
// WithStatusCheck specifies a function fn which reports whether the passed
// statusCode should be considered an error.
func WithStatusCheck(fn func(statusCode int) bool) Option {
return func(cfg *config) {
cfg.isStatusError = fn
}
}
func isServerError(statusCode int) bool {
return statusCode >= 500 && statusCode < 600
}
// WithHeaderTags enables the integration to attach HTTP request headers as span tags.
// Warning:
// Using this feature can risk exposing sensitive data such as authorization tokens to Datadog.
// Special headers can not be sub-selected. E.g., an entire Cookie header would be transmitted, without the ability to choose specific Cookies.
func WithHeaderTags(headers []string) Option {
headerTagsMap := normalizer.HeaderTagSlice(headers)
return func(cfg *config) {
cfg.headerTags = internal.NewLockMap(headerTagsMap)
}
}
// WithCustomTag will attach the value to the span tagged by the key. Standard
// span tags cannot be replaced.
func WithCustomTag(key string, value interface{}) Option {
return func(cfg *config) {
if cfg.tags == nil {
cfg.tags = make(map[string]interface{})
}
cfg.tags[key] = value
}
}