@frugalco/frugal-sdk-node 0.1.0 → 0.3.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 +52 -3
- package/dist/config.d.ts +6 -0
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +33 -4
- package/dist/config.js.map +1 -1
- package/dist/debug.d.ts +25 -0
- package/dist/debug.d.ts.map +1 -0
- package/dist/debug.js +77 -0
- package/dist/debug.js.map +1 -0
- package/dist/index.d.ts +5 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -0
- package/dist/index.js.map +1 -1
- package/dist/instrument.d.ts +4 -1
- package/dist/instrument.d.ts.map +1 -1
- package/dist/instrument.js +20 -5
- package/dist/instrument.js.map +1 -1
- package/dist/otel.d.ts +23 -1
- package/dist/otel.d.ts.map +1 -1
- package/dist/otel.js +93 -11
- package/dist/otel.js.map +1 -1
- package/dist/providers.d.ts +86 -0
- package/dist/providers.d.ts.map +1 -0
- package/dist/providers.js +125 -0
- package/dist/providers.js.map +1 -0
- package/dist/semconv.d.ts +2 -0
- package/dist/semconv.d.ts.map +1 -1
- package/dist/semconv.js +10 -0
- package/dist/semconv.js.map +1 -1
- package/dist/shutdown.d.ts +28 -0
- package/dist/shutdown.d.ts.map +1 -0
- package/dist/shutdown.js +111 -0
- package/dist/shutdown.js.map +1 -0
- package/dist/track.d.ts +14 -4
- package/dist/track.d.ts.map +1 -1
- package/dist/track.js +5 -2
- package/dist/track.js.map +1 -1
- package/dist/wrappers/anthropic.d.ts.map +1 -1
- package/dist/wrappers/anthropic.js +6 -0
- package/dist/wrappers/anthropic.js.map +1 -1
- package/dist/wrappers/openai.d.ts.map +1 -1
- package/dist/wrappers/openai.js +6 -0
- package/dist/wrappers/openai.js.map +1 -1
- package/package.json +5 -5
package/dist/otel.js
CHANGED
|
@@ -8,9 +8,11 @@
|
|
|
8
8
|
// backends) reject application/json on /v1/metrics with HTTP 400. The proto
|
|
9
9
|
// package has the same exporter API but ships application/x-protobuf, which
|
|
10
10
|
// is the broadly-supported OTLP wire format.
|
|
11
|
+
import { ExportResultCode } from "@opentelemetry/core";
|
|
11
12
|
import { OTLPMetricExporter } from "@opentelemetry/exporter-metrics-otlp-proto";
|
|
12
|
-
import {
|
|
13
|
-
import {
|
|
13
|
+
import { resourceFromAttributes } from "@opentelemetry/resources";
|
|
14
|
+
import { AggregationType, ConsoleMetricExporter, MeterProvider, PeriodicExportingMetricReader, } from "@opentelemetry/sdk-metrics";
|
|
15
|
+
import { emitLog } from "./debug.js";
|
|
14
16
|
import { FRUGAL_COMPONENT, FRUGAL_CUSTOMER_ID, FRUGAL_PROJECT_ID, METRIC_CACHE_PREFIX_STABLE, METRIC_CACHE_READ_TOKENS, METRIC_CACHE_WRITE_TOKENS, METRIC_CALLS, METRIC_ERRORS, METRIC_FEW_SHOT_COUNT, METRIC_HISTORY_DEPTH, METRIC_NOISE_RATIO, METRIC_OPERATION_DURATION, METRIC_INTERNAL_ERRORS, METRIC_OUTPUT_CAP_UTILIZATION, METRIC_REASONING_TOKENS, METRIC_STRUCTURED_OUTPUT_HINT, METRIC_TOKEN_USAGE, } from "./semconv.js";
|
|
15
17
|
const INSTRUMENTATION_NAME = "frugal-metrics";
|
|
16
18
|
const INSTRUMENTATION_VERSION = "0.1.0";
|
|
@@ -18,9 +20,20 @@ let cached = null;
|
|
|
18
20
|
export function getInstruments(config) {
|
|
19
21
|
if (cached !== null)
|
|
20
22
|
return cached;
|
|
21
|
-
|
|
23
|
+
try {
|
|
24
|
+
cached = buildInstruments(config);
|
|
25
|
+
}
|
|
26
|
+
catch (err) {
|
|
27
|
+
emitLog("error", `failed to initialize metrics: ${errorMessage(err)}`);
|
|
28
|
+
throw err;
|
|
29
|
+
}
|
|
22
30
|
return cached;
|
|
23
31
|
}
|
|
32
|
+
function errorMessage(err) {
|
|
33
|
+
if (err instanceof Error)
|
|
34
|
+
return err.message;
|
|
35
|
+
return String(err);
|
|
36
|
+
}
|
|
24
37
|
function buildInstruments(config) {
|
|
25
38
|
const reader = buildReader(config);
|
|
26
39
|
return buildFromReader(config, reader);
|
|
@@ -40,7 +53,7 @@ export function buildFromReader(config, reader) {
|
|
|
40
53
|
if (config.customerId) {
|
|
41
54
|
resourceAttrs[FRUGAL_CUSTOMER_ID] = config.customerId;
|
|
42
55
|
}
|
|
43
|
-
const resource =
|
|
56
|
+
const resource = resourceFromAttributes(resourceAttrs);
|
|
44
57
|
const provider = new MeterProvider({
|
|
45
58
|
resource,
|
|
46
59
|
readers: [reader],
|
|
@@ -52,17 +65,24 @@ export function buildFromReader(config, reader) {
|
|
|
52
65
|
// every call site. These boundaries give visible P50/P95/P99 spread for
|
|
53
66
|
// realistic LLM workloads.
|
|
54
67
|
views: [
|
|
55
|
-
|
|
68
|
+
{
|
|
56
69
|
instrumentName: METRIC_OPERATION_DURATION,
|
|
57
|
-
aggregation:
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
70
|
+
aggregation: {
|
|
71
|
+
type: AggregationType.EXPLICIT_BUCKET_HISTOGRAM,
|
|
72
|
+
options: {
|
|
73
|
+
boundaries: [
|
|
74
|
+
0.05, 0.1, 0.25, 0.5, 0.75, 1, 1.5, 2, 3, 5, 7.5, 10, 15, 20, 30,
|
|
75
|
+
60,
|
|
76
|
+
],
|
|
77
|
+
},
|
|
78
|
+
},
|
|
79
|
+
},
|
|
61
80
|
],
|
|
62
81
|
});
|
|
63
82
|
const meter = provider.getMeter(INSTRUMENTATION_NAME, INSTRUMENTATION_VERSION);
|
|
64
83
|
const raw = {
|
|
65
84
|
meterProvider: provider,
|
|
85
|
+
reader,
|
|
66
86
|
operationDuration: meter.createHistogram(METRIC_OPERATION_DURATION, {
|
|
67
87
|
unit: "s",
|
|
68
88
|
description: "Duration of AI client operations.",
|
|
@@ -169,17 +189,79 @@ function fanoutHistogram(inner, components) {
|
|
|
169
189
|
};
|
|
170
190
|
}
|
|
171
191
|
function buildReader(config) {
|
|
172
|
-
const
|
|
192
|
+
const base = config.otlpEndpoint
|
|
173
193
|
? new OTLPMetricExporter({
|
|
174
194
|
url: config.otlpEndpoint,
|
|
175
195
|
headers: parseHeaders(config.otlpHeaders),
|
|
176
196
|
})
|
|
177
197
|
: new ConsoleMetricExporter();
|
|
178
198
|
return new PeriodicExportingMetricReader({
|
|
179
|
-
exporter,
|
|
199
|
+
exporter: wrapExporterForHealth(base),
|
|
180
200
|
exportIntervalMillis: config.exportIntervalMs,
|
|
181
201
|
});
|
|
182
202
|
}
|
|
203
|
+
/**
|
|
204
|
+
* Wrap an OTLP exporter so persistent export failures surface as a single
|
|
205
|
+
* de-duped `error` debug callback. The periodic reader retries silently
|
|
206
|
+
* forever; without this, a wrong endpoint / bad token / down backend is
|
|
207
|
+
* invisible to the customer. We emit on the FIRST failure after a success
|
|
208
|
+
* (0→1 edge) and re-arm on the next success, so a flapping backend produces
|
|
209
|
+
* one alert per failure run, not one per export tick.
|
|
210
|
+
*
|
|
211
|
+
* Delegates every other exporter method so behavior is otherwise unchanged.
|
|
212
|
+
*/
|
|
213
|
+
export function wrapExporterForHealth(exporter) {
|
|
214
|
+
let consecutiveFailures = 0;
|
|
215
|
+
return {
|
|
216
|
+
export(metrics, resultCallback) {
|
|
217
|
+
exporter.export(metrics, (result) => {
|
|
218
|
+
if (result.code === ExportResultCode.SUCCESS) {
|
|
219
|
+
if (consecutiveFailures > 0)
|
|
220
|
+
consecutiveFailures = 0;
|
|
221
|
+
}
|
|
222
|
+
else {
|
|
223
|
+
consecutiveFailures += 1;
|
|
224
|
+
if (consecutiveFailures === 1) {
|
|
225
|
+
const reason = result.error ? result.error.message : "unknown error";
|
|
226
|
+
emitLog("error", `metric export failing: ${reason}`, {
|
|
227
|
+
"frugal.export.error": reason,
|
|
228
|
+
});
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
resultCallback(result);
|
|
232
|
+
});
|
|
233
|
+
},
|
|
234
|
+
forceFlush() {
|
|
235
|
+
return exporter.forceFlush();
|
|
236
|
+
},
|
|
237
|
+
shutdown() {
|
|
238
|
+
return exporter.shutdown();
|
|
239
|
+
},
|
|
240
|
+
selectAggregationTemporality: exporter.selectAggregationTemporality
|
|
241
|
+
? (instrumentType) => exporter.selectAggregationTemporality(instrumentType)
|
|
242
|
+
: undefined,
|
|
243
|
+
};
|
|
244
|
+
}
|
|
245
|
+
/**
|
|
246
|
+
* Force an immediate export of buffered metrics. No-op when uninitialized.
|
|
247
|
+
* Never throws on uninit (callers in shutdown.ts also guard).
|
|
248
|
+
*/
|
|
249
|
+
export async function flushMetrics() {
|
|
250
|
+
if (cached === null)
|
|
251
|
+
return;
|
|
252
|
+
await cached.reader.forceFlush();
|
|
253
|
+
}
|
|
254
|
+
/**
|
|
255
|
+
* Shut down the provider (which flushes + stops the reader) and drop the
|
|
256
|
+
* cache so a later wrap call lazily rebuilds. No-op when uninitialized.
|
|
257
|
+
*/
|
|
258
|
+
export async function shutdownMetrics() {
|
|
259
|
+
if (cached === null)
|
|
260
|
+
return;
|
|
261
|
+
const provider = cached.meterProvider;
|
|
262
|
+
cached = null;
|
|
263
|
+
await provider.shutdown();
|
|
264
|
+
}
|
|
183
265
|
function parseHeaders(raw) {
|
|
184
266
|
if (!raw)
|
|
185
267
|
return undefined;
|
package/dist/otel.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"otel.js","sourceRoot":"","sources":["../src/otel.ts"],"names":[],"mappings":"AAAA,sDAAsD;AACtD,EAAE;AACF,6EAA6E;AAC7E,wEAAwE;AACxE,2EAA2E;AAC3E,YAAY;AAGZ,yEAAyE;AACzE,4EAA4E;AAC5E,4EAA4E;AAC5E,6CAA6C;AAC7C,OAAO,EAAE,kBAAkB,EAAE,MAAM,4CAA4C,CAAC;AAChF,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"otel.js","sourceRoot":"","sources":["../src/otel.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import { OP_OTHER } from "./semconv.js";
|
|
2
|
+
export interface ProviderEntry {
|
|
3
|
+
/** Legacy `gen_ai.system` value — kept for back-compat. */
|
|
4
|
+
system: string;
|
|
5
|
+
/** New `gen_ai.provider.name` value — current OTel spelling. */
|
|
6
|
+
providerName: string;
|
|
7
|
+
}
|
|
8
|
+
export declare const PROVIDERS: readonly [{
|
|
9
|
+
readonly system: "openai";
|
|
10
|
+
readonly providerName: "openai";
|
|
11
|
+
}, {
|
|
12
|
+
readonly system: "anthropic";
|
|
13
|
+
readonly providerName: "anthropic";
|
|
14
|
+
}, {
|
|
15
|
+
readonly system: "aws.bedrock";
|
|
16
|
+
readonly providerName: "aws.bedrock";
|
|
17
|
+
}, {
|
|
18
|
+
readonly system: "vertex_ai";
|
|
19
|
+
readonly providerName: "gcp.vertex_ai";
|
|
20
|
+
}, {
|
|
21
|
+
readonly system: "az.ai.openai";
|
|
22
|
+
readonly providerName: "azure.ai.openai";
|
|
23
|
+
}, {
|
|
24
|
+
readonly system: "cohere";
|
|
25
|
+
readonly providerName: "cohere";
|
|
26
|
+
}, {
|
|
27
|
+
readonly system: "mistral_ai";
|
|
28
|
+
readonly providerName: "mistral_ai";
|
|
29
|
+
}, {
|
|
30
|
+
readonly system: "deepseek";
|
|
31
|
+
readonly providerName: "deepseek";
|
|
32
|
+
}, {
|
|
33
|
+
readonly system: "groq";
|
|
34
|
+
readonly providerName: "groq";
|
|
35
|
+
}, {
|
|
36
|
+
readonly system: "perplexity";
|
|
37
|
+
readonly providerName: "perplexity";
|
|
38
|
+
}, {
|
|
39
|
+
readonly system: "x_ai";
|
|
40
|
+
readonly providerName: "x_ai";
|
|
41
|
+
}, {
|
|
42
|
+
readonly system: "ibm.watsonx.ai";
|
|
43
|
+
readonly providerName: "ibm.watsonx.ai";
|
|
44
|
+
}, {
|
|
45
|
+
readonly system: "gcp.gemini";
|
|
46
|
+
readonly providerName: "gcp.gemini";
|
|
47
|
+
}];
|
|
48
|
+
/**
|
|
49
|
+
* Accepted provider values (legacy `gen_ai.system` spelling). Derived from
|
|
50
|
+
* PROVIDERS so the autocomplete vocabulary can never drift from the runtime
|
|
51
|
+
* registry — add a provider in one place. The public API fields are typed
|
|
52
|
+
* `GenAiSystem | (string & {})` so this gives autocomplete and catches obvious
|
|
53
|
+
* typos, while still permitting a free-form custom string. Includes BOTH spellings
|
|
54
|
+
* (legacy `system` and new `providerName`) since `normalizeProvider` accepts either.
|
|
55
|
+
*/
|
|
56
|
+
export type GenAiSystem = (typeof PROVIDERS)[number]["system"] | (typeof PROVIDERS)[number]["providerName"] | "custom";
|
|
57
|
+
declare const OPERATIONS: readonly ["chat", "text_completion", "embeddings", "generate_content", "execute_tool", "create_agent", "invoke_agent"];
|
|
58
|
+
/**
|
|
59
|
+
* Accepted `gen_ai.operation.name` values. Derived from OPERATIONS so the
|
|
60
|
+
* autocomplete vocabulary can't drift from what the runtime accepts (mirrors
|
|
61
|
+
* GenAiSystem ← PROVIDERS). Plus the `other` sentinel that unknown operations
|
|
62
|
+
* coerce to (passes through without a warning).
|
|
63
|
+
*/
|
|
64
|
+
export type GenAiOperation = (typeof OPERATIONS)[number] | typeof OP_OTHER;
|
|
65
|
+
/** Test-only — clear the bounded invalid-value warning state. */
|
|
66
|
+
export declare function resetProviderWarningsForTests(): void;
|
|
67
|
+
/**
|
|
68
|
+
* Resolve a caller-supplied provider string to its canonical
|
|
69
|
+
* `{ system, providerName }` pair. Accepts either spelling (legacy
|
|
70
|
+
* `gen_ai.system` or new `gen_ai.provider.name`). A value the customer has
|
|
71
|
+
* registered via `customProviders` passes through verbatim (system ==
|
|
72
|
+
* providerName). Any other unknown value is coerced to the `custom` sentinel and
|
|
73
|
+
* reported (bounded warn-once). `undefined` resolves to `custom` silently (the
|
|
74
|
+
* intended default). Never throws.
|
|
75
|
+
*/
|
|
76
|
+
export declare function normalizeProvider(input?: string, customProviders?: readonly string[]): ProviderEntry;
|
|
77
|
+
/**
|
|
78
|
+
* Resolve a caller-supplied operation string. Unknown values are coerced to the
|
|
79
|
+
* `other` sentinel — NOT `chat` — so a typo lands in a distinguishable bucket
|
|
80
|
+
* instead of inflating the real chat series, and reported (bounded warn-once).
|
|
81
|
+
* `undefined` resolves to `chat` (the default); an explicit `other` passes
|
|
82
|
+
* through silently. Never throws.
|
|
83
|
+
*/
|
|
84
|
+
export declare function normalizeOperation(input?: string): string;
|
|
85
|
+
export {};
|
|
86
|
+
//# sourceMappingURL=providers.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"providers.d.ts","sourceRoot":"","sources":["../src/providers.ts"],"names":[],"mappings":"AAkBA,OAAO,EAAW,QAAQ,EAAiB,MAAM,cAAc,CAAC;AAEhE,MAAM,WAAW,aAAa;IAC5B,2DAA2D;IAC3D,MAAM,EAAE,MAAM,CAAC;IACf,gEAAgE;IAChE,YAAY,EAAE,MAAM,CAAC;CACtB;AAMD,eAAO,MAAM,SAAS;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAcuB,CAAC;AAE9C;;;;;;;GAOG;AACH,MAAM,MAAM,WAAW,GACnB,CAAC,OAAO,SAAS,CAAC,CAAC,MAAM,CAAC,CAAC,QAAQ,CAAC,GACpC,CAAC,OAAO,SAAS,CAAC,CAAC,MAAM,CAAC,CAAC,cAAc,CAAC,GAC1C,QAAQ,CAAC;AAKb,QAAA,MAAM,UAAU,wHAQN,CAAC;AAEX;;;;;GAKG;AACH,MAAM,MAAM,cAAc,GAAG,CAAC,OAAO,UAAU,CAAC,CAAC,MAAM,CAAC,GAAG,OAAO,QAAQ,CAAC;AAuC3E,iEAAiE;AACjE,wBAAgB,6BAA6B,IAAI,IAAI,CAGpD;AAED;;;;;;;;GAQG;AACH,wBAAgB,iBAAiB,CAC/B,KAAK,CAAC,EAAE,MAAM,EACd,eAAe,GAAE,SAAS,MAAM,EAAO,GACtC,aAAa,CAcf;AAED;;;;;;GAMG;AACH,wBAAgB,kBAAkB,CAAC,KAAK,CAAC,EAAE,MAAM,GAAG,MAAM,CAUzD"}
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
// Canonical provider registry + sentinel normalization.
|
|
2
|
+
//
|
|
3
|
+
// `gen_ai.system` is the OpenTelemetry GenAI semantic-convention attribute that
|
|
4
|
+
// identifies the provider/platform a model runs on. OTel has since renamed it to
|
|
5
|
+
// `gen_ai.provider.name`, with a few new value spellings (e.g. `vertex_ai` →
|
|
6
|
+
// `gcp.vertex_ai`). We dual-emit both attributes: the legacy `gen_ai.system`
|
|
7
|
+
// value (unchanged for the providers we already supported, so existing queries
|
|
8
|
+
// and historical series keep matching) plus the new `gen_ai.provider.name`
|
|
9
|
+
// value. Consumers migrate to the new attribute at their own pace; the old one
|
|
10
|
+
// is dropped afterward.
|
|
11
|
+
//
|
|
12
|
+
// Any value outside the well-known set is a bug (a typo like `amazon-bedrock`
|
|
13
|
+
// silently produces a series no query ever matches). Such values are coerced to
|
|
14
|
+
// the `custom` sentinel — a wrong label never reaches metrics — and surfaced
|
|
15
|
+
// once via the debug channel so the mistake is visible. Everything here is pure
|
|
16
|
+
// and never throws: the SDK is safe by construction.
|
|
17
|
+
import { emitLog } from "./debug.js";
|
|
18
|
+
import { OP_CHAT, OP_OTHER, SYSTEM_CUSTOM } from "./semconv.js";
|
|
19
|
+
// Single source of truth. `system` preserves the spelling Frugal already emitted
|
|
20
|
+
// for the providers it historically supported (so existing dashboards/history
|
|
21
|
+
// keep matching); `providerName` is the current OTel spelling. For providers we
|
|
22
|
+
// never emitted before, both columns are the same OTel-standard string.
|
|
23
|
+
export const PROVIDERS = [
|
|
24
|
+
{ system: "openai", providerName: "openai" },
|
|
25
|
+
{ system: "anthropic", providerName: "anthropic" },
|
|
26
|
+
{ system: "aws.bedrock", providerName: "aws.bedrock" },
|
|
27
|
+
{ system: "vertex_ai", providerName: "gcp.vertex_ai" },
|
|
28
|
+
{ system: "az.ai.openai", providerName: "azure.ai.openai" },
|
|
29
|
+
{ system: "cohere", providerName: "cohere" },
|
|
30
|
+
{ system: "mistral_ai", providerName: "mistral_ai" },
|
|
31
|
+
{ system: "deepseek", providerName: "deepseek" },
|
|
32
|
+
{ system: "groq", providerName: "groq" },
|
|
33
|
+
{ system: "perplexity", providerName: "perplexity" },
|
|
34
|
+
{ system: "x_ai", providerName: "x_ai" },
|
|
35
|
+
{ system: "ibm.watsonx.ai", providerName: "ibm.watsonx.ai" },
|
|
36
|
+
{ system: "gcp.gemini", providerName: "gcp.gemini" },
|
|
37
|
+
];
|
|
38
|
+
// Operations accepted without warning: the three defaults plus other OTel-defined
|
|
39
|
+
// values. Single source of truth for both GenAiOperation below and the coercion
|
|
40
|
+
// warning's "use one of" list.
|
|
41
|
+
const OPERATIONS = [
|
|
42
|
+
"chat",
|
|
43
|
+
"text_completion",
|
|
44
|
+
"embeddings",
|
|
45
|
+
"generate_content",
|
|
46
|
+
"execute_tool",
|
|
47
|
+
"create_agent",
|
|
48
|
+
"invoke_agent",
|
|
49
|
+
];
|
|
50
|
+
const CUSTOM = { system: SYSTEM_CUSTOM, providerName: SYSTEM_CUSTOM };
|
|
51
|
+
// Lookup by either spelling, built once — keeps normalizeProvider O(1) on the hot
|
|
52
|
+
// path instead of scanning PROVIDERS on every call.
|
|
53
|
+
const BY_VALUE = new Map();
|
|
54
|
+
for (const entry of PROVIDERS) {
|
|
55
|
+
BY_VALUE.set(entry.system, entry);
|
|
56
|
+
BY_VALUE.set(entry.providerName, entry);
|
|
57
|
+
}
|
|
58
|
+
// Bounded warn-once: surface each distinct invalid provider/operation value
|
|
59
|
+
// once, but cap how many distinct values we track so a high-cardinality caller
|
|
60
|
+
// (e.g. a gateway labeling calls from request data) can't grow this set without
|
|
61
|
+
// bound. Past the cap, further unknown values are coerced silently after a
|
|
62
|
+
// single generic notice. We do our own de-dup here (emitLog, not emitLogOnce) so
|
|
63
|
+
// the cap is enforced in one place — and so every distinct typo is surfaced, not
|
|
64
|
+
// just the first one.
|
|
65
|
+
const MAX_TRACKED_INVALID = 32;
|
|
66
|
+
const warnedInvalid = new Set();
|
|
67
|
+
let capNoticeEmitted = false;
|
|
68
|
+
function warnInvalidOnce(key, message) {
|
|
69
|
+
if (warnedInvalid.has(key))
|
|
70
|
+
return;
|
|
71
|
+
if (warnedInvalid.size >= MAX_TRACKED_INVALID) {
|
|
72
|
+
if (!capNoticeEmitted) {
|
|
73
|
+
capNoticeEmitted = true;
|
|
74
|
+
emitLog("warn", `frugal-metrics: ${MAX_TRACKED_INVALID}+ distinct invalid provider/operation values seen; further unknown values are coerced to the sentinel without an individual warning.`);
|
|
75
|
+
}
|
|
76
|
+
return;
|
|
77
|
+
}
|
|
78
|
+
warnedInvalid.add(key);
|
|
79
|
+
emitLog("warn", message);
|
|
80
|
+
}
|
|
81
|
+
/** Test-only — clear the bounded invalid-value warning state. */
|
|
82
|
+
export function resetProviderWarningsForTests() {
|
|
83
|
+
warnedInvalid.clear();
|
|
84
|
+
capNoticeEmitted = false;
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* Resolve a caller-supplied provider string to its canonical
|
|
88
|
+
* `{ system, providerName }` pair. Accepts either spelling (legacy
|
|
89
|
+
* `gen_ai.system` or new `gen_ai.provider.name`). A value the customer has
|
|
90
|
+
* registered via `customProviders` passes through verbatim (system ==
|
|
91
|
+
* providerName). Any other unknown value is coerced to the `custom` sentinel and
|
|
92
|
+
* reported (bounded warn-once). `undefined` resolves to `custom` silently (the
|
|
93
|
+
* intended default). Never throws.
|
|
94
|
+
*/
|
|
95
|
+
export function normalizeProvider(input, customProviders = []) {
|
|
96
|
+
if (input === undefined || input === SYSTEM_CUSTOM)
|
|
97
|
+
return CUSTOM;
|
|
98
|
+
const entry = BY_VALUE.get(input);
|
|
99
|
+
if (entry !== undefined)
|
|
100
|
+
return entry;
|
|
101
|
+
// Customer-registered passthrough: no OTel mapping, so both labels carry the
|
|
102
|
+
// raw name. The set is capped at config-load time, so cardinality stays bounded.
|
|
103
|
+
if (customProviders.includes(input)) {
|
|
104
|
+
return { system: input, providerName: input };
|
|
105
|
+
}
|
|
106
|
+
warnInvalidOnce(`provider:${input}`, `unknown gen_ai provider "${input}" — coerced to "custom". Use a well-known OpenTelemetry GenAI provider value (e.g. "aws.bedrock", "vertex_ai", "anthropic", "openai"), or register it via FRUGAL_CUSTOM_PROVIDERS.`);
|
|
107
|
+
return CUSTOM;
|
|
108
|
+
}
|
|
109
|
+
/**
|
|
110
|
+
* Resolve a caller-supplied operation string. Unknown values are coerced to the
|
|
111
|
+
* `other` sentinel — NOT `chat` — so a typo lands in a distinguishable bucket
|
|
112
|
+
* instead of inflating the real chat series, and reported (bounded warn-once).
|
|
113
|
+
* `undefined` resolves to `chat` (the default); an explicit `other` passes
|
|
114
|
+
* through silently. Never throws.
|
|
115
|
+
*/
|
|
116
|
+
export function normalizeOperation(input) {
|
|
117
|
+
if (input === undefined)
|
|
118
|
+
return OP_CHAT;
|
|
119
|
+
if (input === OP_OTHER || OPERATIONS.includes(input)) {
|
|
120
|
+
return input;
|
|
121
|
+
}
|
|
122
|
+
warnInvalidOnce(`operation:${input}`, `unknown gen_ai.operation.name "${input}" — coerced to "other". Use one of: ${OPERATIONS.join(", ")}.`);
|
|
123
|
+
return OP_OTHER;
|
|
124
|
+
}
|
|
125
|
+
//# sourceMappingURL=providers.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"providers.js","sourceRoot":"","sources":["../src/providers.ts"],"names":[],"mappings":"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"}
|
package/dist/semconv.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
export declare const GEN_AI_SYSTEM = "gen_ai.system";
|
|
2
|
+
export declare const GEN_AI_PROVIDER_NAME = "gen_ai.provider.name";
|
|
2
3
|
export declare const GEN_AI_REQUEST_MODEL = "gen_ai.request.model";
|
|
3
4
|
export declare const GEN_AI_RESPONSE_MODEL = "gen_ai.response.model";
|
|
4
5
|
export declare const GEN_AI_OPERATION_NAME = "gen_ai.operation.name";
|
|
@@ -12,6 +13,7 @@ export declare const SYSTEM_CUSTOM = "custom";
|
|
|
12
13
|
export declare const OP_CHAT = "chat";
|
|
13
14
|
export declare const OP_TEXT_COMPLETION = "text_completion";
|
|
14
15
|
export declare const OP_EMBEDDINGS = "embeddings";
|
|
16
|
+
export declare const OP_OTHER = "other";
|
|
15
17
|
export declare const TOKEN_INPUT = "input";
|
|
16
18
|
export declare const TOKEN_OUTPUT = "output";
|
|
17
19
|
export declare const METRIC_OPERATION_DURATION = "gen_ai.client.operation.duration";
|
package/dist/semconv.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"semconv.d.ts","sourceRoot":"","sources":["../src/semconv.ts"],"names":[],"mappings":"AAEA,eAAO,MAAM,aAAa,kBAAkB,CAAC;
|
|
1
|
+
{"version":3,"file":"semconv.d.ts","sourceRoot":"","sources":["../src/semconv.ts"],"names":[],"mappings":"AAEA,eAAO,MAAM,aAAa,kBAAkB,CAAC;AAG7C,eAAO,MAAM,oBAAoB,yBAAyB,CAAC;AAC3D,eAAO,MAAM,oBAAoB,yBAAyB,CAAC;AAC3D,eAAO,MAAM,qBAAqB,0BAA0B,CAAC;AAC7D,eAAO,MAAM,qBAAqB,0BAA0B,CAAC;AAC7D,eAAO,MAAM,iBAAiB,sBAAsB,CAAC;AAMrD,eAAO,MAAM,aAAa,WAAW,CAAC;AACtC,eAAO,MAAM,gBAAgB,cAAc,CAAC;AAC5C,eAAO,MAAM,mBAAmB,iBAAiB,CAAC;AAClD,eAAO,MAAM,kBAAkB,gBAAgB,CAAC;AAChD,eAAO,MAAM,gBAAgB,cAAc,CAAC;AAC5C,eAAO,MAAM,aAAa,WAAW,CAAC;AAEtC,eAAO,MAAM,OAAO,SAAS,CAAC;AAC9B,eAAO,MAAM,kBAAkB,oBAAoB,CAAC;AACpD,eAAO,MAAM,aAAa,eAAe,CAAC;AAG1C,eAAO,MAAM,QAAQ,UAAU,CAAC;AAEhC,eAAO,MAAM,WAAW,UAAU,CAAC;AACnC,eAAO,MAAM,YAAY,WAAW,CAAC;AAErC,eAAO,MAAM,yBAAyB,qCAAqC,CAAC;AAC5E,eAAO,MAAM,kBAAkB,8BAA8B,CAAC;AAE9D,eAAO,MAAM,YAAY,wBAAwB,CAAC;AAClD,eAAO,MAAM,wBAAwB,oCAAoC,CAAC;AAC1E,eAAO,MAAM,yBAAyB,qCAAqC,CAAC;AAC5E,eAAO,MAAM,uBAAuB,mCAAmC,CAAC;AACxE,eAAO,MAAM,aAAa,yBAAyB,CAAC;AACpD,eAAO,MAAM,sBAAsB,kCAAkC,CAAC;AACtE,eAAO,MAAM,6BAA6B,yCAAyC,CAAC;AACpF,eAAO,MAAM,0BAA0B,sCAAsC,CAAC;AAC9E,eAAO,MAAM,oBAAoB,gCAAgC,CAAC;AAClE,eAAO,MAAM,qBAAqB,iCAAiC,CAAC;AACpE,eAAO,MAAM,kBAAkB,8BAA8B,CAAC;AAC9D,eAAO,MAAM,6BAA6B,yCAAyC,CAAC;AAEpF,eAAO,MAAM,kBAAkB,uBAAuB,CAAC;AACvD,eAAO,MAAM,iBAAiB,sBAAsB,CAAC;AACrD,eAAO,MAAM,gBAAgB,qBAAqB,CAAC;AACnD,eAAO,MAAM,kBAAkB,uBAAuB,CAAC;AACvD,eAAO,MAAM,sBAAsB,2BAA2B,CAAC;AAC/D,eAAO,MAAM,iBAAiB,sBAAsB,CAAC;AACrD,eAAO,MAAM,cAAc,mBAAmB,CAAC;AAC/C,eAAO,MAAM,6BAA6B,kCAAkC,CAAC;AAC7E,eAAO,MAAM,YAAY,iBAAiB,CAAC;AAC3C,eAAO,MAAM,aAAa,kBAAkB,CAAC;AAE7C,eAAO,MAAM,sBAAsB,SAAS,CAAC;AAC7C,eAAO,MAAM,6BAA6B,gBAAgB,CAAC;AAC3D,eAAO,MAAM,6BAA6B,gBAAgB,CAAC;AAC3D,eAAO,MAAM,uBAAuB,UAAU,CAAC;AAE/C,eAAO,MAAM,YAAY,WAAW,CAAC;AACrC,eAAO,MAAM,UAAU,SAAS,CAAC;AACjC,eAAO,MAAM,WAAW,UAAU,CAAC;AACnC,eAAO,MAAM,YAAY,WAAW,CAAC;AAErC,eAAO,MAAM,oBAAoB,eAAe,CAAC;AACjD,eAAO,MAAM,mBAAmB,cAAc,CAAC;AAC/C,eAAO,MAAM,eAAe,eAAe,CAAC"}
|
package/dist/semconv.js
CHANGED
|
@@ -1,9 +1,16 @@
|
|
|
1
1
|
// OpenTelemetry GenAI semantic convention constants + Frugal extensions.
|
|
2
2
|
export const GEN_AI_SYSTEM = "gen_ai.system";
|
|
3
|
+
// OTel renamed gen_ai.system → gen_ai.provider.name; we dual-emit both during the
|
|
4
|
+
// transition. See providers.ts for the value mapping.
|
|
5
|
+
export const GEN_AI_PROVIDER_NAME = "gen_ai.provider.name";
|
|
3
6
|
export const GEN_AI_REQUEST_MODEL = "gen_ai.request.model";
|
|
4
7
|
export const GEN_AI_RESPONSE_MODEL = "gen_ai.response.model";
|
|
5
8
|
export const GEN_AI_OPERATION_NAME = "gen_ai.operation.name";
|
|
6
9
|
export const GEN_AI_TOKEN_TYPE = "gen_ai.token.type";
|
|
10
|
+
// Legacy gen_ai.system spellings exposed as named constants for the wrapper
|
|
11
|
+
// modules. The full cross-provider registry (cohere, mistral_ai, deepseek,
|
|
12
|
+
// groq, …) lives solely in the PROVIDERS table in providers.ts — the single
|
|
13
|
+
// source of truth — and those values are not re-declared here.
|
|
7
14
|
export const SYSTEM_OPENAI = "openai";
|
|
8
15
|
export const SYSTEM_ANTHROPIC = "anthropic";
|
|
9
16
|
export const SYSTEM_AZURE_OPENAI = "az.ai.openai";
|
|
@@ -13,6 +20,9 @@ export const SYSTEM_CUSTOM = "custom";
|
|
|
13
20
|
export const OP_CHAT = "chat";
|
|
14
21
|
export const OP_TEXT_COMPLETION = "text_completion";
|
|
15
22
|
export const OP_EMBEDDINGS = "embeddings";
|
|
23
|
+
// Sentinel for an operation outside the accepted set — parallels SYSTEM_CUSTOM so
|
|
24
|
+
// a typo lands in a distinguishable bucket instead of corrupting the real chat series.
|
|
25
|
+
export const OP_OTHER = "other";
|
|
16
26
|
export const TOKEN_INPUT = "input";
|
|
17
27
|
export const TOKEN_OUTPUT = "output";
|
|
18
28
|
export const METRIC_OPERATION_DURATION = "gen_ai.client.operation.duration";
|
package/dist/semconv.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"semconv.js","sourceRoot":"","sources":["../src/semconv.ts"],"names":[],"mappings":"AAAA,yEAAyE;AAEzE,MAAM,CAAC,MAAM,aAAa,GAAG,eAAe,CAAC;AAC7C,MAAM,CAAC,MAAM,oBAAoB,GAAG,sBAAsB,CAAC;AAC3D,MAAM,CAAC,MAAM,qBAAqB,GAAG,uBAAuB,CAAC;AAC7D,MAAM,CAAC,MAAM,qBAAqB,GAAG,uBAAuB,CAAC;AAC7D,MAAM,CAAC,MAAM,iBAAiB,GAAG,mBAAmB,CAAC;AAErD,MAAM,CAAC,MAAM,aAAa,GAAG,QAAQ,CAAC;AACtC,MAAM,CAAC,MAAM,gBAAgB,GAAG,WAAW,CAAC;AAC5C,MAAM,CAAC,MAAM,mBAAmB,GAAG,cAAc,CAAC;AAClD,MAAM,CAAC,MAAM,kBAAkB,GAAG,aAAa,CAAC;AAChD,MAAM,CAAC,MAAM,gBAAgB,GAAG,WAAW,CAAC;AAC5C,MAAM,CAAC,MAAM,aAAa,GAAG,QAAQ,CAAC;AAEtC,MAAM,CAAC,MAAM,OAAO,GAAG,MAAM,CAAC;AAC9B,MAAM,CAAC,MAAM,kBAAkB,GAAG,iBAAiB,CAAC;AACpD,MAAM,CAAC,MAAM,aAAa,GAAG,YAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"semconv.js","sourceRoot":"","sources":["../src/semconv.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Force an immediate export of pending metrics WITHOUT tearing down the
|
|
3
|
+
* provider — the SDK keeps recording afterwards. No-op (and never throws) when
|
|
4
|
+
* the SDK was never initialized.
|
|
5
|
+
*/
|
|
6
|
+
export declare function flush(): Promise<void>;
|
|
7
|
+
/**
|
|
8
|
+
* Flush pending metrics and shut down the provider. Idempotent and safe when
|
|
9
|
+
* uninitialized; never throws. After this, the SDK lazily rebuilds its provider
|
|
10
|
+
* on the next wrap call.
|
|
11
|
+
*/
|
|
12
|
+
export declare function shutdown(): Promise<void>;
|
|
13
|
+
/**
|
|
14
|
+
* Opt-in: flush + shut down automatically when the process is exiting.
|
|
15
|
+
*
|
|
16
|
+
* Registers a `beforeExit` handler and SIGTERM/SIGINT handlers. Idempotent —
|
|
17
|
+
* repeat calls add no additional listeners. On a signal, after shutdown
|
|
18
|
+
* completes the process exits with code 0 unless `exitOnSignal: false`.
|
|
19
|
+
*
|
|
20
|
+
* Customers who run their own signal handling should NOT call this; prefer
|
|
21
|
+
* awaiting `shutdown()` manually inside their own handler.
|
|
22
|
+
*/
|
|
23
|
+
export declare function enableAutoShutdown(options?: {
|
|
24
|
+
exitOnSignal?: boolean;
|
|
25
|
+
}): void;
|
|
26
|
+
/** Test-only hook — remove our listeners and clear the install/guard flags. */
|
|
27
|
+
export declare function resetAutoShutdownForTests(): void;
|
|
28
|
+
//# sourceMappingURL=shutdown.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"shutdown.d.ts","sourceRoot":"","sources":["../src/shutdown.ts"],"names":[],"mappings":"AAaA;;;;GAIG;AACH,wBAAsB,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAM3C;AAED;;;;GAIG;AACH,wBAAsB,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC,CAO9C;AAyBD;;;;;;;;;GASG;AACH,wBAAgB,kBAAkB,CAAC,OAAO,CAAC,EAAE;IAAE,YAAY,CAAC,EAAE,OAAO,CAAA;CAAE,GAAG,IAAI,CAuB7E;AAED,+EAA+E;AAC/E,wBAAgB,yBAAyB,IAAI,IAAI,CAehD"}
|
package/dist/shutdown.js
ADDED
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
// Flush / shutdown — manual control over the metric pipeline, plus opt-in
|
|
2
|
+
// automatic flush+shutdown on process exit.
|
|
3
|
+
//
|
|
4
|
+
// A short-lived process (a CLI, a job, a serverless invocation) may exit before
|
|
5
|
+
// the periodic exporter's next tick, dropping the final batch of metrics.
|
|
6
|
+
// `flush()` forces an immediate export; `shutdown()` flushes and tears down the
|
|
7
|
+
// provider. `enableAutoShutdown()` wires these into process-exit signals — it is
|
|
8
|
+
// OPT-IN because installing signal handlers is intrusive: a customer running
|
|
9
|
+
// their own SIGTERM/SIGINT handling should prefer calling `shutdown()` manually
|
|
10
|
+
// from within their own handler rather than letting us register ours.
|
|
11
|
+
import { flushMetrics, shutdownMetrics } from "./otel.js";
|
|
12
|
+
/**
|
|
13
|
+
* Force an immediate export of pending metrics WITHOUT tearing down the
|
|
14
|
+
* provider — the SDK keeps recording afterwards. No-op (and never throws) when
|
|
15
|
+
* the SDK was never initialized.
|
|
16
|
+
*/
|
|
17
|
+
export async function flush() {
|
|
18
|
+
try {
|
|
19
|
+
await flushMetrics();
|
|
20
|
+
}
|
|
21
|
+
catch {
|
|
22
|
+
// Internal flush failure must never propagate to the caller.
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Flush pending metrics and shut down the provider. Idempotent and safe when
|
|
27
|
+
* uninitialized; never throws. After this, the SDK lazily rebuilds its provider
|
|
28
|
+
* on the next wrap call.
|
|
29
|
+
*/
|
|
30
|
+
export async function shutdown() {
|
|
31
|
+
try {
|
|
32
|
+
await flushMetrics();
|
|
33
|
+
await shutdownMetrics();
|
|
34
|
+
}
|
|
35
|
+
catch {
|
|
36
|
+
// Internal shutdown failure must never propagate to the caller.
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
let autoShutdownInstalled = false;
|
|
40
|
+
let shuttingDown = false;
|
|
41
|
+
// Held so the test-only reset can remove exactly the listeners we registered.
|
|
42
|
+
let beforeExitListener = null;
|
|
43
|
+
let sigtermListener = null;
|
|
44
|
+
let sigintListener = null;
|
|
45
|
+
async function runShutdownOnce() {
|
|
46
|
+
// Guard against re-entrancy while a shutdown is already in flight (e.g.
|
|
47
|
+
// SIGTERM and SIGINT racing), but re-arm once it completes. With
|
|
48
|
+
// `exitOnSignal: false` the process survives the signal and keeps recording;
|
|
49
|
+
// latching permanently would silently drop every later exit's final window —
|
|
50
|
+
// the exact loss this is meant to prevent. `shutdown()` is itself idempotent.
|
|
51
|
+
if (shuttingDown)
|
|
52
|
+
return;
|
|
53
|
+
shuttingDown = true;
|
|
54
|
+
try {
|
|
55
|
+
await shutdown();
|
|
56
|
+
}
|
|
57
|
+
finally {
|
|
58
|
+
shuttingDown = false;
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Opt-in: flush + shut down automatically when the process is exiting.
|
|
63
|
+
*
|
|
64
|
+
* Registers a `beforeExit` handler and SIGTERM/SIGINT handlers. Idempotent —
|
|
65
|
+
* repeat calls add no additional listeners. On a signal, after shutdown
|
|
66
|
+
* completes the process exits with code 0 unless `exitOnSignal: false`.
|
|
67
|
+
*
|
|
68
|
+
* Customers who run their own signal handling should NOT call this; prefer
|
|
69
|
+
* awaiting `shutdown()` manually inside their own handler.
|
|
70
|
+
*/
|
|
71
|
+
export function enableAutoShutdown(options) {
|
|
72
|
+
if (autoShutdownInstalled)
|
|
73
|
+
return;
|
|
74
|
+
autoShutdownInstalled = true;
|
|
75
|
+
const exitOnSignal = options?.exitOnSignal !== false;
|
|
76
|
+
beforeExitListener = () => {
|
|
77
|
+
// beforeExit fires when the loop is about to drain; the async work keeps
|
|
78
|
+
// the process alive long enough to export.
|
|
79
|
+
void runShutdownOnce();
|
|
80
|
+
};
|
|
81
|
+
process.once("beforeExit", beforeExitListener);
|
|
82
|
+
const onSignal = () => {
|
|
83
|
+
void (async () => {
|
|
84
|
+
await runShutdownOnce();
|
|
85
|
+
if (exitOnSignal)
|
|
86
|
+
process.exit(0);
|
|
87
|
+
})();
|
|
88
|
+
};
|
|
89
|
+
sigtermListener = onSignal;
|
|
90
|
+
sigintListener = onSignal;
|
|
91
|
+
process.on("SIGTERM", sigtermListener);
|
|
92
|
+
process.on("SIGINT", sigintListener);
|
|
93
|
+
}
|
|
94
|
+
/** Test-only hook — remove our listeners and clear the install/guard flags. */
|
|
95
|
+
export function resetAutoShutdownForTests() {
|
|
96
|
+
if (beforeExitListener) {
|
|
97
|
+
process.removeListener("beforeExit", beforeExitListener);
|
|
98
|
+
beforeExitListener = null;
|
|
99
|
+
}
|
|
100
|
+
if (sigtermListener) {
|
|
101
|
+
process.removeListener("SIGTERM", sigtermListener);
|
|
102
|
+
sigtermListener = null;
|
|
103
|
+
}
|
|
104
|
+
if (sigintListener) {
|
|
105
|
+
process.removeListener("SIGINT", sigintListener);
|
|
106
|
+
sigintListener = null;
|
|
107
|
+
}
|
|
108
|
+
autoShutdownInstalled = false;
|
|
109
|
+
shuttingDown = false;
|
|
110
|
+
}
|
|
111
|
+
//# sourceMappingURL=shutdown.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"shutdown.js","sourceRoot":"","sources":["../src/shutdown.ts"],"names":[],"mappings":"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"}
|