@comprehend/telemetry-node 0.1.4 → 0.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +112 -27
- package/dist/ComprehendDevSpanProcessor.d.ts +10 -6
- package/dist/ComprehendDevSpanProcessor.js +154 -87
- package/dist/ComprehendDevSpanProcessor.test.js +270 -449
- package/dist/ComprehendMetricsExporter.d.ts +18 -0
- package/dist/ComprehendMetricsExporter.js +178 -0
- package/dist/ComprehendMetricsExporter.test.d.ts +1 -0
- package/dist/ComprehendMetricsExporter.test.js +266 -0
- package/dist/ComprehendSDK.d.ts +18 -0
- package/dist/ComprehendSDK.js +56 -0
- package/dist/ComprehendSDK.test.d.ts +1 -0
- package/dist/ComprehendSDK.test.js +126 -0
- package/dist/WebSocketConnection.d.ts +23 -3
- package/dist/WebSocketConnection.js +106 -12
- package/dist/WebSocketConnection.test.js +236 -169
- package/dist/index.d.ts +3 -1
- package/dist/index.js +5 -1
- package/dist/util.d.ts +2 -0
- package/dist/util.js +7 -0
- package/dist/wire-protocol.d.ts +168 -28
- package/package.json +3 -1
- package/src/ComprehendDevSpanProcessor.test.ts +311 -507
- package/src/ComprehendDevSpanProcessor.ts +178 -105
- package/src/ComprehendMetricsExporter.test.ts +334 -0
- package/src/ComprehendMetricsExporter.ts +225 -0
- package/src/ComprehendSDK.test.ts +160 -0
- package/src/ComprehendSDK.ts +63 -0
- package/src/WebSocketConnection.test.ts +286 -205
- package/src/WebSocketConnection.ts +135 -13
- package/src/index.ts +3 -2
- package/src/util.ts +6 -0
- package/src/wire-protocol.ts +204 -29
- package/src/sql-analyzer.test.ts +0 -599
- package/src/sql-analyzer.ts +0 -439
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
import { ComprehendSDK } from './ComprehendSDK';
|
|
2
|
+
import { WebSocketConnection } from './WebSocketConnection';
|
|
3
|
+
import { ComprehendDevSpanProcessor } from './ComprehendDevSpanProcessor';
|
|
4
|
+
import { ComprehendMetricsExporter } from './ComprehendMetricsExporter';
|
|
5
|
+
import { InitAck, CustomMetricSpecification } from './wire-protocol';
|
|
6
|
+
|
|
7
|
+
jest.mock('./WebSocketConnection');
|
|
8
|
+
jest.mock('./ComprehendDevSpanProcessor');
|
|
9
|
+
jest.mock('./ComprehendMetricsExporter');
|
|
10
|
+
|
|
11
|
+
const MockedWebSocketConnection = WebSocketConnection as jest.MockedClass<typeof WebSocketConnection>;
|
|
12
|
+
const MockedSpanProcessor = ComprehendDevSpanProcessor as jest.MockedClass<typeof ComprehendDevSpanProcessor>;
|
|
13
|
+
const MockedMetricsExporter = ComprehendMetricsExporter as jest.MockedClass<typeof ComprehendMetricsExporter>;
|
|
14
|
+
|
|
15
|
+
describe('ComprehendSDK', () => {
|
|
16
|
+
let capturedOnAuthorized: ((ack: InitAck) => void) | undefined;
|
|
17
|
+
let capturedOnCustomMetricChange: ((specs: CustomMetricSpecification[]) => void) | undefined;
|
|
18
|
+
let mockConnectionInstance: any;
|
|
19
|
+
|
|
20
|
+
beforeEach(() => {
|
|
21
|
+
jest.clearAllMocks();
|
|
22
|
+
capturedOnAuthorized = undefined;
|
|
23
|
+
capturedOnCustomMetricChange = undefined;
|
|
24
|
+
mockConnectionInstance = null;
|
|
25
|
+
|
|
26
|
+
MockedWebSocketConnection.mockImplementation((options: any) => {
|
|
27
|
+
capturedOnAuthorized = options.onAuthorized;
|
|
28
|
+
capturedOnCustomMetricChange = options.onCustomMetricChange;
|
|
29
|
+
mockConnectionInstance = {
|
|
30
|
+
sendMessage: jest.fn(),
|
|
31
|
+
setProcessContext: jest.fn(),
|
|
32
|
+
nextSeq: jest.fn(),
|
|
33
|
+
close: jest.fn(),
|
|
34
|
+
};
|
|
35
|
+
return mockConnectionInstance;
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
MockedSpanProcessor.mockImplementation(() => ({
|
|
39
|
+
onStart: jest.fn(),
|
|
40
|
+
onEnd: jest.fn(),
|
|
41
|
+
forceFlush: jest.fn().mockResolvedValue(undefined),
|
|
42
|
+
shutdown: jest.fn().mockResolvedValue(undefined),
|
|
43
|
+
updateCustomMetrics: jest.fn(),
|
|
44
|
+
} as any));
|
|
45
|
+
|
|
46
|
+
MockedMetricsExporter.mockImplementation(() => ({
|
|
47
|
+
export: jest.fn(),
|
|
48
|
+
forceFlush: jest.fn().mockResolvedValue(undefined),
|
|
49
|
+
shutdown: jest.fn().mockResolvedValue(undefined),
|
|
50
|
+
selectAggregationTemporality: jest.fn(),
|
|
51
|
+
updateCustomMetrics: jest.fn(),
|
|
52
|
+
} as any));
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
it('should create a WebSocketConnection with the correct options', () => {
|
|
56
|
+
new ComprehendSDK({ organization: 'test-org', token: 'test-token' });
|
|
57
|
+
|
|
58
|
+
expect(MockedWebSocketConnection).toHaveBeenCalledTimes(1);
|
|
59
|
+
const opts = MockedWebSocketConnection.mock.calls[0][0];
|
|
60
|
+
expect(opts.organization).toBe('test-org');
|
|
61
|
+
expect(opts.token).toBe('test-token');
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
it('should pass console.log as logger when debug is true', () => {
|
|
65
|
+
new ComprehendSDK({ organization: 'org', token: 'tok', debug: true });
|
|
66
|
+
|
|
67
|
+
const opts = MockedWebSocketConnection.mock.calls[0][0];
|
|
68
|
+
expect(opts.logger).toBe(console.log);
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
it('should pass custom logger function', () => {
|
|
72
|
+
const myLogger = jest.fn();
|
|
73
|
+
new ComprehendSDK({ organization: 'org', token: 'tok', debug: myLogger });
|
|
74
|
+
|
|
75
|
+
const opts = MockedWebSocketConnection.mock.calls[0][0];
|
|
76
|
+
expect(opts.logger).toBe(myLogger);
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
it('should return the same span processor on multiple calls', () => {
|
|
80
|
+
const sdk = new ComprehendSDK({ organization: 'org', token: 'tok' });
|
|
81
|
+
|
|
82
|
+
const proc1 = sdk.getSpanProcessor();
|
|
83
|
+
const proc2 = sdk.getSpanProcessor();
|
|
84
|
+
|
|
85
|
+
expect(proc1).toBe(proc2);
|
|
86
|
+
expect(MockedSpanProcessor).toHaveBeenCalledTimes(1);
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
it('should return the same metrics exporter on multiple calls', () => {
|
|
90
|
+
const sdk = new ComprehendSDK({ organization: 'org', token: 'tok' });
|
|
91
|
+
|
|
92
|
+
const exp1 = sdk.getMetricsExporter();
|
|
93
|
+
const exp2 = sdk.getMetricsExporter();
|
|
94
|
+
|
|
95
|
+
expect(exp1).toBe(exp2);
|
|
96
|
+
expect(MockedMetricsExporter).toHaveBeenCalledTimes(1);
|
|
97
|
+
});
|
|
98
|
+
|
|
99
|
+
it('should share the same WebSocketConnection between processor and exporter', () => {
|
|
100
|
+
const sdk = new ComprehendSDK({ organization: 'org', token: 'tok' });
|
|
101
|
+
|
|
102
|
+
sdk.getSpanProcessor();
|
|
103
|
+
sdk.getMetricsExporter();
|
|
104
|
+
|
|
105
|
+
// Both should receive the same connection instance
|
|
106
|
+
expect(MockedSpanProcessor).toHaveBeenCalledWith(mockConnectionInstance);
|
|
107
|
+
expect(MockedMetricsExporter).toHaveBeenCalledWith(mockConnectionInstance);
|
|
108
|
+
});
|
|
109
|
+
|
|
110
|
+
it('should distribute custom metrics from onAuthorized to processor and exporter', () => {
|
|
111
|
+
const sdk = new ComprehendSDK({ organization: 'org', token: 'tok' });
|
|
112
|
+
const processor = sdk.getSpanProcessor();
|
|
113
|
+
const exporter = sdk.getMetricsExporter();
|
|
114
|
+
|
|
115
|
+
const specs: CustomMetricSpecification[] = [
|
|
116
|
+
{ type: 'span', rule: { kind: 'type', value: 'server' }, subject: 's1' },
|
|
117
|
+
{ type: 'cumulative', id: 'm1', attributes: ['a'], subject: 's2' },
|
|
118
|
+
];
|
|
119
|
+
|
|
120
|
+
// Simulate the auth callback
|
|
121
|
+
capturedOnAuthorized!({ type: 'ack-authorized', customMetrics: specs });
|
|
122
|
+
|
|
123
|
+
expect((processor as any).updateCustomMetrics).toHaveBeenCalledWith(specs);
|
|
124
|
+
expect((exporter as any).updateCustomMetrics).toHaveBeenCalledWith(specs);
|
|
125
|
+
});
|
|
126
|
+
|
|
127
|
+
it('should distribute custom metrics from onCustomMetricChange', () => {
|
|
128
|
+
const sdk = new ComprehendSDK({ organization: 'org', token: 'tok' });
|
|
129
|
+
const processor = sdk.getSpanProcessor();
|
|
130
|
+
const exporter = sdk.getMetricsExporter();
|
|
131
|
+
|
|
132
|
+
const specs: CustomMetricSpecification[] = [
|
|
133
|
+
{ type: 'timeseries', id: 'new-metric', attributes: [], subject: 's3' },
|
|
134
|
+
];
|
|
135
|
+
|
|
136
|
+
capturedOnCustomMetricChange!(specs);
|
|
137
|
+
|
|
138
|
+
expect((processor as any).updateCustomMetrics).toHaveBeenCalledWith(specs);
|
|
139
|
+
expect((exporter as any).updateCustomMetrics).toHaveBeenCalledWith(specs);
|
|
140
|
+
});
|
|
141
|
+
|
|
142
|
+
it('should shutdown processor, exporter, and connection', async () => {
|
|
143
|
+
const sdk = new ComprehendSDK({ organization: 'org', token: 'tok' });
|
|
144
|
+
const processor = sdk.getSpanProcessor();
|
|
145
|
+
const exporter = sdk.getMetricsExporter();
|
|
146
|
+
|
|
147
|
+
await sdk.shutdown();
|
|
148
|
+
|
|
149
|
+
expect((processor as any).shutdown).toHaveBeenCalled();
|
|
150
|
+
expect((exporter as any).shutdown).toHaveBeenCalled();
|
|
151
|
+
expect(mockConnectionInstance.close).toHaveBeenCalled();
|
|
152
|
+
});
|
|
153
|
+
|
|
154
|
+
it('should shutdown cleanly even without processor or exporter created', async () => {
|
|
155
|
+
const sdk = new ComprehendSDK({ organization: 'org', token: 'tok' });
|
|
156
|
+
|
|
157
|
+
await expect(sdk.shutdown()).resolves.toBeUndefined();
|
|
158
|
+
expect(mockConnectionInstance.close).toHaveBeenCalled();
|
|
159
|
+
});
|
|
160
|
+
});
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import { CustomMetricSpecification, InitAck } from './wire-protocol';
|
|
2
|
+
import { WebSocketConnection } from './WebSocketConnection';
|
|
3
|
+
import { ComprehendDevSpanProcessor } from './ComprehendDevSpanProcessor';
|
|
4
|
+
import { ComprehendMetricsExporter } from './ComprehendMetricsExporter';
|
|
5
|
+
|
|
6
|
+
export type LogFn = (message: string) => void;
|
|
7
|
+
|
|
8
|
+
export class ComprehendSDK {
|
|
9
|
+
private readonly connection: WebSocketConnection;
|
|
10
|
+
private spanProcessor: ComprehendDevSpanProcessor | null = null;
|
|
11
|
+
private metricsExporter: ComprehendMetricsExporter | null = null;
|
|
12
|
+
private customMetricListeners: Array<(specs: CustomMetricSpecification[]) => void> = [];
|
|
13
|
+
|
|
14
|
+
constructor(options: { organization: string, token: string, debug?: boolean | LogFn }) {
|
|
15
|
+
const logger = options.debug === true ? console.log
|
|
16
|
+
: options.debug === false ? undefined
|
|
17
|
+
: options.debug;
|
|
18
|
+
|
|
19
|
+
this.connection = new WebSocketConnection({
|
|
20
|
+
organization: options.organization,
|
|
21
|
+
token: options.token,
|
|
22
|
+
logger,
|
|
23
|
+
onAuthorized: (ack: InitAck) => {
|
|
24
|
+
this.distributeCustomMetrics(ack.customMetrics);
|
|
25
|
+
},
|
|
26
|
+
onCustomMetricChange: (specs: CustomMetricSpecification[]) => {
|
|
27
|
+
this.distributeCustomMetrics(specs);
|
|
28
|
+
},
|
|
29
|
+
});
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
private distributeCustomMetrics(specs: CustomMetricSpecification[]): void {
|
|
33
|
+
for (const listener of this.customMetricListeners) {
|
|
34
|
+
listener(specs);
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
getSpanProcessor(): ComprehendDevSpanProcessor {
|
|
39
|
+
if (!this.spanProcessor) {
|
|
40
|
+
this.spanProcessor = new ComprehendDevSpanProcessor(this.connection);
|
|
41
|
+
this.customMetricListeners.push((specs) => this.spanProcessor!.updateCustomMetrics(specs));
|
|
42
|
+
}
|
|
43
|
+
return this.spanProcessor;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
getMetricsExporter(): ComprehendMetricsExporter {
|
|
47
|
+
if (!this.metricsExporter) {
|
|
48
|
+
this.metricsExporter = new ComprehendMetricsExporter(this.connection);
|
|
49
|
+
this.customMetricListeners.push((specs) => this.metricsExporter!.updateCustomMetrics(specs));
|
|
50
|
+
}
|
|
51
|
+
return this.metricsExporter;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
async shutdown(): Promise<void> {
|
|
55
|
+
if (this.spanProcessor) {
|
|
56
|
+
await this.spanProcessor.shutdown();
|
|
57
|
+
}
|
|
58
|
+
if (this.metricsExporter) {
|
|
59
|
+
await this.metricsExporter.shutdown();
|
|
60
|
+
}
|
|
61
|
+
this.connection.close();
|
|
62
|
+
}
|
|
63
|
+
}
|