-
Notifications
You must be signed in to change notification settings - Fork 135
/
AsyncHooksScopeManager.ts
140 lines (119 loc) · 4.17 KB
/
AsyncHooksScopeManager.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
import { CorrelationContextManager, CorrelationContext } from "./CorrelationContextManager"
import { ISpanContext } from "diagnostic-channel";
import { EventEmitter } from "events";
/**
* Type of span. Can be used to specify additional relationships between spans
* in addition to a parent/child relationship.
*/
export enum SpanKind {
/** Default value. Indicates that the span is used internally. */
INTERNAL = 0,
/**
* Indicates that the span covers server-side handling of an RPC or other
* remote request.
*/
SERVER = 1,
/**
* Indicates that the span covers the client-side wrapper around an RPC or
* other remote request.
*/
CLIENT = 2,
/**
* Indicates that the span describes producer sending a message to a
* broker. Unlike client and server, there is no direct critical path latency
* relationship between producer and consumer spans.
*/
PRODUCER = 3,
/**
* Indicates that the span describes consumer receiving a message from a
* broker. Unlike client and server, there is no direct critical path latency
* relationship between producer and consumer spans.
*/
CONSUMER = 4,
}
export type LinkContext = Pick<SpanContext, 'traceId' | 'spanId'>;
export interface Attributes {
[attributeKey: string]: AttributeValue | undefined;
}
export type AttributeValue =
| string
| number
| boolean
| Array<null | undefined | string>
| Array<null | undefined | number>
| Array<null | undefined | boolean>;
export interface Link {
/** The {@link SpanContext} of a linked span. */
context: LinkContext;
/** A set of {@link Attributes} on the link. */
attributes?: Attributes;
}
export interface SpanContext {
traceId: string;
spanId: string;
traceFlags?: { toString: () => string };
tracestate?: string;
}
export interface Span {
_duration: [number, number]; // hrTime
name: string;
parentSpanId?: string;
status: { code: number, message?: string },
attributes: Record<string, string>,
kind: SpanKind;
links: Link[];
context: () => SpanContext;
}
export class OpenTelemetryScopeManagerWrapper {
private _activeSymbol: symbol | undefined;
public active() {
const context = CorrelationContextManager.getCurrentContext() as any;
return {
...context,
getValue: (key: symbol) => {
// todo: lazy import activeSymbol from opentelemetry/api
if (!this._activeSymbol) {
this._activeSymbol = key;
return context;
}
if (key === this._activeSymbol) {
return context;
}
return false;
},
setValue: () => { }
};
}
public with(span: Span, fn: () => any) {
const parentSpanId = span.parentSpanId;
const name = span.name;
const correlationContext = OpenTelemetryScopeManagerWrapper._spanToContext(span, parentSpanId, name);
return CorrelationContextManager.runWithContext(correlationContext, fn)();
}
public bind<T>(target: T): T {
if (typeof target === "function") {
return CorrelationContextManager.wrapCallback(target);
} else if (target instanceof EventEmitter) {
CorrelationContextManager.wrapEmitter(target);
}
return target;
}
public enable(): this {
CorrelationContextManager.enable();
return this;
}
public disable(): this {
CorrelationContextManager.disable();
return this;
}
private static _spanToContext(span: Span, parentSpanId?: string, name?: string): CorrelationContext {
const _parentId = parentSpanId ? `|${span.context().traceId}.${parentSpanId}.` : span.context().traceId;
const context: ISpanContext = {
...span.context(),
traceFlags: span.context().traceFlags.toString()
};
const correlationContext = CorrelationContextManager.spanToContextObject(context, _parentId, name)
return correlationContext;
}
}
export const AsyncScopeManager = new OpenTelemetryScopeManagerWrapper();