This repository has been archived by the owner on May 23, 2023. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 108
/
tracer.ts
182 lines (166 loc) · 6.77 KB
/
tracer.ts
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
import * as Functions from './functions';
import * as Noop from './noop';
import Reference from './reference';
import Span from './span';
import SpanContext from './span_context';
export interface SpanOptions {
/**
* a parent SpanContext (or Span, for convenience) that the newly-started
* span will be the child of (per REFERENCE_CHILD_OF). If specified,
* `references` must be unspecified.
*/
childOf?: Span | SpanContext;
/**
* an array of Reference instances, each pointing to a causal parent
* SpanContext. If specified, `fields.childOf` must be unspecified.
*/
references?: Reference[];
/**
* set of key-value pairs which will be set as tags on the newly created
* Span. Ownership of the object is passed to the created span for
* efficiency reasons (the caller should not modify this object after
* calling startSpan).
*/
tags?: { [key: string]: any };
/**
* a manually specified start time for the created Span object. The time
* should be specified in milliseconds as Unix timestamp. Decimal value are
* supported to represent time values with sub-millisecond accuracy.
*/
startTime?: number;
}
/**
* Tracer is the entry-point between the instrumentation API and the tracing
* implementation.
*
* The default object acts as a no-op implementation.
*
* Note to implementators: derived classes can choose to directly implement the
* methods in the "OpenTracing API methods" section, or optionally the subset of
* underscore-prefixed methods to pick up the argument checking and handling
* automatically from the base class.
*/
export class Tracer {
// ---------------------------------------------------------------------- //
// OpenTracing API methods
// ---------------------------------------------------------------------- //
/**
* Starts and returns a new Span representing a logical unit of work.
*
* For example:
*
* // Start a new (parentless) root Span:
* var parent = Tracer.startSpan('DoWork');
*
* // Start a new (child) Span:
* var child = Tracer.startSpan('load-from-db', {
* childOf: parent.context(),
* });
*
* // Start a new async (FollowsFrom) Span:
* var child = Tracer.startSpan('async-cache-write', {
* references: [
* opentracing.followsFrom(parent.context())
* ],
* });
*
* @param {string} name - the name of the operation (REQUIRED).
* @param {SpanOptions} [options] - options for the newly created span.
* @return {Span} - a new Span object.
*/
startSpan(name: string, options: SpanOptions = {}): Span {
// Convert options.childOf to fields.references as needed.
if (options.childOf) {
// Convert from a Span or a SpanContext into a Reference.
const childOf = Functions.childOf(options.childOf);
if (options.references) {
options.references.push(childOf);
} else {
options.references = [childOf];
}
delete(options.childOf);
}
return this._startSpan(name, options);
}
/**
* Injects the given SpanContext instance for cross-process propagation
* within `carrier`. The expected type of `carrier` depends on the value of
* `format.
*
* OpenTracing defines a common set of `format` values (see
* FORMAT_TEXT_MAP, FORMAT_HTTP_HEADERS, and FORMAT_BINARY), and each has
* an expected carrier type.
*
* Consider this pseudocode example:
*
* var clientSpan = ...;
* ...
* // Inject clientSpan into a text carrier.
* var headersCarrier = {};
* Tracer.inject(clientSpan.context(), Tracer.FORMAT_HTTP_HEADERS, headersCarrier);
* // Incorporate the textCarrier into the outbound HTTP request header
* // map.
* Object.assign(outboundHTTPReq.headers, headersCarrier);
* // ... send the httpReq
*
* @param {SpanContext} spanContext - the SpanContext to inject into the
* carrier object. As a convenience, a Span instance may be passed
* in instead (in which case its .context() is used for the
* inject()).
* @param {string} format - the format of the carrier.
* @param {any} carrier - see the documentation for the chosen `format`
* for a description of the carrier object.
*/
inject(spanContext: SpanContext | Span, format: string, carrier: any): void {
// Allow the user to pass a Span instead of a SpanContext
if (spanContext instanceof Span) {
spanContext = spanContext.context();
}
return this._inject(spanContext, format, carrier);
}
/**
* Returns a SpanContext instance extracted from `carrier` in the given
* `format`.
*
* OpenTracing defines a common set of `format` values (see
* FORMAT_TEXT_MAP, FORMAT_HTTP_HEADERS, and FORMAT_BINARY), and each has
* an expected carrier type.
*
* Consider this pseudocode example:
*
* // Use the inbound HTTP request's headers as a text map carrier.
* var headersCarrier = inboundHTTPReq.headers;
* var wireCtx = Tracer.extract(Tracer.FORMAT_HTTP_HEADERS, headersCarrier);
* var serverSpan = Tracer.startSpan('...', { childOf : wireCtx });
*
* @param {string} format - the format of the carrier.
* @param {any} carrier - the type of the carrier object is determined by
* the format.
* @return {SpanContext}
* The extracted SpanContext, or null if no such SpanContext could
* be found in `carrier`
*/
extract(format: string, carrier: any): SpanContext | null {
return this._extract(format, carrier);
}
// ---------------------------------------------------------------------- //
// Derived classes can choose to implement the below
// ---------------------------------------------------------------------- //
// NOTE: the input to this method is *always* an associative array. The
// public-facing startSpan() method normalizes the arguments so that
// all N implementations do not need to worry about variations in the call
// signature.
//
// The default behavior returns a no-op span.
protected _startSpan(name: string, fields: SpanOptions): Span {
return Noop.span!;
}
// The default behavior is a no-op.
protected _inject(spanContext: SpanContext, format: string, carrier: any): void {
}
// The default behavior is to return a no-op SpanContext.
protected _extract(format: string, carrier: any): SpanContext | null {
return Noop.spanContext!;
}
}
export default Tracer;