camusdb 0.6.0 → 0.8.0
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 +250 -0
- package/dist/client.d.ts +73 -39
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +158 -169
- package/dist/client.js.map +1 -1
- package/dist/config.d.ts +22 -0
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +19 -0
- package/dist/config.js.map +1 -1
- package/dist/endpoint-pool.d.ts +8 -0
- package/dist/endpoint-pool.d.ts.map +1 -1
- package/dist/endpoint-pool.js +25 -0
- package/dist/endpoint-pool.js.map +1 -1
- package/dist/index.d.ts +6 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -0
- package/dist/index.js.map +1 -1
- package/dist/node-stats.d.ts +113 -0
- package/dist/node-stats.d.ts.map +1 -0
- package/dist/node-stats.js +90 -0
- package/dist/node-stats.js.map +1 -0
- package/dist/options.d.ts +10 -0
- package/dist/options.d.ts.map +1 -1
- package/dist/options.js +1 -0
- package/dist/options.js.map +1 -1
- package/dist/pipeline.d.ts +136 -0
- package/dist/pipeline.d.ts.map +1 -0
- package/dist/pipeline.js +375 -0
- package/dist/pipeline.js.map +1 -0
- package/dist/prepared/auto-prepare.d.ts +51 -0
- package/dist/prepared/auto-prepare.d.ts.map +1 -0
- package/dist/prepared/auto-prepare.js +150 -0
- package/dist/prepared/auto-prepare.js.map +1 -0
- package/dist/prepared/policy.d.ts +7 -0
- package/dist/prepared/policy.d.ts.map +1 -1
- package/dist/prepared/policy.js +16 -0
- package/dist/prepared/policy.js.map +1 -1
- package/dist/query-stream.d.ts +9 -1
- package/dist/query-stream.d.ts.map +1 -1
- package/dist/query-stream.js +20 -2
- package/dist/query-stream.js.map +1 -1
- package/dist/retry.d.ts +8 -0
- package/dist/retry.d.ts.map +1 -1
- package/dist/retry.js +12 -1
- package/dist/retry.js.map +1 -1
- package/dist/sql-syntax.d.ts +6 -0
- package/dist/sql-syntax.d.ts.map +1 -1
- package/dist/sql-syntax.js +8 -0
- package/dist/sql-syntax.js.map +1 -1
- package/dist/statements.d.ts +14 -0
- package/dist/statements.d.ts.map +1 -1
- package/dist/statements.js +45 -3
- package/dist/statements.js.map +1 -1
- package/dist/telemetry.d.ts +199 -0
- package/dist/telemetry.d.ts.map +1 -0
- package/dist/telemetry.js +423 -0
- package/dist/telemetry.js.map +1 -0
- package/dist/transaction.d.ts +60 -5
- package/dist/transaction.d.ts.map +1 -1
- package/dist/transaction.js +124 -24
- package/dist/transaction.js.map +1 -1
- package/dist/transport/authenticating-transport.d.ts +9 -1
- package/dist/transport/authenticating-transport.d.ts.map +1 -1
- package/dist/transport/authenticating-transport.js +13 -0
- package/dist/transport/authenticating-transport.js.map +1 -1
- package/dist/transport/grpc/batch-frames.d.ts +23 -5
- package/dist/transport/grpc/batch-frames.d.ts.map +1 -1
- package/dist/transport/grpc/batch-frames.js +29 -8
- package/dist/transport/grpc/batch-frames.js.map +1 -1
- package/dist/transport/grpc/batcher.d.ts +69 -5
- package/dist/transport/grpc/batcher.d.ts.map +1 -1
- package/dist/transport/grpc/batcher.js +217 -10
- package/dist/transport/grpc/batcher.js.map +1 -1
- package/dist/transport/grpc/grpc-transport.d.ts +35 -1
- package/dist/transport/grpc/grpc-transport.d.ts.map +1 -1
- package/dist/transport/grpc/grpc-transport.js +193 -7
- package/dist/transport/grpc/grpc-transport.js.map +1 -1
- package/dist/transport/grpc/messages.d.ts +15 -0
- package/dist/transport/grpc/messages.d.ts.map +1 -1
- package/dist/transport/grpc/messages.js +9 -0
- package/dist/transport/grpc/messages.js.map +1 -1
- package/dist/transport/rest-transport.d.ts +9 -1
- package/dist/transport/rest-transport.d.ts.map +1 -1
- package/dist/transport/rest-transport.js +24 -0
- package/dist/transport/rest-transport.js.map +1 -1
- package/dist/transport/sequential-pipeline.d.ts +21 -0
- package/dist/transport/sequential-pipeline.d.ts.map +1 -0
- package/dist/transport/sequential-pipeline.js +119 -0
- package/dist/transport/sequential-pipeline.js.map +1 -0
- package/dist/transport/transport.d.ts +94 -0
- package/dist/transport/transport.d.ts.map +1 -1
- package/dist/transport/transport.js +10 -0
- package/dist/transport/transport.js.map +1 -1
- package/package.json +10 -4
- package/proto/camus_sql.proto +114 -0
|
@@ -0,0 +1,199 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* This file is part of CamusDB
|
|
3
|
+
*
|
|
4
|
+
* For the full copyright and license information, please view the LICENSE.txt
|
|
5
|
+
* file that was distributed with this source code.
|
|
6
|
+
*/
|
|
7
|
+
/**
|
|
8
|
+
* Traces and metrics through `@opentelemetry/api`.
|
|
9
|
+
*
|
|
10
|
+
* The package is an optional peer dependency, as the gRPC packages are. When it is installed, the
|
|
11
|
+
* driver reports through the global tracer and meter that it names `camusdb`. When it is not
|
|
12
|
+
* installed, every function here returns at once and the driver reports nothing. Install an
|
|
13
|
+
* OpenTelemetry SDK and register it as usual to collect the data. The driver needs no plugin.
|
|
14
|
+
*
|
|
15
|
+
* The span and metric names and attributes are those of the .NET driver, and they follow the
|
|
16
|
+
* OpenTelemetry database conventions. See the README for the list.
|
|
17
|
+
*/
|
|
18
|
+
/** The instrumentation scope that the driver's tracer and meter report under. */
|
|
19
|
+
export declare const CAMUS_TELEMETRY_NAME = "camusdb";
|
|
20
|
+
/** The `camusdb.retry.kind` values: what the driver sent again. */
|
|
21
|
+
export declare const CamusRetryKind: {
|
|
22
|
+
/** A commit or a rollback sent again after `CADB0509`. */
|
|
23
|
+
readonly Finalize: "finalize";
|
|
24
|
+
/** A unit of work of `withRetry` run again after a serializable conflict. */
|
|
25
|
+
readonly Autocommit: "autocommit";
|
|
26
|
+
/** A unit of work of `client.transaction` run again, from `BEGIN`, after a serializable conflict. */
|
|
27
|
+
readonly Transaction: "transaction";
|
|
28
|
+
/** A call sent again with a new token after the server refused the old one. */
|
|
29
|
+
readonly TokenRenewal: "token_renewal";
|
|
30
|
+
/** A `CREATE DATABASE` or a branch creation sent again after a transient failure. */
|
|
31
|
+
readonly CreateDatabase: "create_database";
|
|
32
|
+
};
|
|
33
|
+
export type CamusRetryKind = (typeof CamusRetryKind)[keyof typeof CamusRetryKind];
|
|
34
|
+
/** The `camusdb.prepared_statement.result` values. */
|
|
35
|
+
export declare const PreparedResult: {
|
|
36
|
+
readonly Hit: "hit";
|
|
37
|
+
readonly Registered: "registered";
|
|
38
|
+
readonly Miss: "miss";
|
|
39
|
+
readonly Success: "success";
|
|
40
|
+
readonly Refused: "refused";
|
|
41
|
+
readonly Unsupported: "unsupported";
|
|
42
|
+
};
|
|
43
|
+
type AttributeValue = string | number | boolean;
|
|
44
|
+
type Attributes = Record<string, AttributeValue | undefined>;
|
|
45
|
+
interface OtelSpan {
|
|
46
|
+
isRecording(): boolean;
|
|
47
|
+
setAttribute(key: string, value: AttributeValue): unknown;
|
|
48
|
+
setStatus(status: {
|
|
49
|
+
code: number;
|
|
50
|
+
message?: string;
|
|
51
|
+
}): unknown;
|
|
52
|
+
recordException(exception: unknown): void;
|
|
53
|
+
addEvent(name: string, attributes?: Attributes): unknown;
|
|
54
|
+
end(): void;
|
|
55
|
+
}
|
|
56
|
+
interface OtelTracer {
|
|
57
|
+
startSpan(name: string, options?: {
|
|
58
|
+
kind?: number;
|
|
59
|
+
attributes?: Attributes;
|
|
60
|
+
}, context?: unknown): OtelSpan;
|
|
61
|
+
}
|
|
62
|
+
interface OtelObservableResult {
|
|
63
|
+
observe(value: number, attributes?: Attributes): void;
|
|
64
|
+
}
|
|
65
|
+
interface OtelObservable {
|
|
66
|
+
addCallback(callback: (result: OtelObservableResult) => void): void;
|
|
67
|
+
}
|
|
68
|
+
interface OtelInstrumentOptions {
|
|
69
|
+
description?: string;
|
|
70
|
+
unit?: string;
|
|
71
|
+
advice?: {
|
|
72
|
+
explicitBucketBoundaries?: number[];
|
|
73
|
+
};
|
|
74
|
+
}
|
|
75
|
+
interface OtelMeter {
|
|
76
|
+
createHistogram(name: string, options?: OtelInstrumentOptions): {
|
|
77
|
+
record(value: number, attributes?: Attributes): void;
|
|
78
|
+
};
|
|
79
|
+
createCounter(name: string, options?: OtelInstrumentOptions): {
|
|
80
|
+
add(value: number, attributes?: Attributes): void;
|
|
81
|
+
};
|
|
82
|
+
createObservableGauge(name: string, options?: OtelInstrumentOptions): OtelObservable;
|
|
83
|
+
createObservableUpDownCounter(name: string, options?: OtelInstrumentOptions): OtelObservable;
|
|
84
|
+
}
|
|
85
|
+
/** @internal The subset of `@opentelemetry/api` the driver uses. */
|
|
86
|
+
export interface OtelApi {
|
|
87
|
+
readonly trace: {
|
|
88
|
+
getTracer(name: string, version?: string): OtelTracer;
|
|
89
|
+
setSpan(context: unknown, span: OtelSpan): unknown;
|
|
90
|
+
getActiveSpan(): OtelSpan | undefined;
|
|
91
|
+
};
|
|
92
|
+
readonly context: {
|
|
93
|
+
active(): unknown;
|
|
94
|
+
with<T>(context: unknown, fn: () => T): T;
|
|
95
|
+
};
|
|
96
|
+
readonly metrics: {
|
|
97
|
+
getMeterProvider(): unknown;
|
|
98
|
+
getMeter(name: string, version?: string): OtelMeter;
|
|
99
|
+
};
|
|
100
|
+
readonly SpanKind: {
|
|
101
|
+
readonly CLIENT: number;
|
|
102
|
+
};
|
|
103
|
+
readonly SpanStatusCode: {
|
|
104
|
+
readonly ERROR: number;
|
|
105
|
+
};
|
|
106
|
+
}
|
|
107
|
+
/**
|
|
108
|
+
* @internal Test hook: replaces the API, or with `null` plays a process without the package.
|
|
109
|
+
* `undefined` loads it again on the next operation.
|
|
110
|
+
*/
|
|
111
|
+
export declare function setTelemetryApi(replacement: OtelApi | null | undefined): void;
|
|
112
|
+
/** What an operation reads from the client it runs for. `ClientRuntime` has this shape. */
|
|
113
|
+
export interface TelemetryScope {
|
|
114
|
+
readonly database: string;
|
|
115
|
+
readonly config: {
|
|
116
|
+
readonly protocol: string;
|
|
117
|
+
readonly traceQueryText: boolean;
|
|
118
|
+
};
|
|
119
|
+
}
|
|
120
|
+
/** What one operation reports about itself. */
|
|
121
|
+
export interface OperationInit {
|
|
122
|
+
/** `SELECT`, `BEGIN`, `BATCH`, and so on. See `operationName`. */
|
|
123
|
+
readonly operationName?: string | undefined;
|
|
124
|
+
/** The table, when the driver knows it without a parse of the SQL text. */
|
|
125
|
+
readonly collection?: string | undefined;
|
|
126
|
+
/** The SQL text. It goes on the span only with `traceQueryText`. */
|
|
127
|
+
readonly queryText?: string | undefined;
|
|
128
|
+
/** The statement count of a pipeline exchange. */
|
|
129
|
+
readonly batchSize?: number | undefined;
|
|
130
|
+
}
|
|
131
|
+
/**
|
|
132
|
+
* One instrumented operation: its span, and its start time for the duration histogram.
|
|
133
|
+
*
|
|
134
|
+
* It ends once. The first `complete` or `fail` ends it, and later calls do nothing.
|
|
135
|
+
*/
|
|
136
|
+
export declare class CamusOperation {
|
|
137
|
+
private readonly otel;
|
|
138
|
+
private readonly span;
|
|
139
|
+
private readonly startedAt;
|
|
140
|
+
private readonly database;
|
|
141
|
+
private readonly operationName;
|
|
142
|
+
private ended;
|
|
143
|
+
private serverAddress;
|
|
144
|
+
private serverPort;
|
|
145
|
+
/** @internal Use `startOperation`. */
|
|
146
|
+
constructor(otel: OtelApi, span: OtelSpan, startedAt: number, database: string, operationName: string | undefined);
|
|
147
|
+
/** Records the server the operation goes to, as `server.address` and `server.port`. */
|
|
148
|
+
setEndpoint(endpoint: string): void;
|
|
149
|
+
setAttribute(key: string, value: AttributeValue): void;
|
|
150
|
+
/**
|
|
151
|
+
* Runs `fn` with this operation's span as the active span, so the HTTP or gRPC spans of the
|
|
152
|
+
* transport are its children.
|
|
153
|
+
*/
|
|
154
|
+
run<T>(fn: () => T): T;
|
|
155
|
+
/** Adds a `camusdb.retry` event to this operation's span. */
|
|
156
|
+
addRetryEvent(kind: CamusRetryKind, errorType: string | undefined): void;
|
|
157
|
+
/** Ends the operation as a success. */
|
|
158
|
+
complete(): void;
|
|
159
|
+
/** Ends the operation as a failure. */
|
|
160
|
+
fail(error: unknown): void;
|
|
161
|
+
private end;
|
|
162
|
+
}
|
|
163
|
+
/**
|
|
164
|
+
* Starts an operation, or reports `undefined` when `@opentelemetry/api` is not installed.
|
|
165
|
+
*
|
|
166
|
+
* The span is a child of the active span. Its name is `{operation} {target}`, where the target is
|
|
167
|
+
* the table when it is known, and the database if not.
|
|
168
|
+
*/
|
|
169
|
+
export declare function startOperation(scope: TelemetryScope, init: OperationInit): CamusOperation | undefined;
|
|
170
|
+
/**
|
|
171
|
+
* Runs one operation under a span, and ends the span with the operation's outcome.
|
|
172
|
+
*
|
|
173
|
+
* Without `@opentelemetry/api`, it only calls `run`.
|
|
174
|
+
*/
|
|
175
|
+
export declare function traced<T>(scope: TelemetryScope, init: OperationInit, run: (operation: CamusOperation | undefined) => Promise<T>): Promise<T>;
|
|
176
|
+
/**
|
|
177
|
+
* The operation name of a statement: its first keyword in upper case when that keyword is a known
|
|
178
|
+
* verb, and `undefined` if not. Leading white space and opening parentheses are skipped.
|
|
179
|
+
*/
|
|
180
|
+
export declare function operationName(sql: string): string | undefined;
|
|
181
|
+
/**
|
|
182
|
+
* Counts one retry, and adds a `camusdb.retry` event to the driver span of the operation, or to the
|
|
183
|
+
* active span when it is one of the driver's.
|
|
184
|
+
*/
|
|
185
|
+
export declare function recordRetry(kind: CamusRetryKind, error: unknown, details?: {
|
|
186
|
+
database?: string;
|
|
187
|
+
operationName?: string;
|
|
188
|
+
operation?: CamusOperation | undefined;
|
|
189
|
+
}): void;
|
|
190
|
+
/** Counts one endpoint set aside after a transport failure. */
|
|
191
|
+
export declare function recordQuarantine(endpoint: string): void;
|
|
192
|
+
/** Counts one execution of a preparable statement: `hit`, `registered`, or `miss`. */
|
|
193
|
+
export declare function recordPreparedLookup(database: string, result: string): void;
|
|
194
|
+
/** Counts one request to prepare a statement: `success`, `refused`, or `unsupported`. */
|
|
195
|
+
export declare function recordPreparedRegistration(database: string, result: string, error?: unknown): void;
|
|
196
|
+
/** Counts one prepared statement released to make room for one used more recently. */
|
|
197
|
+
export declare function recordPreparedEviction(database: string): void;
|
|
198
|
+
export {};
|
|
199
|
+
//# sourceMappingURL=telemetry.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"telemetry.d.ts","sourceRoot":"","sources":["../src/telemetry.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,423 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* This file is part of CamusDB
|
|
3
|
+
*
|
|
4
|
+
* For the full copyright and license information, please view the LICENSE.txt
|
|
5
|
+
* file that was distributed with this source code.
|
|
6
|
+
*/
|
|
7
|
+
import { createRequire } from 'node:module';
|
|
8
|
+
import { CamusEndpointPool } from './endpoint-pool.js';
|
|
9
|
+
import { CamusError } from './errors.js';
|
|
10
|
+
import { CamusPreparedStatementPolicy } from './prepared/policy.js';
|
|
11
|
+
/**
|
|
12
|
+
* Traces and metrics through `@opentelemetry/api`.
|
|
13
|
+
*
|
|
14
|
+
* The package is an optional peer dependency, as the gRPC packages are. When it is installed, the
|
|
15
|
+
* driver reports through the global tracer and meter that it names `camusdb`. When it is not
|
|
16
|
+
* installed, every function here returns at once and the driver reports nothing. Install an
|
|
17
|
+
* OpenTelemetry SDK and register it as usual to collect the data. The driver needs no plugin.
|
|
18
|
+
*
|
|
19
|
+
* The span and metric names and attributes are those of the .NET driver, and they follow the
|
|
20
|
+
* OpenTelemetry database conventions. See the README for the list.
|
|
21
|
+
*/
|
|
22
|
+
/** The instrumentation scope that the driver's tracer and meter report under. */
|
|
23
|
+
export const CAMUS_TELEMETRY_NAME = 'camusdb';
|
|
24
|
+
/** The `db.system.name` of every span and measurement. */
|
|
25
|
+
const SYSTEM_NAME = 'camusdb';
|
|
26
|
+
/** The `camusdb.retry.kind` values: what the driver sent again. */
|
|
27
|
+
export const CamusRetryKind = {
|
|
28
|
+
/** A commit or a rollback sent again after `CADB0509`. */
|
|
29
|
+
Finalize: 'finalize',
|
|
30
|
+
/** A unit of work of `withRetry` run again after a serializable conflict. */
|
|
31
|
+
Autocommit: 'autocommit',
|
|
32
|
+
/** A unit of work of `client.transaction` run again, from `BEGIN`, after a serializable conflict. */
|
|
33
|
+
Transaction: 'transaction',
|
|
34
|
+
/** A call sent again with a new token after the server refused the old one. */
|
|
35
|
+
TokenRenewal: 'token_renewal',
|
|
36
|
+
/** A `CREATE DATABASE` or a branch creation sent again after a transient failure. */
|
|
37
|
+
CreateDatabase: 'create_database',
|
|
38
|
+
};
|
|
39
|
+
/** The `camusdb.prepared_statement.result` values. */
|
|
40
|
+
export const PreparedResult = {
|
|
41
|
+
Hit: 'hit',
|
|
42
|
+
Registered: 'registered',
|
|
43
|
+
Miss: 'miss',
|
|
44
|
+
Success: 'success',
|
|
45
|
+
Refused: 'refused',
|
|
46
|
+
Unsupported: 'unsupported',
|
|
47
|
+
};
|
|
48
|
+
// ─── Loading ────────────────────────────────────────────────────────────────
|
|
49
|
+
/** `undefined` until the first try, `null` when the package is not installed. */
|
|
50
|
+
let loadedApi;
|
|
51
|
+
let packageVersion;
|
|
52
|
+
/**
|
|
53
|
+
* The API, or `undefined` when the package is not installed.
|
|
54
|
+
*
|
|
55
|
+
* It is loaded with `require`, so the first operation is instrumented too: a dynamic `import` would
|
|
56
|
+
* leave every operation before it settles without a span. The API keeps its registrations in a
|
|
57
|
+
* process-wide global, so the copy that `require` loads sees the SDK that an ES module registered.
|
|
58
|
+
*/
|
|
59
|
+
function api() {
|
|
60
|
+
if (loadedApi === undefined) {
|
|
61
|
+
const require = createRequire(import.meta.url);
|
|
62
|
+
try {
|
|
63
|
+
loadedApi = require('@opentelemetry/api');
|
|
64
|
+
}
|
|
65
|
+
catch {
|
|
66
|
+
loadedApi = null;
|
|
67
|
+
}
|
|
68
|
+
try {
|
|
69
|
+
packageVersion = require('../package.json').version;
|
|
70
|
+
}
|
|
71
|
+
catch {
|
|
72
|
+
packageVersion = undefined;
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
return loadedApi ?? undefined;
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* @internal Test hook: replaces the API, or with `null` plays a process without the package.
|
|
79
|
+
* `undefined` loads it again on the next operation.
|
|
80
|
+
*/
|
|
81
|
+
export function setTelemetryApi(replacement) {
|
|
82
|
+
loadedApi = replacement;
|
|
83
|
+
tracer = undefined;
|
|
84
|
+
instruments = undefined;
|
|
85
|
+
}
|
|
86
|
+
let tracer;
|
|
87
|
+
/** The global tracer. The API hands out a proxy, so a provider registered later still gets the spans. */
|
|
88
|
+
function tracerFor(otel) {
|
|
89
|
+
if (tracer?.api !== otel)
|
|
90
|
+
tracer = { api: otel, tracer: otel.trace.getTracer(CAMUS_TELEMETRY_NAME, packageVersion) };
|
|
91
|
+
return tracer.tracer;
|
|
92
|
+
}
|
|
93
|
+
let instruments;
|
|
94
|
+
/**
|
|
95
|
+
* The instruments, made on the meter of the current global provider.
|
|
96
|
+
*
|
|
97
|
+
* The metrics API has no proxy provider, so an instrument made before the SDK registered stays a
|
|
98
|
+
* no-op for good. The instruments are made again whenever the global provider changes.
|
|
99
|
+
*/
|
|
100
|
+
function instrumentsFor(otel) {
|
|
101
|
+
const provider = otel.metrics.getMeterProvider();
|
|
102
|
+
if (instruments?.api === otel && instruments.provider === provider)
|
|
103
|
+
return instruments;
|
|
104
|
+
const meter = otel.metrics.getMeter(CAMUS_TELEMETRY_NAME, packageVersion);
|
|
105
|
+
const quarantined = meter.createObservableGauge('camusdb.client.endpoint.quarantined', {
|
|
106
|
+
unit: '{endpoint}',
|
|
107
|
+
description: '1 while the endpoint is set aside after a transport failure, 0 while it takes traffic.',
|
|
108
|
+
});
|
|
109
|
+
quarantined.addCallback((result) => {
|
|
110
|
+
for (const [endpoint, isQuarantined] of CamusEndpointPool.collectQuarantine()) {
|
|
111
|
+
result.observe(isQuarantined ? 1 : 0, endpointAttributes(endpoint));
|
|
112
|
+
}
|
|
113
|
+
});
|
|
114
|
+
const preparedCount = meter.createObservableUpDownCounter('camusdb.client.prepared_statement.count', {
|
|
115
|
+
unit: '{statement}',
|
|
116
|
+
description: 'Statements kept prepared now.',
|
|
117
|
+
});
|
|
118
|
+
preparedCount.addCallback((result) => {
|
|
119
|
+
for (const [database, count] of CamusPreparedStatementPolicy.collectPreparedCounts()) {
|
|
120
|
+
result.observe(count, { 'db.namespace': database });
|
|
121
|
+
}
|
|
122
|
+
});
|
|
123
|
+
instruments = {
|
|
124
|
+
api: otel,
|
|
125
|
+
provider,
|
|
126
|
+
duration: meter.createHistogram('db.client.operation.duration', {
|
|
127
|
+
unit: 's',
|
|
128
|
+
description: 'Duration of database client operations.',
|
|
129
|
+
advice: { explicitBucketBoundaries: [0.001, 0.005, 0.01, 0.05, 0.1, 0.5, 1, 5, 10] },
|
|
130
|
+
}),
|
|
131
|
+
retries: meter.createCounter('camusdb.client.operation.retries', {
|
|
132
|
+
unit: '{retry}',
|
|
133
|
+
description: 'Operations the driver sent again after a failure it knows to be safe to retry.',
|
|
134
|
+
}),
|
|
135
|
+
quarantines: meter.createCounter('camusdb.client.endpoint.quarantines', {
|
|
136
|
+
unit: '{quarantine}',
|
|
137
|
+
description: 'Times an endpoint failed at the transport level and was set aside for 30 seconds.',
|
|
138
|
+
}),
|
|
139
|
+
lookups: meter.createCounter('camusdb.client.prepared_statement.lookups', {
|
|
140
|
+
unit: '{lookup}',
|
|
141
|
+
description: 'Executions of a preparable statement, by whether the statement went as a prepared handle.',
|
|
142
|
+
}),
|
|
143
|
+
registrations: meter.createCounter('camusdb.client.prepared_statement.registrations', {
|
|
144
|
+
unit: '{registration}',
|
|
145
|
+
description: 'Requests to the server to prepare a statement.',
|
|
146
|
+
}),
|
|
147
|
+
evictions: meter.createCounter('camusdb.client.prepared_statement.evictions', {
|
|
148
|
+
unit: '{eviction}',
|
|
149
|
+
description: 'Prepared statements released to make room for a statement used more recently.',
|
|
150
|
+
}),
|
|
151
|
+
};
|
|
152
|
+
return instruments;
|
|
153
|
+
}
|
|
154
|
+
/** The spans this driver started, so a retry adds its event only to one of them. */
|
|
155
|
+
const ownSpans = new WeakSet();
|
|
156
|
+
/**
|
|
157
|
+
* One instrumented operation: its span, and its start time for the duration histogram.
|
|
158
|
+
*
|
|
159
|
+
* It ends once. The first `complete` or `fail` ends it, and later calls do nothing.
|
|
160
|
+
*/
|
|
161
|
+
export class CamusOperation {
|
|
162
|
+
otel;
|
|
163
|
+
span;
|
|
164
|
+
startedAt;
|
|
165
|
+
database;
|
|
166
|
+
operationName;
|
|
167
|
+
ended = false;
|
|
168
|
+
serverAddress;
|
|
169
|
+
serverPort = 0;
|
|
170
|
+
/** @internal Use `startOperation`. */
|
|
171
|
+
constructor(otel, span, startedAt, database, operationName) {
|
|
172
|
+
this.otel = otel;
|
|
173
|
+
this.span = span;
|
|
174
|
+
this.startedAt = startedAt;
|
|
175
|
+
this.database = database;
|
|
176
|
+
this.operationName = operationName;
|
|
177
|
+
}
|
|
178
|
+
/** Records the server the operation goes to, as `server.address` and `server.port`. */
|
|
179
|
+
setEndpoint(endpoint) {
|
|
180
|
+
const { host, port } = parseEndpoint(endpoint);
|
|
181
|
+
this.serverAddress = host;
|
|
182
|
+
this.serverPort = port;
|
|
183
|
+
if (this.span.isRecording()) {
|
|
184
|
+
this.span.setAttribute('server.address', host);
|
|
185
|
+
if (port > 0)
|
|
186
|
+
this.span.setAttribute('server.port', port);
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
setAttribute(key, value) {
|
|
190
|
+
if (this.span.isRecording())
|
|
191
|
+
this.span.setAttribute(key, value);
|
|
192
|
+
}
|
|
193
|
+
/**
|
|
194
|
+
* Runs `fn` with this operation's span as the active span, so the HTTP or gRPC spans of the
|
|
195
|
+
* transport are its children.
|
|
196
|
+
*/
|
|
197
|
+
run(fn) {
|
|
198
|
+
return this.otel.context.with(this.otel.trace.setSpan(this.otel.context.active(), this.span), fn);
|
|
199
|
+
}
|
|
200
|
+
/** Adds a `camusdb.retry` event to this operation's span. */
|
|
201
|
+
addRetryEvent(kind, errorType) {
|
|
202
|
+
this.span.addEvent('camusdb.retry', defined({ 'camusdb.retry.kind': kind, 'error.type': errorType }));
|
|
203
|
+
}
|
|
204
|
+
/** Ends the operation as a success. */
|
|
205
|
+
complete() {
|
|
206
|
+
this.end(undefined, false);
|
|
207
|
+
}
|
|
208
|
+
/** Ends the operation as a failure. */
|
|
209
|
+
fail(error) {
|
|
210
|
+
this.end(error, true);
|
|
211
|
+
}
|
|
212
|
+
end(error, failed) {
|
|
213
|
+
if (this.ended)
|
|
214
|
+
return;
|
|
215
|
+
this.ended = true;
|
|
216
|
+
// The conventions use the database status code as the error type when there is one.
|
|
217
|
+
const statusCode = failed && CamusError.is(error) ? error.code : undefined;
|
|
218
|
+
const errorType = failed ? (statusCode ?? errorTypeName(error)) : undefined;
|
|
219
|
+
if (failed) {
|
|
220
|
+
if (this.span.isRecording()) {
|
|
221
|
+
this.span.setAttribute('error.type', errorType);
|
|
222
|
+
if (statusCode !== undefined)
|
|
223
|
+
this.span.setAttribute('db.response.status_code', statusCode);
|
|
224
|
+
this.span.recordException(error instanceof Error ? error : String(error));
|
|
225
|
+
}
|
|
226
|
+
this.span.setStatus({
|
|
227
|
+
code: this.otel.SpanStatusCode.ERROR,
|
|
228
|
+
message: error instanceof Error ? error.message : String(error),
|
|
229
|
+
});
|
|
230
|
+
}
|
|
231
|
+
this.span.end();
|
|
232
|
+
instrumentsFor(this.otel).duration.record((performance.now() - this.startedAt) / 1000, defined({
|
|
233
|
+
'db.system.name': SYSTEM_NAME,
|
|
234
|
+
'db.namespace': this.database,
|
|
235
|
+
'db.operation.name': this.operationName,
|
|
236
|
+
'server.address': this.serverAddress,
|
|
237
|
+
'server.port': this.serverPort > 0 ? this.serverPort : undefined,
|
|
238
|
+
'error.type': errorType,
|
|
239
|
+
'db.response.status_code': statusCode,
|
|
240
|
+
}));
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
/**
|
|
244
|
+
* Starts an operation, or reports `undefined` when `@opentelemetry/api` is not installed.
|
|
245
|
+
*
|
|
246
|
+
* The span is a child of the active span. Its name is `{operation} {target}`, where the target is
|
|
247
|
+
* the table when it is known, and the database if not.
|
|
248
|
+
*/
|
|
249
|
+
export function startOperation(scope, init) {
|
|
250
|
+
const otel = api();
|
|
251
|
+
if (otel === undefined)
|
|
252
|
+
return undefined;
|
|
253
|
+
const database = scope.database;
|
|
254
|
+
const target = init.collection ?? database;
|
|
255
|
+
const name = init.operationName === undefined ? target : `${init.operationName} ${target}`;
|
|
256
|
+
const span = tracerFor(otel).startSpan(name, { kind: otel.SpanKind.CLIENT }, otel.context.active());
|
|
257
|
+
ownSpans.add(span);
|
|
258
|
+
if (span.isRecording()) {
|
|
259
|
+
span.setAttribute('db.system.name', SYSTEM_NAME);
|
|
260
|
+
span.setAttribute('db.namespace', database);
|
|
261
|
+
if (init.operationName !== undefined)
|
|
262
|
+
span.setAttribute('db.operation.name', init.operationName);
|
|
263
|
+
if (init.collection !== undefined)
|
|
264
|
+
span.setAttribute('db.collection.name', init.collection);
|
|
265
|
+
if (init.batchSize !== undefined && init.batchSize > 0) {
|
|
266
|
+
span.setAttribute('db.operation.batch.size', init.batchSize);
|
|
267
|
+
}
|
|
268
|
+
if (init.queryText !== undefined && scope.config.traceQueryText) {
|
|
269
|
+
span.setAttribute('db.query.text', init.queryText);
|
|
270
|
+
}
|
|
271
|
+
span.setAttribute('camusdb.transport', scope.config.protocol);
|
|
272
|
+
}
|
|
273
|
+
return new CamusOperation(otel, span, performance.now(), database, init.operationName);
|
|
274
|
+
}
|
|
275
|
+
/**
|
|
276
|
+
* Runs one operation under a span, and ends the span with the operation's outcome.
|
|
277
|
+
*
|
|
278
|
+
* Without `@opentelemetry/api`, it only calls `run`.
|
|
279
|
+
*/
|
|
280
|
+
export async function traced(scope, init, run) {
|
|
281
|
+
const operation = startOperation(scope, init);
|
|
282
|
+
if (operation === undefined)
|
|
283
|
+
return run(undefined);
|
|
284
|
+
try {
|
|
285
|
+
const result = await operation.run(() => run(operation));
|
|
286
|
+
operation.complete();
|
|
287
|
+
return result;
|
|
288
|
+
}
|
|
289
|
+
catch (error) {
|
|
290
|
+
operation.fail(error);
|
|
291
|
+
throw error;
|
|
292
|
+
}
|
|
293
|
+
}
|
|
294
|
+
/**
|
|
295
|
+
* The statement verbs that become `db.operation.name`. A first keyword that is not in this list
|
|
296
|
+
* gives no operation name, so the metric keeps a small set of values.
|
|
297
|
+
*/
|
|
298
|
+
const KNOWN_OPERATIONS = new Set([
|
|
299
|
+
'SELECT',
|
|
300
|
+
'INSERT',
|
|
301
|
+
'UPDATE',
|
|
302
|
+
'DELETE',
|
|
303
|
+
'CREATE',
|
|
304
|
+
'ALTER',
|
|
305
|
+
'DROP',
|
|
306
|
+
'TRUNCATE',
|
|
307
|
+
'EXPLAIN',
|
|
308
|
+
'SHOW',
|
|
309
|
+
'REFRESH',
|
|
310
|
+
'COMMENT',
|
|
311
|
+
'GRANT',
|
|
312
|
+
'REVOKE',
|
|
313
|
+
'SET',
|
|
314
|
+
'CALL',
|
|
315
|
+
]);
|
|
316
|
+
/**
|
|
317
|
+
* The operation name of a statement: its first keyword in upper case when that keyword is a known
|
|
318
|
+
* verb, and `undefined` if not. Leading white space and opening parentheses are skipped.
|
|
319
|
+
*/
|
|
320
|
+
export function operationName(sql) {
|
|
321
|
+
const match = /^[\s(]*([A-Za-z]+)/.exec(sql);
|
|
322
|
+
const keyword = match?.[1]?.toUpperCase();
|
|
323
|
+
return keyword !== undefined && KNOWN_OPERATIONS.has(keyword) ? keyword : undefined;
|
|
324
|
+
}
|
|
325
|
+
// ─── Driver metrics ─────────────────────────────────────────────────────────
|
|
326
|
+
/**
|
|
327
|
+
* Counts one retry, and adds a `camusdb.retry` event to the driver span of the operation, or to the
|
|
328
|
+
* active span when it is one of the driver's.
|
|
329
|
+
*/
|
|
330
|
+
export function recordRetry(kind, error, details = {}) {
|
|
331
|
+
const otel = api();
|
|
332
|
+
if (otel === undefined)
|
|
333
|
+
return;
|
|
334
|
+
const errorType = CamusError.is(error) ? error.code : errorTypeName(error);
|
|
335
|
+
if (details.operation !== undefined) {
|
|
336
|
+
details.operation.addRetryEvent(kind, errorType);
|
|
337
|
+
}
|
|
338
|
+
else {
|
|
339
|
+
const active = otel.trace.getActiveSpan();
|
|
340
|
+
if (active !== undefined && ownSpans.has(active)) {
|
|
341
|
+
active.addEvent('camusdb.retry', defined({ 'camusdb.retry.kind': kind, 'error.type': errorType }));
|
|
342
|
+
}
|
|
343
|
+
}
|
|
344
|
+
instrumentsFor(otel).retries.add(1, defined({
|
|
345
|
+
'camusdb.retry.kind': kind,
|
|
346
|
+
'error.type': errorType,
|
|
347
|
+
'db.namespace': details.database,
|
|
348
|
+
'db.operation.name': details.operationName,
|
|
349
|
+
}));
|
|
350
|
+
}
|
|
351
|
+
/** Counts one endpoint set aside after a transport failure. */
|
|
352
|
+
export function recordQuarantine(endpoint) {
|
|
353
|
+
const otel = api();
|
|
354
|
+
if (otel === undefined)
|
|
355
|
+
return;
|
|
356
|
+
instrumentsFor(otel).quarantines.add(1, endpointAttributes(endpoint));
|
|
357
|
+
}
|
|
358
|
+
/** Counts one execution of a preparable statement: `hit`, `registered`, or `miss`. */
|
|
359
|
+
export function recordPreparedLookup(database, result) {
|
|
360
|
+
const otel = api();
|
|
361
|
+
if (otel === undefined)
|
|
362
|
+
return;
|
|
363
|
+
instrumentsFor(otel).lookups.add(1, {
|
|
364
|
+
'db.namespace': database,
|
|
365
|
+
'camusdb.prepared_statement.result': result,
|
|
366
|
+
});
|
|
367
|
+
}
|
|
368
|
+
/** Counts one request to prepare a statement: `success`, `refused`, or `unsupported`. */
|
|
369
|
+
export function recordPreparedRegistration(database, result, error) {
|
|
370
|
+
const otel = api();
|
|
371
|
+
if (otel === undefined)
|
|
372
|
+
return;
|
|
373
|
+
instrumentsFor(otel).registrations.add(1, defined({
|
|
374
|
+
'db.namespace': database,
|
|
375
|
+
'camusdb.prepared_statement.result': result,
|
|
376
|
+
'error.type': error === undefined ? undefined : CamusError.is(error) ? error.code : errorTypeName(error),
|
|
377
|
+
}));
|
|
378
|
+
}
|
|
379
|
+
/** Counts one prepared statement released to make room for one used more recently. */
|
|
380
|
+
export function recordPreparedEviction(database) {
|
|
381
|
+
const otel = api();
|
|
382
|
+
if (otel === undefined)
|
|
383
|
+
return;
|
|
384
|
+
instrumentsFor(otel).evictions.add(1, { 'db.namespace': database });
|
|
385
|
+
}
|
|
386
|
+
// ─── Helpers ────────────────────────────────────────────────────────────────
|
|
387
|
+
/** The parsed host and port of each endpoint. Endpoints come from configuration, so the map stays small. */
|
|
388
|
+
const parsedEndpoints = new Map();
|
|
389
|
+
function parseEndpoint(endpoint) {
|
|
390
|
+
let parsed = parsedEndpoints.get(endpoint);
|
|
391
|
+
if (parsed === undefined) {
|
|
392
|
+
try {
|
|
393
|
+
const url = new URL(endpoint);
|
|
394
|
+
const port = url.port.length > 0 ? Number(url.port) : url.protocol === 'https:' ? 443 : 80;
|
|
395
|
+
parsed = { host: url.hostname, port };
|
|
396
|
+
}
|
|
397
|
+
catch {
|
|
398
|
+
parsed = { host: endpoint, port: 0 };
|
|
399
|
+
}
|
|
400
|
+
if (parsedEndpoints.size < 1024)
|
|
401
|
+
parsedEndpoints.set(endpoint, parsed);
|
|
402
|
+
}
|
|
403
|
+
return parsed;
|
|
404
|
+
}
|
|
405
|
+
function endpointAttributes(endpoint) {
|
|
406
|
+
const { host, port } = parseEndpoint(endpoint);
|
|
407
|
+
return port > 0 ? { 'server.address': host, 'server.port': port } : { 'server.address': host };
|
|
408
|
+
}
|
|
409
|
+
/** The attributes without the keys whose value is unknown. The SDK warns about an `undefined` value. */
|
|
410
|
+
function defined(attributes) {
|
|
411
|
+
const result = {};
|
|
412
|
+
for (const [key, value] of Object.entries(attributes)) {
|
|
413
|
+
if (value !== undefined)
|
|
414
|
+
result[key] = value;
|
|
415
|
+
}
|
|
416
|
+
return result;
|
|
417
|
+
}
|
|
418
|
+
function errorTypeName(error) {
|
|
419
|
+
if (error instanceof Error)
|
|
420
|
+
return error.name.length > 0 ? error.name : 'Error';
|
|
421
|
+
return '_OTHER';
|
|
422
|
+
}
|
|
423
|
+
//# sourceMappingURL=telemetry.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"telemetry.js","sourceRoot":"","sources":["../src/telemetry.ts"],"names":[],"mappings":"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"}
|