-
Notifications
You must be signed in to change notification settings - Fork 1
/
OTInstrumenter.class.st
197 lines (148 loc) · 5.16 KB
/
OTInstrumenter.class.st
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
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
"
An instrumenter of the start and end of a request/response lifecycle.
Almost all instrumentation of libraries falls into modeling start and end, generating observability signals from these such as a tracing `OTSpan`, or metrics such as the duration taken, active requests, etc.
If you want to produce spans, you should create and configure an instance in `OTInstrumentation class>>#defineInstrumenter`.
When instrumenting a library, there will generally be four steps:
- Instantiate an `OTInstrumenter` and configure any library-specific customizations, and also expose useful knobs to your user.
- Call `OTInstrumenter>>#shouldStartUnder:request:` and do not proceed if `false`.
- Call `OTInstrumenter>>#startUnder:request:` at the beginning of a request.
- Call `OTInstrumenter>>#end:request:response:error:` at the end of a request.
The `end` method is called when the instrumented operation finished. It is of extreme importance for this method to be always called after `start`. Calling `start` without later `end` will result in inaccurate or wrong telemetry and context leaks.
"
Class {
#name : 'OTInstrumenter',
#superclass : 'Object',
#instVars : [
'spanSuppressionStrategy',
'spanKindExtractor',
'spanNameExtractor',
'contextProducer',
'instrumentationName'
],
#classInstVars : [
'default',
'defaultContextProducer',
'defaultSpanNameExtractor'
],
#category : 'OpenTelemetry-Instrumentation',
#package : 'OpenTelemetry-Instrumentation'
}
{ #category : 'instance creation' }
OTInstrumenter class >> default [
"A shared instrumenter with default configurations."
^ default ifNil: [ default := self new ]
]
{ #category : 'defaults' }
OTInstrumenter class >> defaultContextProducer [
^ defaultContextProducer ifNil: [
defaultContextProducer := [ OTContext new ] ]
]
{ #category : 'defaults' }
OTInstrumenter class >> defaultSpanKindExtractor [
^ OTSpan alwaysInternal
]
{ #category : 'defaults' }
OTInstrumenter class >> defaultSpanNameExtractor [
^ defaultSpanNameExtractor ifNil: [
defaultSpanNameExtractor := [ :request |
request printStringLimitedTo: 50 ] ]
]
{ #category : 'instance creation' }
OTInstrumenter class >> forInstrumentationNamed: aString [
^ self new instrumentationName: aString
]
{ #category : 'accessing' }
OTInstrumenter >> contextProducer [
^ contextProducer ifNil: [
contextProducer := self class defaultContextProducer ]
]
{ #category : 'accessing' }
OTInstrumenter >> contextProducer: anObject [
contextProducer := anObject
]
{ #category : 'instrumenting' }
OTInstrumenter >> end [
"Mark the end of the current span."
^ self end: OTSpan current error: nil
]
{ #category : 'instrumenting' }
OTInstrumenter >> end: span [
"Mark the end of a span execution."
^ self end: span error: nil
]
{ #category : 'instrumenting' }
OTInstrumenter >> end: span error: error [
"Mark the end of a span execution."
error ifNotNil: [ span recordException: error ].
span end.
^ OTSpanProcessor current process: span
]
{ #category : 'instrumenting' }
OTInstrumenter >> end: span request: request response: response error: error [
"Mark the end of a span execution."
error ifNotNil: [ span recordException: error ].
span end.
^ OTSpanProcessor current process: span
]
{ #category : 'accessing' }
OTInstrumenter >> instrumentationName [
^ instrumentationName
]
{ #category : 'accessing' }
OTInstrumenter >> instrumentationName: aString [
instrumentationName := aString
]
{ #category : 'instrumenting' }
OTInstrumenter >> produceContext [
^ self contextProducer value
]
{ #category : 'instrumenting' }
OTInstrumenter >> shouldStartUnder: span request: request [
^ spanSuppressionStrategy ifNil: [ true ] ifNotNil: [
(spanSuppressionStrategy
value: span
value: (self spanKindExtractor value: request)) not ]
]
{ #category : 'accessing' }
OTInstrumenter >> spanKindExtractor [
^ spanKindExtractor ifNil: [
spanKindExtractor := self class defaultSpanKindExtractor ]
]
{ #category : 'accessing' }
OTInstrumenter >> spanKindExtractor: aBlock [
spanKindExtractor := aBlock
]
{ #category : 'accessing' }
OTInstrumenter >> spanNameExtractor [
^ spanNameExtractor ifNil: [
spanNameExtractor := self class defaultSpanNameExtractor ]
]
{ #category : 'accessing' }
OTInstrumenter >> spanNameExtractor: aBlock [
spanNameExtractor := aBlock
]
{ #category : 'accessing' }
OTInstrumenter >> spanSuppressionStrategy [
^ spanSuppressionStrategy
]
{ #category : 'accessing' }
OTInstrumenter >> spanSuppressionStrategy: aBlock [
spanSuppressionStrategy := aBlock
]
{ #category : 'instrumenting' }
OTInstrumenter >> startRequest: request [
"Start a new operation to be instrumented."
^ self startUnder: OTSpan current request: request
]
{ #category : 'instrumenting' }
OTInstrumenter >> startUnder: parentSpan request: request [
"Start a new operation to be instrumented.
The parentSpan is the parent context of the resulting instrumented operation."
^ (parentSpan
ifNil: [ OTSpan rootIn: self produceContext ]
ifNotNil: [ OTSpan under: parentSpan ])
name: (self spanNameExtractor value: request);
kind: (self spanKindExtractor value: request);
instrumentationName: instrumentationName;
start
]