axiom
Version:
Axiom AI SDK provides - an API to wrap your AI calls with observability instrumentation. - offline evals - online evals
262 lines (256 loc) • 8.24 kB
JavaScript
// src/otel/utils/redaction.ts
import { context, propagation } from "@opentelemetry/api";
// src/otel/withSpanBaggageKey.ts
var WITHSPAN_BAGGAGE_KEY = "__withspan_gen_ai_call";
var WITHSPAN_REDACTION_POLICY_KEY = "__withspan_redaction_policy";
// src/otel/utils/redaction.ts
var RedactionPolicy = {
/**
* Includes message content on chat spans, and mirrors tool
* payload on tool spans for more convenient querying.
*/
AxiomDefault: {
captureMessageContent: "full",
mirrorToolPayloadOnToolSpan: true
},
/**
* Redacts message content on chat spans, and does not put
* tool payload on tool spans.
*/
OpenTelemetryDefault: {
captureMessageContent: "off",
mirrorToolPayloadOnToolSpan: false
}
};
var AXIOM_AI_REDACTION_KEY = Symbol.for("__axiom_ai_redaction__");
function getGlobalRedactionPolicy() {
return globalThis[AXIOM_AI_REDACTION_KEY];
}
function getEffectiveRedactionPolicy(globalPolicy, localPolicy) {
return {
captureMessageContent: localPolicy?.captureMessageContent ?? globalPolicy?.captureMessageContent ?? RedactionPolicy.AxiomDefault.captureMessageContent,
mirrorToolPayloadOnToolSpan: localPolicy?.mirrorToolPayloadOnToolSpan ?? globalPolicy?.mirrorToolPayloadOnToolSpan ?? RedactionPolicy.AxiomDefault.mirrorToolPayloadOnToolSpan
};
}
function getRedactionPolicy() {
return getEffectiveRedactionPolicy(getGlobalRedactionPolicy(), getPerCallRedactionPolicy());
}
function handleMaybeRedactedAttribute(span, attribute, value, captureMessageContent) {
if (captureMessageContent === "full") {
span.setAttribute(attribute, value);
}
}
function getPerCallRedactionPolicy() {
const baggage = propagation.getBaggage(context.active()) || propagation.createBaggage();
const serializedPolicy = baggage.getEntry(WITHSPAN_REDACTION_POLICY_KEY)?.value;
if (!serializedPolicy) {
return void 0;
}
try {
return JSON.parse(serializedPolicy);
} catch (error) {
console.warn("[AxiomAI] Failed to parse redaction policy from baggage:", error);
return void 0;
}
}
// src/otel/initAxiomAI.ts
import { trace } from "@opentelemetry/api";
// package.json
var package_default = {
name: "axiom",
version: "0.51.1",
type: "module",
author: "Axiom, Inc.",
contributors: [
"Islam Shehata <islam@axiom.co>",
"Chris Ehrlich <chris@axiom.co>",
"Gabriel de Andrade <gabriel@axiom.co>"
],
scripts: {
dev: "tsup --watch",
build: "tsup && chmod +x dist/bin.js && typedoc && pnpm check:vitest-entrypoints",
"check:vitest-entrypoints": "node ./scripts/check-vitest-entrypoints.mjs",
format: "prettier --write .",
"format:check": "prettier --check .",
lint: "eslint './**/*.{js,ts}'",
typecheck: "tsc --noEmit",
test: "vitest run",
"test:watch": "vitest --watch",
"test:wrangler-smoke": "pnpm build && vitest run --config vitest.smoke.config.ts",
publint: "npx publint"
},
types: "./dist/index.d.ts",
main: "./dist/index.js",
module: "./dist/index.js",
bin: {
axiom: "./dist/bin.js"
},
exports: {
"./ai": {
types: "./dist/index.d.ts",
default: "./dist/index.js"
},
"./ai/evals": {
types: "./dist/evals.d.ts",
default: "./dist/evals.js"
},
"./ai/evals/online": {
types: "./dist/evals/online.d.ts",
default: "./dist/evals/online.js"
},
"./ai/scorers": {
types: "./dist/scorers/scorers.d.ts",
default: "./dist/scorers/scorers.js"
},
"./ai/scorers/aggregations": {
types: "./dist/scorers/aggregations.d.ts",
default: "./dist/scorers/aggregations.js"
},
"./ai/config": {
types: "./dist/config.d.ts",
default: "./dist/config.js"
},
"./ai/feedback": {
types: "./dist/feedback.d.ts",
default: "./dist/feedback.js"
}
},
keywords: [
"axiom",
"logging",
"ai",
"otel",
"opentelemetry"
],
repository: {
type: "git",
url: "git+https://github.com/axiomhq/ai.git",
directory: "packages/ai"
},
license: "MIT",
dependencies: {
"@next/env": "^15.4.2",
"@opentelemetry/auto-instrumentations-node": "^0.60.1",
"@opentelemetry/context-async-hooks": "^2.0.1",
"@opentelemetry/exporter-trace-otlp-http": "^0.202.0",
"@opentelemetry/resources": "^2.0.1",
"@opentelemetry/sdk-trace-node": "^2.0.1",
"@opentelemetry/semantic-conventions": "^1.38.0",
"@sinclair/typebox": "^0.34.37",
c12: "^3.3.3",
commander: "^14.0.0",
defu: "^6.1.4",
handlebars: "^4.7.8",
nanoid: "^5.1.5",
open: "^10.1.0",
"vite-tsconfig-paths": "^5.1.4",
vitest: "^4.0.0"
},
peerDependencies: {
"@opentelemetry/api": "^1.9.0",
typescript: ">=5.4",
zod: "^3.25.0 || ^4.0.0"
},
peerDependenciesMeta: {
typescript: {
optional: true
}
},
devDependencies: {
"@ai-sdk/anthropicv1": "npm:@ai-sdk/anthropic@^1.2.12",
"@ai-sdk/anthropicv2": "npm:@ai-sdk/anthropic@^2.0.57",
"@ai-sdk/anthropicv3": "npm:@ai-sdk/anthropic@^3.0.9",
"@ai-sdk/openaiv1": "npm:@ai-sdk/openai@^1.3.24",
"@ai-sdk/openaiv2": "npm:@ai-sdk/openai@^2.0.88",
"@ai-sdk/openaiv3": "npm:@ai-sdk/openai@^3.0.7",
"@ai-sdk/providerv1": "npm:@ai-sdk/provider@^1.1.3",
"@ai-sdk/providerv2": "npm:@ai-sdk/provider@^2.0.1",
"@ai-sdk/providerv3": "npm:@ai-sdk/provider@^3.0.2",
"@opentelemetry/api": "^1.9.0",
"@opentelemetry/core": "^2.0.1",
"@opentelemetry/sdk-trace-base": "^2.0.1",
"@opentelemetry/sdk-trace-node": "^2.0.1",
"@repo/eslint-config": "workspace:*",
"@types/node": "^22.15.29",
"@vitest/coverage-v8": "^4.0.0",
aiv4: "npm:ai@^4.3.19",
aiv5: "npm:ai@^5.0.118",
aiv6: "npm:ai@^6.0.6",
esbuild: "^0.25.8",
eslint: "catalog:",
msw: "^2.12.2",
prettier: "catalog:",
tinyrainbow: "^2.0.0",
tsup: "catalog:",
typedoc: "^0.28.17",
"typedoc-plugin-markdown": "^4.10.0",
typescript: "catalog:",
vitest: "catalog:",
zod: "catalog:"
},
files: [
"dist"
],
packageManager: "pnpm@10.16.1"
};
// src/otel/initAxiomAI.ts
var AXIOM_AI_SCOPE_KEY = Symbol.for("__axiom_ai_scope__");
function extractTracerScope(tracer) {
const tracerAny = tracer;
const name = tracerAny._instrumentationScope?.name || tracerAny.instrumentationLibrary?.name || package_default.name;
const version = tracerAny._instrumentationScope?.version || tracerAny.instrumentationLibrary?.version || package_default.version;
return { name, version };
}
function initAxiomAI(config) {
const newScope = extractTracerScope(config.tracer);
const existingScope = globalThis[AXIOM_AI_SCOPE_KEY];
if (existingScope && existingScope.name === newScope.name && existingScope.version === newScope.version) {
return;
}
if (existingScope) {
console.warn(
`[AxiomAI] initAxiomAI() called multiple times with different scopes. Previous: ${existingScope.name}@${existingScope.version}, New: ${newScope.name}@${newScope.version}`
);
}
globalThis[AXIOM_AI_SCOPE_KEY] = newScope;
if (config.redactionPolicy) {
globalThis[AXIOM_AI_REDACTION_KEY] = config.redactionPolicy;
}
}
function getGlobalTracer() {
const scope = globalThis[AXIOM_AI_SCOPE_KEY];
if (!scope) {
const isDebug = process.env.AXIOM_DEBUG === "true";
if (!isDebug) {
console.warn(
"[AxiomAI] AXIOM_AI_SCOPE_KEY is undefined. This probably means that initAxiomAI() was never called. Make sure to call initAxiomAI({ tracer }) in your instrumentation setup."
);
}
}
let { name, version } = scope || { name: package_default.name, version: package_default.version };
if (!name || !version) {
name = package_default.name;
version = package_default.version;
if (!name || !version) {
name = "axiom";
version = "unknown";
}
}
return trace.getTracer(name, version);
}
function resetAxiomAI() {
globalThis[AXIOM_AI_SCOPE_KEY] = void 0;
globalThis[AXIOM_AI_REDACTION_KEY] = void 0;
}
export {
WITHSPAN_BAGGAGE_KEY,
WITHSPAN_REDACTION_POLICY_KEY,
package_default,
RedactionPolicy,
getRedactionPolicy,
handleMaybeRedactedAttribute,
initAxiomAI,
getGlobalTracer,
resetAxiomAI
};
//# sourceMappingURL=chunk-PU64TWX4.js.map