@juspay/neurolink 9.23.0 → 9.25.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/CHANGELOG.md +12 -0
- package/README.md +10 -13
- package/dist/adapters/tts/googleTTSHandler.js +26 -1
- package/dist/adapters/video/vertexVideoHandler.js +23 -17
- package/dist/cli/commands/config.d.ts +3 -3
- package/dist/cli/commands/observability.d.ts +53 -0
- package/dist/cli/commands/observability.js +453 -0
- package/dist/cli/commands/telemetry.d.ts +63 -0
- package/dist/cli/commands/telemetry.js +689 -0
- package/dist/cli/factories/commandFactory.d.ts +34 -0
- package/dist/cli/factories/commandFactory.js +321 -116
- package/dist/cli/parser.js +6 -9
- package/dist/cli/utils/formatters.d.ts +13 -0
- package/dist/cli/utils/formatters.js +23 -0
- package/dist/constants/contextWindows.js +6 -0
- package/dist/constants/enums.d.ts +6 -0
- package/dist/constants/enums.js +8 -2
- package/dist/context/budgetChecker.js +75 -48
- package/dist/context/contextCompactor.js +135 -127
- package/dist/core/baseProvider.d.ts +5 -0
- package/dist/core/baseProvider.js +158 -102
- package/dist/core/conversationMemoryInitializer.js +7 -4
- package/dist/core/conversationMemoryManager.d.ts +2 -0
- package/dist/core/conversationMemoryManager.js +6 -2
- package/dist/core/modules/GenerationHandler.d.ts +2 -2
- package/dist/core/modules/GenerationHandler.js +12 -12
- package/dist/evaluation/ragasEvaluator.js +39 -19
- package/dist/evaluation/scoring.js +46 -20
- package/dist/features/ppt/index.d.ts +1 -1
- package/dist/features/ppt/index.js +1 -1
- package/dist/features/ppt/presentationOrchestrator.js +23 -0
- package/dist/features/ppt/slideGenerator.js +13 -0
- package/dist/features/ppt/slideRenderers.d.ts +1 -1
- package/dist/features/ppt/slideRenderers.js +6 -4
- package/dist/features/ppt/slideTypeInference.d.ts +1 -1
- package/dist/features/ppt/slideTypeInference.js +75 -73
- package/dist/files/fileTools.d.ts +6 -6
- package/dist/index.d.ts +46 -12
- package/dist/index.js +79 -17
- package/dist/lib/adapters/tts/googleTTSHandler.js +26 -1
- package/dist/lib/adapters/video/vertexVideoHandler.js +23 -17
- package/dist/lib/constants/contextWindows.js +6 -0
- package/dist/lib/constants/enums.d.ts +6 -0
- package/dist/lib/constants/enums.js +8 -2
- package/dist/lib/context/budgetChecker.js +75 -48
- package/dist/lib/context/contextCompactor.js +135 -127
- package/dist/lib/core/baseProvider.d.ts +5 -0
- package/dist/lib/core/baseProvider.js +158 -102
- package/dist/lib/core/conversationMemoryInitializer.js +7 -4
- package/dist/lib/core/conversationMemoryManager.d.ts +2 -0
- package/dist/lib/core/conversationMemoryManager.js +6 -2
- package/dist/lib/core/modules/GenerationHandler.d.ts +2 -2
- package/dist/lib/core/modules/GenerationHandler.js +12 -12
- package/dist/lib/evaluation/ragasEvaluator.js +39 -19
- package/dist/lib/evaluation/scoring.js +46 -20
- package/dist/lib/features/ppt/index.d.ts +1 -1
- package/dist/lib/features/ppt/index.js +1 -1
- package/dist/lib/features/ppt/presentationOrchestrator.js +23 -0
- package/dist/lib/features/ppt/slideGenerator.js +13 -0
- package/dist/lib/features/ppt/slideRenderers.d.ts +1 -1
- package/dist/lib/features/ppt/slideRenderers.js +6 -4
- package/dist/lib/features/ppt/slideTypeInference.d.ts +1 -1
- package/dist/lib/features/ppt/slideTypeInference.js +75 -73
- package/dist/lib/files/fileTools.d.ts +6 -6
- package/dist/lib/index.d.ts +46 -12
- package/dist/lib/index.js +79 -17
- package/dist/lib/mcp/httpRateLimiter.js +39 -12
- package/dist/lib/mcp/httpRetryHandler.js +22 -1
- package/dist/lib/mcp/mcpClientFactory.js +13 -15
- package/dist/lib/memory/memoryRetrievalTools.js +22 -0
- package/dist/lib/neurolink.d.ts +64 -72
- package/dist/lib/neurolink.js +984 -566
- package/dist/lib/observability/exporterRegistry.d.ts +152 -0
- package/dist/lib/observability/exporterRegistry.js +414 -0
- package/dist/lib/observability/exporters/arizeExporter.d.ts +32 -0
- package/dist/lib/observability/exporters/arizeExporter.js +139 -0
- package/dist/lib/observability/exporters/baseExporter.d.ts +117 -0
- package/dist/lib/observability/exporters/baseExporter.js +191 -0
- package/dist/lib/observability/exporters/braintrustExporter.d.ts +30 -0
- package/dist/lib/observability/exporters/braintrustExporter.js +155 -0
- package/dist/lib/observability/exporters/datadogExporter.d.ts +37 -0
- package/dist/lib/observability/exporters/datadogExporter.js +197 -0
- package/dist/lib/observability/exporters/index.d.ts +13 -0
- package/dist/lib/observability/exporters/index.js +14 -0
- package/dist/lib/observability/exporters/laminarExporter.d.ts +48 -0
- package/dist/lib/observability/exporters/laminarExporter.js +303 -0
- package/dist/lib/observability/exporters/langfuseExporter.d.ts +47 -0
- package/dist/lib/observability/exporters/langfuseExporter.js +200 -0
- package/dist/lib/observability/exporters/langsmithExporter.d.ts +26 -0
- package/dist/lib/observability/exporters/langsmithExporter.js +124 -0
- package/dist/lib/observability/exporters/otelExporter.d.ts +39 -0
- package/dist/lib/observability/exporters/otelExporter.js +165 -0
- package/dist/lib/observability/exporters/posthogExporter.d.ts +48 -0
- package/dist/lib/observability/exporters/posthogExporter.js +288 -0
- package/dist/lib/observability/exporters/sentryExporter.d.ts +32 -0
- package/dist/lib/observability/exporters/sentryExporter.js +166 -0
- package/dist/lib/observability/index.d.ts +25 -0
- package/dist/lib/observability/index.js +32 -0
- package/dist/lib/observability/metricsAggregator.d.ts +260 -0
- package/dist/lib/observability/metricsAggregator.js +553 -0
- package/dist/lib/observability/otelBridge.d.ts +49 -0
- package/dist/lib/observability/otelBridge.js +132 -0
- package/dist/lib/observability/retryPolicy.d.ts +192 -0
- package/dist/lib/observability/retryPolicy.js +384 -0
- package/dist/lib/observability/sampling/index.d.ts +4 -0
- package/dist/lib/observability/sampling/index.js +5 -0
- package/dist/lib/observability/sampling/samplers.d.ts +116 -0
- package/dist/lib/observability/sampling/samplers.js +217 -0
- package/dist/lib/observability/spanProcessor.d.ts +129 -0
- package/dist/lib/observability/spanProcessor.js +288 -0
- package/dist/lib/observability/tokenTracker.d.ts +156 -0
- package/dist/lib/observability/tokenTracker.js +414 -0
- package/dist/lib/observability/types/exporterTypes.d.ts +250 -0
- package/dist/lib/observability/types/exporterTypes.js +6 -0
- package/dist/lib/observability/types/index.d.ts +6 -0
- package/dist/lib/observability/types/index.js +5 -0
- package/dist/lib/observability/types/spanTypes.d.ts +244 -0
- package/dist/lib/observability/types/spanTypes.js +93 -0
- package/dist/lib/observability/utils/index.d.ts +4 -0
- package/dist/lib/observability/utils/index.js +5 -0
- package/dist/lib/observability/utils/spanSerializer.d.ts +115 -0
- package/dist/lib/observability/utils/spanSerializer.js +287 -0
- package/dist/lib/providers/amazonSagemaker.d.ts +5 -4
- package/dist/lib/providers/amazonSagemaker.js +3 -4
- package/dist/lib/providers/googleVertex.d.ts +7 -0
- package/dist/lib/providers/googleVertex.js +80 -2
- package/dist/lib/rag/pipeline/RAGPipeline.d.ts +0 -5
- package/dist/lib/rag/pipeline/RAGPipeline.js +122 -87
- package/dist/lib/rag/ragIntegration.js +30 -0
- package/dist/lib/rag/retrieval/hybridSearch.js +22 -0
- package/dist/lib/server/abstract/baseServerAdapter.js +51 -19
- package/dist/lib/server/middleware/common.js +44 -12
- package/dist/lib/services/server/ai/observability/instrumentation.d.ts +2 -2
- package/dist/lib/services/server/ai/observability/instrumentation.js +10 -5
- package/dist/lib/types/cli.d.ts +18 -2
- package/dist/lib/types/conversationMemoryInterface.d.ts +2 -0
- package/dist/lib/types/generateTypes.d.ts +2 -2
- package/dist/lib/types/modelTypes.d.ts +18 -18
- package/dist/lib/types/providers.d.ts +5 -0
- package/dist/lib/utils/pricing.js +25 -1
- package/dist/lib/utils/ttsProcessor.js +74 -59
- package/dist/lib/workflow/config.d.ts +36 -36
- package/dist/lib/workflow/core/ensembleExecutor.js +10 -0
- package/dist/lib/workflow/core/judgeScorer.js +20 -2
- package/dist/lib/workflow/core/workflowRunner.js +34 -1
- package/dist/mcp/httpRateLimiter.js +39 -12
- package/dist/mcp/httpRetryHandler.js +22 -1
- package/dist/mcp/mcpClientFactory.js +13 -15
- package/dist/memory/memoryRetrievalTools.js +22 -0
- package/dist/neurolink.d.ts +64 -72
- package/dist/neurolink.js +984 -566
- package/dist/observability/FEATURE-STATUS.md +269 -0
- package/dist/observability/exporterRegistry.d.ts +152 -0
- package/dist/observability/exporterRegistry.js +413 -0
- package/dist/observability/exporters/arizeExporter.d.ts +32 -0
- package/dist/observability/exporters/arizeExporter.js +138 -0
- package/dist/observability/exporters/baseExporter.d.ts +117 -0
- package/dist/observability/exporters/baseExporter.js +190 -0
- package/dist/observability/exporters/braintrustExporter.d.ts +30 -0
- package/dist/observability/exporters/braintrustExporter.js +154 -0
- package/dist/observability/exporters/datadogExporter.d.ts +37 -0
- package/dist/observability/exporters/datadogExporter.js +196 -0
- package/dist/observability/exporters/index.d.ts +13 -0
- package/dist/observability/exporters/index.js +13 -0
- package/dist/observability/exporters/laminarExporter.d.ts +48 -0
- package/dist/observability/exporters/laminarExporter.js +302 -0
- package/dist/observability/exporters/langfuseExporter.d.ts +47 -0
- package/dist/observability/exporters/langfuseExporter.js +199 -0
- package/dist/observability/exporters/langsmithExporter.d.ts +26 -0
- package/dist/observability/exporters/langsmithExporter.js +123 -0
- package/dist/observability/exporters/otelExporter.d.ts +39 -0
- package/dist/observability/exporters/otelExporter.js +164 -0
- package/dist/observability/exporters/posthogExporter.d.ts +48 -0
- package/dist/observability/exporters/posthogExporter.js +287 -0
- package/dist/observability/exporters/sentryExporter.d.ts +32 -0
- package/dist/observability/exporters/sentryExporter.js +165 -0
- package/dist/observability/index.d.ts +25 -0
- package/dist/observability/index.js +31 -0
- package/dist/observability/metricsAggregator.d.ts +260 -0
- package/dist/observability/metricsAggregator.js +552 -0
- package/dist/observability/otelBridge.d.ts +49 -0
- package/dist/observability/otelBridge.js +131 -0
- package/dist/observability/retryPolicy.d.ts +192 -0
- package/dist/observability/retryPolicy.js +383 -0
- package/dist/observability/sampling/index.d.ts +4 -0
- package/dist/observability/sampling/index.js +4 -0
- package/dist/observability/sampling/samplers.d.ts +116 -0
- package/dist/observability/sampling/samplers.js +216 -0
- package/dist/observability/spanProcessor.d.ts +129 -0
- package/dist/observability/spanProcessor.js +287 -0
- package/dist/observability/tokenTracker.d.ts +156 -0
- package/dist/observability/tokenTracker.js +413 -0
- package/dist/observability/types/exporterTypes.d.ts +250 -0
- package/dist/observability/types/exporterTypes.js +5 -0
- package/dist/observability/types/index.d.ts +6 -0
- package/dist/observability/types/index.js +4 -0
- package/dist/observability/types/spanTypes.d.ts +244 -0
- package/dist/observability/types/spanTypes.js +92 -0
- package/dist/observability/utils/index.d.ts +4 -0
- package/dist/observability/utils/index.js +4 -0
- package/dist/observability/utils/spanSerializer.d.ts +115 -0
- package/dist/observability/utils/spanSerializer.js +286 -0
- package/dist/providers/amazonSagemaker.d.ts +5 -4
- package/dist/providers/amazonSagemaker.js +3 -4
- package/dist/providers/googleVertex.d.ts +7 -0
- package/dist/providers/googleVertex.js +80 -2
- package/dist/rag/pipeline/RAGPipeline.d.ts +0 -5
- package/dist/rag/pipeline/RAGPipeline.js +122 -87
- package/dist/rag/ragIntegration.js +30 -0
- package/dist/rag/retrieval/hybridSearch.js +22 -0
- package/dist/server/abstract/baseServerAdapter.js +51 -19
- package/dist/server/middleware/common.js +44 -12
- package/dist/services/server/ai/observability/instrumentation.d.ts +2 -2
- package/dist/services/server/ai/observability/instrumentation.js +10 -5
- package/dist/types/cli.d.ts +18 -2
- package/dist/types/conversationMemoryInterface.d.ts +2 -0
- package/dist/types/generateTypes.d.ts +2 -2
- package/dist/types/providers.d.ts +5 -0
- package/dist/utils/pricing.js +25 -1
- package/dist/utils/ttsProcessor.js +74 -59
- package/dist/workflow/config.d.ts +52 -52
- package/dist/workflow/core/ensembleExecutor.js +10 -0
- package/dist/workflow/core/judgeScorer.js +20 -2
- package/dist/workflow/core/workflowRunner.js +34 -1
- package/package.json +1 -1
|
@@ -0,0 +1,413 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Exporter Registry
|
|
3
|
+
* Manages multiple observability exporters with circuit breaker protection
|
|
4
|
+
*/
|
|
5
|
+
import { logger } from "../utils/logger.js";
|
|
6
|
+
import { AlwaysSampler } from "./sampling/samplers.js";
|
|
7
|
+
/** Default timeout for exporter API calls (30 seconds) */
|
|
8
|
+
const DEFAULT_EXPORT_TIMEOUT_MS = 30_000;
|
|
9
|
+
/**
|
|
10
|
+
* Wrap a promise with a timeout. Rejects with a descriptive error if the
|
|
11
|
+
* promise does not settle within `timeoutMs` milliseconds.
|
|
12
|
+
*/
|
|
13
|
+
function withExportTimeout(promise, timeoutMs, label) {
|
|
14
|
+
return new Promise((resolve, reject) => {
|
|
15
|
+
const timer = setTimeout(() => {
|
|
16
|
+
reject(new Error(`Export to '${label}' timed out after ${timeoutMs}ms`));
|
|
17
|
+
}, timeoutMs);
|
|
18
|
+
promise.then((v) => {
|
|
19
|
+
clearTimeout(timer);
|
|
20
|
+
resolve(v);
|
|
21
|
+
}, (e) => {
|
|
22
|
+
clearTimeout(timer);
|
|
23
|
+
reject(e);
|
|
24
|
+
});
|
|
25
|
+
});
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Registry for managing multiple observability exporters
|
|
29
|
+
* Includes circuit breaker protection to prevent cascading failures
|
|
30
|
+
*/
|
|
31
|
+
export class ExporterRegistry {
|
|
32
|
+
exporters = new Map();
|
|
33
|
+
defaultExporter = null;
|
|
34
|
+
sampler = new AlwaysSampler();
|
|
35
|
+
circuitBreakers = new Map();
|
|
36
|
+
circuitBreakerConfig = {
|
|
37
|
+
failureThreshold: 5,
|
|
38
|
+
resetTimeout: 30000, // 30 seconds
|
|
39
|
+
};
|
|
40
|
+
/**
|
|
41
|
+
* Register an exporter
|
|
42
|
+
*/
|
|
43
|
+
register(exporter) {
|
|
44
|
+
this.exporters.set(exporter.getName(), exporter);
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Unregister an exporter
|
|
48
|
+
*/
|
|
49
|
+
unregister(name) {
|
|
50
|
+
return this.exporters.delete(name);
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Get an exporter by name
|
|
54
|
+
*/
|
|
55
|
+
get(name) {
|
|
56
|
+
return this.exporters.get(name);
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Get all registered exporter names
|
|
60
|
+
*/
|
|
61
|
+
getNames() {
|
|
62
|
+
return Array.from(this.exporters.keys());
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Get total exporter count
|
|
66
|
+
*/
|
|
67
|
+
getCount() {
|
|
68
|
+
return this.exporters.size;
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Set the default exporter
|
|
72
|
+
*/
|
|
73
|
+
setDefault(name) {
|
|
74
|
+
if (!this.exporters.has(name)) {
|
|
75
|
+
throw new Error(`Exporter '${name}' not registered`);
|
|
76
|
+
}
|
|
77
|
+
this.defaultExporter = name;
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* Get the default exporter
|
|
81
|
+
*/
|
|
82
|
+
getDefault() {
|
|
83
|
+
if (!this.defaultExporter) {
|
|
84
|
+
return undefined;
|
|
85
|
+
}
|
|
86
|
+
return this.exporters.get(this.defaultExporter);
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* Set the sampler for the registry
|
|
90
|
+
*/
|
|
91
|
+
setSampler(sampler) {
|
|
92
|
+
this.sampler = sampler;
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* Get the current sampler
|
|
96
|
+
*/
|
|
97
|
+
getSampler() {
|
|
98
|
+
return this.sampler;
|
|
99
|
+
}
|
|
100
|
+
/**
|
|
101
|
+
* Configure the circuit breaker settings
|
|
102
|
+
* @param config - Partial circuit breaker configuration
|
|
103
|
+
*/
|
|
104
|
+
configureCircuitBreaker(config) {
|
|
105
|
+
Object.assign(this.circuitBreakerConfig, config);
|
|
106
|
+
}
|
|
107
|
+
/**
|
|
108
|
+
* Check if circuit is open for an exporter
|
|
109
|
+
* @param exporterName - Name of the exporter
|
|
110
|
+
* @returns true if circuit is open (exporter should be skipped)
|
|
111
|
+
*/
|
|
112
|
+
isCircuitOpen(exporterName) {
|
|
113
|
+
const breaker = this.circuitBreakers.get(exporterName);
|
|
114
|
+
if (!breaker) {
|
|
115
|
+
return false;
|
|
116
|
+
}
|
|
117
|
+
if (breaker.state === "open") {
|
|
118
|
+
// Check if we should try half-open
|
|
119
|
+
if (Date.now() - breaker.lastFailure >
|
|
120
|
+
this.circuitBreakerConfig.resetTimeout) {
|
|
121
|
+
breaker.state = "half-open";
|
|
122
|
+
logger.info(`[ExporterRegistry] Circuit half-open for ${exporterName}, attempting recovery`);
|
|
123
|
+
return false;
|
|
124
|
+
}
|
|
125
|
+
return true;
|
|
126
|
+
}
|
|
127
|
+
return false;
|
|
128
|
+
}
|
|
129
|
+
/**
|
|
130
|
+
* Record a failure for an exporter's circuit breaker
|
|
131
|
+
* @param exporterName - Name of the exporter
|
|
132
|
+
*/
|
|
133
|
+
recordFailure(exporterName) {
|
|
134
|
+
let breaker = this.circuitBreakers.get(exporterName);
|
|
135
|
+
if (!breaker) {
|
|
136
|
+
breaker = { failures: 0, lastFailure: 0, state: "closed" };
|
|
137
|
+
this.circuitBreakers.set(exporterName, breaker);
|
|
138
|
+
}
|
|
139
|
+
breaker.failures++;
|
|
140
|
+
breaker.lastFailure = Date.now();
|
|
141
|
+
if (breaker.failures >= this.circuitBreakerConfig.failureThreshold) {
|
|
142
|
+
breaker.state = "open";
|
|
143
|
+
logger.warn(`[ExporterRegistry] Circuit opened for ${exporterName} after ${breaker.failures} failures`);
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
/**
|
|
147
|
+
* Record a success for an exporter's circuit breaker
|
|
148
|
+
* Resets the circuit to closed state
|
|
149
|
+
* @param exporterName - Name of the exporter
|
|
150
|
+
*/
|
|
151
|
+
recordSuccess(exporterName) {
|
|
152
|
+
const breaker = this.circuitBreakers.get(exporterName);
|
|
153
|
+
if (breaker) {
|
|
154
|
+
if (breaker.state === "half-open") {
|
|
155
|
+
logger.info(`[ExporterRegistry] Circuit closed for ${exporterName} after successful recovery`);
|
|
156
|
+
}
|
|
157
|
+
breaker.failures = 0;
|
|
158
|
+
breaker.state = "closed";
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
/**
|
|
162
|
+
* Get circuit breaker status for an exporter
|
|
163
|
+
* @param exporterName - Name of the exporter
|
|
164
|
+
* @returns Circuit breaker state or undefined if not tracked
|
|
165
|
+
*/
|
|
166
|
+
getCircuitBreakerStatus(exporterName) {
|
|
167
|
+
return this.circuitBreakers.get(exporterName);
|
|
168
|
+
}
|
|
169
|
+
/**
|
|
170
|
+
* Reset circuit breaker for an exporter
|
|
171
|
+
* @param exporterName - Name of the exporter
|
|
172
|
+
*/
|
|
173
|
+
resetCircuitBreaker(exporterName) {
|
|
174
|
+
this.circuitBreakers.delete(exporterName);
|
|
175
|
+
}
|
|
176
|
+
/**
|
|
177
|
+
* Export span to all registered exporters
|
|
178
|
+
* Applies sampling and circuit breaker protection before export
|
|
179
|
+
*/
|
|
180
|
+
async exportToAll(span) {
|
|
181
|
+
const results = new Map();
|
|
182
|
+
// Apply sampling
|
|
183
|
+
if (!this.sampler.shouldSample(span)) {
|
|
184
|
+
// Return empty results if not sampled
|
|
185
|
+
return results;
|
|
186
|
+
}
|
|
187
|
+
const exportPromises = Array.from(this.exporters.entries()).map(async ([name, exporter]) => {
|
|
188
|
+
// Check circuit breaker before attempting export
|
|
189
|
+
if (this.isCircuitOpen(name)) {
|
|
190
|
+
results.set(name, {
|
|
191
|
+
success: false,
|
|
192
|
+
exportedCount: 0,
|
|
193
|
+
failedCount: 1,
|
|
194
|
+
errors: [
|
|
195
|
+
{
|
|
196
|
+
spanId: span.spanId,
|
|
197
|
+
error: "Circuit breaker open - exporter temporarily disabled",
|
|
198
|
+
retryable: true,
|
|
199
|
+
},
|
|
200
|
+
],
|
|
201
|
+
durationMs: 0,
|
|
202
|
+
});
|
|
203
|
+
return;
|
|
204
|
+
}
|
|
205
|
+
if (exporter.isInitialized()) {
|
|
206
|
+
try {
|
|
207
|
+
const result = await withExportTimeout(exporter.exportSpan(span), DEFAULT_EXPORT_TIMEOUT_MS, name);
|
|
208
|
+
results.set(name, result);
|
|
209
|
+
// Record success or failure based on result
|
|
210
|
+
if (result.success) {
|
|
211
|
+
this.recordSuccess(name);
|
|
212
|
+
}
|
|
213
|
+
else {
|
|
214
|
+
this.recordFailure(name);
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
catch (error) {
|
|
218
|
+
this.recordFailure(name);
|
|
219
|
+
results.set(name, {
|
|
220
|
+
success: false,
|
|
221
|
+
exportedCount: 0,
|
|
222
|
+
failedCount: 1,
|
|
223
|
+
errors: [
|
|
224
|
+
{
|
|
225
|
+
spanId: span.spanId,
|
|
226
|
+
error: error instanceof Error ? error.message : String(error),
|
|
227
|
+
retryable: true,
|
|
228
|
+
},
|
|
229
|
+
],
|
|
230
|
+
durationMs: 0,
|
|
231
|
+
});
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
else {
|
|
235
|
+
logger.debug(`[ExporterRegistry] Skipping uninitialized exporter '${name}' for span ${span.spanId}`);
|
|
236
|
+
}
|
|
237
|
+
});
|
|
238
|
+
await Promise.all(exportPromises);
|
|
239
|
+
return results;
|
|
240
|
+
}
|
|
241
|
+
/**
|
|
242
|
+
* Export span to a specific exporter
|
|
243
|
+
* Applies sampling and circuit breaker protection
|
|
244
|
+
*/
|
|
245
|
+
async exportTo(name, span) {
|
|
246
|
+
const exporter = this.exporters.get(name);
|
|
247
|
+
if (!exporter) {
|
|
248
|
+
return null;
|
|
249
|
+
}
|
|
250
|
+
if (!exporter.isInitialized()) {
|
|
251
|
+
logger.debug(`[ExporterRegistry] Skipping uninitialized exporter '${name}' for span ${span.spanId}`);
|
|
252
|
+
return null;
|
|
253
|
+
}
|
|
254
|
+
// Check circuit breaker before attempting export
|
|
255
|
+
if (this.isCircuitOpen(name)) {
|
|
256
|
+
return {
|
|
257
|
+
success: false,
|
|
258
|
+
exportedCount: 0,
|
|
259
|
+
failedCount: 1,
|
|
260
|
+
errors: [
|
|
261
|
+
{
|
|
262
|
+
spanId: span.spanId,
|
|
263
|
+
error: "Circuit breaker open - exporter temporarily disabled",
|
|
264
|
+
retryable: true,
|
|
265
|
+
},
|
|
266
|
+
],
|
|
267
|
+
durationMs: 0,
|
|
268
|
+
};
|
|
269
|
+
}
|
|
270
|
+
// Apply sampling
|
|
271
|
+
if (!this.sampler.shouldSample(span)) {
|
|
272
|
+
return {
|
|
273
|
+
success: true,
|
|
274
|
+
exportedCount: 0,
|
|
275
|
+
failedCount: 0,
|
|
276
|
+
durationMs: 0,
|
|
277
|
+
};
|
|
278
|
+
}
|
|
279
|
+
try {
|
|
280
|
+
const result = await withExportTimeout(exporter.exportSpan(span), DEFAULT_EXPORT_TIMEOUT_MS, name);
|
|
281
|
+
if (result.success) {
|
|
282
|
+
this.recordSuccess(name);
|
|
283
|
+
}
|
|
284
|
+
else {
|
|
285
|
+
this.recordFailure(name);
|
|
286
|
+
}
|
|
287
|
+
return result;
|
|
288
|
+
}
|
|
289
|
+
catch (error) {
|
|
290
|
+
this.recordFailure(name);
|
|
291
|
+
return {
|
|
292
|
+
success: false,
|
|
293
|
+
exportedCount: 0,
|
|
294
|
+
failedCount: 1,
|
|
295
|
+
errors: [
|
|
296
|
+
{
|
|
297
|
+
spanId: span.spanId,
|
|
298
|
+
error: error instanceof Error ? error.message : String(error),
|
|
299
|
+
retryable: true,
|
|
300
|
+
},
|
|
301
|
+
],
|
|
302
|
+
durationMs: 0,
|
|
303
|
+
};
|
|
304
|
+
}
|
|
305
|
+
}
|
|
306
|
+
/**
|
|
307
|
+
* Initialize all exporters
|
|
308
|
+
*/
|
|
309
|
+
async initializeAll() {
|
|
310
|
+
const results = await Promise.allSettled(Array.from(this.exporters.entries()).map(([name, e]) => e.initialize().catch((err) => {
|
|
311
|
+
logger.error(`[ExporterRegistry] Failed to initialize exporter '${name}':`, err);
|
|
312
|
+
throw err;
|
|
313
|
+
})));
|
|
314
|
+
for (const result of results) {
|
|
315
|
+
if (result.status === "rejected") {
|
|
316
|
+
logger.warn(`[ExporterRegistry] One or more exporters failed to initialize`);
|
|
317
|
+
break;
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
}
|
|
321
|
+
/**
|
|
322
|
+
* Shutdown all exporters
|
|
323
|
+
*/
|
|
324
|
+
async shutdownAll() {
|
|
325
|
+
const results = await Promise.allSettled(Array.from(this.exporters.entries()).map(([name, e]) => e.shutdown().catch((err) => {
|
|
326
|
+
logger.error(`[ExporterRegistry] Failed to shutdown exporter '${name}':`, err);
|
|
327
|
+
throw err;
|
|
328
|
+
})));
|
|
329
|
+
for (const result of results) {
|
|
330
|
+
if (result.status === "rejected") {
|
|
331
|
+
logger.warn(`[ExporterRegistry] One or more exporters failed to shutdown`);
|
|
332
|
+
break;
|
|
333
|
+
}
|
|
334
|
+
}
|
|
335
|
+
}
|
|
336
|
+
/**
|
|
337
|
+
* Flush all exporters
|
|
338
|
+
*/
|
|
339
|
+
async flushAll() {
|
|
340
|
+
const results = await Promise.allSettled(Array.from(this.exporters.entries()).map(([name, e]) => e.flush().catch((err) => {
|
|
341
|
+
logger.error(`[ExporterRegistry] Failed to flush exporter '${name}':`, err);
|
|
342
|
+
throw err;
|
|
343
|
+
})));
|
|
344
|
+
for (const result of results) {
|
|
345
|
+
if (result.status === "rejected") {
|
|
346
|
+
logger.warn(`[ExporterRegistry] One or more exporters failed to flush`);
|
|
347
|
+
break;
|
|
348
|
+
}
|
|
349
|
+
}
|
|
350
|
+
}
|
|
351
|
+
/**
|
|
352
|
+
* Get health status of all exporters
|
|
353
|
+
*/
|
|
354
|
+
async healthCheckAll() {
|
|
355
|
+
const results = new Map();
|
|
356
|
+
const healthPromises = Array.from(this.exporters.entries()).map(async ([name, exporter]) => {
|
|
357
|
+
const status = await exporter.healthCheck();
|
|
358
|
+
results.set(name, status);
|
|
359
|
+
});
|
|
360
|
+
await Promise.all(healthPromises);
|
|
361
|
+
return results;
|
|
362
|
+
}
|
|
363
|
+
/**
|
|
364
|
+
* Check if all exporters are healthy
|
|
365
|
+
*/
|
|
366
|
+
async isHealthy() {
|
|
367
|
+
const statuses = await this.healthCheckAll();
|
|
368
|
+
return Array.from(statuses.values()).every((s) => s.healthy);
|
|
369
|
+
}
|
|
370
|
+
/**
|
|
371
|
+
* Get total pending spans across all exporters
|
|
372
|
+
*/
|
|
373
|
+
getTotalPendingSpans() {
|
|
374
|
+
let total = 0;
|
|
375
|
+
const exporterArray = Array.from(this.exporters.values());
|
|
376
|
+
for (const exporter of exporterArray) {
|
|
377
|
+
total += exporter.getPendingCount();
|
|
378
|
+
}
|
|
379
|
+
return total;
|
|
380
|
+
}
|
|
381
|
+
/**
|
|
382
|
+
* Clear all registered exporters and reset state
|
|
383
|
+
* (For testing and cleanup)
|
|
384
|
+
*/
|
|
385
|
+
clear() {
|
|
386
|
+
this.exporters.clear();
|
|
387
|
+
this.defaultExporter = null;
|
|
388
|
+
this.circuitBreakers.clear();
|
|
389
|
+
this.sampler = new AlwaysSampler();
|
|
390
|
+
}
|
|
391
|
+
}
|
|
392
|
+
/**
|
|
393
|
+
* Global exporter registry instance (singleton pattern from main)
|
|
394
|
+
*/
|
|
395
|
+
let globalRegistry = null;
|
|
396
|
+
/**
|
|
397
|
+
* Get the global exporter registry instance
|
|
398
|
+
*/
|
|
399
|
+
export function getExporterRegistry() {
|
|
400
|
+
if (!globalRegistry) {
|
|
401
|
+
globalRegistry = new ExporterRegistry();
|
|
402
|
+
}
|
|
403
|
+
return globalRegistry;
|
|
404
|
+
}
|
|
405
|
+
/**
|
|
406
|
+
* Reset the global exporter registry (for testing)
|
|
407
|
+
*/
|
|
408
|
+
export function resetExporterRegistry() {
|
|
409
|
+
if (globalRegistry) {
|
|
410
|
+
globalRegistry.clear();
|
|
411
|
+
}
|
|
412
|
+
globalRegistry = null;
|
|
413
|
+
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Arize Exporter
|
|
3
|
+
* Exports spans to Arize ML monitoring platform
|
|
4
|
+
*/
|
|
5
|
+
import type { ArizeExporterConfig, ExporterHealthStatus, ExportResult, SpanData } from "../types/index.js";
|
|
6
|
+
import { BaseExporter } from "./baseExporter.js";
|
|
7
|
+
/**
|
|
8
|
+
* Arize exporter for ML monitoring and prediction logs
|
|
9
|
+
* Supports feature tracking and model performance monitoring
|
|
10
|
+
*/
|
|
11
|
+
export declare class ArizeExporter extends BaseExporter {
|
|
12
|
+
private readonly spaceKey;
|
|
13
|
+
private readonly apiKey;
|
|
14
|
+
private readonly modelId;
|
|
15
|
+
private readonly modelVersion;
|
|
16
|
+
private readonly endpoint;
|
|
17
|
+
constructor(config: ArizeExporterConfig);
|
|
18
|
+
initialize(): Promise<void>;
|
|
19
|
+
exportSpan(span: SpanData): Promise<ExportResult>;
|
|
20
|
+
exportBatch(spans: SpanData[]): Promise<ExportResult>;
|
|
21
|
+
flush(): Promise<void>;
|
|
22
|
+
shutdown(): Promise<void>;
|
|
23
|
+
healthCheck(): Promise<ExporterHealthStatus>;
|
|
24
|
+
/**
|
|
25
|
+
* Verify connectivity to Arize API
|
|
26
|
+
*/
|
|
27
|
+
protected ping(): Promise<void>;
|
|
28
|
+
/**
|
|
29
|
+
* Convert span to Arize prediction log format
|
|
30
|
+
*/
|
|
31
|
+
private convertToArizePrediction;
|
|
32
|
+
}
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Arize Exporter
|
|
3
|
+
* Exports spans to Arize ML monitoring platform
|
|
4
|
+
*/
|
|
5
|
+
import { BaseExporter } from "./baseExporter.js";
|
|
6
|
+
/**
|
|
7
|
+
* Arize exporter for ML monitoring and prediction logs
|
|
8
|
+
* Supports feature tracking and model performance monitoring
|
|
9
|
+
*/
|
|
10
|
+
export class ArizeExporter extends BaseExporter {
|
|
11
|
+
spaceKey;
|
|
12
|
+
apiKey;
|
|
13
|
+
modelId;
|
|
14
|
+
modelVersion;
|
|
15
|
+
endpoint = "https://api.arize.com/v1";
|
|
16
|
+
constructor(config) {
|
|
17
|
+
super("arize", config);
|
|
18
|
+
this.spaceKey = config.spaceKey;
|
|
19
|
+
this.apiKey = config.apiKey;
|
|
20
|
+
this.modelId = config.modelId ?? "neurolink-ai";
|
|
21
|
+
this.modelVersion = config.modelVersion ?? "1.0.0";
|
|
22
|
+
}
|
|
23
|
+
async initialize() {
|
|
24
|
+
if (this.initialized) {
|
|
25
|
+
return;
|
|
26
|
+
}
|
|
27
|
+
this.initialized = true;
|
|
28
|
+
this.startFlushInterval(this.config.flushIntervalMs ?? 10000);
|
|
29
|
+
}
|
|
30
|
+
async exportSpan(span) {
|
|
31
|
+
const startTime = Date.now();
|
|
32
|
+
try {
|
|
33
|
+
const prediction = this.convertToArizePrediction(span);
|
|
34
|
+
const response = await fetch(`${this.endpoint}/log`, {
|
|
35
|
+
method: "POST",
|
|
36
|
+
headers: {
|
|
37
|
+
"Content-Type": "application/json",
|
|
38
|
+
Authorization: `Bearer ${this.apiKey}`,
|
|
39
|
+
"space-key": this.spaceKey,
|
|
40
|
+
},
|
|
41
|
+
body: JSON.stringify(prediction),
|
|
42
|
+
});
|
|
43
|
+
if (!response.ok) {
|
|
44
|
+
throw new Error(`Export failed: ${response.statusText}`);
|
|
45
|
+
}
|
|
46
|
+
return this.createSuccessResult(1, Date.now() - startTime);
|
|
47
|
+
}
|
|
48
|
+
catch (error) {
|
|
49
|
+
return this.createFailureResult([span.spanId], error instanceof Error ? error.message : String(error), Date.now() - startTime);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
async exportBatch(spans) {
|
|
53
|
+
// Arize's /v1/log endpoint does not support batch payloads, so we send
|
|
54
|
+
// individual requests in parallel. This is intentional — not a missed
|
|
55
|
+
// optimization.
|
|
56
|
+
const results = await Promise.all(spans.map((s) => this.exportSpan(s)));
|
|
57
|
+
const successful = results.filter((r) => r.success).length;
|
|
58
|
+
const failed = spans.length - successful;
|
|
59
|
+
return {
|
|
60
|
+
success: failed === 0,
|
|
61
|
+
exportedCount: successful,
|
|
62
|
+
failedCount: failed,
|
|
63
|
+
errors: results.flatMap((r) => r.errors ?? []),
|
|
64
|
+
durationMs: results.reduce((sum, r) => sum + r.durationMs, 0),
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
async flush() {
|
|
68
|
+
if (!this.initialized || this.buffer.length === 0) {
|
|
69
|
+
return;
|
|
70
|
+
}
|
|
71
|
+
const spans = [...this.buffer];
|
|
72
|
+
this.buffer = [];
|
|
73
|
+
await this.exportBatch(spans);
|
|
74
|
+
}
|
|
75
|
+
async shutdown() {
|
|
76
|
+
await this.flush();
|
|
77
|
+
this.stopFlushInterval();
|
|
78
|
+
this.initialized = false;
|
|
79
|
+
}
|
|
80
|
+
async healthCheck() {
|
|
81
|
+
try {
|
|
82
|
+
await this.withRetry(() => this.ping(), "health check");
|
|
83
|
+
return this.createHealthStatus(true);
|
|
84
|
+
}
|
|
85
|
+
catch {
|
|
86
|
+
return this.createHealthStatus(false, ["Health check failed"]);
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* Verify connectivity to Arize API
|
|
91
|
+
*/
|
|
92
|
+
async ping() {
|
|
93
|
+
const response = await fetch(`${this.endpoint}/health`, {
|
|
94
|
+
method: "GET",
|
|
95
|
+
headers: {
|
|
96
|
+
Authorization: `Bearer ${this.apiKey}`,
|
|
97
|
+
"space-key": this.spaceKey,
|
|
98
|
+
},
|
|
99
|
+
});
|
|
100
|
+
if (!response.ok && response.status !== 404) {
|
|
101
|
+
// 404 is acceptable as health endpoint may not exist
|
|
102
|
+
throw new Error(`Arize API unreachable: ${response.status}`);
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
/**
|
|
106
|
+
* Convert span to Arize prediction log format
|
|
107
|
+
*/
|
|
108
|
+
convertToArizePrediction(span) {
|
|
109
|
+
return {
|
|
110
|
+
space_key: this.spaceKey,
|
|
111
|
+
model_id: span.attributes["ai.model"] ?? this.modelId,
|
|
112
|
+
model_version: this.modelVersion,
|
|
113
|
+
prediction_id: span.spanId,
|
|
114
|
+
prediction_timestamp: new Date(span.startTime).getTime(),
|
|
115
|
+
features: {
|
|
116
|
+
provider: span.attributes["ai.provider"],
|
|
117
|
+
temperature: span.attributes["ai.temperature"],
|
|
118
|
+
max_tokens: span.attributes["ai.max_tokens"],
|
|
119
|
+
user_id: span.attributes["user.id"],
|
|
120
|
+
session_id: span.attributes["session.id"],
|
|
121
|
+
},
|
|
122
|
+
prediction: {
|
|
123
|
+
input: span.attributes["input"],
|
|
124
|
+
output: span.attributes["output"],
|
|
125
|
+
},
|
|
126
|
+
tags: {
|
|
127
|
+
span_type: span.type,
|
|
128
|
+
environment: this.config.environment,
|
|
129
|
+
},
|
|
130
|
+
latency_ms: span.durationMs,
|
|
131
|
+
token_count: {
|
|
132
|
+
prompt: span.attributes["ai.tokens.input"],
|
|
133
|
+
completion: span.attributes["ai.tokens.output"],
|
|
134
|
+
total: span.attributes["ai.tokens.total"],
|
|
135
|
+
},
|
|
136
|
+
};
|
|
137
|
+
}
|
|
138
|
+
}
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Abstract base class for all observability exporters
|
|
3
|
+
* Follows NeuroLink's factory pattern and Mastra's unified exporter interface
|
|
4
|
+
*/
|
|
5
|
+
import type { ExporterConfig, ExporterHealthStatus, ExportResult, SpanData } from "../types/index.js";
|
|
6
|
+
/**
|
|
7
|
+
* Abstract base class for all observability exporters
|
|
8
|
+
* Provides common functionality: buffering, flush intervals, health checks, retry logic
|
|
9
|
+
*/
|
|
10
|
+
export declare abstract class BaseExporter {
|
|
11
|
+
protected readonly name: string;
|
|
12
|
+
protected readonly config: ExporterConfig;
|
|
13
|
+
protected initialized: boolean;
|
|
14
|
+
protected buffer: SpanData[];
|
|
15
|
+
protected readonly maxBufferSize: number;
|
|
16
|
+
protected readonly retries: number;
|
|
17
|
+
protected flushInterval: ReturnType<typeof setInterval> | null;
|
|
18
|
+
protected lastExportTime: number;
|
|
19
|
+
constructor(name: string, config: ExporterConfig);
|
|
20
|
+
/**
|
|
21
|
+
* Initialize the exporter connection
|
|
22
|
+
* Must be called before exporting spans
|
|
23
|
+
*/
|
|
24
|
+
abstract initialize(): Promise<void>;
|
|
25
|
+
/**
|
|
26
|
+
* Export a single span
|
|
27
|
+
* @param span - The span data to export
|
|
28
|
+
*/
|
|
29
|
+
abstract exportSpan(span: SpanData): Promise<ExportResult>;
|
|
30
|
+
/**
|
|
31
|
+
* Export multiple spans in batch
|
|
32
|
+
* @param spans - Array of span data to export
|
|
33
|
+
*/
|
|
34
|
+
abstract exportBatch(spans: SpanData[]): Promise<ExportResult>;
|
|
35
|
+
/**
|
|
36
|
+
* Flush all buffered spans
|
|
37
|
+
*/
|
|
38
|
+
abstract flush(): Promise<void>;
|
|
39
|
+
/**
|
|
40
|
+
* Shutdown the exporter gracefully
|
|
41
|
+
* Should flush remaining spans before closing
|
|
42
|
+
*/
|
|
43
|
+
abstract shutdown(): Promise<void>;
|
|
44
|
+
/**
|
|
45
|
+
* Check exporter health status
|
|
46
|
+
* Implementations should make an actual API call to verify connectivity
|
|
47
|
+
*/
|
|
48
|
+
abstract healthCheck(): Promise<ExporterHealthStatus>;
|
|
49
|
+
/**
|
|
50
|
+
* Ping the exporter's backend to verify connectivity
|
|
51
|
+
* Override this in subclasses to provide backend-specific health check
|
|
52
|
+
*/
|
|
53
|
+
protected ping(): Promise<void>;
|
|
54
|
+
/**
|
|
55
|
+
* Buffer a span for batch export
|
|
56
|
+
* Triggers flush if buffer is full
|
|
57
|
+
*/
|
|
58
|
+
protected bufferSpan(span: SpanData): void;
|
|
59
|
+
/**
|
|
60
|
+
* Start automatic flush interval
|
|
61
|
+
* @param intervalMs - Interval in milliseconds between flushes
|
|
62
|
+
*/
|
|
63
|
+
protected startFlushInterval(intervalMs: number): void;
|
|
64
|
+
/**
|
|
65
|
+
* Stop the automatic flush interval
|
|
66
|
+
*/
|
|
67
|
+
protected stopFlushInterval(): void;
|
|
68
|
+
/**
|
|
69
|
+
* Get exporter name
|
|
70
|
+
*/
|
|
71
|
+
getName(): string;
|
|
72
|
+
/**
|
|
73
|
+
* Check if exporter is initialized
|
|
74
|
+
*/
|
|
75
|
+
isInitialized(): boolean;
|
|
76
|
+
/**
|
|
77
|
+
* Get number of pending spans in buffer
|
|
78
|
+
*/
|
|
79
|
+
getPendingCount(): number;
|
|
80
|
+
/**
|
|
81
|
+
* Get last export timestamp
|
|
82
|
+
*/
|
|
83
|
+
getLastExportTime(): number;
|
|
84
|
+
/**
|
|
85
|
+
* Create a standard export result for success
|
|
86
|
+
*/
|
|
87
|
+
protected createSuccessResult(exportedCount: number, durationMs: number): ExportResult;
|
|
88
|
+
/**
|
|
89
|
+
* Create a standard export result for failure
|
|
90
|
+
*/
|
|
91
|
+
protected createFailureResult(spanIds: string[], error: string, durationMs: number, retryable?: boolean): ExportResult;
|
|
92
|
+
/**
|
|
93
|
+
* Create a standard health status
|
|
94
|
+
*/
|
|
95
|
+
protected createHealthStatus(healthy: boolean, errors?: string[]): ExporterHealthStatus;
|
|
96
|
+
/**
|
|
97
|
+
* Execute an operation with exponential backoff retry
|
|
98
|
+
* @param operation - The async operation to execute
|
|
99
|
+
* @param operationName - Name for logging purposes
|
|
100
|
+
* @returns The result of the operation
|
|
101
|
+
* @throws The last error if all retries fail
|
|
102
|
+
*/
|
|
103
|
+
protected withRetry<T>(operation: () => Promise<T>, operationName: string): Promise<T>;
|
|
104
|
+
}
|
|
105
|
+
/**
|
|
106
|
+
* No-op exporter for when observability is disabled
|
|
107
|
+
* Provides zero-overhead behavior
|
|
108
|
+
*/
|
|
109
|
+
export declare class NoOpExporter extends BaseExporter {
|
|
110
|
+
constructor();
|
|
111
|
+
initialize(): Promise<void>;
|
|
112
|
+
exportSpan(_span: SpanData): Promise<ExportResult>;
|
|
113
|
+
exportBatch(_spans: SpanData[]): Promise<ExportResult>;
|
|
114
|
+
flush(): Promise<void>;
|
|
115
|
+
shutdown(): Promise<void>;
|
|
116
|
+
healthCheck(): Promise<ExporterHealthStatus>;
|
|
117
|
+
}
|