tokenmeter 0.9.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/LICENSE +21 -0
- package/README.md +346 -0
- package/dist/__tests__/context.test.d.ts +2 -0
- package/dist/__tests__/context.test.d.ts.map +1 -0
- package/dist/__tests__/context.test.js +94 -0
- package/dist/__tests__/context.test.js.map +1 -0
- package/dist/__tests__/elevenlabs.test.d.ts +2 -0
- package/dist/__tests__/elevenlabs.test.d.ts.map +1 -0
- package/dist/__tests__/elevenlabs.test.js +108 -0
- package/dist/__tests__/elevenlabs.test.js.map +1 -0
- package/dist/__tests__/fal.test.d.ts +2 -0
- package/dist/__tests__/fal.test.d.ts.map +1 -0
- package/dist/__tests__/fal.test.js +153 -0
- package/dist/__tests__/fal.test.js.map +1 -0
- package/dist/__tests__/pricing.test.d.ts +2 -0
- package/dist/__tests__/pricing.test.d.ts.map +1 -0
- package/dist/__tests__/pricing.test.js +76 -0
- package/dist/__tests__/pricing.test.js.map +1 -0
- package/dist/__tests__/recorder.test.d.ts +2 -0
- package/dist/__tests__/recorder.test.d.ts.map +1 -0
- package/dist/__tests__/recorder.test.js +133 -0
- package/dist/__tests__/recorder.test.js.map +1 -0
- package/dist/__tests__/storage.test.d.ts +2 -0
- package/dist/__tests__/storage.test.d.ts.map +1 -0
- package/dist/__tests__/storage.test.js +106 -0
- package/dist/__tests__/storage.test.js.map +1 -0
- package/dist/client/index.d.ts +8 -0
- package/dist/client/index.d.ts.map +1 -0
- package/dist/client/index.js +7 -0
- package/dist/client/index.js.map +1 -0
- package/dist/config.d.ts +92 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +166 -0
- package/dist/config.js.map +1 -0
- package/dist/context.d.ts +80 -0
- package/dist/context.d.ts.map +1 -0
- package/dist/context.js +131 -0
- package/dist/context.js.map +1 -0
- package/dist/exporter/PostgresExporter.d.ts +82 -0
- package/dist/exporter/PostgresExporter.d.ts.map +1 -0
- package/dist/exporter/PostgresExporter.js +237 -0
- package/dist/exporter/PostgresExporter.js.map +1 -0
- package/dist/exporter/index.d.ts +8 -0
- package/dist/exporter/index.d.ts.map +1 -0
- package/dist/exporter/index.js +7 -0
- package/dist/exporter/index.js.map +1 -0
- package/dist/index.d.ts +31 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +37 -0
- package/dist/index.js.map +1 -0
- package/dist/instrumentation/proxy.d.ts +26 -0
- package/dist/instrumentation/proxy.d.ts.map +1 -0
- package/dist/instrumentation/proxy.js +337 -0
- package/dist/instrumentation/proxy.js.map +1 -0
- package/dist/instrumentation/strategies/index.d.ts +55 -0
- package/dist/instrumentation/strategies/index.d.ts.map +1 -0
- package/dist/instrumentation/strategies/index.js +429 -0
- package/dist/instrumentation/strategies/index.js.map +1 -0
- package/dist/integrations/express/index.d.ts +137 -0
- package/dist/integrations/express/index.d.ts.map +1 -0
- package/dist/integrations/express/index.js +186 -0
- package/dist/integrations/express/index.js.map +1 -0
- package/dist/integrations/inngest/index.d.ts +222 -0
- package/dist/integrations/inngest/index.d.ts.map +1 -0
- package/dist/integrations/inngest/index.js +223 -0
- package/dist/integrations/inngest/index.js.map +1 -0
- package/dist/integrations/langfuse/index.d.ts +170 -0
- package/dist/integrations/langfuse/index.d.ts.map +1 -0
- package/dist/integrations/langfuse/index.js +225 -0
- package/dist/integrations/langfuse/index.js.map +1 -0
- package/dist/integrations/next/index.d.ts +138 -0
- package/dist/integrations/next/index.d.ts.map +1 -0
- package/dist/integrations/next/index.js +170 -0
- package/dist/integrations/next/index.js.map +1 -0
- package/dist/integrations/nextjs/index.d.ts +198 -0
- package/dist/integrations/nextjs/index.d.ts.map +1 -0
- package/dist/integrations/nextjs/index.js +181 -0
- package/dist/integrations/nextjs/index.js.map +1 -0
- package/dist/integrations/vercel-ai/index.d.ts +288 -0
- package/dist/integrations/vercel-ai/index.d.ts.map +1 -0
- package/dist/integrations/vercel-ai/index.js +260 -0
- package/dist/integrations/vercel-ai/index.js.map +1 -0
- package/dist/logger.d.ts +58 -0
- package/dist/logger.d.ts.map +1 -0
- package/dist/logger.js +89 -0
- package/dist/logger.js.map +1 -0
- package/dist/pricing/catalog.d.ts +10 -0
- package/dist/pricing/catalog.d.ts.map +1 -0
- package/dist/pricing/catalog.js +297 -0
- package/dist/pricing/catalog.js.map +1 -0
- package/dist/pricing/index.d.ts +77 -0
- package/dist/pricing/index.d.ts.map +1 -0
- package/dist/pricing/index.js +251 -0
- package/dist/pricing/index.js.map +1 -0
- package/dist/pricing/manifest.d.ts +156 -0
- package/dist/pricing/manifest.d.ts.map +1 -0
- package/dist/pricing/manifest.js +381 -0
- package/dist/pricing/manifest.js.map +1 -0
- package/dist/pricing/manifest.json +12786 -0
- package/dist/pricing/providers/anthropic.json +253 -0
- package/dist/pricing/providers/bedrock.json +341 -0
- package/dist/pricing/providers/bfl.json +220 -0
- package/dist/pricing/providers/elevenlabs.json +142 -0
- package/dist/pricing/providers/fal.json +15866 -0
- package/dist/pricing/providers/google.json +346 -0
- package/dist/pricing/providers/openai.json +1035 -0
- package/dist/pricing/schema.d.ts +102 -0
- package/dist/pricing/schema.d.ts.map +1 -0
- package/dist/pricing/schema.js +56 -0
- package/dist/pricing/schema.js.map +1 -0
- package/dist/processor/TokenMeterProcessor.d.ts +55 -0
- package/dist/processor/TokenMeterProcessor.d.ts.map +1 -0
- package/dist/processor/TokenMeterProcessor.js +132 -0
- package/dist/processor/TokenMeterProcessor.js.map +1 -0
- package/dist/query/client.d.ts +61 -0
- package/dist/query/client.d.ts.map +1 -0
- package/dist/query/client.js +206 -0
- package/dist/query/client.js.map +1 -0
- package/dist/query/index.d.ts +8 -0
- package/dist/query/index.d.ts.map +1 -0
- package/dist/query/index.js +7 -0
- package/dist/query/index.js.map +1 -0
- package/dist/recorder.d.ts +74 -0
- package/dist/recorder.d.ts.map +1 -0
- package/dist/recorder.js +227 -0
- package/dist/recorder.js.map +1 -0
- package/dist/sdks/anthropic.d.ts +21 -0
- package/dist/sdks/anthropic.d.ts.map +1 -0
- package/dist/sdks/anthropic.js +258 -0
- package/dist/sdks/anthropic.js.map +1 -0
- package/dist/sdks/elevenlabs.d.ts +59 -0
- package/dist/sdks/elevenlabs.d.ts.map +1 -0
- package/dist/sdks/elevenlabs.js +192 -0
- package/dist/sdks/elevenlabs.js.map +1 -0
- package/dist/sdks/fal.d.ts +102 -0
- package/dist/sdks/fal.d.ts.map +1 -0
- package/dist/sdks/fal.js +306 -0
- package/dist/sdks/fal.js.map +1 -0
- package/dist/sdks/openai.d.ts +17 -0
- package/dist/sdks/openai.d.ts.map +1 -0
- package/dist/sdks/openai.js +191 -0
- package/dist/sdks/openai.js.map +1 -0
- package/dist/storage/interface.d.ts +15 -0
- package/dist/storage/interface.d.ts.map +1 -0
- package/dist/storage/interface.js +53 -0
- package/dist/storage/interface.js.map +1 -0
- package/dist/storage/prisma.d.ts +15 -0
- package/dist/storage/prisma.d.ts.map +1 -0
- package/dist/storage/prisma.js +135 -0
- package/dist/storage/prisma.js.map +1 -0
- package/dist/types.d.ts +206 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +45 -0
- package/dist/types.js.map +1 -0
- package/dist/vercel-ai/index.d.ts +89 -0
- package/dist/vercel-ai/index.d.ts.map +1 -0
- package/dist/vercel-ai/index.js +298 -0
- package/dist/vercel-ai/index.js.map +1 -0
- package/package.json +119 -0
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
import type { CostEvent } from "../../types.js";
|
|
2
|
+
/**
|
|
3
|
+
* Langfuse client interface - minimal types to avoid hard dependency
|
|
4
|
+
*/
|
|
5
|
+
export interface LangfuseClient {
|
|
6
|
+
trace: (params: TraceParams) => LangfuseTrace;
|
|
7
|
+
flushAsync: () => Promise<void>;
|
|
8
|
+
shutdownAsync: () => Promise<void>;
|
|
9
|
+
}
|
|
10
|
+
export interface TraceParams {
|
|
11
|
+
id?: string;
|
|
12
|
+
name?: string;
|
|
13
|
+
userId?: string;
|
|
14
|
+
sessionId?: string;
|
|
15
|
+
metadata?: Record<string, unknown>;
|
|
16
|
+
input?: unknown;
|
|
17
|
+
output?: unknown;
|
|
18
|
+
tags?: string[];
|
|
19
|
+
}
|
|
20
|
+
export interface LangfuseTrace {
|
|
21
|
+
id: string;
|
|
22
|
+
generation: (params: GenerationParams) => LangfuseGeneration;
|
|
23
|
+
span: (params: SpanParams) => LangfuseSpan;
|
|
24
|
+
update: (params: Partial<TraceParams>) => void;
|
|
25
|
+
}
|
|
26
|
+
export interface GenerationParams {
|
|
27
|
+
name?: string;
|
|
28
|
+
model?: string;
|
|
29
|
+
modelParameters?: Record<string, unknown>;
|
|
30
|
+
input?: unknown;
|
|
31
|
+
output?: unknown;
|
|
32
|
+
metadata?: Record<string, unknown>;
|
|
33
|
+
startTime?: Date;
|
|
34
|
+
endTime?: Date;
|
|
35
|
+
usageDetails?: Record<string, number>;
|
|
36
|
+
costDetails?: Record<string, number>;
|
|
37
|
+
}
|
|
38
|
+
export interface LangfuseGeneration {
|
|
39
|
+
id: string;
|
|
40
|
+
update: (params: Partial<GenerationParams>) => void;
|
|
41
|
+
end: (params?: Partial<GenerationParams>) => void;
|
|
42
|
+
}
|
|
43
|
+
export interface SpanParams {
|
|
44
|
+
name?: string;
|
|
45
|
+
input?: unknown;
|
|
46
|
+
output?: unknown;
|
|
47
|
+
metadata?: Record<string, unknown>;
|
|
48
|
+
startTime?: Date;
|
|
49
|
+
endTime?: Date;
|
|
50
|
+
}
|
|
51
|
+
export interface LangfuseSpan {
|
|
52
|
+
id: string;
|
|
53
|
+
update: (params: Partial<SpanParams>) => void;
|
|
54
|
+
end: (params?: Partial<SpanParams>) => void;
|
|
55
|
+
generation: (params: GenerationParams) => LangfuseGeneration;
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Configuration for the Langfuse exporter
|
|
59
|
+
*/
|
|
60
|
+
export interface LangfuseExporterConfig {
|
|
61
|
+
/**
|
|
62
|
+
* The Langfuse client instance.
|
|
63
|
+
* Create one with: `new Langfuse({ publicKey, secretKey })`
|
|
64
|
+
*/
|
|
65
|
+
client: LangfuseClient;
|
|
66
|
+
/**
|
|
67
|
+
* Whether to create a trace per workflow or per event.
|
|
68
|
+
* - "workflow": One trace per workflowId, with generations as children
|
|
69
|
+
* - "event": One trace per cost event
|
|
70
|
+
* Default: "workflow"
|
|
71
|
+
*/
|
|
72
|
+
traceMode?: "workflow" | "event";
|
|
73
|
+
/**
|
|
74
|
+
* Optional: Map tokenmeter identifiers to Langfuse user IDs.
|
|
75
|
+
* By default, the identifier is used as the userId.
|
|
76
|
+
*/
|
|
77
|
+
getUserId?: (event: CostEvent) => string | undefined;
|
|
78
|
+
/**
|
|
79
|
+
* Optional: Map tokenmeter workflow IDs to Langfuse session IDs.
|
|
80
|
+
* By default, the workflowId is used as the sessionId.
|
|
81
|
+
*/
|
|
82
|
+
getSessionId?: (event: CostEvent) => string | undefined;
|
|
83
|
+
/**
|
|
84
|
+
* Optional: Add custom tags to traces.
|
|
85
|
+
*/
|
|
86
|
+
getTags?: (event: CostEvent) => string[];
|
|
87
|
+
/**
|
|
88
|
+
* Optional: Transform metadata before sending to Langfuse.
|
|
89
|
+
*/
|
|
90
|
+
transformMetadata?: (event: CostEvent) => Record<string, unknown> | undefined;
|
|
91
|
+
/**
|
|
92
|
+
* Whether to flush after each export. Default: false
|
|
93
|
+
*/
|
|
94
|
+
flushOnExport?: boolean;
|
|
95
|
+
}
|
|
96
|
+
/**
|
|
97
|
+
* Export tokenmeter cost events to Langfuse.
|
|
98
|
+
*
|
|
99
|
+
* @param events - Array of cost events to export
|
|
100
|
+
* @param config - Langfuse exporter configuration
|
|
101
|
+
*
|
|
102
|
+
* @example
|
|
103
|
+
* ```typescript
|
|
104
|
+
* import { Langfuse } from 'langfuse';
|
|
105
|
+
* import { exportToLangfuse } from 'tokenmeter/langfuse';
|
|
106
|
+
*
|
|
107
|
+
* const langfuse = new Langfuse({
|
|
108
|
+
* publicKey: process.env.LANGFUSE_PUBLIC_KEY,
|
|
109
|
+
* secretKey: process.env.LANGFUSE_SECRET_KEY,
|
|
110
|
+
* });
|
|
111
|
+
*
|
|
112
|
+
* // Export events after a workflow completes
|
|
113
|
+
* const events = getContextEvents();
|
|
114
|
+
* await exportToLangfuse(events, { client: langfuse });
|
|
115
|
+
* ```
|
|
116
|
+
*/
|
|
117
|
+
export declare function exportToLangfuse(events: CostEvent[], config: LangfuseExporterConfig): Promise<void>;
|
|
118
|
+
/**
|
|
119
|
+
* Create a storage adapter that automatically exports to Langfuse.
|
|
120
|
+
*
|
|
121
|
+
* This wraps another storage adapter and exports events to Langfuse
|
|
122
|
+
* in addition to the primary storage.
|
|
123
|
+
*
|
|
124
|
+
* @example
|
|
125
|
+
* ```typescript
|
|
126
|
+
* import { Langfuse } from 'langfuse';
|
|
127
|
+
* import { init, PrismaStorageAdapter } from 'tokenmeter';
|
|
128
|
+
* import { createLangfuseStorageAdapter } from 'tokenmeter/langfuse';
|
|
129
|
+
*
|
|
130
|
+
* const langfuse = new Langfuse({
|
|
131
|
+
* publicKey: process.env.LANGFUSE_PUBLIC_KEY,
|
|
132
|
+
* secretKey: process.env.LANGFUSE_SECRET_KEY,
|
|
133
|
+
* });
|
|
134
|
+
*
|
|
135
|
+
* const primaryStorage = new PrismaStorageAdapter(process.env.DATABASE_URL);
|
|
136
|
+
*
|
|
137
|
+
* init({
|
|
138
|
+
* storage: createLangfuseStorageAdapter(primaryStorage, {
|
|
139
|
+
* client: langfuse,
|
|
140
|
+
* traceMode: 'workflow',
|
|
141
|
+
* }),
|
|
142
|
+
* });
|
|
143
|
+
* ```
|
|
144
|
+
*/
|
|
145
|
+
export declare function createLangfuseStorageAdapter(primaryAdapter: {
|
|
146
|
+
writeEvent: (event: CostEvent) => Promise<void>;
|
|
147
|
+
writeBatch: (events: CostEvent[]) => Promise<void>;
|
|
148
|
+
query: (params: unknown) => Promise<{
|
|
149
|
+
totalCost: number;
|
|
150
|
+
events: CostEvent[];
|
|
151
|
+
}>;
|
|
152
|
+
disconnect: () => Promise<void>;
|
|
153
|
+
}, config: LangfuseExporterConfig): {
|
|
154
|
+
writeEvent(event: CostEvent): Promise<void>;
|
|
155
|
+
writeBatch(events: CostEvent[]): Promise<void>;
|
|
156
|
+
query(params: unknown): Promise<{
|
|
157
|
+
totalCost: number;
|
|
158
|
+
events: CostEvent[];
|
|
159
|
+
}>;
|
|
160
|
+
disconnect(): Promise<void>;
|
|
161
|
+
};
|
|
162
|
+
/**
|
|
163
|
+
* Clear the workflow traces cache for a specific config.
|
|
164
|
+
* Call this when switching contexts or at the end of a request.
|
|
165
|
+
*
|
|
166
|
+
* @param config - The Langfuse exporter config to clear traces for
|
|
167
|
+
*/
|
|
168
|
+
export declare function clearWorkflowTraces(config: LangfuseExporterConfig): void;
|
|
169
|
+
export default exportToLangfuse;
|
|
170
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/integrations/langfuse/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,225 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Active workflow traces cache - stored per-config to avoid cross-request contamination
|
|
3
|
+
* Uses WeakMap with config as key so cache is garbage collected with the config
|
|
4
|
+
*/
|
|
5
|
+
const workflowTracesCache = new WeakMap();
|
|
6
|
+
/**
|
|
7
|
+
* Get or create the workflow traces map for a given config
|
|
8
|
+
*/
|
|
9
|
+
function getWorkflowTracesMap(config) {
|
|
10
|
+
let traces = workflowTracesCache.get(config);
|
|
11
|
+
if (!traces) {
|
|
12
|
+
traces = new Map();
|
|
13
|
+
workflowTracesCache.set(config, traces);
|
|
14
|
+
}
|
|
15
|
+
return traces;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Export tokenmeter cost events to Langfuse.
|
|
19
|
+
*
|
|
20
|
+
* @param events - Array of cost events to export
|
|
21
|
+
* @param config - Langfuse exporter configuration
|
|
22
|
+
*
|
|
23
|
+
* @example
|
|
24
|
+
* ```typescript
|
|
25
|
+
* import { Langfuse } from 'langfuse';
|
|
26
|
+
* import { exportToLangfuse } from 'tokenmeter/langfuse';
|
|
27
|
+
*
|
|
28
|
+
* const langfuse = new Langfuse({
|
|
29
|
+
* publicKey: process.env.LANGFUSE_PUBLIC_KEY,
|
|
30
|
+
* secretKey: process.env.LANGFUSE_SECRET_KEY,
|
|
31
|
+
* });
|
|
32
|
+
*
|
|
33
|
+
* // Export events after a workflow completes
|
|
34
|
+
* const events = getContextEvents();
|
|
35
|
+
* await exportToLangfuse(events, { client: langfuse });
|
|
36
|
+
* ```
|
|
37
|
+
*/
|
|
38
|
+
export async function exportToLangfuse(events, config) {
|
|
39
|
+
const { client, traceMode = "workflow" } = config;
|
|
40
|
+
if (traceMode === "workflow") {
|
|
41
|
+
await exportAsWorkflows(events, config);
|
|
42
|
+
}
|
|
43
|
+
else {
|
|
44
|
+
await exportAsEvents(events, config);
|
|
45
|
+
}
|
|
46
|
+
if (config.flushOnExport) {
|
|
47
|
+
await client.flushAsync();
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Export events grouped by workflow
|
|
52
|
+
*/
|
|
53
|
+
async function exportAsWorkflows(events, config) {
|
|
54
|
+
const { client } = config;
|
|
55
|
+
const workflowTraces = getWorkflowTracesMap(config);
|
|
56
|
+
// Group events by workflowId
|
|
57
|
+
const byWorkflow = new Map();
|
|
58
|
+
for (const event of events) {
|
|
59
|
+
const workflowId = event.workflowId || "default";
|
|
60
|
+
const existing = byWorkflow.get(workflowId) || [];
|
|
61
|
+
existing.push(event);
|
|
62
|
+
byWorkflow.set(workflowId, existing);
|
|
63
|
+
}
|
|
64
|
+
// Create traces and generations for each workflow
|
|
65
|
+
for (const [workflowId, workflowEvents] of byWorkflow) {
|
|
66
|
+
// Get or create trace for this workflow
|
|
67
|
+
let trace = workflowTraces.get(workflowId);
|
|
68
|
+
if (!trace) {
|
|
69
|
+
const firstEvent = workflowEvents[0];
|
|
70
|
+
if (!firstEvent)
|
|
71
|
+
continue;
|
|
72
|
+
trace = client.trace({
|
|
73
|
+
id: workflowId,
|
|
74
|
+
name: firstEvent.workflowType || "tokenmeter-workflow",
|
|
75
|
+
userId: config.getUserId?.(firstEvent) ?? firstEvent.identifier,
|
|
76
|
+
sessionId: config.getSessionId?.(firstEvent) ?? workflowId,
|
|
77
|
+
metadata: {
|
|
78
|
+
source: "tokenmeter",
|
|
79
|
+
identifier: firstEvent.identifier,
|
|
80
|
+
secondaryIdentifier: firstEvent.secondaryIdentifier,
|
|
81
|
+
},
|
|
82
|
+
tags: config.getTags?.(firstEvent) ?? ["tokenmeter"],
|
|
83
|
+
});
|
|
84
|
+
workflowTraces.set(workflowId, trace);
|
|
85
|
+
}
|
|
86
|
+
// Add generations for each event
|
|
87
|
+
for (const event of workflowEvents) {
|
|
88
|
+
const metadata = config.transformMetadata?.(event) ?? event.metadata;
|
|
89
|
+
trace.generation({
|
|
90
|
+
name: `${event.provider}/${event.model}`,
|
|
91
|
+
model: event.model,
|
|
92
|
+
startTime: event.createdAt,
|
|
93
|
+
endTime: event.createdAt,
|
|
94
|
+
metadata: {
|
|
95
|
+
...metadata,
|
|
96
|
+
provider: event.provider,
|
|
97
|
+
operation: event.operation,
|
|
98
|
+
status: event.status,
|
|
99
|
+
billable: event.billable,
|
|
100
|
+
errorMessage: event.errorMessage,
|
|
101
|
+
requestId: event.requestId,
|
|
102
|
+
},
|
|
103
|
+
usageDetails: {
|
|
104
|
+
input: event.inputTokens ?? 0,
|
|
105
|
+
output: event.outputTokens ?? 0,
|
|
106
|
+
},
|
|
107
|
+
costDetails: {
|
|
108
|
+
total: event.costUsd,
|
|
109
|
+
},
|
|
110
|
+
});
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
/**
|
|
115
|
+
* Export each event as a separate trace
|
|
116
|
+
*/
|
|
117
|
+
async function exportAsEvents(events, config) {
|
|
118
|
+
const { client } = config;
|
|
119
|
+
for (const event of events) {
|
|
120
|
+
const metadata = config.transformMetadata?.(event) ?? event.metadata;
|
|
121
|
+
const trace = client.trace({
|
|
122
|
+
id: event.id || crypto.randomUUID(),
|
|
123
|
+
name: `${event.provider}/${event.model}`,
|
|
124
|
+
userId: config.getUserId?.(event) ?? event.identifier,
|
|
125
|
+
sessionId: config.getSessionId?.(event) ?? event.workflowId,
|
|
126
|
+
metadata: {
|
|
127
|
+
source: "tokenmeter",
|
|
128
|
+
identifier: event.identifier,
|
|
129
|
+
secondaryIdentifier: event.secondaryIdentifier,
|
|
130
|
+
workflowType: event.workflowType,
|
|
131
|
+
},
|
|
132
|
+
tags: config.getTags?.(event) ?? ["tokenmeter"],
|
|
133
|
+
});
|
|
134
|
+
trace.generation({
|
|
135
|
+
name: event.operation || "generation",
|
|
136
|
+
model: event.model,
|
|
137
|
+
startTime: event.createdAt,
|
|
138
|
+
endTime: event.createdAt,
|
|
139
|
+
metadata: {
|
|
140
|
+
...metadata,
|
|
141
|
+
provider: event.provider,
|
|
142
|
+
status: event.status,
|
|
143
|
+
billable: event.billable,
|
|
144
|
+
errorMessage: event.errorMessage,
|
|
145
|
+
requestId: event.requestId,
|
|
146
|
+
},
|
|
147
|
+
usageDetails: {
|
|
148
|
+
input: event.inputTokens ?? 0,
|
|
149
|
+
output: event.outputTokens ?? 0,
|
|
150
|
+
},
|
|
151
|
+
costDetails: {
|
|
152
|
+
total: event.costUsd,
|
|
153
|
+
},
|
|
154
|
+
});
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
/**
|
|
158
|
+
* Create a storage adapter that automatically exports to Langfuse.
|
|
159
|
+
*
|
|
160
|
+
* This wraps another storage adapter and exports events to Langfuse
|
|
161
|
+
* in addition to the primary storage.
|
|
162
|
+
*
|
|
163
|
+
* @example
|
|
164
|
+
* ```typescript
|
|
165
|
+
* import { Langfuse } from 'langfuse';
|
|
166
|
+
* import { init, PrismaStorageAdapter } from 'tokenmeter';
|
|
167
|
+
* import { createLangfuseStorageAdapter } from 'tokenmeter/langfuse';
|
|
168
|
+
*
|
|
169
|
+
* const langfuse = new Langfuse({
|
|
170
|
+
* publicKey: process.env.LANGFUSE_PUBLIC_KEY,
|
|
171
|
+
* secretKey: process.env.LANGFUSE_SECRET_KEY,
|
|
172
|
+
* });
|
|
173
|
+
*
|
|
174
|
+
* const primaryStorage = new PrismaStorageAdapter(process.env.DATABASE_URL);
|
|
175
|
+
*
|
|
176
|
+
* init({
|
|
177
|
+
* storage: createLangfuseStorageAdapter(primaryStorage, {
|
|
178
|
+
* client: langfuse,
|
|
179
|
+
* traceMode: 'workflow',
|
|
180
|
+
* }),
|
|
181
|
+
* });
|
|
182
|
+
* ```
|
|
183
|
+
*/
|
|
184
|
+
export function createLangfuseStorageAdapter(primaryAdapter, config) {
|
|
185
|
+
return {
|
|
186
|
+
async writeEvent(event) {
|
|
187
|
+
// Write to primary storage
|
|
188
|
+
await primaryAdapter.writeEvent(event);
|
|
189
|
+
// Export to Langfuse
|
|
190
|
+
await exportToLangfuse([event], config);
|
|
191
|
+
},
|
|
192
|
+
async writeBatch(events) {
|
|
193
|
+
// Write to primary storage
|
|
194
|
+
await primaryAdapter.writeBatch(events);
|
|
195
|
+
// Export to Langfuse
|
|
196
|
+
await exportToLangfuse(events, config);
|
|
197
|
+
},
|
|
198
|
+
async query(params) {
|
|
199
|
+
// Query from primary storage only
|
|
200
|
+
return primaryAdapter.query(params);
|
|
201
|
+
},
|
|
202
|
+
async disconnect() {
|
|
203
|
+
// Flush Langfuse before disconnecting
|
|
204
|
+
await config.client.flushAsync();
|
|
205
|
+
// Clear workflow traces cache for this config
|
|
206
|
+
clearWorkflowTraces(config);
|
|
207
|
+
// Disconnect primary storage
|
|
208
|
+
await primaryAdapter.disconnect();
|
|
209
|
+
},
|
|
210
|
+
};
|
|
211
|
+
}
|
|
212
|
+
/**
|
|
213
|
+
* Clear the workflow traces cache for a specific config.
|
|
214
|
+
* Call this when switching contexts or at the end of a request.
|
|
215
|
+
*
|
|
216
|
+
* @param config - The Langfuse exporter config to clear traces for
|
|
217
|
+
*/
|
|
218
|
+
export function clearWorkflowTraces(config) {
|
|
219
|
+
const traces = workflowTracesCache.get(config);
|
|
220
|
+
if (traces) {
|
|
221
|
+
traces.clear();
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
export default exportToLangfuse;
|
|
225
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/integrations/langfuse/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Next.js Integration
|
|
3
|
+
*
|
|
4
|
+
* Provides helpers for App Router route handlers to automatically
|
|
5
|
+
* set up cost tracking context.
|
|
6
|
+
*/
|
|
7
|
+
/**
|
|
8
|
+
* Context for tokenmeter tracking
|
|
9
|
+
*/
|
|
10
|
+
export interface TokenMeterContext {
|
|
11
|
+
/** User ID for cost attribution */
|
|
12
|
+
userId?: string;
|
|
13
|
+
/** Organization ID for cost attribution */
|
|
14
|
+
orgId?: string;
|
|
15
|
+
/** Workflow ID for grouping related calls */
|
|
16
|
+
workflowId?: string;
|
|
17
|
+
/** Additional metadata */
|
|
18
|
+
metadata?: Record<string, string>;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Next.js App Router route handler type
|
|
22
|
+
*/
|
|
23
|
+
export type RouteHandler = (request: Request, context?: {
|
|
24
|
+
params?: Promise<Record<string, string>>;
|
|
25
|
+
}) => Response | Promise<Response>;
|
|
26
|
+
/**
|
|
27
|
+
* Function to extract context from a request
|
|
28
|
+
*/
|
|
29
|
+
export type ContextExtractor = (request: Request) => TokenMeterContext | Promise<TokenMeterContext>;
|
|
30
|
+
/**
|
|
31
|
+
* Options for withTokenmeter wrapper
|
|
32
|
+
*/
|
|
33
|
+
export interface WithTokenmeterOptions {
|
|
34
|
+
/** Custom context extractor function */
|
|
35
|
+
getContext?: ContextExtractor;
|
|
36
|
+
/** Header name for user ID (default: x-user-id) */
|
|
37
|
+
userIdHeader?: string;
|
|
38
|
+
/** Header name for org ID (default: x-org-id) */
|
|
39
|
+
orgIdHeader?: string;
|
|
40
|
+
/** Header name for workflow ID (default: x-request-id) */
|
|
41
|
+
workflowIdHeader?: string;
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Wrap a Next.js App Router route handler with tokenmeter context.
|
|
45
|
+
*
|
|
46
|
+
* All AI calls made with `monitor()`-wrapped clients within the handler
|
|
47
|
+
* will automatically be attributed to the user/org extracted from the request.
|
|
48
|
+
*
|
|
49
|
+
* @example
|
|
50
|
+
* ```typescript
|
|
51
|
+
* // app/api/chat/route.ts
|
|
52
|
+
* import { withTokenmeter } from 'tokenmeter/next';
|
|
53
|
+
* import { monitor } from 'tokenmeter';
|
|
54
|
+
* import OpenAI from 'openai';
|
|
55
|
+
*
|
|
56
|
+
* const openai = monitor(new OpenAI());
|
|
57
|
+
*
|
|
58
|
+
* export const POST = withTokenmeter(async (req) => {
|
|
59
|
+
* const { message } = await req.json();
|
|
60
|
+
*
|
|
61
|
+
* // This call is automatically attributed to the user
|
|
62
|
+
* const result = await openai.chat.completions.create({
|
|
63
|
+
* model: 'gpt-4o',
|
|
64
|
+
* messages: [{ role: 'user', content: message }],
|
|
65
|
+
* });
|
|
66
|
+
*
|
|
67
|
+
* return Response.json({ reply: result.choices[0].message.content });
|
|
68
|
+
* });
|
|
69
|
+
* ```
|
|
70
|
+
*
|
|
71
|
+
* @example
|
|
72
|
+
* ```typescript
|
|
73
|
+
* // With custom context extraction (e.g., from auth)
|
|
74
|
+
* import { auth } from '@clerk/nextjs/server';
|
|
75
|
+
*
|
|
76
|
+
* export const POST = withTokenmeter(
|
|
77
|
+
* async (req) => {
|
|
78
|
+
* // Handler code
|
|
79
|
+
* },
|
|
80
|
+
* {
|
|
81
|
+
* getContext: async (req) => {
|
|
82
|
+
* const { userId, orgId } = await auth();
|
|
83
|
+
* return { userId, orgId };
|
|
84
|
+
* },
|
|
85
|
+
* }
|
|
86
|
+
* );
|
|
87
|
+
* ```
|
|
88
|
+
*/
|
|
89
|
+
export declare function withTokenmeter(handler: RouteHandler, options?: WithTokenmeterOptions): RouteHandler;
|
|
90
|
+
/**
|
|
91
|
+
* Create a reusable tokenmeter wrapper with preset options.
|
|
92
|
+
*
|
|
93
|
+
* Useful when you have common context extraction logic across multiple routes.
|
|
94
|
+
*
|
|
95
|
+
* @example
|
|
96
|
+
* ```typescript
|
|
97
|
+
* // lib/tokenmeter.ts
|
|
98
|
+
* import { createTokenmeterWrapper } from 'tokenmeter/next';
|
|
99
|
+
* import { auth } from '@clerk/nextjs/server';
|
|
100
|
+
*
|
|
101
|
+
* export const withCostTracking = createTokenmeterWrapper({
|
|
102
|
+
* getContext: async (req) => {
|
|
103
|
+
* const { userId, orgId } = await auth();
|
|
104
|
+
* return { userId, orgId };
|
|
105
|
+
* },
|
|
106
|
+
* });
|
|
107
|
+
*
|
|
108
|
+
* // app/api/chat/route.ts
|
|
109
|
+
* import { withCostTracking } from '@/lib/tokenmeter';
|
|
110
|
+
*
|
|
111
|
+
* export const POST = withCostTracking(async (req) => {
|
|
112
|
+
* // ...
|
|
113
|
+
* });
|
|
114
|
+
* ```
|
|
115
|
+
*/
|
|
116
|
+
export declare function createTokenmeterWrapper(defaultOptions: WithTokenmeterOptions): (handler: RouteHandler, options?: WithTokenmeterOptions) => RouteHandler;
|
|
117
|
+
/**
|
|
118
|
+
* Helper to extract common headers from a request
|
|
119
|
+
*/
|
|
120
|
+
export declare const headerExtractors: {
|
|
121
|
+
/**
|
|
122
|
+
* Extract user ID from x-user-id header
|
|
123
|
+
*/
|
|
124
|
+
userId: (request: Request) => string | undefined;
|
|
125
|
+
/**
|
|
126
|
+
* Extract org ID from x-org-id header
|
|
127
|
+
*/
|
|
128
|
+
orgId: (request: Request) => string | undefined;
|
|
129
|
+
/**
|
|
130
|
+
* Extract API key from Authorization header (Bearer token)
|
|
131
|
+
*/
|
|
132
|
+
apiKey: (request: Request) => string | undefined;
|
|
133
|
+
/**
|
|
134
|
+
* Extract request ID from x-request-id header
|
|
135
|
+
*/
|
|
136
|
+
requestId: (request: Request) => string | undefined;
|
|
137
|
+
};
|
|
138
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/integrations/next/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAKH;;GAEG;AACH,MAAM,WAAW,iBAAiB;IAChC,mCAAmC;IACnC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,2CAA2C;IAC3C,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,6CAA6C;IAC7C,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,0BAA0B;IAC1B,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CACnC;AAED;;GAEG;AACH,MAAM,MAAM,YAAY,GAAG,CACzB,OAAO,EAAE,OAAO,EAChB,OAAO,CAAC,EAAE;IAAE,MAAM,CAAC,EAAE,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAA;CAAE,KACnD,QAAQ,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAC;AAElC;;GAEG;AACH,MAAM,MAAM,gBAAgB,GAAG,CAC7B,OAAO,EAAE,OAAO,KACb,iBAAiB,GAAG,OAAO,CAAC,iBAAiB,CAAC,CAAC;AAEpD;;GAEG;AACH,MAAM,WAAW,qBAAqB;IACpC,wCAAwC;IACxC,UAAU,CAAC,EAAE,gBAAgB,CAAC;IAC9B,mDAAmD;IACnD,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,iDAAiD;IACjD,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,0DAA0D;IAC1D,gBAAgB,CAAC,EAAE,MAAM,CAAC;CAC3B;AA6CD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6CG;AACH,wBAAgB,cAAc,CAC5B,OAAO,EAAE,YAAY,EACrB,OAAO,GAAE,qBAA0B,GAClC,YAAY,CAkBd;AAED;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,wBAAgB,uBAAuB,CACrC,cAAc,EAAE,qBAAqB,GACpC,CAAC,OAAO,EAAE,YAAY,EAAE,OAAO,CAAC,EAAE,qBAAqB,KAAK,YAAY,CAI1E;AAED;;GAEG;AACH,eAAO,MAAM,gBAAgB;IAC3B;;OAEG;sBACe,OAAO,KAAG,MAAM,GAAG,SAAS;IAI9C;;OAEG;qBACc,OAAO,KAAG,MAAM,GAAG,SAAS;IAI7C;;OAEG;sBACe,OAAO,KAAG,MAAM,GAAG,SAAS;IAQ9C;;OAEG;yBACkB,OAAO,KAAG,MAAM,GAAG,SAAS;CAGlD,CAAC"}
|