@vtex/api 6.52.0 → 6.53.0-beta.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/CHANGELOG.md +11 -1
- package/lib/HttpClient/middlewares/metrics.js +52 -5
- package/lib/HttpClient/middlewares/request/HttpAgentSingleton.d.ts +5 -0
- package/lib/HttpClient/middlewares/request/HttpAgentSingleton.js +15 -0
- package/lib/constants.d.ts +15 -0
- package/lib/constants.js +18 -1
- package/lib/metrics/DiagnosticsMetrics.d.ts +189 -0
- package/lib/metrics/DiagnosticsMetrics.js +342 -0
- package/lib/service/index.d.ts +9 -1
- package/lib/service/index.js +5 -1
- package/lib/service/logger/client.js +0 -5
- package/lib/service/metrics/client.d.ts +2 -0
- package/lib/service/metrics/client.js +38 -0
- package/lib/service/metrics/instruments/hostMetrics.d.ts +14 -0
- package/lib/service/metrics/instruments/hostMetrics.js +33 -0
- package/lib/service/telemetry/client.d.ts +9 -1
- package/lib/service/telemetry/client.js +93 -27
- package/lib/service/telemetry/resourceAttributes.d.ts +1 -0
- package/lib/service/telemetry/resourceAttributes.js +21 -0
- package/lib/service/worker/runtime/graphql/schema/schemaDirectives/Metric.js +20 -2
- package/lib/service/worker/runtime/http/middlewares/requestStats.js +42 -2
- package/lib/service/worker/runtime/http/middlewares/timings.js +49 -9
- package/lib/service/worker/runtime/statusTrack.js +3 -0
- package/package.json +7 -2
package/CHANGELOG.md
CHANGED
|
@@ -5,7 +5,17 @@ All notable changes to this project will be documented in this file.
|
|
|
5
5
|
The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/)
|
|
6
6
|
and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html).
|
|
7
7
|
|
|
8
|
-
## [
|
|
8
|
+
## [6.53.0-beta.1]
|
|
9
|
+
### Added
|
|
10
|
+
- Diagnostics metrics observability, backported from the `master` (7.x) line: `DiagnosticsMetrics`
|
|
11
|
+
(`recordLatency`, `incrementCounter`, `setGauge`, `runWithBaseAttributes`), a split
|
|
12
|
+
traces/metrics/logs telemetry client (`@vtex/diagnostics-nodejs@0.1.8-io`,
|
|
13
|
+
`@vtex/diagnostics-semconv`), cluster resource attributes, and automatic Koa + host-metrics
|
|
14
|
+
instrumentation. Metrics are wired into the request pipeline itself, not just exposed as a
|
|
15
|
+
library API: HTTP handler latency/counters, request closed/aborted/total counters, outbound
|
|
16
|
+
HTTP client metrics, HTTP agent socket gauges, and the `@metric` GraphQL directive all emit
|
|
17
|
+
through `DiagnosticsMetrics` at the same points `master` does. Disabled by default; opt in
|
|
18
|
+
per app with `VTEX_DIAGNOSTICS_TELEMETRY_ENABLED=true`.
|
|
9
19
|
|
|
10
20
|
## [6.52.0]
|
|
11
21
|
### Added
|
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.metricsMiddleware = void 0;
|
|
4
|
+
const constants_1 = require("../../constants");
|
|
4
5
|
const RequestCancelledError_1 = require("../../errors/RequestCancelledError");
|
|
5
6
|
const requestStats_1 = require("../../service/worker/runtime/http/middlewares/requestStats");
|
|
6
7
|
const utils_1 = require("../../utils");
|
|
7
8
|
const retry_1 = require("../../utils/retry");
|
|
8
9
|
const status_1 = require("../../utils/status");
|
|
10
|
+
const DEFAULT_ACCOUNT = 'unknown';
|
|
9
11
|
const metricsMiddleware = ({ metrics, serverTiming, name }) => {
|
|
10
12
|
const serverTimingStart = process.hrtime();
|
|
11
13
|
const serverTimingLabel = (0, utils_1.shrinkTimings)((0, utils_1.formatTimingName)({
|
|
@@ -14,6 +16,7 @@ const metricsMiddleware = ({ metrics, serverTiming, name }) => {
|
|
|
14
16
|
target: name || 'unknown',
|
|
15
17
|
}));
|
|
16
18
|
return async (ctx, next) => {
|
|
19
|
+
var _a, _b;
|
|
17
20
|
const start = process.hrtime();
|
|
18
21
|
let status = 'unknown';
|
|
19
22
|
let errorCode;
|
|
@@ -57,29 +60,73 @@ const metricsMiddleware = ({ metrics, serverTiming, name }) => {
|
|
|
57
60
|
const label = `http-client-${ctx.config.metric}`;
|
|
58
61
|
const extensions = {};
|
|
59
62
|
Object.assign(extensions, { [status]: 1 });
|
|
63
|
+
// Determine cache state for diagnostics metrics
|
|
64
|
+
let cacheState = 'none';
|
|
60
65
|
if (ctx.cacheHit) {
|
|
61
66
|
Object.assign(extensions, ctx.cacheHit, { [`${status}-hit`]: 1 });
|
|
67
|
+
cacheState = 'hit';
|
|
62
68
|
}
|
|
63
69
|
else if (!ctx.inflightHit && !ctx.memoizedHit) {
|
|
64
70
|
// Lets us know how many calls passed through to origin
|
|
65
71
|
Object.assign(extensions, { [`${status}-miss`]: 1 });
|
|
72
|
+
cacheState = 'miss';
|
|
66
73
|
}
|
|
67
74
|
if (ctx.inflightHit) {
|
|
68
75
|
Object.assign(extensions, { [`${status}-inflight`]: 1 });
|
|
76
|
+
cacheState = 'inflight';
|
|
69
77
|
}
|
|
70
78
|
if (ctx.memoizedHit) {
|
|
71
79
|
Object.assign(extensions, { [`${status}-memoized`]: 1 });
|
|
80
|
+
cacheState = 'memoized';
|
|
72
81
|
}
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
extensions[`retry-${status}-${retryCount}`] = 1;
|
|
77
|
-
}
|
|
82
|
+
const retryCount = ctx.config.retryCount || 0;
|
|
83
|
+
if (retryCount > 0) {
|
|
84
|
+
extensions[`retry-${status}-${retryCount}`] = 1;
|
|
78
85
|
}
|
|
79
86
|
const end = status === 'success' && !ctx.cacheHit && !ctx.inflightHit && !ctx.memoizedHit
|
|
80
87
|
? process.hrtime(start)
|
|
81
88
|
: undefined;
|
|
89
|
+
// Legacy metrics (backward compatibility)
|
|
82
90
|
metrics.batch(label, end, extensions);
|
|
91
|
+
// New diagnostics metrics with stable names and attributes
|
|
92
|
+
if (global.diagnosticsMetrics) {
|
|
93
|
+
const elapsed = process.hrtime(start);
|
|
94
|
+
const rawStatusCode = ((_a = ctx.response) === null || _a === void 0 ? void 0 : _a.status) || errorStatus;
|
|
95
|
+
// Extract account from request headers, fallback to default
|
|
96
|
+
const account = ((_b = ctx.config.headers) === null || _b === void 0 ? void 0 : _b[constants_1.ACCOUNT_HEADER]) || DEFAULT_ACCOUNT;
|
|
97
|
+
const baseAttributes = {
|
|
98
|
+
[constants_1.AttributeKeys.VTEX_ACCOUNT_NAME]: account,
|
|
99
|
+
component: 'http-client',
|
|
100
|
+
client_metric: ctx.config.metric,
|
|
101
|
+
status_code: rawStatusCode,
|
|
102
|
+
status,
|
|
103
|
+
};
|
|
104
|
+
// Record latency histogram with all context
|
|
105
|
+
global.diagnosticsMetrics.recordLatency(elapsed, {
|
|
106
|
+
...baseAttributes,
|
|
107
|
+
cache_state: cacheState,
|
|
108
|
+
});
|
|
109
|
+
// Increment counters for different event types (replaces extensions behavior)
|
|
110
|
+
// Main request counter with status as attribute
|
|
111
|
+
global.diagnosticsMetrics.incrementCounter('http_client_requests_total', 1, baseAttributes);
|
|
112
|
+
// Cache counter with cache_state as attribute (replaces extensions like 'success-hit', 'error-miss')
|
|
113
|
+
if (cacheState !== 'none') {
|
|
114
|
+
global.diagnosticsMetrics.incrementCounter('http_client_cache_total', 1, {
|
|
115
|
+
...baseAttributes,
|
|
116
|
+
cache_state: cacheState,
|
|
117
|
+
});
|
|
118
|
+
}
|
|
119
|
+
// Retry counter (replaces 'retry-{status}-{count}' extensions)
|
|
120
|
+
if (retryCount > 0) {
|
|
121
|
+
global.diagnosticsMetrics.incrementCounter('http_client_requests_retried_total', 1, {
|
|
122
|
+
...baseAttributes,
|
|
123
|
+
retry_count: retryCount,
|
|
124
|
+
});
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
else {
|
|
128
|
+
console.warn('DiagnosticsMetrics not available. HTTP client metrics not reported.');
|
|
129
|
+
}
|
|
83
130
|
if (ctx.config.verbose) {
|
|
84
131
|
console.log(`VERBOSE: ${name}.${ctx.config.label}`, {
|
|
85
132
|
...extensions,
|
|
@@ -6,6 +6,11 @@ export declare class HttpAgentSingleton {
|
|
|
6
6
|
pendingRequests: number;
|
|
7
7
|
sockets: number;
|
|
8
8
|
};
|
|
9
|
+
/**
|
|
10
|
+
* Update HTTP agent statistics as diagnostics metrics (gauges).
|
|
11
|
+
* This method should be called periodically to export current HTTP agent state.
|
|
12
|
+
*/
|
|
13
|
+
static updateHttpAgentMetrics(): void;
|
|
9
14
|
private static httpAgent;
|
|
10
15
|
private static count;
|
|
11
16
|
}
|
|
@@ -19,6 +19,21 @@ class HttpAgentSingleton {
|
|
|
19
19
|
sockets,
|
|
20
20
|
};
|
|
21
21
|
}
|
|
22
|
+
/**
|
|
23
|
+
* Update HTTP agent statistics as diagnostics metrics (gauges).
|
|
24
|
+
* This method should be called periodically to export current HTTP agent state.
|
|
25
|
+
*/
|
|
26
|
+
static updateHttpAgentMetrics() {
|
|
27
|
+
if (!global.diagnosticsMetrics) {
|
|
28
|
+
console.warn('DiagnosticsMetrics not available. HTTP agent metrics not reported.');
|
|
29
|
+
return;
|
|
30
|
+
}
|
|
31
|
+
const stats = HttpAgentSingleton.httpAgentStats();
|
|
32
|
+
// Report HTTP agent stats as gauges (current state)
|
|
33
|
+
global.diagnosticsMetrics.setGauge('http_agent_sockets_current', stats.sockets, {});
|
|
34
|
+
global.diagnosticsMetrics.setGauge('http_agent_free_sockets_current', stats.freeSockets, {});
|
|
35
|
+
global.diagnosticsMetrics.setGauge('http_agent_pending_requests_current', stats.pendingRequests, {});
|
|
36
|
+
}
|
|
22
37
|
static count(obj) {
|
|
23
38
|
try {
|
|
24
39
|
return Object.values(obj).reduce((acc, val) => acc += val.length, 0);
|
package/lib/constants.d.ts
CHANGED
|
@@ -2,6 +2,8 @@ export declare const NODE_VTEX_API_VERSION: any;
|
|
|
2
2
|
export declare const DEFAULT_WORKSPACE = "master";
|
|
3
3
|
export declare const IS_IO: string | undefined;
|
|
4
4
|
export declare const PID: number;
|
|
5
|
+
export declare const CLUSTER_ID: string;
|
|
6
|
+
export declare const CLUSTER_ROLE: string;
|
|
5
7
|
export declare const CACHE_CONTROL_HEADER = "cache-control";
|
|
6
8
|
export declare const SEGMENT_HEADER = "x-vtex-segment";
|
|
7
9
|
export declare const SESSION_HEADER = "x-vtex-session";
|
|
@@ -40,6 +42,15 @@ export declare const MAX_AGE: {
|
|
|
40
42
|
};
|
|
41
43
|
export declare const HTTP_SERVER_PORT = 5050;
|
|
42
44
|
export declare const MAX_WORKERS = 4;
|
|
45
|
+
export declare const AttributeKeys: {
|
|
46
|
+
VTEX_ACCOUNT_NAME: "vtex.account.name";
|
|
47
|
+
VTEX_IO_APP_AUTHOR_TYPE: "vtex_io.app.author_type";
|
|
48
|
+
VTEX_IO_APP_ID: "vtex_io.app.id";
|
|
49
|
+
VTEX_IO_CLUSTER_ID: "vtex_io.cluster.id";
|
|
50
|
+
VTEX_IO_CLUSTER_ROLE: "vtex_io.cluster.role";
|
|
51
|
+
VTEX_IO_WORKSPACE_NAME: "vtex_io.workspace.name";
|
|
52
|
+
VTEX_IO_WORKSPACE_TYPE: "vtex_io.workspace.type";
|
|
53
|
+
};
|
|
43
54
|
export declare const LINKED: boolean;
|
|
44
55
|
export declare const REGION: string;
|
|
45
56
|
export declare const PUBLIC_ENDPOINT: string;
|
|
@@ -58,3 +69,7 @@ export declare const PRODUCTION: boolean;
|
|
|
58
69
|
export declare const INSPECT_DEBUGGER_PORT = 5858;
|
|
59
70
|
export declare const cancellableMethods: Set<string>;
|
|
60
71
|
export declare const LOG_CLIENT_INIT_TIMEOUT_MS = 5000;
|
|
72
|
+
export declare const METRIC_CLIENT_INIT_TIMEOUT_MS = 5000;
|
|
73
|
+
export declare const OTEL_EXPORTER_OTLP_ENDPOINT: string;
|
|
74
|
+
export declare const DK_APP_ID: string;
|
|
75
|
+
export declare const DIAGNOSTICS_TELEMETRY_ENABLED: boolean;
|
package/lib/constants.js
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.
|
|
3
|
+
exports.cancellableMethods = exports.INSPECT_DEBUGGER_PORT = exports.PRODUCTION = exports.WORKSPACE = exports.ACCOUNT = exports.NODE_ENV = exports.APP = exports.PUBLIC_ENDPOINT = exports.REGION = exports.LINKED = exports.AttributeKeys = exports.MAX_WORKERS = exports.HTTP_SERVER_PORT = exports.MAX_AGE = exports.UP_SIGNAL = exports.BODY_HASH = exports.PROVIDER_HEADER = exports.TRACE_ID_HEADER = exports.COLOSSUS_PARAMS_HEADER = exports.COLOSSUS_ROUTE_ID_HEADER = exports.COLOSSUS_ROUTE_DECLARER_HEADER = exports.EVENT_HANDLER_ID_HEADER = exports.EVENT_SUBJECT_HEADER = exports.EVENT_SENDER_HEADER = exports.EVENT_KEY_HEADER = exports.WORKSPACE_HEADER = exports.WORKSPACE_IS_PRODUCTION_HEADER = exports.PLATFORM_HEADER = exports.OPERATION_ID_HEADER = exports.ROUTER_CACHE_HEADER = exports.REQUEST_ID_HEADER = exports.CREDENTIAL_HEADER = exports.ACCOUNT_HEADER = exports.ETAG_HEADER = exports.META_HEADER_BUCKET = exports.META_HEADER = exports.BINDING_HEADER = exports.TENANT_HEADER = exports.FORWARDED_HOST_HEADER = exports.LOCALE_HEADER = exports.PRODUCT_HEADER = exports.SESSION_HEADER = exports.SEGMENT_HEADER = exports.CACHE_CONTROL_HEADER = exports.CLUSTER_ROLE = exports.CLUSTER_ID = exports.PID = exports.IS_IO = exports.DEFAULT_WORKSPACE = exports.NODE_VTEX_API_VERSION = void 0;
|
|
4
|
+
exports.DIAGNOSTICS_TELEMETRY_ENABLED = exports.DK_APP_ID = exports.OTEL_EXPORTER_OTLP_ENDPOINT = exports.METRIC_CLIENT_INIT_TIMEOUT_MS = exports.LOG_CLIENT_INIT_TIMEOUT_MS = void 0;
|
|
5
|
+
const diagnostics_semconv_1 = require("@vtex/diagnostics-semconv");
|
|
4
6
|
const app_1 = require("./utils/app");
|
|
5
7
|
// tslint:disable-next-line
|
|
6
8
|
const pkg = require('../package.json');
|
|
@@ -8,6 +10,8 @@ exports.NODE_VTEX_API_VERSION = pkg.version;
|
|
|
8
10
|
exports.DEFAULT_WORKSPACE = 'master';
|
|
9
11
|
exports.IS_IO = process.env.VTEX_IO;
|
|
10
12
|
exports.PID = process.pid;
|
|
13
|
+
exports.CLUSTER_ID = process.env.VTEX_CLUSTER_ID;
|
|
14
|
+
exports.CLUSTER_ROLE = process.env.VTEX_CLUSTER_ROLE;
|
|
11
15
|
exports.CACHE_CONTROL_HEADER = 'cache-control';
|
|
12
16
|
exports.SEGMENT_HEADER = 'x-vtex-segment';
|
|
13
17
|
exports.SESSION_HEADER = 'x-vtex-session';
|
|
@@ -45,6 +49,15 @@ exports.MAX_AGE = {
|
|
|
45
49
|
};
|
|
46
50
|
exports.HTTP_SERVER_PORT = 5050;
|
|
47
51
|
exports.MAX_WORKERS = 4;
|
|
52
|
+
exports.AttributeKeys = {
|
|
53
|
+
VTEX_ACCOUNT_NAME: diagnostics_semconv_1.ATTR_VTEX_ACCOUNT_NAME,
|
|
54
|
+
VTEX_IO_APP_AUTHOR_TYPE: diagnostics_semconv_1.ATTR_VTEX_IO_APP_AUTHOR_TYPE,
|
|
55
|
+
VTEX_IO_APP_ID: diagnostics_semconv_1.ATTR_VTEX_IO_APP_ID,
|
|
56
|
+
VTEX_IO_CLUSTER_ID: diagnostics_semconv_1.ATTR_VTEX_IO_CLUSTER_ID,
|
|
57
|
+
VTEX_IO_CLUSTER_ROLE: diagnostics_semconv_1.ATTR_VTEX_IO_CLUSTER_ROLE,
|
|
58
|
+
VTEX_IO_WORKSPACE_NAME: diagnostics_semconv_1.ATTR_VTEX_IO_WORKSPACE_NAME,
|
|
59
|
+
VTEX_IO_WORKSPACE_TYPE: diagnostics_semconv_1.ATTR_VTEX_IO_WORKSPACE_TYPE,
|
|
60
|
+
};
|
|
48
61
|
exports.LINKED = !!process.env.VTEX_APP_LINK;
|
|
49
62
|
exports.REGION = process.env.VTEX_REGION;
|
|
50
63
|
exports.PUBLIC_ENDPOINT = process.env.VTEX_PUBLIC_ENDPOINT || 'myvtex.com';
|
|
@@ -65,3 +78,7 @@ exports.PRODUCTION = process.env.VTEX_PRODUCTION === 'true';
|
|
|
65
78
|
exports.INSPECT_DEBUGGER_PORT = 5858;
|
|
66
79
|
exports.cancellableMethods = new Set(['GET', 'OPTIONS', 'HEAD']);
|
|
67
80
|
exports.LOG_CLIENT_INIT_TIMEOUT_MS = 5000;
|
|
81
|
+
exports.METRIC_CLIENT_INIT_TIMEOUT_MS = 5000;
|
|
82
|
+
exports.OTEL_EXPORTER_OTLP_ENDPOINT = process.env.OTEL_EXPORTER_OTLP_ENDPOINT;
|
|
83
|
+
exports.DK_APP_ID = process.env.NODE_VTEX_API_DK_APP_ID || 'apps-team';
|
|
84
|
+
exports.DIAGNOSTICS_TELEMETRY_ENABLED = process.env.VTEX_DIAGNOSTICS_TELEMETRY_ENABLED === 'true';
|
|
@@ -0,0 +1,189 @@
|
|
|
1
|
+
import { Attributes } from '@opentelemetry/api';
|
|
2
|
+
/**
|
|
3
|
+
* DiagnosticsMetrics provides a high-level API for recording metrics using
|
|
4
|
+
* the @vtex/diagnostics-nodejs library. It completely abstracts instrument
|
|
5
|
+
* management, bucket configuration, and lifecycle.
|
|
6
|
+
*
|
|
7
|
+
* Uses a single histogram for all latency measurements with attributes to differentiate.
|
|
8
|
+
* This follows OpenTelemetry best practices and reduces metric cardinality.
|
|
9
|
+
*
|
|
10
|
+
* ## Base Attributes (Request Context)
|
|
11
|
+
*
|
|
12
|
+
* DiagnosticsMetrics supports automatic merging of request-scoped "base attributes"
|
|
13
|
+
* with custom attributes provided in each metric call. This is useful for automatically
|
|
14
|
+
* including request context (account, status_code, route_id, etc.) in all metrics
|
|
15
|
+
* recorded during a request lifecycle.
|
|
16
|
+
*
|
|
17
|
+
* Use `runWithBaseAttributes()` to set base attributes for a scope. All metric calls
|
|
18
|
+
* within that scope will automatically include these base attributes, merged with
|
|
19
|
+
* any custom attributes provided.
|
|
20
|
+
*
|
|
21
|
+
* **Important:** Base attributes take precedence over custom attributes. If a custom
|
|
22
|
+
* attribute has the same key as a base attribute, the custom attribute is silently
|
|
23
|
+
* dropped and the base attribute value is used.
|
|
24
|
+
*
|
|
25
|
+
* @example
|
|
26
|
+
* ```typescript
|
|
27
|
+
* const diagnosticsMetrics = new DiagnosticsMetrics()
|
|
28
|
+
* diagnosticsMetrics.initMetricClient()
|
|
29
|
+
*
|
|
30
|
+
* // Record latency with operation type in attributes
|
|
31
|
+
* const start = process.hrtime()
|
|
32
|
+
* // ... do work ...
|
|
33
|
+
* diagnosticsMetrics.recordLatency(process.hrtime(start), { operation: 'api-call', status: '2xx' })
|
|
34
|
+
*
|
|
35
|
+
* // Or from milliseconds
|
|
36
|
+
* diagnosticsMetrics.recordLatency(42.5, { operation: 'db-query', status: 'success' })
|
|
37
|
+
*
|
|
38
|
+
* // Increment a counter
|
|
39
|
+
* diagnosticsMetrics.incrementCounter('http_requests_total', 1, { method: 'GET', status: '2xx' })
|
|
40
|
+
*
|
|
41
|
+
* // Set a gauge value
|
|
42
|
+
* diagnosticsMetrics.setGauge('cache_items_current', 1024, { cache: 'pages' })
|
|
43
|
+
*
|
|
44
|
+
* // Using base attributes for request context
|
|
45
|
+
* await diagnosticsMetrics.runWithBaseAttributes(
|
|
46
|
+
* { 'vtex.account.name': 'mystore', status_code: 200 },
|
|
47
|
+
* async () => {
|
|
48
|
+
* // All metrics recorded here will include the base attributes
|
|
49
|
+
* diagnosticsMetrics.recordLatency(100, { operation: 'custom-op' })
|
|
50
|
+
* // Result: { 'vtex.account.name': 'mystore', status_code: 200, operation: 'custom-op' }
|
|
51
|
+
* }
|
|
52
|
+
* )
|
|
53
|
+
* ```
|
|
54
|
+
*/
|
|
55
|
+
export declare class DiagnosticsMetrics {
|
|
56
|
+
private metricsClient;
|
|
57
|
+
private clientInitPromise;
|
|
58
|
+
private latencyHistogram;
|
|
59
|
+
private counters;
|
|
60
|
+
private gauges;
|
|
61
|
+
constructor();
|
|
62
|
+
/**
|
|
63
|
+
* Initialize the metrics client with timeout handling.
|
|
64
|
+
* Called automatically in constructor.
|
|
65
|
+
*/
|
|
66
|
+
private initMetricClient;
|
|
67
|
+
/**
|
|
68
|
+
* Create the single shared histogram for all latency measurements.
|
|
69
|
+
* Called after metric client is initialized.
|
|
70
|
+
*/
|
|
71
|
+
private createLatencyHistogram;
|
|
72
|
+
/**
|
|
73
|
+
* Execute a function with base attributes set in the OpenTelemetry context.
|
|
74
|
+
* All metric calls within the function will automatically include these base attributes,
|
|
75
|
+
* merged with any custom attributes provided in each call.
|
|
76
|
+
*
|
|
77
|
+
* Base attributes take precedence over custom attributes when there are key conflicts.
|
|
78
|
+
* Conflicting custom attributes are silently dropped.
|
|
79
|
+
*
|
|
80
|
+
* @param baseAttributes Base attributes to include in all metrics within the scope
|
|
81
|
+
* @param fn Function to execute with the base attributes context
|
|
82
|
+
* @returns The return value of the function
|
|
83
|
+
*
|
|
84
|
+
* @example
|
|
85
|
+
* ```typescript
|
|
86
|
+
* // In a request middleware
|
|
87
|
+
* await diagnosticsMetrics.runWithBaseAttributes(
|
|
88
|
+
* {
|
|
89
|
+
* 'vtex.account.name': ctx.vtex.account,
|
|
90
|
+
* status_code: ctx.status,
|
|
91
|
+
* route_id: ctx.vtex.route.id,
|
|
92
|
+
* },
|
|
93
|
+
* async () => {
|
|
94
|
+
* await next()
|
|
95
|
+
* }
|
|
96
|
+
* )
|
|
97
|
+
*
|
|
98
|
+
* // In app code (custom attributes are merged with base)
|
|
99
|
+
* diagnosticsMetrics.recordLatency(elapsed, { operation: 'my-operation', status: 'success' })
|
|
100
|
+
* // Result includes both base attributes AND custom attributes
|
|
101
|
+
* ```
|
|
102
|
+
*/
|
|
103
|
+
runWithBaseAttributes<T>(baseAttributes: Attributes, fn: () => T): T;
|
|
104
|
+
/**
|
|
105
|
+
* Get the base attributes from the current OpenTelemetry context.
|
|
106
|
+
* Returns undefined if no base attributes are set.
|
|
107
|
+
*/
|
|
108
|
+
private getBaseAttributes;
|
|
109
|
+
/**
|
|
110
|
+
* Merge base attributes from context with provided custom attributes.
|
|
111
|
+
* Base attributes take precedence over custom attributes when there are key conflicts.
|
|
112
|
+
*
|
|
113
|
+
* Custom attributes are limited to MAX_CUSTOM_ATTRIBUTES before merging.
|
|
114
|
+
* Custom attributes with keys that conflict with base attributes are silently dropped.
|
|
115
|
+
* Base attributes are not limited.
|
|
116
|
+
*
|
|
117
|
+
* @param customAttributes Custom attributes provided by the caller
|
|
118
|
+
* @returns Merged attributes (base + non-conflicting limited custom) or undefined if both are empty
|
|
119
|
+
*/
|
|
120
|
+
private mergeAttributes;
|
|
121
|
+
/**
|
|
122
|
+
* Record a latency measurement using the single shared histogram.
|
|
123
|
+
* Accepts either an hrtime tuple from process.hrtime() or milliseconds as a number.
|
|
124
|
+
* Use attributes to differentiate between different operations.
|
|
125
|
+
*
|
|
126
|
+
* Base attributes from the current context (set via `runWithBaseAttributes`) are
|
|
127
|
+
* automatically merged with the provided custom attributes. Base attributes take
|
|
128
|
+
* precedence - if a custom attribute key conflicts with a base attribute key,
|
|
129
|
+
* the custom attribute is silently dropped.
|
|
130
|
+
*
|
|
131
|
+
* Custom attributes are limited to MAX_CUSTOM_ATTRIBUTES (5). Base attributes are not limited.
|
|
132
|
+
*
|
|
133
|
+
* @param value Either [seconds, nanoseconds] from process.hrtime() or milliseconds
|
|
134
|
+
* @param attributes Custom attributes including 'operation' to identify the operation type (max 5 custom attributes)
|
|
135
|
+
*
|
|
136
|
+
* @example
|
|
137
|
+
* ```typescript
|
|
138
|
+
* const start = process.hrtime()
|
|
139
|
+
* // ... do work ...
|
|
140
|
+
* diagnosticsMetrics.recordLatency(process.hrtime(start), { operation: 'api-call', status: '2xx' })
|
|
141
|
+
*
|
|
142
|
+
* // Or with milliseconds
|
|
143
|
+
* diagnosticsMetrics.recordLatency(42.5, { operation: 'db-query', status: 'success' })
|
|
144
|
+
* ```
|
|
145
|
+
*/
|
|
146
|
+
recordLatency(value: [number, number] | number, attributes?: Attributes): void;
|
|
147
|
+
/**
|
|
148
|
+
* Increment a counter by a specific value.
|
|
149
|
+
* Multiple counters are stored by name since counters represent different types of events.
|
|
150
|
+
*
|
|
151
|
+
* Base attributes from the current context (set via `runWithBaseAttributes`) are
|
|
152
|
+
* automatically merged with the provided custom attributes. Base attributes take
|
|
153
|
+
* precedence - if a custom attribute key conflicts with a base attribute key,
|
|
154
|
+
* the custom attribute is silently dropped.
|
|
155
|
+
*
|
|
156
|
+
* Custom attributes are limited to MAX_CUSTOM_ATTRIBUTES (5). Base attributes are not limited.
|
|
157
|
+
*
|
|
158
|
+
* @param name Counter name (e.g., 'http_requests_total', 'cache_hits_total')
|
|
159
|
+
* @param value Amount to increment by (typically 1)
|
|
160
|
+
* @param attributes Optional custom attributes for the counter (max 5 custom attributes, e.g., { method: 'GET', status: '2xx' })
|
|
161
|
+
*
|
|
162
|
+
* @example
|
|
163
|
+
* ```typescript
|
|
164
|
+
* diagnosticsMetrics.incrementCounter('http_requests_total', 1, { method: 'GET', status: '2xx' })
|
|
165
|
+
* ```
|
|
166
|
+
*/
|
|
167
|
+
incrementCounter(name: string, value: number, attributes?: Attributes): void;
|
|
168
|
+
/**
|
|
169
|
+
* Set a gauge to a specific value (current state).
|
|
170
|
+
* Multiple gauges are stored by name since gauges represent different types of measurements.
|
|
171
|
+
*
|
|
172
|
+
* Base attributes from the current context (set via `runWithBaseAttributes`) are
|
|
173
|
+
* automatically merged with the provided custom attributes. Base attributes take
|
|
174
|
+
* precedence - if a custom attribute key conflicts with a base attribute key,
|
|
175
|
+
* the custom attribute is silently dropped.
|
|
176
|
+
*
|
|
177
|
+
* Custom attributes are limited to MAX_CUSTOM_ATTRIBUTES (5). Base attributes are not limited.
|
|
178
|
+
*
|
|
179
|
+
* @param name Gauge name (e.g., 'cache_items_current', 'memory_usage_bytes')
|
|
180
|
+
* @param value Current value
|
|
181
|
+
* @param attributes Optional custom attributes for the gauge (max 5 custom attributes, e.g., { cache: 'pages' })
|
|
182
|
+
*
|
|
183
|
+
* @example
|
|
184
|
+
* ```typescript
|
|
185
|
+
* diagnosticsMetrics.setGauge('cache_items_current', 1024, { cache: 'pages' })
|
|
186
|
+
* ```
|
|
187
|
+
*/
|
|
188
|
+
setGauge(name: string, value: number, attributes?: Attributes): void;
|
|
189
|
+
}
|