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.
Files changed (159) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +346 -0
  3. package/dist/__tests__/context.test.d.ts +2 -0
  4. package/dist/__tests__/context.test.d.ts.map +1 -0
  5. package/dist/__tests__/context.test.js +94 -0
  6. package/dist/__tests__/context.test.js.map +1 -0
  7. package/dist/__tests__/elevenlabs.test.d.ts +2 -0
  8. package/dist/__tests__/elevenlabs.test.d.ts.map +1 -0
  9. package/dist/__tests__/elevenlabs.test.js +108 -0
  10. package/dist/__tests__/elevenlabs.test.js.map +1 -0
  11. package/dist/__tests__/fal.test.d.ts +2 -0
  12. package/dist/__tests__/fal.test.d.ts.map +1 -0
  13. package/dist/__tests__/fal.test.js +153 -0
  14. package/dist/__tests__/fal.test.js.map +1 -0
  15. package/dist/__tests__/pricing.test.d.ts +2 -0
  16. package/dist/__tests__/pricing.test.d.ts.map +1 -0
  17. package/dist/__tests__/pricing.test.js +76 -0
  18. package/dist/__tests__/pricing.test.js.map +1 -0
  19. package/dist/__tests__/recorder.test.d.ts +2 -0
  20. package/dist/__tests__/recorder.test.d.ts.map +1 -0
  21. package/dist/__tests__/recorder.test.js +133 -0
  22. package/dist/__tests__/recorder.test.js.map +1 -0
  23. package/dist/__tests__/storage.test.d.ts +2 -0
  24. package/dist/__tests__/storage.test.d.ts.map +1 -0
  25. package/dist/__tests__/storage.test.js +106 -0
  26. package/dist/__tests__/storage.test.js.map +1 -0
  27. package/dist/client/index.d.ts +8 -0
  28. package/dist/client/index.d.ts.map +1 -0
  29. package/dist/client/index.js +7 -0
  30. package/dist/client/index.js.map +1 -0
  31. package/dist/config.d.ts +92 -0
  32. package/dist/config.d.ts.map +1 -0
  33. package/dist/config.js +166 -0
  34. package/dist/config.js.map +1 -0
  35. package/dist/context.d.ts +80 -0
  36. package/dist/context.d.ts.map +1 -0
  37. package/dist/context.js +131 -0
  38. package/dist/context.js.map +1 -0
  39. package/dist/exporter/PostgresExporter.d.ts +82 -0
  40. package/dist/exporter/PostgresExporter.d.ts.map +1 -0
  41. package/dist/exporter/PostgresExporter.js +237 -0
  42. package/dist/exporter/PostgresExporter.js.map +1 -0
  43. package/dist/exporter/index.d.ts +8 -0
  44. package/dist/exporter/index.d.ts.map +1 -0
  45. package/dist/exporter/index.js +7 -0
  46. package/dist/exporter/index.js.map +1 -0
  47. package/dist/index.d.ts +31 -0
  48. package/dist/index.d.ts.map +1 -0
  49. package/dist/index.js +37 -0
  50. package/dist/index.js.map +1 -0
  51. package/dist/instrumentation/proxy.d.ts +26 -0
  52. package/dist/instrumentation/proxy.d.ts.map +1 -0
  53. package/dist/instrumentation/proxy.js +337 -0
  54. package/dist/instrumentation/proxy.js.map +1 -0
  55. package/dist/instrumentation/strategies/index.d.ts +55 -0
  56. package/dist/instrumentation/strategies/index.d.ts.map +1 -0
  57. package/dist/instrumentation/strategies/index.js +429 -0
  58. package/dist/instrumentation/strategies/index.js.map +1 -0
  59. package/dist/integrations/express/index.d.ts +137 -0
  60. package/dist/integrations/express/index.d.ts.map +1 -0
  61. package/dist/integrations/express/index.js +186 -0
  62. package/dist/integrations/express/index.js.map +1 -0
  63. package/dist/integrations/inngest/index.d.ts +222 -0
  64. package/dist/integrations/inngest/index.d.ts.map +1 -0
  65. package/dist/integrations/inngest/index.js +223 -0
  66. package/dist/integrations/inngest/index.js.map +1 -0
  67. package/dist/integrations/langfuse/index.d.ts +170 -0
  68. package/dist/integrations/langfuse/index.d.ts.map +1 -0
  69. package/dist/integrations/langfuse/index.js +225 -0
  70. package/dist/integrations/langfuse/index.js.map +1 -0
  71. package/dist/integrations/next/index.d.ts +138 -0
  72. package/dist/integrations/next/index.d.ts.map +1 -0
  73. package/dist/integrations/next/index.js +170 -0
  74. package/dist/integrations/next/index.js.map +1 -0
  75. package/dist/integrations/nextjs/index.d.ts +198 -0
  76. package/dist/integrations/nextjs/index.d.ts.map +1 -0
  77. package/dist/integrations/nextjs/index.js +181 -0
  78. package/dist/integrations/nextjs/index.js.map +1 -0
  79. package/dist/integrations/vercel-ai/index.d.ts +288 -0
  80. package/dist/integrations/vercel-ai/index.d.ts.map +1 -0
  81. package/dist/integrations/vercel-ai/index.js +260 -0
  82. package/dist/integrations/vercel-ai/index.js.map +1 -0
  83. package/dist/logger.d.ts +58 -0
  84. package/dist/logger.d.ts.map +1 -0
  85. package/dist/logger.js +89 -0
  86. package/dist/logger.js.map +1 -0
  87. package/dist/pricing/catalog.d.ts +10 -0
  88. package/dist/pricing/catalog.d.ts.map +1 -0
  89. package/dist/pricing/catalog.js +297 -0
  90. package/dist/pricing/catalog.js.map +1 -0
  91. package/dist/pricing/index.d.ts +77 -0
  92. package/dist/pricing/index.d.ts.map +1 -0
  93. package/dist/pricing/index.js +251 -0
  94. package/dist/pricing/index.js.map +1 -0
  95. package/dist/pricing/manifest.d.ts +156 -0
  96. package/dist/pricing/manifest.d.ts.map +1 -0
  97. package/dist/pricing/manifest.js +381 -0
  98. package/dist/pricing/manifest.js.map +1 -0
  99. package/dist/pricing/manifest.json +12786 -0
  100. package/dist/pricing/providers/anthropic.json +253 -0
  101. package/dist/pricing/providers/bedrock.json +341 -0
  102. package/dist/pricing/providers/bfl.json +220 -0
  103. package/dist/pricing/providers/elevenlabs.json +142 -0
  104. package/dist/pricing/providers/fal.json +15866 -0
  105. package/dist/pricing/providers/google.json +346 -0
  106. package/dist/pricing/providers/openai.json +1035 -0
  107. package/dist/pricing/schema.d.ts +102 -0
  108. package/dist/pricing/schema.d.ts.map +1 -0
  109. package/dist/pricing/schema.js +56 -0
  110. package/dist/pricing/schema.js.map +1 -0
  111. package/dist/processor/TokenMeterProcessor.d.ts +55 -0
  112. package/dist/processor/TokenMeterProcessor.d.ts.map +1 -0
  113. package/dist/processor/TokenMeterProcessor.js +132 -0
  114. package/dist/processor/TokenMeterProcessor.js.map +1 -0
  115. package/dist/query/client.d.ts +61 -0
  116. package/dist/query/client.d.ts.map +1 -0
  117. package/dist/query/client.js +206 -0
  118. package/dist/query/client.js.map +1 -0
  119. package/dist/query/index.d.ts +8 -0
  120. package/dist/query/index.d.ts.map +1 -0
  121. package/dist/query/index.js +7 -0
  122. package/dist/query/index.js.map +1 -0
  123. package/dist/recorder.d.ts +74 -0
  124. package/dist/recorder.d.ts.map +1 -0
  125. package/dist/recorder.js +227 -0
  126. package/dist/recorder.js.map +1 -0
  127. package/dist/sdks/anthropic.d.ts +21 -0
  128. package/dist/sdks/anthropic.d.ts.map +1 -0
  129. package/dist/sdks/anthropic.js +258 -0
  130. package/dist/sdks/anthropic.js.map +1 -0
  131. package/dist/sdks/elevenlabs.d.ts +59 -0
  132. package/dist/sdks/elevenlabs.d.ts.map +1 -0
  133. package/dist/sdks/elevenlabs.js +192 -0
  134. package/dist/sdks/elevenlabs.js.map +1 -0
  135. package/dist/sdks/fal.d.ts +102 -0
  136. package/dist/sdks/fal.d.ts.map +1 -0
  137. package/dist/sdks/fal.js +306 -0
  138. package/dist/sdks/fal.js.map +1 -0
  139. package/dist/sdks/openai.d.ts +17 -0
  140. package/dist/sdks/openai.d.ts.map +1 -0
  141. package/dist/sdks/openai.js +191 -0
  142. package/dist/sdks/openai.js.map +1 -0
  143. package/dist/storage/interface.d.ts +15 -0
  144. package/dist/storage/interface.d.ts.map +1 -0
  145. package/dist/storage/interface.js +53 -0
  146. package/dist/storage/interface.js.map +1 -0
  147. package/dist/storage/prisma.d.ts +15 -0
  148. package/dist/storage/prisma.d.ts.map +1 -0
  149. package/dist/storage/prisma.js +135 -0
  150. package/dist/storage/prisma.js.map +1 -0
  151. package/dist/types.d.ts +206 -0
  152. package/dist/types.d.ts.map +1 -0
  153. package/dist/types.js +45 -0
  154. package/dist/types.js.map +1 -0
  155. package/dist/vercel-ai/index.d.ts +89 -0
  156. package/dist/vercel-ai/index.d.ts.map +1 -0
  157. package/dist/vercel-ai/index.js +298 -0
  158. package/dist/vercel-ai/index.js.map +1 -0
  159. package/package.json +119 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,gBAAgB,EAChB,cAAc,EACd,aAAa,EACb,cAAc,EACf,MAAM,YAAY,CAAC;AAoCpB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoCG;AACH,wBAAgB,IAAI,CAAC,MAAM,EAAE,gBAAgB,GAAG,IAAI,CA2CnD;AAED;;GAEG;AACH,wBAAgB,UAAU,IAAI,cAAc,CAO3C;AAED;;GAEG;AACH,wBAAgB,UAAU,IAAI,aAAa,CAE1C;AAED;;GAEG;AACH,wBAAgB,eAAe,IAAI,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAExD;AAED;;GAEG;AACH,wBAAgB,WAAW,IAAI,cAAc,CAE5C;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,aAAa,IAAI,OAAO,CAEvC;AAED;;GAEG;AACH,wBAAgB,YAAY,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAElD;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAsB,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC,CAM9C"}
package/dist/config.js ADDED
@@ -0,0 +1,166 @@
1
+ import { PrismaStorageAdapter } from "./storage/prisma.js";
2
+ import { defaultPricing, mergePricing } from "./pricing/index.js";
3
+ import { initRecorder } from "./recorder.js";
4
+ /**
5
+ * Default batching configuration
6
+ */
7
+ const DEFAULT_BATCHING = {
8
+ enabled: true,
9
+ flushInterval: 1000,
10
+ maxBatchSize: 100,
11
+ flushOnExit: true,
12
+ };
13
+ const state = {
14
+ initialized: false,
15
+ storage: null,
16
+ pricing: defaultPricing,
17
+ modelAliases: {},
18
+ batching: DEFAULT_BATCHING,
19
+ identifierType: "userId",
20
+ };
21
+ /**
22
+ * Initialize tokenmeter with configuration.
23
+ *
24
+ * Must be called before using any tokenmeter functions. Typically called
25
+ * once at application startup.
26
+ *
27
+ * @param config - Configuration options
28
+ * @param config.databaseUrl - PostgreSQL connection URL (required if no storage adapter)
29
+ * @param config.storage - Custom storage adapter (overrides databaseUrl)
30
+ * @param config.pricing - Custom pricing overrides for models
31
+ * @param config.modelAliases - Map of model aliases to canonical names
32
+ * @param config.batching - Batching configuration (enabled, flushInterval, maxBatchSize, flushOnExit)
33
+ * @param config.identifierType - Label for the identifier field (documentation only)
34
+ *
35
+ * @throws Error if neither databaseUrl nor storage is provided
36
+ *
37
+ * @example
38
+ * ```typescript
39
+ * // With PostgreSQL
40
+ * init({
41
+ * databaseUrl: process.env.DATABASE_URL,
42
+ * });
43
+ *
44
+ * // With custom storage adapter
45
+ * init({
46
+ * storage: new InMemoryStorageAdapter(),
47
+ * });
48
+ *
49
+ * // With pricing overrides
50
+ * init({
51
+ * databaseUrl: process.env.DATABASE_URL,
52
+ * pricing: {
53
+ * "custom-model": { input: 0.001, output: 0.002 },
54
+ * },
55
+ * });
56
+ * ```
57
+ */
58
+ export function init(config) {
59
+ if (state.initialized) {
60
+ console.warn("[tokenmeter] Already initialized. Call shutdown() before reinitializing.");
61
+ return;
62
+ }
63
+ // Set up storage adapter
64
+ if (config.storage) {
65
+ state.storage = config.storage;
66
+ }
67
+ else if (config.databaseUrl) {
68
+ state.storage = new PrismaStorageAdapter(config.databaseUrl);
69
+ }
70
+ else {
71
+ throw new Error("[tokenmeter] Either databaseUrl or storage adapter must be provided");
72
+ }
73
+ // Merge pricing with defaults
74
+ if (config.pricing) {
75
+ state.pricing = mergePricing(defaultPricing, config.pricing);
76
+ }
77
+ // Set model aliases
78
+ if (config.modelAliases) {
79
+ state.modelAliases = config.modelAliases;
80
+ }
81
+ // Merge batching config
82
+ if (config.batching) {
83
+ state.batching = { ...DEFAULT_BATCHING, ...config.batching };
84
+ }
85
+ // Set identifier type
86
+ if (config.identifierType) {
87
+ state.identifierType = config.identifierType;
88
+ }
89
+ state.initialized = true;
90
+ // Initialize recorder (registers shutdown hooks)
91
+ initRecorder();
92
+ }
93
+ /**
94
+ * Get the current storage adapter
95
+ */
96
+ export function getStorage() {
97
+ if (!state.initialized || !state.storage) {
98
+ throw new Error("[tokenmeter] Not initialized. Call init() before using tokenmeter.");
99
+ }
100
+ return state.storage;
101
+ }
102
+ /**
103
+ * Get pricing configuration
104
+ */
105
+ export function getPricing() {
106
+ return state.pricing;
107
+ }
108
+ /**
109
+ * Get model aliases
110
+ */
111
+ export function getModelAliases() {
112
+ return state.modelAliases;
113
+ }
114
+ /**
115
+ * Get batching configuration
116
+ */
117
+ export function getBatching() {
118
+ return state.batching;
119
+ }
120
+ /**
121
+ * Check if tokenmeter has been initialized.
122
+ *
123
+ * @returns true if init() has been called and shutdown() has not been called
124
+ *
125
+ * @example
126
+ * ```typescript
127
+ * if (!isInitialized()) {
128
+ * init({ databaseUrl: process.env.DATABASE_URL });
129
+ * }
130
+ * ```
131
+ */
132
+ export function isInitialized() {
133
+ return state.initialized;
134
+ }
135
+ /**
136
+ * Resolve a model name through aliases
137
+ */
138
+ export function resolveModel(model) {
139
+ return state.modelAliases[model] || model;
140
+ }
141
+ /**
142
+ * Shutdown tokenmeter and clean up resources.
143
+ *
144
+ * Disconnects from the database and resets the initialized state.
145
+ * Call this before reinitializing or when shutting down your application.
146
+ *
147
+ * @returns A promise that resolves when shutdown is complete
148
+ *
149
+ * @example
150
+ * ```typescript
151
+ * // Graceful shutdown
152
+ * process.on("SIGTERM", async () => {
153
+ * await flush();
154
+ * await shutdown();
155
+ * process.exit(0);
156
+ * });
157
+ * ```
158
+ */
159
+ export async function shutdown() {
160
+ if (state.storage) {
161
+ await state.storage.disconnect();
162
+ state.storage = null;
163
+ }
164
+ state.initialized = false;
165
+ }
166
+ //# sourceMappingURL=config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,80 @@
1
+ /**
2
+ * Context Management
3
+ *
4
+ * Provides a simple API for setting attributes that propagate to all spans
5
+ * created within a scope. Abstracts OTel Baggage/Context complexity.
6
+ */
7
+ import { type Context } from "@opentelemetry/api";
8
+ import type { TokenMeterAttributes } from "./types.js";
9
+ /**
10
+ * Run a function with custom attributes that will be added to all spans created within.
11
+ *
12
+ * Uses OTel Baggage for propagation across async boundaries and to child spans.
13
+ *
14
+ * @param attributes - Key-value pairs to add to all spans in this scope
15
+ * @param fn - The async function to execute
16
+ * @returns The result of the function
17
+ *
18
+ * @example
19
+ * ```typescript
20
+ * import { withAttributes } from 'tokenmeter';
21
+ *
22
+ * await withAttributes({
23
+ * 'org.id': 'org_123',
24
+ * 'user.id': 'user_456',
25
+ * 'workflow.id': 'video-gen-99'
26
+ * }, async () => {
27
+ * // All spans created here will have these attributes
28
+ * await openai.chat.completions.create({...});
29
+ * await fal.subscribe({...});
30
+ * });
31
+ * ```
32
+ */
33
+ export declare function withAttributes<T>(attributes: TokenMeterAttributes, fn: () => Promise<T>): Promise<T>;
34
+ /**
35
+ * Synchronous version of withAttributes for cases where async isn't needed
36
+ *
37
+ * @param attributes - Key-value pairs to add to all spans in this scope
38
+ * @param fn - The function to execute
39
+ * @returns The result of the function
40
+ */
41
+ export declare function withAttributesSync<T>(attributes: TokenMeterAttributes, fn: () => T): T;
42
+ /**
43
+ * Get the current attributes from the active context's baggage
44
+ *
45
+ * @returns Record of current baggage entries
46
+ */
47
+ export declare function getCurrentAttributes(): Record<string, string>;
48
+ /**
49
+ * Get a specific attribute from the current context
50
+ *
51
+ * @param key - The attribute key to retrieve
52
+ * @returns The attribute value, or undefined if not set
53
+ */
54
+ export declare function getAttribute(key: string): string | undefined;
55
+ /**
56
+ * Extract traceparent header for cross-service propagation
57
+ *
58
+ * Useful for propagating context to external services (e.g., Inngest jobs)
59
+ *
60
+ * @returns Object with traceparent and tracestate headers
61
+ */
62
+ export declare function extractTraceHeaders(): Record<string, string>;
63
+ /**
64
+ * Create a context from trace headers (for receiving propagated context)
65
+ *
66
+ * @param headers - Object containing traceparent/tracestate headers
67
+ * @returns OTel Context with extracted trace info
68
+ */
69
+ export declare function contextFromHeaders(headers: Record<string, string>): Context;
70
+ /**
71
+ * Run a function within a context extracted from headers
72
+ *
73
+ * Useful for continuing a trace from an external source (e.g., incoming webhook)
74
+ *
75
+ * @param headers - Object containing traceparent/tracestate headers
76
+ * @param fn - The async function to execute
77
+ * @returns The result of the function
78
+ */
79
+ export declare function withExtractedContext<T>(headers: Record<string, string>, fn: () => Promise<T>): Promise<T>;
80
+ //# sourceMappingURL=context.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"context.d.ts","sourceRoot":"","sources":["../src/context.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAIL,KAAK,OAAO,EAGb,MAAM,oBAAoB,CAAC;AAC5B,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,YAAY,CAAC;AAEvD;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,wBAAsB,cAAc,CAAC,CAAC,EACpC,UAAU,EAAE,oBAAoB,EAChC,EAAE,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,GACnB,OAAO,CAAC,CAAC,CAAC,CAkBZ;AAED;;;;;;GAMG;AACH,wBAAgB,kBAAkB,CAAC,CAAC,EAClC,UAAU,EAAE,oBAAoB,EAChC,EAAE,EAAE,MAAM,CAAC,GACV,CAAC,CAaH;AAED;;;;GAIG;AACH,wBAAgB,oBAAoB,IAAI,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAc7D;AAED;;;;;GAKG;AACH,wBAAgB,YAAY,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAU5D;AAED;;;;;;GAMG;AACH,wBAAgB,mBAAmB,IAAI,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAI5D;AAED;;;;;GAKG;AACH,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,OAAO,CAE3E;AAED;;;;;;;;GAQG;AACH,wBAAsB,oBAAoB,CAAC,CAAC,EAC1C,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EAC/B,EAAE,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,GACnB,OAAO,CAAC,CAAC,CAAC,CAGZ"}
@@ -0,0 +1,131 @@
1
+ /**
2
+ * Context Management
3
+ *
4
+ * Provides a simple API for setting attributes that propagate to all spans
5
+ * created within a scope. Abstracts OTel Baggage/Context complexity.
6
+ */
7
+ import { context, propagation, ROOT_CONTEXT, } from "@opentelemetry/api";
8
+ /**
9
+ * Run a function with custom attributes that will be added to all spans created within.
10
+ *
11
+ * Uses OTel Baggage for propagation across async boundaries and to child spans.
12
+ *
13
+ * @param attributes - Key-value pairs to add to all spans in this scope
14
+ * @param fn - The async function to execute
15
+ * @returns The result of the function
16
+ *
17
+ * @example
18
+ * ```typescript
19
+ * import { withAttributes } from 'tokenmeter';
20
+ *
21
+ * await withAttributes({
22
+ * 'org.id': 'org_123',
23
+ * 'user.id': 'user_456',
24
+ * 'workflow.id': 'video-gen-99'
25
+ * }, async () => {
26
+ * // All spans created here will have these attributes
27
+ * await openai.chat.completions.create({...});
28
+ * await fal.subscribe({...});
29
+ * });
30
+ * ```
31
+ */
32
+ export async function withAttributes(attributes, fn) {
33
+ // Get current baggage or create new one
34
+ const currentContext = context.active();
35
+ let baggage = propagation.getBaggage(currentContext) || propagation.createBaggage();
36
+ // Add attributes to baggage
37
+ for (const [key, value] of Object.entries(attributes)) {
38
+ baggage = baggage.setEntry(key, {
39
+ value: String(value),
40
+ });
41
+ }
42
+ // Create new context with updated baggage
43
+ const newContext = propagation.setBaggage(currentContext, baggage);
44
+ // Run function within the new context
45
+ return context.with(newContext, fn);
46
+ }
47
+ /**
48
+ * Synchronous version of withAttributes for cases where async isn't needed
49
+ *
50
+ * @param attributes - Key-value pairs to add to all spans in this scope
51
+ * @param fn - The function to execute
52
+ * @returns The result of the function
53
+ */
54
+ export function withAttributesSync(attributes, fn) {
55
+ const currentContext = context.active();
56
+ let baggage = propagation.getBaggage(currentContext) || propagation.createBaggage();
57
+ for (const [key, value] of Object.entries(attributes)) {
58
+ baggage = baggage.setEntry(key, {
59
+ value: String(value),
60
+ });
61
+ }
62
+ const newContext = propagation.setBaggage(currentContext, baggage);
63
+ return context.with(newContext, fn);
64
+ }
65
+ /**
66
+ * Get the current attributes from the active context's baggage
67
+ *
68
+ * @returns Record of current baggage entries
69
+ */
70
+ export function getCurrentAttributes() {
71
+ const currentContext = context.active();
72
+ const baggage = propagation.getBaggage(currentContext);
73
+ if (!baggage) {
74
+ return {};
75
+ }
76
+ const attributes = {};
77
+ baggage.getAllEntries().forEach(([key, entry]) => {
78
+ attributes[key] = entry.value;
79
+ });
80
+ return attributes;
81
+ }
82
+ /**
83
+ * Get a specific attribute from the current context
84
+ *
85
+ * @param key - The attribute key to retrieve
86
+ * @returns The attribute value, or undefined if not set
87
+ */
88
+ export function getAttribute(key) {
89
+ const currentContext = context.active();
90
+ const baggage = propagation.getBaggage(currentContext);
91
+ if (!baggage) {
92
+ return undefined;
93
+ }
94
+ const entry = baggage.getEntry(key);
95
+ return entry?.value;
96
+ }
97
+ /**
98
+ * Extract traceparent header for cross-service propagation
99
+ *
100
+ * Useful for propagating context to external services (e.g., Inngest jobs)
101
+ *
102
+ * @returns Object with traceparent and tracestate headers
103
+ */
104
+ export function extractTraceHeaders() {
105
+ const headers = {};
106
+ propagation.inject(context.active(), headers);
107
+ return headers;
108
+ }
109
+ /**
110
+ * Create a context from trace headers (for receiving propagated context)
111
+ *
112
+ * @param headers - Object containing traceparent/tracestate headers
113
+ * @returns OTel Context with extracted trace info
114
+ */
115
+ export function contextFromHeaders(headers) {
116
+ return propagation.extract(ROOT_CONTEXT, headers);
117
+ }
118
+ /**
119
+ * Run a function within a context extracted from headers
120
+ *
121
+ * Useful for continuing a trace from an external source (e.g., incoming webhook)
122
+ *
123
+ * @param headers - Object containing traceparent/tracestate headers
124
+ * @param fn - The async function to execute
125
+ * @returns The result of the function
126
+ */
127
+ export async function withExtractedContext(headers, fn) {
128
+ const extractedContext = contextFromHeaders(headers);
129
+ return context.with(extractedContext, fn);
130
+ }
131
+ //# sourceMappingURL=context.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"context.js","sourceRoot":"","sources":["../src/context.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EACL,OAAO,EACP,WAAW,EACX,YAAY,GAIb,MAAM,oBAAoB,CAAC;AAG5B;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,MAAM,CAAC,KAAK,UAAU,cAAc,CAClC,UAAgC,EAChC,EAAoB;IAEpB,wCAAwC;IACxC,MAAM,cAAc,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC;IACxC,IAAI,OAAO,GACT,WAAW,CAAC,UAAU,CAAC,cAAc,CAAC,IAAI,WAAW,CAAC,aAAa,EAAE,CAAC;IAExE,4BAA4B;IAC5B,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,UAAU,CAAC,EAAE,CAAC;QACtD,OAAO,GAAG,OAAO,CAAC,QAAQ,CAAC,GAAG,EAAE;YAC9B,KAAK,EAAE,MAAM,CAAC,KAAK,CAAC;SACrB,CAAC,CAAC;IACL,CAAC;IAED,0CAA0C;IAC1C,MAAM,UAAU,GAAG,WAAW,CAAC,UAAU,CAAC,cAAc,EAAE,OAAO,CAAC,CAAC;IAEnE,sCAAsC;IACtC,OAAO,OAAO,CAAC,IAAI,CAAC,UAAU,EAAE,EAAE,CAAC,CAAC;AACtC,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,kBAAkB,CAChC,UAAgC,EAChC,EAAW;IAEX,MAAM,cAAc,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC;IACxC,IAAI,OAAO,GACT,WAAW,CAAC,UAAU,CAAC,cAAc,CAAC,IAAI,WAAW,CAAC,aAAa,EAAE,CAAC;IAExE,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,UAAU,CAAC,EAAE,CAAC;QACtD,OAAO,GAAG,OAAO,CAAC,QAAQ,CAAC,GAAG,EAAE;YAC9B,KAAK,EAAE,MAAM,CAAC,KAAK,CAAC;SACrB,CAAC,CAAC;IACL,CAAC;IAED,MAAM,UAAU,GAAG,WAAW,CAAC,UAAU,CAAC,cAAc,EAAE,OAAO,CAAC,CAAC;IACnE,OAAO,OAAO,CAAC,IAAI,CAAC,UAAU,EAAE,EAAE,CAAC,CAAC;AACtC,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,oBAAoB;IAClC,MAAM,cAAc,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC;IACxC,MAAM,OAAO,GAAG,WAAW,CAAC,UAAU,CAAC,cAAc,CAAC,CAAC;IAEvD,IAAI,CAAC,OAAO,EAAE,CAAC;QACb,OAAO,EAAE,CAAC;IACZ,CAAC;IAED,MAAM,UAAU,GAA2B,EAAE,CAAC;IAC9C,OAAO,CAAC,aAAa,EAAE,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,EAAE,KAAK,CAAC,EAAE,EAAE;QAC/C,UAAU,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC,KAAK,CAAC;IAChC,CAAC,CAAC,CAAC;IAEH,OAAO,UAAU,CAAC;AACpB,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,YAAY,CAAC,GAAW;IACtC,MAAM,cAAc,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC;IACxC,MAAM,OAAO,GAAG,WAAW,CAAC,UAAU,CAAC,cAAc,CAAC,CAAC;IAEvD,IAAI,CAAC,OAAO,EAAE,CAAC;QACb,OAAO,SAAS,CAAC;IACnB,CAAC;IAED,MAAM,KAAK,GAAG,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC;IACpC,OAAO,KAAK,EAAE,KAAK,CAAC;AACtB,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,mBAAmB;IACjC,MAAM,OAAO,GAA2B,EAAE,CAAC;IAC3C,WAAW,CAAC,MAAM,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,OAAO,CAAC,CAAC;IAC9C,OAAO,OAAO,CAAC;AACjB,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,kBAAkB,CAAC,OAA+B;IAChE,OAAO,WAAW,CAAC,OAAO,CAAC,YAAY,EAAE,OAAO,CAAC,CAAC;AACpD,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,CAAC,KAAK,UAAU,oBAAoB,CACxC,OAA+B,EAC/B,EAAoB;IAEpB,MAAM,gBAAgB,GAAG,kBAAkB,CAAC,OAAO,CAAC,CAAC;IACrD,OAAO,OAAO,CAAC,IAAI,CAAC,gBAAgB,EAAE,EAAE,CAAC,CAAC;AAC5C,CAAC"}
@@ -0,0 +1,82 @@
1
+ /**
2
+ * PostgreSQL Span Exporter
3
+ *
4
+ * Exports tokenmeter cost spans to PostgreSQL for persistence and querying.
5
+ */
6
+ import type { ReadableSpan } from "@opentelemetry/sdk-trace-base";
7
+ import type { ExportResult } from "@opentelemetry/core";
8
+ import type { PostgresExporterConfig } from "../types.js";
9
+ /**
10
+ * SpanExporter interface (subset we need)
11
+ * We define this to avoid requiring @opentelemetry/sdk-trace-base at runtime
12
+ */
13
+ export interface SpanExporter {
14
+ export(spans: ReadableSpan[], resultCallback: (result: ExportResult) => void): void;
15
+ shutdown(): Promise<void>;
16
+ }
17
+ /**
18
+ * PostgreSQL exporter for tokenmeter cost spans
19
+ *
20
+ * @example
21
+ * ```typescript
22
+ * import { NodeTracerProvider } from '@opentelemetry/sdk-trace-node';
23
+ * import { BatchSpanProcessor } from '@opentelemetry/sdk-trace-base';
24
+ * import { PostgresExporter } from 'tokenmeter/exporter';
25
+ *
26
+ * const exporter = new PostgresExporter({
27
+ * connectionString: process.env.DATABASE_URL,
28
+ * });
29
+ *
30
+ * const provider = new NodeTracerProvider();
31
+ * provider.addSpanProcessor(new BatchSpanProcessor(exporter));
32
+ * provider.register();
33
+ * ```
34
+ */
35
+ export declare class PostgresExporter implements SpanExporter {
36
+ private config;
37
+ private pool;
38
+ private buffer;
39
+ private flushTimer;
40
+ private flushPromise;
41
+ private isShuttingDown;
42
+ constructor(config: PostgresExporterConfig);
43
+ /**
44
+ * Lazily initialize the database pool
45
+ */
46
+ private getPool;
47
+ /**
48
+ * Export spans to PostgreSQL
49
+ */
50
+ export(spans: ReadableSpan[], resultCallback: (result: ExportResult) => void): void;
51
+ /**
52
+ * Convert a ReadableSpan to a CostRecord
53
+ * Returns null if the span doesn't have cost data
54
+ */
55
+ private spanToCostRecord;
56
+ /**
57
+ * Extract custom attributes (exclude standard tokenmeter attributes)
58
+ */
59
+ private extractCustomAttributes;
60
+ /**
61
+ * Convert HrTime to Date
62
+ */
63
+ private hrTimeToDate;
64
+ /**
65
+ * Flush buffered records to the database
66
+ */
67
+ private flushBuffer;
68
+ /**
69
+ * Insert records into the database
70
+ */
71
+ private insertRecords;
72
+ /**
73
+ * Shutdown the exporter
74
+ */
75
+ shutdown(): Promise<void>;
76
+ /**
77
+ * Force flush (for testing or manual control)
78
+ */
79
+ forceFlush(): Promise<void>;
80
+ }
81
+ export default PostgresExporter;
82
+ //# sourceMappingURL=PostgresExporter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"PostgresExporter.d.ts","sourceRoot":"","sources":["../../src/exporter/PostgresExporter.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,+BAA+B,CAAC;AAClE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAExD,OAAO,KAAK,EAAE,sBAAsB,EAAc,MAAM,aAAa,CAAC;AAItE;;;GAGG;AACH,MAAM,WAAW,YAAY;IAC3B,MAAM,CACJ,KAAK,EAAE,YAAY,EAAE,EACrB,cAAc,EAAE,CAAC,MAAM,EAAE,YAAY,KAAK,IAAI,GAC7C,IAAI,CAAC;IACR,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CAC3B;AAoBD;;;;;;;;;;;;;;;;;GAiBG;AACH,qBAAa,gBAAiB,YAAW,YAAY;IACnD,OAAO,CAAC,MAAM,CAAiB;IAC/B,OAAO,CAAC,IAAI,CAAqB;IACjC,OAAO,CAAC,MAAM,CAAoB;IAClC,OAAO,CAAC,UAAU,CAA+C;IACjE,OAAO,CAAC,YAAY,CAA8B;IAClD,OAAO,CAAC,cAAc,CAAS;gBAEnB,MAAM,EAAE,sBAAsB;IAgB1C;;OAEG;YACW,OAAO;IAcrB;;OAEG;IACH,MAAM,CACJ,KAAK,EAAE,YAAY,EAAE,EACrB,cAAc,EAAE,CAAC,MAAM,EAAE,YAAY,KAAK,IAAI,GAC7C,IAAI;IAkCP;;;OAGG;IACH,OAAO,CAAC,gBAAgB;IA+BxB;;OAEG;IACH,OAAO,CAAC,uBAAuB;IAiB/B;;OAEG;IACH,OAAO,CAAC,YAAY;IAKpB;;OAEG;YACW,WAAW;IAqBzB;;OAEG;YACW,aAAa;IA8D3B;;OAEG;IACG,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC;IAmB/B;;OAEG;IACG,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;CAGlC;AAED,eAAe,gBAAgB,CAAC"}