@logtide/sdk-node 0.2.0 → 0.2.2
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/dist/index.cjs +174 -12
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +62 -2
- package/dist/index.d.ts +62 -2
- package/dist/index.js +174 -12
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -42,25 +42,98 @@ var CircuitBreaker = class {
|
|
|
42
42
|
return this.state;
|
|
43
43
|
}
|
|
44
44
|
};
|
|
45
|
+
function parseNodeStackTrace(stack) {
|
|
46
|
+
if (!stack) return [];
|
|
47
|
+
const frames = [];
|
|
48
|
+
const lines = stack.split("\n");
|
|
49
|
+
for (const line of lines) {
|
|
50
|
+
const trimmed = line.trim();
|
|
51
|
+
if (!trimmed.startsWith("at ")) continue;
|
|
52
|
+
const match1 = trimmed.match(/^at\s+(.+?)\s+\((.+):(\d+):(\d+)\)$/);
|
|
53
|
+
if (match1) {
|
|
54
|
+
frames.push({
|
|
55
|
+
function: match1[1],
|
|
56
|
+
file: match1[2],
|
|
57
|
+
line: parseInt(match1[3], 10),
|
|
58
|
+
column: parseInt(match1[4], 10)
|
|
59
|
+
});
|
|
60
|
+
continue;
|
|
61
|
+
}
|
|
62
|
+
const match2 = trimmed.match(/^at\s+(.+):(\d+):(\d+)$/);
|
|
63
|
+
if (match2) {
|
|
64
|
+
frames.push({
|
|
65
|
+
file: match2[1],
|
|
66
|
+
line: parseInt(match2[2], 10),
|
|
67
|
+
column: parseInt(match2[3], 10)
|
|
68
|
+
});
|
|
69
|
+
continue;
|
|
70
|
+
}
|
|
71
|
+
const match3 = trimmed.match(/^at\s+(.+?)\s+\((.+)\)$/);
|
|
72
|
+
if (match3) {
|
|
73
|
+
frames.push({
|
|
74
|
+
function: match3[1],
|
|
75
|
+
file: match3[2]
|
|
76
|
+
});
|
|
77
|
+
continue;
|
|
78
|
+
}
|
|
79
|
+
const match4 = trimmed.match(/^at\s+(.+)$/);
|
|
80
|
+
if (match4) {
|
|
81
|
+
frames.push({
|
|
82
|
+
function: match4[1]
|
|
83
|
+
});
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
return frames;
|
|
87
|
+
}
|
|
45
88
|
function serializeError(error) {
|
|
46
89
|
if (error instanceof Error) {
|
|
47
90
|
const result = {
|
|
48
|
-
|
|
91
|
+
type: error.name,
|
|
49
92
|
message: error.message,
|
|
50
|
-
|
|
93
|
+
language: "nodejs",
|
|
94
|
+
stacktrace: parseNodeStackTrace(error.stack),
|
|
95
|
+
raw: error.stack
|
|
51
96
|
};
|
|
52
97
|
if (error.cause) {
|
|
53
98
|
result.cause = serializeError(error.cause);
|
|
54
99
|
}
|
|
100
|
+
const errorMetadata = {};
|
|
101
|
+
const standardProps = ["name", "message", "stack", "cause"];
|
|
102
|
+
for (const key of Object.keys(error)) {
|
|
103
|
+
if (!standardProps.includes(key)) {
|
|
104
|
+
errorMetadata[key] = error[key];
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
if ("code" in error) errorMetadata.code = error.code;
|
|
108
|
+
if ("errno" in error) errorMetadata.errno = error.errno;
|
|
109
|
+
if ("syscall" in error) errorMetadata.syscall = error.syscall;
|
|
110
|
+
if ("path" in error) errorMetadata.path = error.path;
|
|
111
|
+
if (Object.keys(errorMetadata).length > 0) {
|
|
112
|
+
result.metadata = errorMetadata;
|
|
113
|
+
}
|
|
55
114
|
return result;
|
|
56
115
|
}
|
|
57
116
|
if (typeof error === "string") {
|
|
58
|
-
return {
|
|
117
|
+
return {
|
|
118
|
+
type: "Error",
|
|
119
|
+
message: error,
|
|
120
|
+
language: "nodejs"
|
|
121
|
+
};
|
|
59
122
|
}
|
|
60
123
|
if (typeof error === "object" && error !== null) {
|
|
61
|
-
|
|
124
|
+
const obj = error;
|
|
125
|
+
return {
|
|
126
|
+
type: typeof obj.type === "string" ? obj.type : typeof obj.name === "string" ? obj.name : "Error",
|
|
127
|
+
message: typeof obj.message === "string" ? obj.message : JSON.stringify(error),
|
|
128
|
+
language: "nodejs",
|
|
129
|
+
metadata: obj
|
|
130
|
+
};
|
|
62
131
|
}
|
|
63
|
-
return {
|
|
132
|
+
return {
|
|
133
|
+
type: "Error",
|
|
134
|
+
message: String(error),
|
|
135
|
+
language: "nodejs"
|
|
136
|
+
};
|
|
64
137
|
}
|
|
65
138
|
var LogTideClient = class {
|
|
66
139
|
apiUrl;
|
|
@@ -92,6 +165,8 @@ var LogTideClient = class {
|
|
|
92
165
|
// Console interception
|
|
93
166
|
consoleInterceptOptions = null;
|
|
94
167
|
originalConsole = null;
|
|
168
|
+
// Payload limits
|
|
169
|
+
payloadLimits;
|
|
95
170
|
constructor(options) {
|
|
96
171
|
this.apiUrl = options.apiUrl.replace(/\/$/, "");
|
|
97
172
|
this.apiKey = options.apiKey;
|
|
@@ -108,6 +183,14 @@ var LogTideClient = class {
|
|
|
108
183
|
options.circuitBreakerThreshold || 5,
|
|
109
184
|
options.circuitBreakerResetMs || 3e4
|
|
110
185
|
);
|
|
186
|
+
this.payloadLimits = {
|
|
187
|
+
maxFieldSize: options.payloadLimits?.maxFieldSize ?? 10 * 1024,
|
|
188
|
+
// 10KB
|
|
189
|
+
maxLogSize: options.payloadLimits?.maxLogSize ?? 100 * 1024,
|
|
190
|
+
// 100KB
|
|
191
|
+
excludeFields: options.payloadLimits?.excludeFields ?? [],
|
|
192
|
+
truncationMarker: options.payloadLimits?.truncationMarker ?? "...[TRUNCATED]"
|
|
193
|
+
};
|
|
111
194
|
this.startFlushTimer();
|
|
112
195
|
if (options.interceptConsole?.enabled) {
|
|
113
196
|
this.startConsoleInterception(options.interceptConsole);
|
|
@@ -234,6 +317,12 @@ var LogTideClient = class {
|
|
|
234
317
|
return arg;
|
|
235
318
|
});
|
|
236
319
|
}
|
|
320
|
+
if (level === "error" || level === "critical") {
|
|
321
|
+
const errorArg = args.find((arg) => arg instanceof Error);
|
|
322
|
+
if (errorArg instanceof Error) {
|
|
323
|
+
metadata.exception = serializeError(errorArg);
|
|
324
|
+
}
|
|
325
|
+
}
|
|
237
326
|
this.log({
|
|
238
327
|
service: config.service,
|
|
239
328
|
level,
|
|
@@ -275,6 +364,76 @@ var LogTideClient = class {
|
|
|
275
364
|
isConsoleInterceptionActive() {
|
|
276
365
|
return this.originalConsole !== null;
|
|
277
366
|
}
|
|
367
|
+
// ==================== Payload Processing ====================
|
|
368
|
+
/**
|
|
369
|
+
* Check if a string looks like base64 encoded data
|
|
370
|
+
*/
|
|
371
|
+
looksLikeBase64(str) {
|
|
372
|
+
if (typeof str !== "string" || str.length < 100) return false;
|
|
373
|
+
if (str.startsWith("data:")) return true;
|
|
374
|
+
const base64Regex = /^[A-Za-z0-9+/=]{100,}$/;
|
|
375
|
+
return base64Regex.test(str.replace(/\s/g, ""));
|
|
376
|
+
}
|
|
377
|
+
/**
|
|
378
|
+
* Process a value for payload limits (truncation, base64 removal, etc.)
|
|
379
|
+
*/
|
|
380
|
+
processValue(value, fieldPath) {
|
|
381
|
+
const fieldName = fieldPath.split(".").pop() || fieldPath;
|
|
382
|
+
if (this.payloadLimits.excludeFields.includes(fieldName)) {
|
|
383
|
+
return "[EXCLUDED]";
|
|
384
|
+
}
|
|
385
|
+
if (value === null || value === void 0) {
|
|
386
|
+
return value;
|
|
387
|
+
}
|
|
388
|
+
if (typeof value === "string") {
|
|
389
|
+
if (this.looksLikeBase64(value)) {
|
|
390
|
+
return "[BASE64 DATA REMOVED]";
|
|
391
|
+
}
|
|
392
|
+
if (value.length > this.payloadLimits.maxFieldSize) {
|
|
393
|
+
return value.substring(0, this.payloadLimits.maxFieldSize) + this.payloadLimits.truncationMarker;
|
|
394
|
+
}
|
|
395
|
+
return value;
|
|
396
|
+
}
|
|
397
|
+
if (Array.isArray(value)) {
|
|
398
|
+
return value.map((item, index) => this.processValue(item, `${fieldPath}[${index}]`));
|
|
399
|
+
}
|
|
400
|
+
if (typeof value === "object") {
|
|
401
|
+
const processed = {};
|
|
402
|
+
for (const [key, val] of Object.entries(value)) {
|
|
403
|
+
processed[key] = this.processValue(val, `${fieldPath}.${key}`);
|
|
404
|
+
}
|
|
405
|
+
return processed;
|
|
406
|
+
}
|
|
407
|
+
return value;
|
|
408
|
+
}
|
|
409
|
+
/**
|
|
410
|
+
* Process metadata to apply payload limits
|
|
411
|
+
*/
|
|
412
|
+
processMetadata(metadata) {
|
|
413
|
+
if (!metadata) return metadata;
|
|
414
|
+
return this.processValue(metadata, "metadata");
|
|
415
|
+
}
|
|
416
|
+
/**
|
|
417
|
+
* Ensure log entry doesn't exceed max size
|
|
418
|
+
*/
|
|
419
|
+
enforceMaxLogSize(entry) {
|
|
420
|
+
const serialized = JSON.stringify(entry);
|
|
421
|
+
if (serialized.length <= this.payloadLimits.maxLogSize) {
|
|
422
|
+
return entry;
|
|
423
|
+
}
|
|
424
|
+
if (this.debugMode) {
|
|
425
|
+
console.warn(`[LogTide] Log entry too large (${serialized.length} bytes), truncating metadata`);
|
|
426
|
+
}
|
|
427
|
+
const truncated = {
|
|
428
|
+
...entry,
|
|
429
|
+
metadata: {
|
|
430
|
+
_truncated: true,
|
|
431
|
+
_originalSize: serialized.length,
|
|
432
|
+
message: entry.message
|
|
433
|
+
}
|
|
434
|
+
};
|
|
435
|
+
return truncated;
|
|
436
|
+
}
|
|
278
437
|
// ==================== Logging Methods ====================
|
|
279
438
|
startFlushTimer() {
|
|
280
439
|
this.timer = setInterval(() => {
|
|
@@ -290,15 +449,18 @@ var LogTideClient = class {
|
|
|
290
449
|
return;
|
|
291
450
|
}
|
|
292
451
|
const traceId = entry.trace_id || this.currentTraceId || (this.autoTraceId ? crypto.randomUUID() : void 0);
|
|
293
|
-
const
|
|
452
|
+
const mergedMetadata = {
|
|
453
|
+
...this.globalMetadata,
|
|
454
|
+
...entry.metadata
|
|
455
|
+
};
|
|
456
|
+
const processedMetadata = this.processMetadata(mergedMetadata);
|
|
457
|
+
let internalEntry = {
|
|
294
458
|
...entry,
|
|
295
459
|
time: entry.time || (/* @__PURE__ */ new Date()).toISOString(),
|
|
296
|
-
metadata:
|
|
297
|
-
...this.globalMetadata,
|
|
298
|
-
...entry.metadata
|
|
299
|
-
},
|
|
460
|
+
metadata: processedMetadata,
|
|
300
461
|
trace_id: traceId
|
|
301
462
|
};
|
|
463
|
+
internalEntry = this.enforceMaxLogSize(internalEntry);
|
|
302
464
|
this.buffer.push(internalEntry);
|
|
303
465
|
if (this.buffer.length >= this.batchSize) {
|
|
304
466
|
this.flush();
|
|
@@ -316,7 +478,7 @@ var LogTideClient = class {
|
|
|
316
478
|
error(service, message, metadataOrError) {
|
|
317
479
|
let metadata = {};
|
|
318
480
|
if (metadataOrError instanceof Error) {
|
|
319
|
-
metadata = {
|
|
481
|
+
metadata = { exception: serializeError(metadataOrError) };
|
|
320
482
|
} else if (metadataOrError) {
|
|
321
483
|
metadata = metadataOrError;
|
|
322
484
|
}
|
|
@@ -325,7 +487,7 @@ var LogTideClient = class {
|
|
|
325
487
|
critical(service, message, metadataOrError) {
|
|
326
488
|
let metadata = {};
|
|
327
489
|
if (metadataOrError instanceof Error) {
|
|
328
|
-
metadata = {
|
|
490
|
+
metadata = { exception: serializeError(metadataOrError) };
|
|
329
491
|
} else if (metadataOrError) {
|
|
330
492
|
metadata = metadataOrError;
|
|
331
493
|
}
|
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts"],"names":["randomUUID"],"mappings":"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","file":"index.cjs","sourcesContent":["import { randomUUID } from 'crypto';\n\n// ==================== Types ====================\n\nexport type LogLevel = 'debug' | 'info' | 'warn' | 'error' | 'critical';\n\nexport interface ConsoleInterceptOptions {\n enabled: boolean;\n service?: string;\n preserveOriginal?: boolean;\n includeStackTrace?: boolean;\n levels?: {\n log?: boolean;\n info?: boolean;\n warn?: boolean;\n error?: boolean;\n debug?: boolean;\n };\n}\n\nexport interface LogTideClientOptions {\n apiUrl: string;\n apiKey: string;\n batchSize?: number;\n flushInterval?: number;\n maxBufferSize?: number;\n maxRetries?: number;\n retryDelayMs?: number;\n circuitBreakerThreshold?: number;\n circuitBreakerResetMs?: number;\n enableMetrics?: boolean;\n debug?: boolean;\n globalMetadata?: Record<string, unknown>;\n autoTraceId?: boolean;\n interceptConsole?: ConsoleInterceptOptions;\n}\n\nexport interface LogEntry {\n service: string;\n level: LogLevel;\n message: string;\n time?: string;\n metadata?: Record<string, unknown>;\n trace_id?: string;\n}\n\nexport interface InternalLogEntry extends LogEntry {\n time: string;\n}\n\nexport interface QueryOptions {\n service?: string;\n level?: LogLevel;\n from?: Date | string;\n to?: Date | string;\n q?: string;\n limit?: number;\n offset?: number;\n}\n\nexport interface LogsResponse {\n logs: InternalLogEntry[];\n total: number;\n limit: number;\n offset: number;\n}\n\nexport interface AggregatedStatsOptions {\n from: Date | string;\n to: Date | string;\n interval?: '1m' | '5m' | '1h' | '1d';\n service?: string;\n}\n\nexport interface AggregatedStatsResponse {\n timeseries: Array<{\n bucket: string;\n total: number;\n by_level: Record<string, number>;\n }>;\n top_services: Array<{ service: string; count: number }>;\n top_errors: Array<{ message: string; count: number }>;\n}\n\nexport interface ClientMetrics {\n logsSent: number;\n logsDropped: number;\n errors: number;\n retries: number;\n avgLatencyMs: number;\n circuitBreakerTrips: number;\n}\n\nexport interface StreamOptions {\n service?: string;\n level?: LogLevel;\n onLog: (log: InternalLogEntry) => void;\n onError?: (error: Error) => void;\n}\n\n// ==================== Circuit Breaker ====================\n\nenum CircuitState {\n CLOSED = 'CLOSED',\n OPEN = 'OPEN',\n HALF_OPEN = 'HALF_OPEN',\n}\n\nclass CircuitBreaker {\n private state: CircuitState = CircuitState.CLOSED;\n private failureCount = 0;\n private lastFailureTime: number | null = null;\n\n constructor(\n private threshold: number,\n private resetMs: number,\n ) {}\n\n recordSuccess() {\n this.failureCount = 0;\n this.state = CircuitState.CLOSED;\n }\n\n recordFailure() {\n this.failureCount++;\n this.lastFailureTime = Date.now();\n\n if (this.failureCount >= this.threshold) {\n this.state = CircuitState.OPEN;\n }\n }\n\n canAttempt(): boolean {\n if (this.state === CircuitState.CLOSED) {\n return true;\n }\n\n if (this.state === CircuitState.OPEN) {\n const now = Date.now();\n if (this.lastFailureTime && now - this.lastFailureTime >= this.resetMs) {\n this.state = CircuitState.HALF_OPEN;\n return true;\n }\n return false;\n }\n\n // HALF_OPEN state - allow one attempt\n return true;\n }\n\n getState(): CircuitState {\n return this.state;\n }\n}\n\n\n// ==================== Error Serialization ====================\n\nexport function serializeError(error: unknown): Record<string, unknown> {\n if (error instanceof Error) {\n const result: Record<string, unknown> = {\n name: error.name,\n message: error.message,\n stack: error.stack,\n };\n\n if (error.cause) {\n result.cause = serializeError(error.cause);\n }\n\n return result;\n }\n\n if (typeof error === 'string') {\n return { message: error };\n }\n\n if (typeof error === 'object' && error !== null) {\n return error as Record<string, unknown>;\n }\n\n return { message: String(error) };\n}\n\n// ==================== Main Client ====================\n\nexport class LogTideClient {\n private apiUrl: string;\n private apiKey: string;\n private batchSize: number;\n private flushInterval: number;\n private maxBufferSize: number;\n private maxRetries: number;\n private retryDelayMs: number;\n private enableMetrics: boolean;\n private debugMode: boolean;\n private globalMetadata: Record<string, unknown>;\n private autoTraceId: boolean;\n\n private buffer: InternalLogEntry[] = [];\n private timer: NodeJS.Timeout | null = null;\n private circuitBreaker: CircuitBreaker;\n\n // Metrics\n private metrics: ClientMetrics = {\n logsSent: 0,\n logsDropped: 0,\n errors: 0,\n retries: 0,\n avgLatencyMs: 0,\n circuitBreakerTrips: 0,\n };\n private latencies: number[] = [];\n\n // Context tracking\n private currentTraceId: string | null = null;\n\n // Console interception\n private consoleInterceptOptions: ConsoleInterceptOptions | null = null;\n private originalConsole: {\n log: typeof console.log;\n info: typeof console.info;\n warn: typeof console.warn;\n error: typeof console.error;\n debug: typeof console.debug;\n } | null = null;\n\n constructor(options: LogTideClientOptions) {\n this.apiUrl = options.apiUrl.replace(/\\/$/, '');\n this.apiKey = options.apiKey;\n this.batchSize = options.batchSize || 100;\n this.flushInterval = options.flushInterval || 5000;\n this.maxBufferSize = options.maxBufferSize || 10000;\n this.maxRetries = options.maxRetries || 3;\n this.retryDelayMs = options.retryDelayMs || 1000;\n this.enableMetrics = options.enableMetrics ?? true;\n this.debugMode = options.debug ?? false;\n this.globalMetadata = options.globalMetadata || {};\n this.autoTraceId = options.autoTraceId ?? false;\n\n this.circuitBreaker = new CircuitBreaker(\n options.circuitBreakerThreshold || 5,\n options.circuitBreakerResetMs || 30000,\n );\n\n this.startFlushTimer();\n\n // Start console interception if configured\n if (options.interceptConsole?.enabled) {\n this.startConsoleInterception(options.interceptConsole);\n }\n }\n\n // ==================== Context Helpers ====================\n\n /**\n * Set trace ID for subsequent logs\n */\n setTraceId(traceId: string | null) {\n this.currentTraceId = traceId;\n }\n\n /**\n * Get current trace ID\n */\n getTraceId(): string | null {\n return this.currentTraceId;\n }\n\n /**\n * Execute function with a specific trace ID context\n */\n withTraceId<T>(traceId: string, fn: () => T): T {\n const previousTraceId = this.currentTraceId;\n this.currentTraceId = traceId;\n try {\n return fn();\n } finally {\n this.currentTraceId = previousTraceId;\n }\n }\n\n /**\n * Execute function with a new auto-generated trace ID\n */\n withNewTraceId<T>(fn: () => T): T {\n return this.withTraceId(randomUUID(), fn);\n }\n\n // ==================== Console Interception ====================\n\n /**\n * Start intercepting console methods and forward them to LogTide\n */\n startConsoleInterception(options?: Partial<ConsoleInterceptOptions>) {\n if (this.originalConsole) {\n // Already intercepting\n return;\n }\n\n const config: ConsoleInterceptOptions = {\n enabled: true,\n service: options?.service ?? 'console',\n preserveOriginal: options?.preserveOriginal ?? true,\n includeStackTrace: options?.includeStackTrace ?? false,\n levels: {\n log: options?.levels?.log ?? true,\n info: options?.levels?.info ?? true,\n warn: options?.levels?.warn ?? true,\n error: options?.levels?.error ?? true,\n debug: options?.levels?.debug ?? true,\n },\n };\n\n this.consoleInterceptOptions = config;\n\n // Save original console methods\n this.originalConsole = {\n log: console.log.bind(console),\n info: console.info.bind(console),\n warn: console.warn.bind(console),\n error: console.error.bind(console),\n debug: console.debug.bind(console),\n };\n\n const createInterceptor = (\n method: 'log' | 'info' | 'warn' | 'error' | 'debug',\n level: LogLevel,\n ) => {\n const original = this.originalConsole![method];\n\n return (...args: unknown[]) => {\n // Always call original if preserveOriginal is true\n if (config.preserveOriginal) {\n original(...args);\n }\n\n // Skip if this method is not configured for interception\n if (!config.levels?.[method]) {\n return;\n }\n\n // Skip internal LogTide logs to prevent infinite loops\n const message = args\n .map((arg) => {\n if (typeof arg === 'string') return arg;\n if (arg instanceof Error) return arg.message;\n try {\n return JSON.stringify(arg);\n } catch {\n return String(arg);\n }\n })\n .join(' ');\n\n if (message.startsWith('[LogTide]')) {\n return;\n }\n\n // Build metadata\n const metadata: Record<string, unknown> = {\n source: 'console',\n originalMethod: method,\n };\n\n // Include stack trace if configured\n if (config.includeStackTrace) {\n const stack = new Error().stack;\n if (stack) {\n // Remove the first two lines (Error + this interceptor function)\n const stackLines = stack.split('\\n').slice(2);\n metadata.stackTrace = stackLines.join('\\n');\n\n // Extract caller location from first relevant stack line\n const callerLine = stackLines[0];\n if (callerLine) {\n const match = callerLine.match(/at\\s+(.+?)\\s+\\((.+):(\\d+):(\\d+)\\)/);\n if (match) {\n metadata.caller = {\n function: match[1],\n file: match[2],\n line: parseInt(match[3], 10),\n column: parseInt(match[4], 10),\n };\n } else {\n // Try alternative format: \"at file:line:column\"\n const altMatch = callerLine.match(/at\\s+(.+):(\\d+):(\\d+)/);\n if (altMatch) {\n metadata.caller = {\n file: altMatch[1],\n line: parseInt(altMatch[2], 10),\n column: parseInt(altMatch[3], 10),\n };\n }\n }\n }\n }\n }\n\n // Include raw arguments for complex objects\n if (args.length > 1 || (args.length === 1 && typeof args[0] !== 'string')) {\n metadata.args = args.map((arg) => {\n if (arg instanceof Error) {\n return serializeError(arg);\n }\n return arg;\n });\n }\n\n // Log to LogTide\n this.log({\n service: config.service!,\n level,\n message,\n metadata,\n });\n };\n };\n\n // Replace console methods\n console.log = createInterceptor('log', 'info');\n console.info = createInterceptor('info', 'info');\n console.warn = createInterceptor('warn', 'warn');\n console.error = createInterceptor('error', 'error');\n console.debug = createInterceptor('debug', 'debug');\n\n if (this.debugMode) {\n this.originalConsole.log('[LogTide] Console interception started');\n }\n }\n\n /**\n * Stop intercepting console methods and restore originals\n */\n stopConsoleInterception() {\n if (!this.originalConsole) {\n return;\n }\n\n // Restore original console methods\n console.log = this.originalConsole.log;\n console.info = this.originalConsole.info;\n console.warn = this.originalConsole.warn;\n console.error = this.originalConsole.error;\n console.debug = this.originalConsole.debug;\n\n if (this.debugMode) {\n console.log('[LogTide] Console interception stopped');\n }\n\n this.originalConsole = null;\n this.consoleInterceptOptions = null;\n }\n\n /**\n * Check if console interception is active\n */\n isConsoleInterceptionActive(): boolean {\n return this.originalConsole !== null;\n }\n\n // ==================== Logging Methods ====================\n\n private startFlushTimer() {\n this.timer = setInterval(() => {\n this.flush();\n }, this.flushInterval);\n }\n\n log(entry: LogEntry) {\n // Check buffer size limit\n if (this.buffer.length >= this.maxBufferSize) {\n this.metrics.logsDropped++;\n if (this.debugMode) {\n console.warn(`[LogTide] Buffer full, dropping log: ${entry.message}`);\n }\n return;\n }\n\n // Determine trace_id: use entry's trace_id, current context, or auto-generate if enabled\n const traceId = entry.trace_id || this.currentTraceId || (this.autoTraceId ? randomUUID() : undefined);\n\n const internalEntry: InternalLogEntry = {\n ...entry,\n time: entry.time || new Date().toISOString(),\n metadata: {\n ...this.globalMetadata,\n ...entry.metadata,\n },\n trace_id: traceId,\n };\n\n this.buffer.push(internalEntry);\n\n if (this.buffer.length >= this.batchSize) {\n this.flush();\n }\n }\n\n debug(service: string, message: string, metadata?: Record<string, unknown>) {\n this.log({ service, level: 'debug', message, metadata });\n }\n\n info(service: string, message: string, metadata?: Record<string, unknown>) {\n this.log({ service, level: 'info', message, metadata });\n }\n\n warn(service: string, message: string, metadata?: Record<string, unknown>) {\n this.log({ service, level: 'warn', message, metadata });\n }\n\n error(service: string, message: string, metadataOrError?: Record<string, unknown> | Error) {\n let metadata: Record<string, unknown> = {};\n\n if (metadataOrError instanceof Error) {\n metadata = { error: serializeError(metadataOrError) };\n } else if (metadataOrError) {\n metadata = metadataOrError;\n }\n\n this.log({ service, level: 'error', message, metadata });\n }\n\n critical(service: string, message: string, metadataOrError?: Record<string, unknown> | Error) {\n let metadata: Record<string, unknown> = {};\n\n if (metadataOrError instanceof Error) {\n metadata = { error: serializeError(metadataOrError) };\n } else if (metadataOrError) {\n metadata = metadataOrError;\n }\n\n this.log({ service, level: 'critical', message, metadata });\n }\n\n // ==================== Flush with Retry & Circuit Breaker ====================\n\n async flush() {\n if (this.buffer.length === 0) return;\n\n // Check circuit breaker\n if (!this.circuitBreaker.canAttempt()) {\n this.metrics.circuitBreakerTrips++;\n if (this.debugMode) {\n console.warn('[LogTide] Circuit breaker OPEN, skipping flush');\n }\n return;\n }\n\n const logs = [...this.buffer];\n this.buffer = [];\n\n const startTime = Date.now();\n let lastError: Error | null = null;\n\n for (let attempt = 0; attempt <= this.maxRetries; attempt++) {\n try {\n const response = await fetch(`${this.apiUrl}/api/v1/ingest`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n 'X-API-Key': this.apiKey,\n },\n body: JSON.stringify({ logs }),\n });\n\n if (!response.ok) {\n const errorText = await response.text();\n throw new Error(`HTTP ${response.status}: ${errorText}`);\n }\n\n // Success\n this.circuitBreaker.recordSuccess();\n this.metrics.logsSent += logs.length;\n\n if (this.enableMetrics) {\n const latency = Date.now() - startTime;\n this.latencies.push(latency);\n if (this.latencies.length > 100) {\n this.latencies.shift();\n }\n this.metrics.avgLatencyMs =\n this.latencies.reduce((a, b) => a + b, 0) / this.latencies.length;\n }\n\n if (this.debugMode) {\n console.log(`[LogTide] Sent ${logs.length} logs successfully`);\n }\n\n return;\n } catch (error) {\n lastError = error instanceof Error ? error : new Error(String(error));\n this.metrics.errors++;\n\n if (attempt < this.maxRetries) {\n this.metrics.retries++;\n const delay = this.retryDelayMs * Math.pow(2, attempt);\n if (this.debugMode) {\n console.warn(\n `[LogTide] Retry ${attempt + 1}/${this.maxRetries} after ${delay}ms: ${lastError.message}`,\n );\n }\n await this.sleep(delay);\n }\n }\n }\n\n // All retries failed\n this.circuitBreaker.recordFailure();\n\n if (this.debugMode) {\n console.error(`[LogTide] Failed to send logs after ${this.maxRetries} retries:`, lastError);\n }\n\n // Re-add logs to buffer if not full\n if (this.buffer.length + logs.length <= this.maxBufferSize) {\n this.buffer.unshift(...logs);\n } else {\n this.metrics.logsDropped += logs.length;\n }\n }\n\n private sleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n }\n\n // ==================== Query Methods ====================\n\n async query(options: QueryOptions = {}): Promise<LogsResponse> {\n const params = new URLSearchParams();\n\n if (options.service) params.append('service', options.service);\n if (options.level) params.append('level', options.level);\n if (options.from) {\n const from = options.from instanceof Date ? options.from.toISOString() : options.from;\n params.append('from', from);\n }\n if (options.to) {\n const to = options.to instanceof Date ? options.to.toISOString() : options.to;\n params.append('to', to);\n }\n if (options.q) params.append('q', options.q);\n if (options.limit) params.append('limit', String(options.limit));\n if (options.offset) params.append('offset', String(options.offset));\n\n const url = `${this.apiUrl}/api/v1/logs?${params.toString()}`;\n\n const response = await fetch(url, {\n headers: {\n 'X-API-Key': this.apiKey,\n },\n });\n\n if (!response.ok) {\n const errorText = await response.text();\n throw new Error(`Query failed: HTTP ${response.status}: ${errorText}`);\n }\n\n return (await response.json()) as LogsResponse;\n }\n\n async getByTraceId(traceId: string): Promise<InternalLogEntry[]> {\n const url = `${this.apiUrl}/api/v1/logs/trace/${traceId}`;\n\n const response = await fetch(url, {\n headers: {\n 'X-API-Key': this.apiKey,\n },\n });\n\n if (!response.ok) {\n const errorText = await response.text();\n throw new Error(`Get by trace ID failed: HTTP ${response.status}: ${errorText}`);\n }\n\n const data = (await response.json()) as { logs?: InternalLogEntry[] };\n return data.logs || [];\n }\n\n async getAggregatedStats(options: AggregatedStatsOptions): Promise<AggregatedStatsResponse> {\n const params = new URLSearchParams();\n\n const from = options.from instanceof Date ? options.from.toISOString() : options.from;\n const to = options.to instanceof Date ? options.to.toISOString() : options.to;\n\n params.append('from', from);\n params.append('to', to);\n if (options.interval) params.append('interval', options.interval);\n if (options.service) params.append('service', options.service);\n\n const url = `${this.apiUrl}/api/v1/logs/aggregated?${params.toString()}`;\n\n const response = await fetch(url, {\n headers: {\n 'X-API-Key': this.apiKey,\n },\n });\n\n if (!response.ok) {\n const errorText = await response.text();\n throw new Error(`Get aggregated stats failed: HTTP ${response.status}: ${errorText}`);\n }\n\n return (await response.json()) as AggregatedStatsResponse;\n }\n\n // ==================== Live Tail (SSE) ====================\n\n stream(options: StreamOptions): () => void {\n const params = new URLSearchParams();\n params.append('token', this.apiKey);\n if (options.service) params.append('service', options.service);\n if (options.level) params.append('level', options.level);\n\n const url = `${this.apiUrl}/api/v1/logs/stream?${params.toString()}`;\n\n const eventSource = new EventSource(url);\n\n eventSource.addEventListener('log', (event: Event) => {\n try {\n const messageEvent = event as MessageEvent;\n const log = JSON.parse(messageEvent.data) as InternalLogEntry;\n options.onLog(log);\n } catch (error) {\n const err = error instanceof Error ? error : new Error(String(error));\n options.onError?.(err);\n }\n });\n\n eventSource.addEventListener('error', () => {\n const error = new Error('SSE connection error');\n options.onError?.(error);\n });\n\n // Return cleanup function\n return () => {\n eventSource.close();\n };\n }\n\n // ==================== Metrics ====================\n\n getMetrics(): ClientMetrics {\n return { ...this.metrics };\n }\n\n resetMetrics() {\n this.metrics = {\n logsSent: 0,\n logsDropped: 0,\n errors: 0,\n retries: 0,\n avgLatencyMs: 0,\n circuitBreakerTrips: 0,\n };\n this.latencies = [];\n }\n\n getCircuitBreakerState(): string {\n return this.circuitBreaker.getState();\n }\n\n // ==================== Cleanup ====================\n\n async close() {\n if (this.timer) {\n clearInterval(this.timer);\n this.timer = null;\n }\n this.stopConsoleInterception();\n await this.flush();\n }\n}\n\nexport default LogTideClient;\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts"],"names":["randomUUID"],"mappings":"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","file":"index.cjs","sourcesContent":["import { randomUUID } from 'crypto';\n\n// ==================== Types ====================\n\nexport type LogLevel = 'debug' | 'info' | 'warn' | 'error' | 'critical';\n\nexport interface ConsoleInterceptOptions {\n enabled: boolean;\n service?: string;\n preserveOriginal?: boolean;\n includeStackTrace?: boolean;\n levels?: {\n log?: boolean;\n info?: boolean;\n warn?: boolean;\n error?: boolean;\n debug?: boolean;\n };\n}\n\nexport interface PayloadLimitsOptions {\n /** Maximum size in bytes for a single field value (default: 10KB) */\n maxFieldSize?: number;\n /** Maximum size in bytes for the entire log entry (default: 100KB) */\n maxLogSize?: number;\n /** Fields to exclude from metadata (e.g., ['body', 'requestBody', 'responseBody']) */\n excludeFields?: string[];\n /** Marker to append when a field is truncated (default: '...[TRUNCATED]') */\n truncationMarker?: string;\n}\n\nexport interface LogTideClientOptions {\n apiUrl: string;\n apiKey: string;\n batchSize?: number;\n flushInterval?: number;\n maxBufferSize?: number;\n maxRetries?: number;\n retryDelayMs?: number;\n circuitBreakerThreshold?: number;\n circuitBreakerResetMs?: number;\n enableMetrics?: boolean;\n debug?: boolean;\n globalMetadata?: Record<string, unknown>;\n autoTraceId?: boolean;\n interceptConsole?: ConsoleInterceptOptions;\n /** Payload size limits to prevent 413 errors */\n payloadLimits?: PayloadLimitsOptions;\n}\n\nexport interface LogEntry {\n service: string;\n level: LogLevel;\n message: string;\n time?: string;\n metadata?: Record<string, unknown>;\n trace_id?: string;\n}\n\nexport interface InternalLogEntry extends LogEntry {\n time: string;\n}\n\nexport interface QueryOptions {\n service?: string;\n level?: LogLevel;\n from?: Date | string;\n to?: Date | string;\n q?: string;\n limit?: number;\n offset?: number;\n}\n\nexport interface LogsResponse {\n logs: InternalLogEntry[];\n total: number;\n limit: number;\n offset: number;\n}\n\nexport interface AggregatedStatsOptions {\n from: Date | string;\n to: Date | string;\n interval?: '1m' | '5m' | '1h' | '1d';\n service?: string;\n}\n\nexport interface AggregatedStatsResponse {\n timeseries: Array<{\n bucket: string;\n total: number;\n by_level: Record<string, number>;\n }>;\n top_services: Array<{ service: string; count: number }>;\n top_errors: Array<{ message: string; count: number }>;\n}\n\nexport interface ClientMetrics {\n logsSent: number;\n logsDropped: number;\n errors: number;\n retries: number;\n avgLatencyMs: number;\n circuitBreakerTrips: number;\n}\n\nexport interface StreamOptions {\n service?: string;\n level?: LogLevel;\n onLog: (log: InternalLogEntry) => void;\n onError?: (error: Error) => void;\n}\n\n// ==================== Circuit Breaker ====================\n\nenum CircuitState {\n CLOSED = 'CLOSED',\n OPEN = 'OPEN',\n HALF_OPEN = 'HALF_OPEN',\n}\n\nclass CircuitBreaker {\n private state: CircuitState = CircuitState.CLOSED;\n private failureCount = 0;\n private lastFailureTime: number | null = null;\n\n constructor(\n private threshold: number,\n private resetMs: number,\n ) {}\n\n recordSuccess() {\n this.failureCount = 0;\n this.state = CircuitState.CLOSED;\n }\n\n recordFailure() {\n this.failureCount++;\n this.lastFailureTime = Date.now();\n\n if (this.failureCount >= this.threshold) {\n this.state = CircuitState.OPEN;\n }\n }\n\n canAttempt(): boolean {\n if (this.state === CircuitState.CLOSED) {\n return true;\n }\n\n if (this.state === CircuitState.OPEN) {\n const now = Date.now();\n if (this.lastFailureTime && now - this.lastFailureTime >= this.resetMs) {\n this.state = CircuitState.HALF_OPEN;\n return true;\n }\n return false;\n }\n\n // HALF_OPEN state - allow one attempt\n return true;\n }\n\n getState(): CircuitState {\n return this.state;\n }\n}\n\n\n// ==================== Structured Exception Types ====================\n\nexport interface StructuredStackFrame {\n /** File path or module name */\n file?: string;\n /** Function/method name */\n function?: string;\n /** Line number (1-based) */\n line?: number;\n /** Column number */\n column?: number;\n /** Additional frame metadata */\n metadata?: Record<string, unknown>;\n}\n\nexport interface StructuredException {\n /** Exception type/class name (e.g., \"TypeError\", \"Error\") */\n type: string;\n /** Human-readable error message */\n message: string;\n /** Stack trace as an array of frames (top to bottom) */\n stacktrace?: StructuredStackFrame[];\n /** Language hint for better fingerprinting */\n language?: string;\n /** Inner/cause exception (for wrapped exceptions) */\n cause?: StructuredException;\n /** Additional exception metadata */\n metadata?: Record<string, unknown>;\n /** Original raw stack trace as a string (fallback) */\n raw?: string;\n}\n\n// ==================== Error Serialization ====================\n\n/**\n * Parse a V8/Node.js stack trace string into structured frames\n */\nfunction parseNodeStackTrace(stack: string | undefined): StructuredStackFrame[] {\n if (!stack) return [];\n\n const frames: StructuredStackFrame[] = [];\n const lines = stack.split('\\n');\n\n for (const line of lines) {\n // Skip the first line (error message) and empty lines\n const trimmed = line.trim();\n if (!trimmed.startsWith('at ')) continue;\n\n // Format 1: \"at functionName (file:line:column)\"\n const match1 = trimmed.match(/^at\\s+(.+?)\\s+\\((.+):(\\d+):(\\d+)\\)$/);\n if (match1) {\n frames.push({\n function: match1[1],\n file: match1[2],\n line: parseInt(match1[3], 10),\n column: parseInt(match1[4], 10),\n });\n continue;\n }\n\n // Format 2: \"at file:line:column\" (anonymous function)\n const match2 = trimmed.match(/^at\\s+(.+):(\\d+):(\\d+)$/);\n if (match2) {\n frames.push({\n file: match2[1],\n line: parseInt(match2[2], 10),\n column: parseInt(match2[3], 10),\n });\n continue;\n }\n\n // Format 3: \"at functionName (native)\" or similar\n const match3 = trimmed.match(/^at\\s+(.+?)\\s+\\((.+)\\)$/);\n if (match3) {\n frames.push({\n function: match3[1],\n file: match3[2],\n });\n continue;\n }\n\n // Format 4: \"at functionName\" (no file info)\n const match4 = trimmed.match(/^at\\s+(.+)$/);\n if (match4) {\n frames.push({\n function: match4[1],\n });\n }\n }\n\n return frames;\n}\n\n/**\n * Serialize an error into the StructuredException format\n */\nexport function serializeError(error: unknown): StructuredException {\n if (error instanceof Error) {\n const result: StructuredException = {\n type: error.name,\n message: error.message,\n language: 'nodejs',\n stacktrace: parseNodeStackTrace(error.stack),\n raw: error.stack,\n };\n\n // Handle error.cause (Node.js 16.9+)\n if (error.cause) {\n result.cause = serializeError(error.cause);\n }\n\n // Extract additional error properties as metadata\n const errorMetadata: Record<string, unknown> = {};\n const standardProps = ['name', 'message', 'stack', 'cause'];\n\n for (const key of Object.keys(error)) {\n if (!standardProps.includes(key)) {\n errorMetadata[key] = (error as unknown as Record<string, unknown>)[key];\n }\n }\n\n // Include common Node.js error properties\n if ('code' in error) errorMetadata.code = (error as NodeJS.ErrnoException).code;\n if ('errno' in error) errorMetadata.errno = (error as NodeJS.ErrnoException).errno;\n if ('syscall' in error) errorMetadata.syscall = (error as NodeJS.ErrnoException).syscall;\n if ('path' in error) errorMetadata.path = (error as NodeJS.ErrnoException).path;\n\n if (Object.keys(errorMetadata).length > 0) {\n result.metadata = errorMetadata;\n }\n\n return result;\n }\n\n if (typeof error === 'string') {\n return {\n type: 'Error',\n message: error,\n language: 'nodejs',\n };\n }\n\n if (typeof error === 'object' && error !== null) {\n // Try to extract type and message from the object\n const obj = error as Record<string, unknown>;\n return {\n type: (typeof obj.type === 'string' ? obj.type : typeof obj.name === 'string' ? obj.name : 'Error'),\n message: (typeof obj.message === 'string' ? obj.message : JSON.stringify(error)),\n language: 'nodejs',\n metadata: obj,\n };\n }\n\n return {\n type: 'Error',\n message: String(error),\n language: 'nodejs',\n };\n}\n\n// ==================== Main Client ====================\n\nexport class LogTideClient {\n private apiUrl: string;\n private apiKey: string;\n private batchSize: number;\n private flushInterval: number;\n private maxBufferSize: number;\n private maxRetries: number;\n private retryDelayMs: number;\n private enableMetrics: boolean;\n private debugMode: boolean;\n private globalMetadata: Record<string, unknown>;\n private autoTraceId: boolean;\n\n private buffer: InternalLogEntry[] = [];\n private timer: NodeJS.Timeout | null = null;\n private circuitBreaker: CircuitBreaker;\n\n // Metrics\n private metrics: ClientMetrics = {\n logsSent: 0,\n logsDropped: 0,\n errors: 0,\n retries: 0,\n avgLatencyMs: 0,\n circuitBreakerTrips: 0,\n };\n private latencies: number[] = [];\n\n // Context tracking\n private currentTraceId: string | null = null;\n\n // Console interception\n private consoleInterceptOptions: ConsoleInterceptOptions | null = null;\n private originalConsole: {\n log: typeof console.log;\n info: typeof console.info;\n warn: typeof console.warn;\n error: typeof console.error;\n debug: typeof console.debug;\n } | null = null;\n\n // Payload limits\n private payloadLimits: Required<PayloadLimitsOptions>;\n\n constructor(options: LogTideClientOptions) {\n this.apiUrl = options.apiUrl.replace(/\\/$/, '');\n this.apiKey = options.apiKey;\n this.batchSize = options.batchSize || 100;\n this.flushInterval = options.flushInterval || 5000;\n this.maxBufferSize = options.maxBufferSize || 10000;\n this.maxRetries = options.maxRetries || 3;\n this.retryDelayMs = options.retryDelayMs || 1000;\n this.enableMetrics = options.enableMetrics ?? true;\n this.debugMode = options.debug ?? false;\n this.globalMetadata = options.globalMetadata || {};\n this.autoTraceId = options.autoTraceId ?? false;\n\n this.circuitBreaker = new CircuitBreaker(\n options.circuitBreakerThreshold || 5,\n options.circuitBreakerResetMs || 30000,\n );\n\n // Initialize payload limits with defaults\n this.payloadLimits = {\n maxFieldSize: options.payloadLimits?.maxFieldSize ?? 10 * 1024, // 10KB\n maxLogSize: options.payloadLimits?.maxLogSize ?? 100 * 1024, // 100KB\n excludeFields: options.payloadLimits?.excludeFields ?? [],\n truncationMarker: options.payloadLimits?.truncationMarker ?? '...[TRUNCATED]',\n };\n\n this.startFlushTimer();\n\n // Start console interception if configured\n if (options.interceptConsole?.enabled) {\n this.startConsoleInterception(options.interceptConsole);\n }\n }\n\n // ==================== Context Helpers ====================\n\n /**\n * Set trace ID for subsequent logs\n */\n setTraceId(traceId: string | null) {\n this.currentTraceId = traceId;\n }\n\n /**\n * Get current trace ID\n */\n getTraceId(): string | null {\n return this.currentTraceId;\n }\n\n /**\n * Execute function with a specific trace ID context\n */\n withTraceId<T>(traceId: string, fn: () => T): T {\n const previousTraceId = this.currentTraceId;\n this.currentTraceId = traceId;\n try {\n return fn();\n } finally {\n this.currentTraceId = previousTraceId;\n }\n }\n\n /**\n * Execute function with a new auto-generated trace ID\n */\n withNewTraceId<T>(fn: () => T): T {\n return this.withTraceId(randomUUID(), fn);\n }\n\n // ==================== Console Interception ====================\n\n /**\n * Start intercepting console methods and forward them to LogTide\n */\n startConsoleInterception(options?: Partial<ConsoleInterceptOptions>) {\n if (this.originalConsole) {\n // Already intercepting\n return;\n }\n\n const config: ConsoleInterceptOptions = {\n enabled: true,\n service: options?.service ?? 'console',\n preserveOriginal: options?.preserveOriginal ?? true,\n includeStackTrace: options?.includeStackTrace ?? false,\n levels: {\n log: options?.levels?.log ?? true,\n info: options?.levels?.info ?? true,\n warn: options?.levels?.warn ?? true,\n error: options?.levels?.error ?? true,\n debug: options?.levels?.debug ?? true,\n },\n };\n\n this.consoleInterceptOptions = config;\n\n // Save original console methods\n this.originalConsole = {\n log: console.log.bind(console),\n info: console.info.bind(console),\n warn: console.warn.bind(console),\n error: console.error.bind(console),\n debug: console.debug.bind(console),\n };\n\n const createInterceptor = (\n method: 'log' | 'info' | 'warn' | 'error' | 'debug',\n level: LogLevel,\n ) => {\n const original = this.originalConsole![method];\n\n return (...args: unknown[]) => {\n // Always call original if preserveOriginal is true\n if (config.preserveOriginal) {\n original(...args);\n }\n\n // Skip if this method is not configured for interception\n if (!config.levels?.[method]) {\n return;\n }\n\n // Skip internal LogTide logs to prevent infinite loops\n const message = args\n .map((arg) => {\n if (typeof arg === 'string') return arg;\n if (arg instanceof Error) return arg.message;\n try {\n return JSON.stringify(arg);\n } catch {\n return String(arg);\n }\n })\n .join(' ');\n\n if (message.startsWith('[LogTide]')) {\n return;\n }\n\n // Build metadata\n const metadata: Record<string, unknown> = {\n source: 'console',\n originalMethod: method,\n };\n\n // Include stack trace if configured\n if (config.includeStackTrace) {\n const stack = new Error().stack;\n if (stack) {\n // Remove the first two lines (Error + this interceptor function)\n const stackLines = stack.split('\\n').slice(2);\n metadata.stackTrace = stackLines.join('\\n');\n\n // Extract caller location from first relevant stack line\n const callerLine = stackLines[0];\n if (callerLine) {\n const match = callerLine.match(/at\\s+(.+?)\\s+\\((.+):(\\d+):(\\d+)\\)/);\n if (match) {\n metadata.caller = {\n function: match[1],\n file: match[2],\n line: parseInt(match[3], 10),\n column: parseInt(match[4], 10),\n };\n } else {\n // Try alternative format: \"at file:line:column\"\n const altMatch = callerLine.match(/at\\s+(.+):(\\d+):(\\d+)/);\n if (altMatch) {\n metadata.caller = {\n file: altMatch[1],\n line: parseInt(altMatch[2], 10),\n column: parseInt(altMatch[3], 10),\n };\n }\n }\n }\n }\n }\n\n // Include raw arguments for complex objects\n if (args.length > 1 || (args.length === 1 && typeof args[0] !== 'string')) {\n metadata.args = args.map((arg) => {\n if (arg instanceof Error) {\n return serializeError(arg);\n }\n return arg;\n });\n }\n\n // For error level, if any argument is an Error, add it to metadata.exception\n if (level === 'error' || level === 'critical') {\n const errorArg = args.find((arg) => arg instanceof Error);\n if (errorArg instanceof Error) {\n metadata.exception = serializeError(errorArg);\n }\n }\n\n // Log to LogTide\n this.log({\n service: config.service!,\n level,\n message,\n metadata,\n });\n };\n };\n\n // Replace console methods\n console.log = createInterceptor('log', 'info');\n console.info = createInterceptor('info', 'info');\n console.warn = createInterceptor('warn', 'warn');\n console.error = createInterceptor('error', 'error');\n console.debug = createInterceptor('debug', 'debug');\n\n if (this.debugMode) {\n this.originalConsole.log('[LogTide] Console interception started');\n }\n }\n\n /**\n * Stop intercepting console methods and restore originals\n */\n stopConsoleInterception() {\n if (!this.originalConsole) {\n return;\n }\n\n // Restore original console methods\n console.log = this.originalConsole.log;\n console.info = this.originalConsole.info;\n console.warn = this.originalConsole.warn;\n console.error = this.originalConsole.error;\n console.debug = this.originalConsole.debug;\n\n if (this.debugMode) {\n console.log('[LogTide] Console interception stopped');\n }\n\n this.originalConsole = null;\n this.consoleInterceptOptions = null;\n }\n\n /**\n * Check if console interception is active\n */\n isConsoleInterceptionActive(): boolean {\n return this.originalConsole !== null;\n }\n\n // ==================== Payload Processing ====================\n\n /**\n * Check if a string looks like base64 encoded data\n */\n private looksLikeBase64(str: string): boolean {\n if (typeof str !== 'string' || str.length < 100) return false;\n // Check for common base64 patterns: data URLs or long base64 strings\n if (str.startsWith('data:')) return true;\n // Check if it's a long string with only base64 characters\n const base64Regex = /^[A-Za-z0-9+/=]{100,}$/;\n return base64Regex.test(str.replace(/\\s/g, ''));\n }\n\n /**\n * Process a value for payload limits (truncation, base64 removal, etc.)\n */\n private processValue(value: unknown, fieldPath: string): unknown {\n // Check if this field should be excluded\n const fieldName = fieldPath.split('.').pop() || fieldPath;\n if (this.payloadLimits.excludeFields.includes(fieldName)) {\n return '[EXCLUDED]';\n }\n\n if (value === null || value === undefined) {\n return value;\n }\n\n if (typeof value === 'string') {\n // Check for base64 data\n if (this.looksLikeBase64(value)) {\n return '[BASE64 DATA REMOVED]';\n }\n // Truncate if too long\n if (value.length > this.payloadLimits.maxFieldSize) {\n return value.substring(0, this.payloadLimits.maxFieldSize) + this.payloadLimits.truncationMarker;\n }\n return value;\n }\n\n if (Array.isArray(value)) {\n return value.map((item, index) => this.processValue(item, `${fieldPath}[${index}]`));\n }\n\n if (typeof value === 'object') {\n const processed: Record<string, unknown> = {};\n for (const [key, val] of Object.entries(value as Record<string, unknown>)) {\n processed[key] = this.processValue(val, `${fieldPath}.${key}`);\n }\n return processed;\n }\n\n return value;\n }\n\n /**\n * Process metadata to apply payload limits\n */\n private processMetadata(metadata: Record<string, unknown> | undefined): Record<string, unknown> | undefined {\n if (!metadata) return metadata;\n return this.processValue(metadata, 'metadata') as Record<string, unknown>;\n }\n\n /**\n * Ensure log entry doesn't exceed max size\n */\n private enforceMaxLogSize(entry: InternalLogEntry): InternalLogEntry {\n const serialized = JSON.stringify(entry);\n if (serialized.length <= this.payloadLimits.maxLogSize) {\n return entry;\n }\n\n // Log is too large, progressively truncate metadata\n if (this.debugMode) {\n console.warn(`[LogTide] Log entry too large (${serialized.length} bytes), truncating metadata`);\n }\n\n // Create a copy and truncate metadata heavily\n const truncated: InternalLogEntry = {\n ...entry,\n metadata: {\n _truncated: true,\n _originalSize: serialized.length,\n message: entry.message,\n },\n };\n\n return truncated;\n }\n\n // ==================== Logging Methods ====================\n\n private startFlushTimer() {\n this.timer = setInterval(() => {\n this.flush();\n }, this.flushInterval);\n }\n\n log(entry: LogEntry) {\n // Check buffer size limit\n if (this.buffer.length >= this.maxBufferSize) {\n this.metrics.logsDropped++;\n if (this.debugMode) {\n console.warn(`[LogTide] Buffer full, dropping log: ${entry.message}`);\n }\n return;\n }\n\n // Determine trace_id: use entry's trace_id, current context, or auto-generate if enabled\n const traceId = entry.trace_id || this.currentTraceId || (this.autoTraceId ? randomUUID() : undefined);\n\n // Merge and process metadata (applies truncation, exclusion, base64 removal)\n const mergedMetadata = {\n ...this.globalMetadata,\n ...entry.metadata,\n };\n const processedMetadata = this.processMetadata(mergedMetadata);\n\n let internalEntry: InternalLogEntry = {\n ...entry,\n time: entry.time || new Date().toISOString(),\n metadata: processedMetadata,\n trace_id: traceId,\n };\n\n // Enforce max log size\n internalEntry = this.enforceMaxLogSize(internalEntry);\n\n this.buffer.push(internalEntry);\n\n if (this.buffer.length >= this.batchSize) {\n this.flush();\n }\n }\n\n debug(service: string, message: string, metadata?: Record<string, unknown>) {\n this.log({ service, level: 'debug', message, metadata });\n }\n\n info(service: string, message: string, metadata?: Record<string, unknown>) {\n this.log({ service, level: 'info', message, metadata });\n }\n\n warn(service: string, message: string, metadata?: Record<string, unknown>) {\n this.log({ service, level: 'warn', message, metadata });\n }\n\n error(service: string, message: string, metadataOrError?: Record<string, unknown> | Error) {\n let metadata: Record<string, unknown> = {};\n\n if (metadataOrError instanceof Error) {\n metadata = { exception: serializeError(metadataOrError) };\n } else if (metadataOrError) {\n metadata = metadataOrError;\n }\n\n this.log({ service, level: 'error', message, metadata });\n }\n\n critical(service: string, message: string, metadataOrError?: Record<string, unknown> | Error) {\n let metadata: Record<string, unknown> = {};\n\n if (metadataOrError instanceof Error) {\n metadata = { exception: serializeError(metadataOrError) };\n } else if (metadataOrError) {\n metadata = metadataOrError;\n }\n\n this.log({ service, level: 'critical', message, metadata });\n }\n\n // ==================== Flush with Retry & Circuit Breaker ====================\n\n async flush() {\n if (this.buffer.length === 0) return;\n\n // Check circuit breaker\n if (!this.circuitBreaker.canAttempt()) {\n this.metrics.circuitBreakerTrips++;\n if (this.debugMode) {\n console.warn('[LogTide] Circuit breaker OPEN, skipping flush');\n }\n return;\n }\n\n const logs = [...this.buffer];\n this.buffer = [];\n\n const startTime = Date.now();\n let lastError: Error | null = null;\n\n for (let attempt = 0; attempt <= this.maxRetries; attempt++) {\n try {\n const response = await fetch(`${this.apiUrl}/api/v1/ingest`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n 'X-API-Key': this.apiKey,\n },\n body: JSON.stringify({ logs }),\n });\n\n if (!response.ok) {\n const errorText = await response.text();\n throw new Error(`HTTP ${response.status}: ${errorText}`);\n }\n\n // Success\n this.circuitBreaker.recordSuccess();\n this.metrics.logsSent += logs.length;\n\n if (this.enableMetrics) {\n const latency = Date.now() - startTime;\n this.latencies.push(latency);\n if (this.latencies.length > 100) {\n this.latencies.shift();\n }\n this.metrics.avgLatencyMs =\n this.latencies.reduce((a, b) => a + b, 0) / this.latencies.length;\n }\n\n if (this.debugMode) {\n console.log(`[LogTide] Sent ${logs.length} logs successfully`);\n }\n\n return;\n } catch (error) {\n lastError = error instanceof Error ? error : new Error(String(error));\n this.metrics.errors++;\n\n if (attempt < this.maxRetries) {\n this.metrics.retries++;\n const delay = this.retryDelayMs * Math.pow(2, attempt);\n if (this.debugMode) {\n console.warn(\n `[LogTide] Retry ${attempt + 1}/${this.maxRetries} after ${delay}ms: ${lastError.message}`,\n );\n }\n await this.sleep(delay);\n }\n }\n }\n\n // All retries failed\n this.circuitBreaker.recordFailure();\n\n if (this.debugMode) {\n console.error(`[LogTide] Failed to send logs after ${this.maxRetries} retries:`, lastError);\n }\n\n // Re-add logs to buffer if not full\n if (this.buffer.length + logs.length <= this.maxBufferSize) {\n this.buffer.unshift(...logs);\n } else {\n this.metrics.logsDropped += logs.length;\n }\n }\n\n private sleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n }\n\n // ==================== Query Methods ====================\n\n async query(options: QueryOptions = {}): Promise<LogsResponse> {\n const params = new URLSearchParams();\n\n if (options.service) params.append('service', options.service);\n if (options.level) params.append('level', options.level);\n if (options.from) {\n const from = options.from instanceof Date ? options.from.toISOString() : options.from;\n params.append('from', from);\n }\n if (options.to) {\n const to = options.to instanceof Date ? options.to.toISOString() : options.to;\n params.append('to', to);\n }\n if (options.q) params.append('q', options.q);\n if (options.limit) params.append('limit', String(options.limit));\n if (options.offset) params.append('offset', String(options.offset));\n\n const url = `${this.apiUrl}/api/v1/logs?${params.toString()}`;\n\n const response = await fetch(url, {\n headers: {\n 'X-API-Key': this.apiKey,\n },\n });\n\n if (!response.ok) {\n const errorText = await response.text();\n throw new Error(`Query failed: HTTP ${response.status}: ${errorText}`);\n }\n\n return (await response.json()) as LogsResponse;\n }\n\n async getByTraceId(traceId: string): Promise<InternalLogEntry[]> {\n const url = `${this.apiUrl}/api/v1/logs/trace/${traceId}`;\n\n const response = await fetch(url, {\n headers: {\n 'X-API-Key': this.apiKey,\n },\n });\n\n if (!response.ok) {\n const errorText = await response.text();\n throw new Error(`Get by trace ID failed: HTTP ${response.status}: ${errorText}`);\n }\n\n const data = (await response.json()) as { logs?: InternalLogEntry[] };\n return data.logs || [];\n }\n\n async getAggregatedStats(options: AggregatedStatsOptions): Promise<AggregatedStatsResponse> {\n const params = new URLSearchParams();\n\n const from = options.from instanceof Date ? options.from.toISOString() : options.from;\n const to = options.to instanceof Date ? options.to.toISOString() : options.to;\n\n params.append('from', from);\n params.append('to', to);\n if (options.interval) params.append('interval', options.interval);\n if (options.service) params.append('service', options.service);\n\n const url = `${this.apiUrl}/api/v1/logs/aggregated?${params.toString()}`;\n\n const response = await fetch(url, {\n headers: {\n 'X-API-Key': this.apiKey,\n },\n });\n\n if (!response.ok) {\n const errorText = await response.text();\n throw new Error(`Get aggregated stats failed: HTTP ${response.status}: ${errorText}`);\n }\n\n return (await response.json()) as AggregatedStatsResponse;\n }\n\n // ==================== Live Tail (SSE) ====================\n\n stream(options: StreamOptions): () => void {\n const params = new URLSearchParams();\n params.append('token', this.apiKey);\n if (options.service) params.append('service', options.service);\n if (options.level) params.append('level', options.level);\n\n const url = `${this.apiUrl}/api/v1/logs/stream?${params.toString()}`;\n\n const eventSource = new EventSource(url);\n\n eventSource.addEventListener('log', (event: Event) => {\n try {\n const messageEvent = event as MessageEvent;\n const log = JSON.parse(messageEvent.data) as InternalLogEntry;\n options.onLog(log);\n } catch (error) {\n const err = error instanceof Error ? error : new Error(String(error));\n options.onError?.(err);\n }\n });\n\n eventSource.addEventListener('error', () => {\n const error = new Error('SSE connection error');\n options.onError?.(error);\n });\n\n // Return cleanup function\n return () => {\n eventSource.close();\n };\n }\n\n // ==================== Metrics ====================\n\n getMetrics(): ClientMetrics {\n return { ...this.metrics };\n }\n\n resetMetrics() {\n this.metrics = {\n logsSent: 0,\n logsDropped: 0,\n errors: 0,\n retries: 0,\n avgLatencyMs: 0,\n circuitBreakerTrips: 0,\n };\n this.latencies = [];\n }\n\n getCircuitBreakerState(): string {\n return this.circuitBreaker.getState();\n }\n\n // ==================== Cleanup ====================\n\n async close() {\n if (this.timer) {\n clearInterval(this.timer);\n this.timer = null;\n }\n this.stopConsoleInterception();\n await this.flush();\n }\n}\n\nexport default LogTideClient;\n"]}
|
package/dist/index.d.cts
CHANGED
|
@@ -12,6 +12,16 @@ interface ConsoleInterceptOptions {
|
|
|
12
12
|
debug?: boolean;
|
|
13
13
|
};
|
|
14
14
|
}
|
|
15
|
+
interface PayloadLimitsOptions {
|
|
16
|
+
/** Maximum size in bytes for a single field value (default: 10KB) */
|
|
17
|
+
maxFieldSize?: number;
|
|
18
|
+
/** Maximum size in bytes for the entire log entry (default: 100KB) */
|
|
19
|
+
maxLogSize?: number;
|
|
20
|
+
/** Fields to exclude from metadata (e.g., ['body', 'requestBody', 'responseBody']) */
|
|
21
|
+
excludeFields?: string[];
|
|
22
|
+
/** Marker to append when a field is truncated (default: '...[TRUNCATED]') */
|
|
23
|
+
truncationMarker?: string;
|
|
24
|
+
}
|
|
15
25
|
interface LogTideClientOptions {
|
|
16
26
|
apiUrl: string;
|
|
17
27
|
apiKey: string;
|
|
@@ -27,6 +37,8 @@ interface LogTideClientOptions {
|
|
|
27
37
|
globalMetadata?: Record<string, unknown>;
|
|
28
38
|
autoTraceId?: boolean;
|
|
29
39
|
interceptConsole?: ConsoleInterceptOptions;
|
|
40
|
+
/** Payload size limits to prevent 413 errors */
|
|
41
|
+
payloadLimits?: PayloadLimitsOptions;
|
|
30
42
|
}
|
|
31
43
|
interface LogEntry {
|
|
32
44
|
service: string;
|
|
@@ -89,7 +101,38 @@ interface StreamOptions {
|
|
|
89
101
|
onLog: (log: InternalLogEntry) => void;
|
|
90
102
|
onError?: (error: Error) => void;
|
|
91
103
|
}
|
|
92
|
-
|
|
104
|
+
interface StructuredStackFrame {
|
|
105
|
+
/** File path or module name */
|
|
106
|
+
file?: string;
|
|
107
|
+
/** Function/method name */
|
|
108
|
+
function?: string;
|
|
109
|
+
/** Line number (1-based) */
|
|
110
|
+
line?: number;
|
|
111
|
+
/** Column number */
|
|
112
|
+
column?: number;
|
|
113
|
+
/** Additional frame metadata */
|
|
114
|
+
metadata?: Record<string, unknown>;
|
|
115
|
+
}
|
|
116
|
+
interface StructuredException {
|
|
117
|
+
/** Exception type/class name (e.g., "TypeError", "Error") */
|
|
118
|
+
type: string;
|
|
119
|
+
/** Human-readable error message */
|
|
120
|
+
message: string;
|
|
121
|
+
/** Stack trace as an array of frames (top to bottom) */
|
|
122
|
+
stacktrace?: StructuredStackFrame[];
|
|
123
|
+
/** Language hint for better fingerprinting */
|
|
124
|
+
language?: string;
|
|
125
|
+
/** Inner/cause exception (for wrapped exceptions) */
|
|
126
|
+
cause?: StructuredException;
|
|
127
|
+
/** Additional exception metadata */
|
|
128
|
+
metadata?: Record<string, unknown>;
|
|
129
|
+
/** Original raw stack trace as a string (fallback) */
|
|
130
|
+
raw?: string;
|
|
131
|
+
}
|
|
132
|
+
/**
|
|
133
|
+
* Serialize an error into the StructuredException format
|
|
134
|
+
*/
|
|
135
|
+
declare function serializeError(error: unknown): StructuredException;
|
|
93
136
|
declare class LogTideClient {
|
|
94
137
|
private apiUrl;
|
|
95
138
|
private apiKey;
|
|
@@ -110,6 +153,7 @@ declare class LogTideClient {
|
|
|
110
153
|
private currentTraceId;
|
|
111
154
|
private consoleInterceptOptions;
|
|
112
155
|
private originalConsole;
|
|
156
|
+
private payloadLimits;
|
|
113
157
|
constructor(options: LogTideClientOptions);
|
|
114
158
|
/**
|
|
115
159
|
* Set trace ID for subsequent logs
|
|
@@ -139,6 +183,22 @@ declare class LogTideClient {
|
|
|
139
183
|
* Check if console interception is active
|
|
140
184
|
*/
|
|
141
185
|
isConsoleInterceptionActive(): boolean;
|
|
186
|
+
/**
|
|
187
|
+
* Check if a string looks like base64 encoded data
|
|
188
|
+
*/
|
|
189
|
+
private looksLikeBase64;
|
|
190
|
+
/**
|
|
191
|
+
* Process a value for payload limits (truncation, base64 removal, etc.)
|
|
192
|
+
*/
|
|
193
|
+
private processValue;
|
|
194
|
+
/**
|
|
195
|
+
* Process metadata to apply payload limits
|
|
196
|
+
*/
|
|
197
|
+
private processMetadata;
|
|
198
|
+
/**
|
|
199
|
+
* Ensure log entry doesn't exceed max size
|
|
200
|
+
*/
|
|
201
|
+
private enforceMaxLogSize;
|
|
142
202
|
private startFlushTimer;
|
|
143
203
|
log(entry: LogEntry): void;
|
|
144
204
|
debug(service: string, message: string, metadata?: Record<string, unknown>): void;
|
|
@@ -158,4 +218,4 @@ declare class LogTideClient {
|
|
|
158
218
|
close(): Promise<void>;
|
|
159
219
|
}
|
|
160
220
|
|
|
161
|
-
export { type AggregatedStatsOptions, type AggregatedStatsResponse, type ClientMetrics, type ConsoleInterceptOptions, type InternalLogEntry, type LogEntry, type LogLevel, LogTideClient, type LogTideClientOptions, type LogsResponse, type QueryOptions, type StreamOptions, LogTideClient as default, serializeError };
|
|
221
|
+
export { type AggregatedStatsOptions, type AggregatedStatsResponse, type ClientMetrics, type ConsoleInterceptOptions, type InternalLogEntry, type LogEntry, type LogLevel, LogTideClient, type LogTideClientOptions, type LogsResponse, type PayloadLimitsOptions, type QueryOptions, type StreamOptions, type StructuredException, type StructuredStackFrame, LogTideClient as default, serializeError };
|
package/dist/index.d.ts
CHANGED
|
@@ -12,6 +12,16 @@ interface ConsoleInterceptOptions {
|
|
|
12
12
|
debug?: boolean;
|
|
13
13
|
};
|
|
14
14
|
}
|
|
15
|
+
interface PayloadLimitsOptions {
|
|
16
|
+
/** Maximum size in bytes for a single field value (default: 10KB) */
|
|
17
|
+
maxFieldSize?: number;
|
|
18
|
+
/** Maximum size in bytes for the entire log entry (default: 100KB) */
|
|
19
|
+
maxLogSize?: number;
|
|
20
|
+
/** Fields to exclude from metadata (e.g., ['body', 'requestBody', 'responseBody']) */
|
|
21
|
+
excludeFields?: string[];
|
|
22
|
+
/** Marker to append when a field is truncated (default: '...[TRUNCATED]') */
|
|
23
|
+
truncationMarker?: string;
|
|
24
|
+
}
|
|
15
25
|
interface LogTideClientOptions {
|
|
16
26
|
apiUrl: string;
|
|
17
27
|
apiKey: string;
|
|
@@ -27,6 +37,8 @@ interface LogTideClientOptions {
|
|
|
27
37
|
globalMetadata?: Record<string, unknown>;
|
|
28
38
|
autoTraceId?: boolean;
|
|
29
39
|
interceptConsole?: ConsoleInterceptOptions;
|
|
40
|
+
/** Payload size limits to prevent 413 errors */
|
|
41
|
+
payloadLimits?: PayloadLimitsOptions;
|
|
30
42
|
}
|
|
31
43
|
interface LogEntry {
|
|
32
44
|
service: string;
|
|
@@ -89,7 +101,38 @@ interface StreamOptions {
|
|
|
89
101
|
onLog: (log: InternalLogEntry) => void;
|
|
90
102
|
onError?: (error: Error) => void;
|
|
91
103
|
}
|
|
92
|
-
|
|
104
|
+
interface StructuredStackFrame {
|
|
105
|
+
/** File path or module name */
|
|
106
|
+
file?: string;
|
|
107
|
+
/** Function/method name */
|
|
108
|
+
function?: string;
|
|
109
|
+
/** Line number (1-based) */
|
|
110
|
+
line?: number;
|
|
111
|
+
/** Column number */
|
|
112
|
+
column?: number;
|
|
113
|
+
/** Additional frame metadata */
|
|
114
|
+
metadata?: Record<string, unknown>;
|
|
115
|
+
}
|
|
116
|
+
interface StructuredException {
|
|
117
|
+
/** Exception type/class name (e.g., "TypeError", "Error") */
|
|
118
|
+
type: string;
|
|
119
|
+
/** Human-readable error message */
|
|
120
|
+
message: string;
|
|
121
|
+
/** Stack trace as an array of frames (top to bottom) */
|
|
122
|
+
stacktrace?: StructuredStackFrame[];
|
|
123
|
+
/** Language hint for better fingerprinting */
|
|
124
|
+
language?: string;
|
|
125
|
+
/** Inner/cause exception (for wrapped exceptions) */
|
|
126
|
+
cause?: StructuredException;
|
|
127
|
+
/** Additional exception metadata */
|
|
128
|
+
metadata?: Record<string, unknown>;
|
|
129
|
+
/** Original raw stack trace as a string (fallback) */
|
|
130
|
+
raw?: string;
|
|
131
|
+
}
|
|
132
|
+
/**
|
|
133
|
+
* Serialize an error into the StructuredException format
|
|
134
|
+
*/
|
|
135
|
+
declare function serializeError(error: unknown): StructuredException;
|
|
93
136
|
declare class LogTideClient {
|
|
94
137
|
private apiUrl;
|
|
95
138
|
private apiKey;
|
|
@@ -110,6 +153,7 @@ declare class LogTideClient {
|
|
|
110
153
|
private currentTraceId;
|
|
111
154
|
private consoleInterceptOptions;
|
|
112
155
|
private originalConsole;
|
|
156
|
+
private payloadLimits;
|
|
113
157
|
constructor(options: LogTideClientOptions);
|
|
114
158
|
/**
|
|
115
159
|
* Set trace ID for subsequent logs
|
|
@@ -139,6 +183,22 @@ declare class LogTideClient {
|
|
|
139
183
|
* Check if console interception is active
|
|
140
184
|
*/
|
|
141
185
|
isConsoleInterceptionActive(): boolean;
|
|
186
|
+
/**
|
|
187
|
+
* Check if a string looks like base64 encoded data
|
|
188
|
+
*/
|
|
189
|
+
private looksLikeBase64;
|
|
190
|
+
/**
|
|
191
|
+
* Process a value for payload limits (truncation, base64 removal, etc.)
|
|
192
|
+
*/
|
|
193
|
+
private processValue;
|
|
194
|
+
/**
|
|
195
|
+
* Process metadata to apply payload limits
|
|
196
|
+
*/
|
|
197
|
+
private processMetadata;
|
|
198
|
+
/**
|
|
199
|
+
* Ensure log entry doesn't exceed max size
|
|
200
|
+
*/
|
|
201
|
+
private enforceMaxLogSize;
|
|
142
202
|
private startFlushTimer;
|
|
143
203
|
log(entry: LogEntry): void;
|
|
144
204
|
debug(service: string, message: string, metadata?: Record<string, unknown>): void;
|
|
@@ -158,4 +218,4 @@ declare class LogTideClient {
|
|
|
158
218
|
close(): Promise<void>;
|
|
159
219
|
}
|
|
160
220
|
|
|
161
|
-
export { type AggregatedStatsOptions, type AggregatedStatsResponse, type ClientMetrics, type ConsoleInterceptOptions, type InternalLogEntry, type LogEntry, type LogLevel, LogTideClient, type LogTideClientOptions, type LogsResponse, type QueryOptions, type StreamOptions, LogTideClient as default, serializeError };
|
|
221
|
+
export { type AggregatedStatsOptions, type AggregatedStatsResponse, type ClientMetrics, type ConsoleInterceptOptions, type InternalLogEntry, type LogEntry, type LogLevel, LogTideClient, type LogTideClientOptions, type LogsResponse, type PayloadLimitsOptions, type QueryOptions, type StreamOptions, type StructuredException, type StructuredStackFrame, LogTideClient as default, serializeError };
|
package/dist/index.js
CHANGED
|
@@ -38,25 +38,98 @@ var CircuitBreaker = class {
|
|
|
38
38
|
return this.state;
|
|
39
39
|
}
|
|
40
40
|
};
|
|
41
|
+
function parseNodeStackTrace(stack) {
|
|
42
|
+
if (!stack) return [];
|
|
43
|
+
const frames = [];
|
|
44
|
+
const lines = stack.split("\n");
|
|
45
|
+
for (const line of lines) {
|
|
46
|
+
const trimmed = line.trim();
|
|
47
|
+
if (!trimmed.startsWith("at ")) continue;
|
|
48
|
+
const match1 = trimmed.match(/^at\s+(.+?)\s+\((.+):(\d+):(\d+)\)$/);
|
|
49
|
+
if (match1) {
|
|
50
|
+
frames.push({
|
|
51
|
+
function: match1[1],
|
|
52
|
+
file: match1[2],
|
|
53
|
+
line: parseInt(match1[3], 10),
|
|
54
|
+
column: parseInt(match1[4], 10)
|
|
55
|
+
});
|
|
56
|
+
continue;
|
|
57
|
+
}
|
|
58
|
+
const match2 = trimmed.match(/^at\s+(.+):(\d+):(\d+)$/);
|
|
59
|
+
if (match2) {
|
|
60
|
+
frames.push({
|
|
61
|
+
file: match2[1],
|
|
62
|
+
line: parseInt(match2[2], 10),
|
|
63
|
+
column: parseInt(match2[3], 10)
|
|
64
|
+
});
|
|
65
|
+
continue;
|
|
66
|
+
}
|
|
67
|
+
const match3 = trimmed.match(/^at\s+(.+?)\s+\((.+)\)$/);
|
|
68
|
+
if (match3) {
|
|
69
|
+
frames.push({
|
|
70
|
+
function: match3[1],
|
|
71
|
+
file: match3[2]
|
|
72
|
+
});
|
|
73
|
+
continue;
|
|
74
|
+
}
|
|
75
|
+
const match4 = trimmed.match(/^at\s+(.+)$/);
|
|
76
|
+
if (match4) {
|
|
77
|
+
frames.push({
|
|
78
|
+
function: match4[1]
|
|
79
|
+
});
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
return frames;
|
|
83
|
+
}
|
|
41
84
|
function serializeError(error) {
|
|
42
85
|
if (error instanceof Error) {
|
|
43
86
|
const result = {
|
|
44
|
-
|
|
87
|
+
type: error.name,
|
|
45
88
|
message: error.message,
|
|
46
|
-
|
|
89
|
+
language: "nodejs",
|
|
90
|
+
stacktrace: parseNodeStackTrace(error.stack),
|
|
91
|
+
raw: error.stack
|
|
47
92
|
};
|
|
48
93
|
if (error.cause) {
|
|
49
94
|
result.cause = serializeError(error.cause);
|
|
50
95
|
}
|
|
96
|
+
const errorMetadata = {};
|
|
97
|
+
const standardProps = ["name", "message", "stack", "cause"];
|
|
98
|
+
for (const key of Object.keys(error)) {
|
|
99
|
+
if (!standardProps.includes(key)) {
|
|
100
|
+
errorMetadata[key] = error[key];
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
if ("code" in error) errorMetadata.code = error.code;
|
|
104
|
+
if ("errno" in error) errorMetadata.errno = error.errno;
|
|
105
|
+
if ("syscall" in error) errorMetadata.syscall = error.syscall;
|
|
106
|
+
if ("path" in error) errorMetadata.path = error.path;
|
|
107
|
+
if (Object.keys(errorMetadata).length > 0) {
|
|
108
|
+
result.metadata = errorMetadata;
|
|
109
|
+
}
|
|
51
110
|
return result;
|
|
52
111
|
}
|
|
53
112
|
if (typeof error === "string") {
|
|
54
|
-
return {
|
|
113
|
+
return {
|
|
114
|
+
type: "Error",
|
|
115
|
+
message: error,
|
|
116
|
+
language: "nodejs"
|
|
117
|
+
};
|
|
55
118
|
}
|
|
56
119
|
if (typeof error === "object" && error !== null) {
|
|
57
|
-
|
|
120
|
+
const obj = error;
|
|
121
|
+
return {
|
|
122
|
+
type: typeof obj.type === "string" ? obj.type : typeof obj.name === "string" ? obj.name : "Error",
|
|
123
|
+
message: typeof obj.message === "string" ? obj.message : JSON.stringify(error),
|
|
124
|
+
language: "nodejs",
|
|
125
|
+
metadata: obj
|
|
126
|
+
};
|
|
58
127
|
}
|
|
59
|
-
return {
|
|
128
|
+
return {
|
|
129
|
+
type: "Error",
|
|
130
|
+
message: String(error),
|
|
131
|
+
language: "nodejs"
|
|
132
|
+
};
|
|
60
133
|
}
|
|
61
134
|
var LogTideClient = class {
|
|
62
135
|
apiUrl;
|
|
@@ -88,6 +161,8 @@ var LogTideClient = class {
|
|
|
88
161
|
// Console interception
|
|
89
162
|
consoleInterceptOptions = null;
|
|
90
163
|
originalConsole = null;
|
|
164
|
+
// Payload limits
|
|
165
|
+
payloadLimits;
|
|
91
166
|
constructor(options) {
|
|
92
167
|
this.apiUrl = options.apiUrl.replace(/\/$/, "");
|
|
93
168
|
this.apiKey = options.apiKey;
|
|
@@ -104,6 +179,14 @@ var LogTideClient = class {
|
|
|
104
179
|
options.circuitBreakerThreshold || 5,
|
|
105
180
|
options.circuitBreakerResetMs || 3e4
|
|
106
181
|
);
|
|
182
|
+
this.payloadLimits = {
|
|
183
|
+
maxFieldSize: options.payloadLimits?.maxFieldSize ?? 10 * 1024,
|
|
184
|
+
// 10KB
|
|
185
|
+
maxLogSize: options.payloadLimits?.maxLogSize ?? 100 * 1024,
|
|
186
|
+
// 100KB
|
|
187
|
+
excludeFields: options.payloadLimits?.excludeFields ?? [],
|
|
188
|
+
truncationMarker: options.payloadLimits?.truncationMarker ?? "...[TRUNCATED]"
|
|
189
|
+
};
|
|
107
190
|
this.startFlushTimer();
|
|
108
191
|
if (options.interceptConsole?.enabled) {
|
|
109
192
|
this.startConsoleInterception(options.interceptConsole);
|
|
@@ -230,6 +313,12 @@ var LogTideClient = class {
|
|
|
230
313
|
return arg;
|
|
231
314
|
});
|
|
232
315
|
}
|
|
316
|
+
if (level === "error" || level === "critical") {
|
|
317
|
+
const errorArg = args.find((arg) => arg instanceof Error);
|
|
318
|
+
if (errorArg instanceof Error) {
|
|
319
|
+
metadata.exception = serializeError(errorArg);
|
|
320
|
+
}
|
|
321
|
+
}
|
|
233
322
|
this.log({
|
|
234
323
|
service: config.service,
|
|
235
324
|
level,
|
|
@@ -271,6 +360,76 @@ var LogTideClient = class {
|
|
|
271
360
|
isConsoleInterceptionActive() {
|
|
272
361
|
return this.originalConsole !== null;
|
|
273
362
|
}
|
|
363
|
+
// ==================== Payload Processing ====================
|
|
364
|
+
/**
|
|
365
|
+
* Check if a string looks like base64 encoded data
|
|
366
|
+
*/
|
|
367
|
+
looksLikeBase64(str) {
|
|
368
|
+
if (typeof str !== "string" || str.length < 100) return false;
|
|
369
|
+
if (str.startsWith("data:")) return true;
|
|
370
|
+
const base64Regex = /^[A-Za-z0-9+/=]{100,}$/;
|
|
371
|
+
return base64Regex.test(str.replace(/\s/g, ""));
|
|
372
|
+
}
|
|
373
|
+
/**
|
|
374
|
+
* Process a value for payload limits (truncation, base64 removal, etc.)
|
|
375
|
+
*/
|
|
376
|
+
processValue(value, fieldPath) {
|
|
377
|
+
const fieldName = fieldPath.split(".").pop() || fieldPath;
|
|
378
|
+
if (this.payloadLimits.excludeFields.includes(fieldName)) {
|
|
379
|
+
return "[EXCLUDED]";
|
|
380
|
+
}
|
|
381
|
+
if (value === null || value === void 0) {
|
|
382
|
+
return value;
|
|
383
|
+
}
|
|
384
|
+
if (typeof value === "string") {
|
|
385
|
+
if (this.looksLikeBase64(value)) {
|
|
386
|
+
return "[BASE64 DATA REMOVED]";
|
|
387
|
+
}
|
|
388
|
+
if (value.length > this.payloadLimits.maxFieldSize) {
|
|
389
|
+
return value.substring(0, this.payloadLimits.maxFieldSize) + this.payloadLimits.truncationMarker;
|
|
390
|
+
}
|
|
391
|
+
return value;
|
|
392
|
+
}
|
|
393
|
+
if (Array.isArray(value)) {
|
|
394
|
+
return value.map((item, index) => this.processValue(item, `${fieldPath}[${index}]`));
|
|
395
|
+
}
|
|
396
|
+
if (typeof value === "object") {
|
|
397
|
+
const processed = {};
|
|
398
|
+
for (const [key, val] of Object.entries(value)) {
|
|
399
|
+
processed[key] = this.processValue(val, `${fieldPath}.${key}`);
|
|
400
|
+
}
|
|
401
|
+
return processed;
|
|
402
|
+
}
|
|
403
|
+
return value;
|
|
404
|
+
}
|
|
405
|
+
/**
|
|
406
|
+
* Process metadata to apply payload limits
|
|
407
|
+
*/
|
|
408
|
+
processMetadata(metadata) {
|
|
409
|
+
if (!metadata) return metadata;
|
|
410
|
+
return this.processValue(metadata, "metadata");
|
|
411
|
+
}
|
|
412
|
+
/**
|
|
413
|
+
* Ensure log entry doesn't exceed max size
|
|
414
|
+
*/
|
|
415
|
+
enforceMaxLogSize(entry) {
|
|
416
|
+
const serialized = JSON.stringify(entry);
|
|
417
|
+
if (serialized.length <= this.payloadLimits.maxLogSize) {
|
|
418
|
+
return entry;
|
|
419
|
+
}
|
|
420
|
+
if (this.debugMode) {
|
|
421
|
+
console.warn(`[LogTide] Log entry too large (${serialized.length} bytes), truncating metadata`);
|
|
422
|
+
}
|
|
423
|
+
const truncated = {
|
|
424
|
+
...entry,
|
|
425
|
+
metadata: {
|
|
426
|
+
_truncated: true,
|
|
427
|
+
_originalSize: serialized.length,
|
|
428
|
+
message: entry.message
|
|
429
|
+
}
|
|
430
|
+
};
|
|
431
|
+
return truncated;
|
|
432
|
+
}
|
|
274
433
|
// ==================== Logging Methods ====================
|
|
275
434
|
startFlushTimer() {
|
|
276
435
|
this.timer = setInterval(() => {
|
|
@@ -286,15 +445,18 @@ var LogTideClient = class {
|
|
|
286
445
|
return;
|
|
287
446
|
}
|
|
288
447
|
const traceId = entry.trace_id || this.currentTraceId || (this.autoTraceId ? randomUUID() : void 0);
|
|
289
|
-
const
|
|
448
|
+
const mergedMetadata = {
|
|
449
|
+
...this.globalMetadata,
|
|
450
|
+
...entry.metadata
|
|
451
|
+
};
|
|
452
|
+
const processedMetadata = this.processMetadata(mergedMetadata);
|
|
453
|
+
let internalEntry = {
|
|
290
454
|
...entry,
|
|
291
455
|
time: entry.time || (/* @__PURE__ */ new Date()).toISOString(),
|
|
292
|
-
metadata:
|
|
293
|
-
...this.globalMetadata,
|
|
294
|
-
...entry.metadata
|
|
295
|
-
},
|
|
456
|
+
metadata: processedMetadata,
|
|
296
457
|
trace_id: traceId
|
|
297
458
|
};
|
|
459
|
+
internalEntry = this.enforceMaxLogSize(internalEntry);
|
|
298
460
|
this.buffer.push(internalEntry);
|
|
299
461
|
if (this.buffer.length >= this.batchSize) {
|
|
300
462
|
this.flush();
|
|
@@ -312,7 +474,7 @@ var LogTideClient = class {
|
|
|
312
474
|
error(service, message, metadataOrError) {
|
|
313
475
|
let metadata = {};
|
|
314
476
|
if (metadataOrError instanceof Error) {
|
|
315
|
-
metadata = {
|
|
477
|
+
metadata = { exception: serializeError(metadataOrError) };
|
|
316
478
|
} else if (metadataOrError) {
|
|
317
479
|
metadata = metadataOrError;
|
|
318
480
|
}
|
|
@@ -321,7 +483,7 @@ var LogTideClient = class {
|
|
|
321
483
|
critical(service, message, metadataOrError) {
|
|
322
484
|
let metadata = {};
|
|
323
485
|
if (metadataOrError instanceof Error) {
|
|
324
|
-
metadata = {
|
|
486
|
+
metadata = { exception: serializeError(metadataOrError) };
|
|
325
487
|
} else if (metadataOrError) {
|
|
326
488
|
metadata = metadataOrError;
|
|
327
489
|
}
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts"],"names":[],"mappings":"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","file":"index.js","sourcesContent":["import { randomUUID } from 'crypto';\n\n// ==================== Types ====================\n\nexport type LogLevel = 'debug' | 'info' | 'warn' | 'error' | 'critical';\n\nexport interface ConsoleInterceptOptions {\n enabled: boolean;\n service?: string;\n preserveOriginal?: boolean;\n includeStackTrace?: boolean;\n levels?: {\n log?: boolean;\n info?: boolean;\n warn?: boolean;\n error?: boolean;\n debug?: boolean;\n };\n}\n\nexport interface LogTideClientOptions {\n apiUrl: string;\n apiKey: string;\n batchSize?: number;\n flushInterval?: number;\n maxBufferSize?: number;\n maxRetries?: number;\n retryDelayMs?: number;\n circuitBreakerThreshold?: number;\n circuitBreakerResetMs?: number;\n enableMetrics?: boolean;\n debug?: boolean;\n globalMetadata?: Record<string, unknown>;\n autoTraceId?: boolean;\n interceptConsole?: ConsoleInterceptOptions;\n}\n\nexport interface LogEntry {\n service: string;\n level: LogLevel;\n message: string;\n time?: string;\n metadata?: Record<string, unknown>;\n trace_id?: string;\n}\n\nexport interface InternalLogEntry extends LogEntry {\n time: string;\n}\n\nexport interface QueryOptions {\n service?: string;\n level?: LogLevel;\n from?: Date | string;\n to?: Date | string;\n q?: string;\n limit?: number;\n offset?: number;\n}\n\nexport interface LogsResponse {\n logs: InternalLogEntry[];\n total: number;\n limit: number;\n offset: number;\n}\n\nexport interface AggregatedStatsOptions {\n from: Date | string;\n to: Date | string;\n interval?: '1m' | '5m' | '1h' | '1d';\n service?: string;\n}\n\nexport interface AggregatedStatsResponse {\n timeseries: Array<{\n bucket: string;\n total: number;\n by_level: Record<string, number>;\n }>;\n top_services: Array<{ service: string; count: number }>;\n top_errors: Array<{ message: string; count: number }>;\n}\n\nexport interface ClientMetrics {\n logsSent: number;\n logsDropped: number;\n errors: number;\n retries: number;\n avgLatencyMs: number;\n circuitBreakerTrips: number;\n}\n\nexport interface StreamOptions {\n service?: string;\n level?: LogLevel;\n onLog: (log: InternalLogEntry) => void;\n onError?: (error: Error) => void;\n}\n\n// ==================== Circuit Breaker ====================\n\nenum CircuitState {\n CLOSED = 'CLOSED',\n OPEN = 'OPEN',\n HALF_OPEN = 'HALF_OPEN',\n}\n\nclass CircuitBreaker {\n private state: CircuitState = CircuitState.CLOSED;\n private failureCount = 0;\n private lastFailureTime: number | null = null;\n\n constructor(\n private threshold: number,\n private resetMs: number,\n ) {}\n\n recordSuccess() {\n this.failureCount = 0;\n this.state = CircuitState.CLOSED;\n }\n\n recordFailure() {\n this.failureCount++;\n this.lastFailureTime = Date.now();\n\n if (this.failureCount >= this.threshold) {\n this.state = CircuitState.OPEN;\n }\n }\n\n canAttempt(): boolean {\n if (this.state === CircuitState.CLOSED) {\n return true;\n }\n\n if (this.state === CircuitState.OPEN) {\n const now = Date.now();\n if (this.lastFailureTime && now - this.lastFailureTime >= this.resetMs) {\n this.state = CircuitState.HALF_OPEN;\n return true;\n }\n return false;\n }\n\n // HALF_OPEN state - allow one attempt\n return true;\n }\n\n getState(): CircuitState {\n return this.state;\n }\n}\n\n\n// ==================== Error Serialization ====================\n\nexport function serializeError(error: unknown): Record<string, unknown> {\n if (error instanceof Error) {\n const result: Record<string, unknown> = {\n name: error.name,\n message: error.message,\n stack: error.stack,\n };\n\n if (error.cause) {\n result.cause = serializeError(error.cause);\n }\n\n return result;\n }\n\n if (typeof error === 'string') {\n return { message: error };\n }\n\n if (typeof error === 'object' && error !== null) {\n return error as Record<string, unknown>;\n }\n\n return { message: String(error) };\n}\n\n// ==================== Main Client ====================\n\nexport class LogTideClient {\n private apiUrl: string;\n private apiKey: string;\n private batchSize: number;\n private flushInterval: number;\n private maxBufferSize: number;\n private maxRetries: number;\n private retryDelayMs: number;\n private enableMetrics: boolean;\n private debugMode: boolean;\n private globalMetadata: Record<string, unknown>;\n private autoTraceId: boolean;\n\n private buffer: InternalLogEntry[] = [];\n private timer: NodeJS.Timeout | null = null;\n private circuitBreaker: CircuitBreaker;\n\n // Metrics\n private metrics: ClientMetrics = {\n logsSent: 0,\n logsDropped: 0,\n errors: 0,\n retries: 0,\n avgLatencyMs: 0,\n circuitBreakerTrips: 0,\n };\n private latencies: number[] = [];\n\n // Context tracking\n private currentTraceId: string | null = null;\n\n // Console interception\n private consoleInterceptOptions: ConsoleInterceptOptions | null = null;\n private originalConsole: {\n log: typeof console.log;\n info: typeof console.info;\n warn: typeof console.warn;\n error: typeof console.error;\n debug: typeof console.debug;\n } | null = null;\n\n constructor(options: LogTideClientOptions) {\n this.apiUrl = options.apiUrl.replace(/\\/$/, '');\n this.apiKey = options.apiKey;\n this.batchSize = options.batchSize || 100;\n this.flushInterval = options.flushInterval || 5000;\n this.maxBufferSize = options.maxBufferSize || 10000;\n this.maxRetries = options.maxRetries || 3;\n this.retryDelayMs = options.retryDelayMs || 1000;\n this.enableMetrics = options.enableMetrics ?? true;\n this.debugMode = options.debug ?? false;\n this.globalMetadata = options.globalMetadata || {};\n this.autoTraceId = options.autoTraceId ?? false;\n\n this.circuitBreaker = new CircuitBreaker(\n options.circuitBreakerThreshold || 5,\n options.circuitBreakerResetMs || 30000,\n );\n\n this.startFlushTimer();\n\n // Start console interception if configured\n if (options.interceptConsole?.enabled) {\n this.startConsoleInterception(options.interceptConsole);\n }\n }\n\n // ==================== Context Helpers ====================\n\n /**\n * Set trace ID for subsequent logs\n */\n setTraceId(traceId: string | null) {\n this.currentTraceId = traceId;\n }\n\n /**\n * Get current trace ID\n */\n getTraceId(): string | null {\n return this.currentTraceId;\n }\n\n /**\n * Execute function with a specific trace ID context\n */\n withTraceId<T>(traceId: string, fn: () => T): T {\n const previousTraceId = this.currentTraceId;\n this.currentTraceId = traceId;\n try {\n return fn();\n } finally {\n this.currentTraceId = previousTraceId;\n }\n }\n\n /**\n * Execute function with a new auto-generated trace ID\n */\n withNewTraceId<T>(fn: () => T): T {\n return this.withTraceId(randomUUID(), fn);\n }\n\n // ==================== Console Interception ====================\n\n /**\n * Start intercepting console methods and forward them to LogTide\n */\n startConsoleInterception(options?: Partial<ConsoleInterceptOptions>) {\n if (this.originalConsole) {\n // Already intercepting\n return;\n }\n\n const config: ConsoleInterceptOptions = {\n enabled: true,\n service: options?.service ?? 'console',\n preserveOriginal: options?.preserveOriginal ?? true,\n includeStackTrace: options?.includeStackTrace ?? false,\n levels: {\n log: options?.levels?.log ?? true,\n info: options?.levels?.info ?? true,\n warn: options?.levels?.warn ?? true,\n error: options?.levels?.error ?? true,\n debug: options?.levels?.debug ?? true,\n },\n };\n\n this.consoleInterceptOptions = config;\n\n // Save original console methods\n this.originalConsole = {\n log: console.log.bind(console),\n info: console.info.bind(console),\n warn: console.warn.bind(console),\n error: console.error.bind(console),\n debug: console.debug.bind(console),\n };\n\n const createInterceptor = (\n method: 'log' | 'info' | 'warn' | 'error' | 'debug',\n level: LogLevel,\n ) => {\n const original = this.originalConsole![method];\n\n return (...args: unknown[]) => {\n // Always call original if preserveOriginal is true\n if (config.preserveOriginal) {\n original(...args);\n }\n\n // Skip if this method is not configured for interception\n if (!config.levels?.[method]) {\n return;\n }\n\n // Skip internal LogTide logs to prevent infinite loops\n const message = args\n .map((arg) => {\n if (typeof arg === 'string') return arg;\n if (arg instanceof Error) return arg.message;\n try {\n return JSON.stringify(arg);\n } catch {\n return String(arg);\n }\n })\n .join(' ');\n\n if (message.startsWith('[LogTide]')) {\n return;\n }\n\n // Build metadata\n const metadata: Record<string, unknown> = {\n source: 'console',\n originalMethod: method,\n };\n\n // Include stack trace if configured\n if (config.includeStackTrace) {\n const stack = new Error().stack;\n if (stack) {\n // Remove the first two lines (Error + this interceptor function)\n const stackLines = stack.split('\\n').slice(2);\n metadata.stackTrace = stackLines.join('\\n');\n\n // Extract caller location from first relevant stack line\n const callerLine = stackLines[0];\n if (callerLine) {\n const match = callerLine.match(/at\\s+(.+?)\\s+\\((.+):(\\d+):(\\d+)\\)/);\n if (match) {\n metadata.caller = {\n function: match[1],\n file: match[2],\n line: parseInt(match[3], 10),\n column: parseInt(match[4], 10),\n };\n } else {\n // Try alternative format: \"at file:line:column\"\n const altMatch = callerLine.match(/at\\s+(.+):(\\d+):(\\d+)/);\n if (altMatch) {\n metadata.caller = {\n file: altMatch[1],\n line: parseInt(altMatch[2], 10),\n column: parseInt(altMatch[3], 10),\n };\n }\n }\n }\n }\n }\n\n // Include raw arguments for complex objects\n if (args.length > 1 || (args.length === 1 && typeof args[0] !== 'string')) {\n metadata.args = args.map((arg) => {\n if (arg instanceof Error) {\n return serializeError(arg);\n }\n return arg;\n });\n }\n\n // Log to LogTide\n this.log({\n service: config.service!,\n level,\n message,\n metadata,\n });\n };\n };\n\n // Replace console methods\n console.log = createInterceptor('log', 'info');\n console.info = createInterceptor('info', 'info');\n console.warn = createInterceptor('warn', 'warn');\n console.error = createInterceptor('error', 'error');\n console.debug = createInterceptor('debug', 'debug');\n\n if (this.debugMode) {\n this.originalConsole.log('[LogTide] Console interception started');\n }\n }\n\n /**\n * Stop intercepting console methods and restore originals\n */\n stopConsoleInterception() {\n if (!this.originalConsole) {\n return;\n }\n\n // Restore original console methods\n console.log = this.originalConsole.log;\n console.info = this.originalConsole.info;\n console.warn = this.originalConsole.warn;\n console.error = this.originalConsole.error;\n console.debug = this.originalConsole.debug;\n\n if (this.debugMode) {\n console.log('[LogTide] Console interception stopped');\n }\n\n this.originalConsole = null;\n this.consoleInterceptOptions = null;\n }\n\n /**\n * Check if console interception is active\n */\n isConsoleInterceptionActive(): boolean {\n return this.originalConsole !== null;\n }\n\n // ==================== Logging Methods ====================\n\n private startFlushTimer() {\n this.timer = setInterval(() => {\n this.flush();\n }, this.flushInterval);\n }\n\n log(entry: LogEntry) {\n // Check buffer size limit\n if (this.buffer.length >= this.maxBufferSize) {\n this.metrics.logsDropped++;\n if (this.debugMode) {\n console.warn(`[LogTide] Buffer full, dropping log: ${entry.message}`);\n }\n return;\n }\n\n // Determine trace_id: use entry's trace_id, current context, or auto-generate if enabled\n const traceId = entry.trace_id || this.currentTraceId || (this.autoTraceId ? randomUUID() : undefined);\n\n const internalEntry: InternalLogEntry = {\n ...entry,\n time: entry.time || new Date().toISOString(),\n metadata: {\n ...this.globalMetadata,\n ...entry.metadata,\n },\n trace_id: traceId,\n };\n\n this.buffer.push(internalEntry);\n\n if (this.buffer.length >= this.batchSize) {\n this.flush();\n }\n }\n\n debug(service: string, message: string, metadata?: Record<string, unknown>) {\n this.log({ service, level: 'debug', message, metadata });\n }\n\n info(service: string, message: string, metadata?: Record<string, unknown>) {\n this.log({ service, level: 'info', message, metadata });\n }\n\n warn(service: string, message: string, metadata?: Record<string, unknown>) {\n this.log({ service, level: 'warn', message, metadata });\n }\n\n error(service: string, message: string, metadataOrError?: Record<string, unknown> | Error) {\n let metadata: Record<string, unknown> = {};\n\n if (metadataOrError instanceof Error) {\n metadata = { error: serializeError(metadataOrError) };\n } else if (metadataOrError) {\n metadata = metadataOrError;\n }\n\n this.log({ service, level: 'error', message, metadata });\n }\n\n critical(service: string, message: string, metadataOrError?: Record<string, unknown> | Error) {\n let metadata: Record<string, unknown> = {};\n\n if (metadataOrError instanceof Error) {\n metadata = { error: serializeError(metadataOrError) };\n } else if (metadataOrError) {\n metadata = metadataOrError;\n }\n\n this.log({ service, level: 'critical', message, metadata });\n }\n\n // ==================== Flush with Retry & Circuit Breaker ====================\n\n async flush() {\n if (this.buffer.length === 0) return;\n\n // Check circuit breaker\n if (!this.circuitBreaker.canAttempt()) {\n this.metrics.circuitBreakerTrips++;\n if (this.debugMode) {\n console.warn('[LogTide] Circuit breaker OPEN, skipping flush');\n }\n return;\n }\n\n const logs = [...this.buffer];\n this.buffer = [];\n\n const startTime = Date.now();\n let lastError: Error | null = null;\n\n for (let attempt = 0; attempt <= this.maxRetries; attempt++) {\n try {\n const response = await fetch(`${this.apiUrl}/api/v1/ingest`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n 'X-API-Key': this.apiKey,\n },\n body: JSON.stringify({ logs }),\n });\n\n if (!response.ok) {\n const errorText = await response.text();\n throw new Error(`HTTP ${response.status}: ${errorText}`);\n }\n\n // Success\n this.circuitBreaker.recordSuccess();\n this.metrics.logsSent += logs.length;\n\n if (this.enableMetrics) {\n const latency = Date.now() - startTime;\n this.latencies.push(latency);\n if (this.latencies.length > 100) {\n this.latencies.shift();\n }\n this.metrics.avgLatencyMs =\n this.latencies.reduce((a, b) => a + b, 0) / this.latencies.length;\n }\n\n if (this.debugMode) {\n console.log(`[LogTide] Sent ${logs.length} logs successfully`);\n }\n\n return;\n } catch (error) {\n lastError = error instanceof Error ? error : new Error(String(error));\n this.metrics.errors++;\n\n if (attempt < this.maxRetries) {\n this.metrics.retries++;\n const delay = this.retryDelayMs * Math.pow(2, attempt);\n if (this.debugMode) {\n console.warn(\n `[LogTide] Retry ${attempt + 1}/${this.maxRetries} after ${delay}ms: ${lastError.message}`,\n );\n }\n await this.sleep(delay);\n }\n }\n }\n\n // All retries failed\n this.circuitBreaker.recordFailure();\n\n if (this.debugMode) {\n console.error(`[LogTide] Failed to send logs after ${this.maxRetries} retries:`, lastError);\n }\n\n // Re-add logs to buffer if not full\n if (this.buffer.length + logs.length <= this.maxBufferSize) {\n this.buffer.unshift(...logs);\n } else {\n this.metrics.logsDropped += logs.length;\n }\n }\n\n private sleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n }\n\n // ==================== Query Methods ====================\n\n async query(options: QueryOptions = {}): Promise<LogsResponse> {\n const params = new URLSearchParams();\n\n if (options.service) params.append('service', options.service);\n if (options.level) params.append('level', options.level);\n if (options.from) {\n const from = options.from instanceof Date ? options.from.toISOString() : options.from;\n params.append('from', from);\n }\n if (options.to) {\n const to = options.to instanceof Date ? options.to.toISOString() : options.to;\n params.append('to', to);\n }\n if (options.q) params.append('q', options.q);\n if (options.limit) params.append('limit', String(options.limit));\n if (options.offset) params.append('offset', String(options.offset));\n\n const url = `${this.apiUrl}/api/v1/logs?${params.toString()}`;\n\n const response = await fetch(url, {\n headers: {\n 'X-API-Key': this.apiKey,\n },\n });\n\n if (!response.ok) {\n const errorText = await response.text();\n throw new Error(`Query failed: HTTP ${response.status}: ${errorText}`);\n }\n\n return (await response.json()) as LogsResponse;\n }\n\n async getByTraceId(traceId: string): Promise<InternalLogEntry[]> {\n const url = `${this.apiUrl}/api/v1/logs/trace/${traceId}`;\n\n const response = await fetch(url, {\n headers: {\n 'X-API-Key': this.apiKey,\n },\n });\n\n if (!response.ok) {\n const errorText = await response.text();\n throw new Error(`Get by trace ID failed: HTTP ${response.status}: ${errorText}`);\n }\n\n const data = (await response.json()) as { logs?: InternalLogEntry[] };\n return data.logs || [];\n }\n\n async getAggregatedStats(options: AggregatedStatsOptions): Promise<AggregatedStatsResponse> {\n const params = new URLSearchParams();\n\n const from = options.from instanceof Date ? options.from.toISOString() : options.from;\n const to = options.to instanceof Date ? options.to.toISOString() : options.to;\n\n params.append('from', from);\n params.append('to', to);\n if (options.interval) params.append('interval', options.interval);\n if (options.service) params.append('service', options.service);\n\n const url = `${this.apiUrl}/api/v1/logs/aggregated?${params.toString()}`;\n\n const response = await fetch(url, {\n headers: {\n 'X-API-Key': this.apiKey,\n },\n });\n\n if (!response.ok) {\n const errorText = await response.text();\n throw new Error(`Get aggregated stats failed: HTTP ${response.status}: ${errorText}`);\n }\n\n return (await response.json()) as AggregatedStatsResponse;\n }\n\n // ==================== Live Tail (SSE) ====================\n\n stream(options: StreamOptions): () => void {\n const params = new URLSearchParams();\n params.append('token', this.apiKey);\n if (options.service) params.append('service', options.service);\n if (options.level) params.append('level', options.level);\n\n const url = `${this.apiUrl}/api/v1/logs/stream?${params.toString()}`;\n\n const eventSource = new EventSource(url);\n\n eventSource.addEventListener('log', (event: Event) => {\n try {\n const messageEvent = event as MessageEvent;\n const log = JSON.parse(messageEvent.data) as InternalLogEntry;\n options.onLog(log);\n } catch (error) {\n const err = error instanceof Error ? error : new Error(String(error));\n options.onError?.(err);\n }\n });\n\n eventSource.addEventListener('error', () => {\n const error = new Error('SSE connection error');\n options.onError?.(error);\n });\n\n // Return cleanup function\n return () => {\n eventSource.close();\n };\n }\n\n // ==================== Metrics ====================\n\n getMetrics(): ClientMetrics {\n return { ...this.metrics };\n }\n\n resetMetrics() {\n this.metrics = {\n logsSent: 0,\n logsDropped: 0,\n errors: 0,\n retries: 0,\n avgLatencyMs: 0,\n circuitBreakerTrips: 0,\n };\n this.latencies = [];\n }\n\n getCircuitBreakerState(): string {\n return this.circuitBreaker.getState();\n }\n\n // ==================== Cleanup ====================\n\n async close() {\n if (this.timer) {\n clearInterval(this.timer);\n this.timer = null;\n }\n this.stopConsoleInterception();\n await this.flush();\n }\n}\n\nexport default LogTideClient;\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts"],"names":[],"mappings":"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","file":"index.js","sourcesContent":["import { randomUUID } from 'crypto';\n\n// ==================== Types ====================\n\nexport type LogLevel = 'debug' | 'info' | 'warn' | 'error' | 'critical';\n\nexport interface ConsoleInterceptOptions {\n enabled: boolean;\n service?: string;\n preserveOriginal?: boolean;\n includeStackTrace?: boolean;\n levels?: {\n log?: boolean;\n info?: boolean;\n warn?: boolean;\n error?: boolean;\n debug?: boolean;\n };\n}\n\nexport interface PayloadLimitsOptions {\n /** Maximum size in bytes for a single field value (default: 10KB) */\n maxFieldSize?: number;\n /** Maximum size in bytes for the entire log entry (default: 100KB) */\n maxLogSize?: number;\n /** Fields to exclude from metadata (e.g., ['body', 'requestBody', 'responseBody']) */\n excludeFields?: string[];\n /** Marker to append when a field is truncated (default: '...[TRUNCATED]') */\n truncationMarker?: string;\n}\n\nexport interface LogTideClientOptions {\n apiUrl: string;\n apiKey: string;\n batchSize?: number;\n flushInterval?: number;\n maxBufferSize?: number;\n maxRetries?: number;\n retryDelayMs?: number;\n circuitBreakerThreshold?: number;\n circuitBreakerResetMs?: number;\n enableMetrics?: boolean;\n debug?: boolean;\n globalMetadata?: Record<string, unknown>;\n autoTraceId?: boolean;\n interceptConsole?: ConsoleInterceptOptions;\n /** Payload size limits to prevent 413 errors */\n payloadLimits?: PayloadLimitsOptions;\n}\n\nexport interface LogEntry {\n service: string;\n level: LogLevel;\n message: string;\n time?: string;\n metadata?: Record<string, unknown>;\n trace_id?: string;\n}\n\nexport interface InternalLogEntry extends LogEntry {\n time: string;\n}\n\nexport interface QueryOptions {\n service?: string;\n level?: LogLevel;\n from?: Date | string;\n to?: Date | string;\n q?: string;\n limit?: number;\n offset?: number;\n}\n\nexport interface LogsResponse {\n logs: InternalLogEntry[];\n total: number;\n limit: number;\n offset: number;\n}\n\nexport interface AggregatedStatsOptions {\n from: Date | string;\n to: Date | string;\n interval?: '1m' | '5m' | '1h' | '1d';\n service?: string;\n}\n\nexport interface AggregatedStatsResponse {\n timeseries: Array<{\n bucket: string;\n total: number;\n by_level: Record<string, number>;\n }>;\n top_services: Array<{ service: string; count: number }>;\n top_errors: Array<{ message: string; count: number }>;\n}\n\nexport interface ClientMetrics {\n logsSent: number;\n logsDropped: number;\n errors: number;\n retries: number;\n avgLatencyMs: number;\n circuitBreakerTrips: number;\n}\n\nexport interface StreamOptions {\n service?: string;\n level?: LogLevel;\n onLog: (log: InternalLogEntry) => void;\n onError?: (error: Error) => void;\n}\n\n// ==================== Circuit Breaker ====================\n\nenum CircuitState {\n CLOSED = 'CLOSED',\n OPEN = 'OPEN',\n HALF_OPEN = 'HALF_OPEN',\n}\n\nclass CircuitBreaker {\n private state: CircuitState = CircuitState.CLOSED;\n private failureCount = 0;\n private lastFailureTime: number | null = null;\n\n constructor(\n private threshold: number,\n private resetMs: number,\n ) {}\n\n recordSuccess() {\n this.failureCount = 0;\n this.state = CircuitState.CLOSED;\n }\n\n recordFailure() {\n this.failureCount++;\n this.lastFailureTime = Date.now();\n\n if (this.failureCount >= this.threshold) {\n this.state = CircuitState.OPEN;\n }\n }\n\n canAttempt(): boolean {\n if (this.state === CircuitState.CLOSED) {\n return true;\n }\n\n if (this.state === CircuitState.OPEN) {\n const now = Date.now();\n if (this.lastFailureTime && now - this.lastFailureTime >= this.resetMs) {\n this.state = CircuitState.HALF_OPEN;\n return true;\n }\n return false;\n }\n\n // HALF_OPEN state - allow one attempt\n return true;\n }\n\n getState(): CircuitState {\n return this.state;\n }\n}\n\n\n// ==================== Structured Exception Types ====================\n\nexport interface StructuredStackFrame {\n /** File path or module name */\n file?: string;\n /** Function/method name */\n function?: string;\n /** Line number (1-based) */\n line?: number;\n /** Column number */\n column?: number;\n /** Additional frame metadata */\n metadata?: Record<string, unknown>;\n}\n\nexport interface StructuredException {\n /** Exception type/class name (e.g., \"TypeError\", \"Error\") */\n type: string;\n /** Human-readable error message */\n message: string;\n /** Stack trace as an array of frames (top to bottom) */\n stacktrace?: StructuredStackFrame[];\n /** Language hint for better fingerprinting */\n language?: string;\n /** Inner/cause exception (for wrapped exceptions) */\n cause?: StructuredException;\n /** Additional exception metadata */\n metadata?: Record<string, unknown>;\n /** Original raw stack trace as a string (fallback) */\n raw?: string;\n}\n\n// ==================== Error Serialization ====================\n\n/**\n * Parse a V8/Node.js stack trace string into structured frames\n */\nfunction parseNodeStackTrace(stack: string | undefined): StructuredStackFrame[] {\n if (!stack) return [];\n\n const frames: StructuredStackFrame[] = [];\n const lines = stack.split('\\n');\n\n for (const line of lines) {\n // Skip the first line (error message) and empty lines\n const trimmed = line.trim();\n if (!trimmed.startsWith('at ')) continue;\n\n // Format 1: \"at functionName (file:line:column)\"\n const match1 = trimmed.match(/^at\\s+(.+?)\\s+\\((.+):(\\d+):(\\d+)\\)$/);\n if (match1) {\n frames.push({\n function: match1[1],\n file: match1[2],\n line: parseInt(match1[3], 10),\n column: parseInt(match1[4], 10),\n });\n continue;\n }\n\n // Format 2: \"at file:line:column\" (anonymous function)\n const match2 = trimmed.match(/^at\\s+(.+):(\\d+):(\\d+)$/);\n if (match2) {\n frames.push({\n file: match2[1],\n line: parseInt(match2[2], 10),\n column: parseInt(match2[3], 10),\n });\n continue;\n }\n\n // Format 3: \"at functionName (native)\" or similar\n const match3 = trimmed.match(/^at\\s+(.+?)\\s+\\((.+)\\)$/);\n if (match3) {\n frames.push({\n function: match3[1],\n file: match3[2],\n });\n continue;\n }\n\n // Format 4: \"at functionName\" (no file info)\n const match4 = trimmed.match(/^at\\s+(.+)$/);\n if (match4) {\n frames.push({\n function: match4[1],\n });\n }\n }\n\n return frames;\n}\n\n/**\n * Serialize an error into the StructuredException format\n */\nexport function serializeError(error: unknown): StructuredException {\n if (error instanceof Error) {\n const result: StructuredException = {\n type: error.name,\n message: error.message,\n language: 'nodejs',\n stacktrace: parseNodeStackTrace(error.stack),\n raw: error.stack,\n };\n\n // Handle error.cause (Node.js 16.9+)\n if (error.cause) {\n result.cause = serializeError(error.cause);\n }\n\n // Extract additional error properties as metadata\n const errorMetadata: Record<string, unknown> = {};\n const standardProps = ['name', 'message', 'stack', 'cause'];\n\n for (const key of Object.keys(error)) {\n if (!standardProps.includes(key)) {\n errorMetadata[key] = (error as unknown as Record<string, unknown>)[key];\n }\n }\n\n // Include common Node.js error properties\n if ('code' in error) errorMetadata.code = (error as NodeJS.ErrnoException).code;\n if ('errno' in error) errorMetadata.errno = (error as NodeJS.ErrnoException).errno;\n if ('syscall' in error) errorMetadata.syscall = (error as NodeJS.ErrnoException).syscall;\n if ('path' in error) errorMetadata.path = (error as NodeJS.ErrnoException).path;\n\n if (Object.keys(errorMetadata).length > 0) {\n result.metadata = errorMetadata;\n }\n\n return result;\n }\n\n if (typeof error === 'string') {\n return {\n type: 'Error',\n message: error,\n language: 'nodejs',\n };\n }\n\n if (typeof error === 'object' && error !== null) {\n // Try to extract type and message from the object\n const obj = error as Record<string, unknown>;\n return {\n type: (typeof obj.type === 'string' ? obj.type : typeof obj.name === 'string' ? obj.name : 'Error'),\n message: (typeof obj.message === 'string' ? obj.message : JSON.stringify(error)),\n language: 'nodejs',\n metadata: obj,\n };\n }\n\n return {\n type: 'Error',\n message: String(error),\n language: 'nodejs',\n };\n}\n\n// ==================== Main Client ====================\n\nexport class LogTideClient {\n private apiUrl: string;\n private apiKey: string;\n private batchSize: number;\n private flushInterval: number;\n private maxBufferSize: number;\n private maxRetries: number;\n private retryDelayMs: number;\n private enableMetrics: boolean;\n private debugMode: boolean;\n private globalMetadata: Record<string, unknown>;\n private autoTraceId: boolean;\n\n private buffer: InternalLogEntry[] = [];\n private timer: NodeJS.Timeout | null = null;\n private circuitBreaker: CircuitBreaker;\n\n // Metrics\n private metrics: ClientMetrics = {\n logsSent: 0,\n logsDropped: 0,\n errors: 0,\n retries: 0,\n avgLatencyMs: 0,\n circuitBreakerTrips: 0,\n };\n private latencies: number[] = [];\n\n // Context tracking\n private currentTraceId: string | null = null;\n\n // Console interception\n private consoleInterceptOptions: ConsoleInterceptOptions | null = null;\n private originalConsole: {\n log: typeof console.log;\n info: typeof console.info;\n warn: typeof console.warn;\n error: typeof console.error;\n debug: typeof console.debug;\n } | null = null;\n\n // Payload limits\n private payloadLimits: Required<PayloadLimitsOptions>;\n\n constructor(options: LogTideClientOptions) {\n this.apiUrl = options.apiUrl.replace(/\\/$/, '');\n this.apiKey = options.apiKey;\n this.batchSize = options.batchSize || 100;\n this.flushInterval = options.flushInterval || 5000;\n this.maxBufferSize = options.maxBufferSize || 10000;\n this.maxRetries = options.maxRetries || 3;\n this.retryDelayMs = options.retryDelayMs || 1000;\n this.enableMetrics = options.enableMetrics ?? true;\n this.debugMode = options.debug ?? false;\n this.globalMetadata = options.globalMetadata || {};\n this.autoTraceId = options.autoTraceId ?? false;\n\n this.circuitBreaker = new CircuitBreaker(\n options.circuitBreakerThreshold || 5,\n options.circuitBreakerResetMs || 30000,\n );\n\n // Initialize payload limits with defaults\n this.payloadLimits = {\n maxFieldSize: options.payloadLimits?.maxFieldSize ?? 10 * 1024, // 10KB\n maxLogSize: options.payloadLimits?.maxLogSize ?? 100 * 1024, // 100KB\n excludeFields: options.payloadLimits?.excludeFields ?? [],\n truncationMarker: options.payloadLimits?.truncationMarker ?? '...[TRUNCATED]',\n };\n\n this.startFlushTimer();\n\n // Start console interception if configured\n if (options.interceptConsole?.enabled) {\n this.startConsoleInterception(options.interceptConsole);\n }\n }\n\n // ==================== Context Helpers ====================\n\n /**\n * Set trace ID for subsequent logs\n */\n setTraceId(traceId: string | null) {\n this.currentTraceId = traceId;\n }\n\n /**\n * Get current trace ID\n */\n getTraceId(): string | null {\n return this.currentTraceId;\n }\n\n /**\n * Execute function with a specific trace ID context\n */\n withTraceId<T>(traceId: string, fn: () => T): T {\n const previousTraceId = this.currentTraceId;\n this.currentTraceId = traceId;\n try {\n return fn();\n } finally {\n this.currentTraceId = previousTraceId;\n }\n }\n\n /**\n * Execute function with a new auto-generated trace ID\n */\n withNewTraceId<T>(fn: () => T): T {\n return this.withTraceId(randomUUID(), fn);\n }\n\n // ==================== Console Interception ====================\n\n /**\n * Start intercepting console methods and forward them to LogTide\n */\n startConsoleInterception(options?: Partial<ConsoleInterceptOptions>) {\n if (this.originalConsole) {\n // Already intercepting\n return;\n }\n\n const config: ConsoleInterceptOptions = {\n enabled: true,\n service: options?.service ?? 'console',\n preserveOriginal: options?.preserveOriginal ?? true,\n includeStackTrace: options?.includeStackTrace ?? false,\n levels: {\n log: options?.levels?.log ?? true,\n info: options?.levels?.info ?? true,\n warn: options?.levels?.warn ?? true,\n error: options?.levels?.error ?? true,\n debug: options?.levels?.debug ?? true,\n },\n };\n\n this.consoleInterceptOptions = config;\n\n // Save original console methods\n this.originalConsole = {\n log: console.log.bind(console),\n info: console.info.bind(console),\n warn: console.warn.bind(console),\n error: console.error.bind(console),\n debug: console.debug.bind(console),\n };\n\n const createInterceptor = (\n method: 'log' | 'info' | 'warn' | 'error' | 'debug',\n level: LogLevel,\n ) => {\n const original = this.originalConsole![method];\n\n return (...args: unknown[]) => {\n // Always call original if preserveOriginal is true\n if (config.preserveOriginal) {\n original(...args);\n }\n\n // Skip if this method is not configured for interception\n if (!config.levels?.[method]) {\n return;\n }\n\n // Skip internal LogTide logs to prevent infinite loops\n const message = args\n .map((arg) => {\n if (typeof arg === 'string') return arg;\n if (arg instanceof Error) return arg.message;\n try {\n return JSON.stringify(arg);\n } catch {\n return String(arg);\n }\n })\n .join(' ');\n\n if (message.startsWith('[LogTide]')) {\n return;\n }\n\n // Build metadata\n const metadata: Record<string, unknown> = {\n source: 'console',\n originalMethod: method,\n };\n\n // Include stack trace if configured\n if (config.includeStackTrace) {\n const stack = new Error().stack;\n if (stack) {\n // Remove the first two lines (Error + this interceptor function)\n const stackLines = stack.split('\\n').slice(2);\n metadata.stackTrace = stackLines.join('\\n');\n\n // Extract caller location from first relevant stack line\n const callerLine = stackLines[0];\n if (callerLine) {\n const match = callerLine.match(/at\\s+(.+?)\\s+\\((.+):(\\d+):(\\d+)\\)/);\n if (match) {\n metadata.caller = {\n function: match[1],\n file: match[2],\n line: parseInt(match[3], 10),\n column: parseInt(match[4], 10),\n };\n } else {\n // Try alternative format: \"at file:line:column\"\n const altMatch = callerLine.match(/at\\s+(.+):(\\d+):(\\d+)/);\n if (altMatch) {\n metadata.caller = {\n file: altMatch[1],\n line: parseInt(altMatch[2], 10),\n column: parseInt(altMatch[3], 10),\n };\n }\n }\n }\n }\n }\n\n // Include raw arguments for complex objects\n if (args.length > 1 || (args.length === 1 && typeof args[0] !== 'string')) {\n metadata.args = args.map((arg) => {\n if (arg instanceof Error) {\n return serializeError(arg);\n }\n return arg;\n });\n }\n\n // For error level, if any argument is an Error, add it to metadata.exception\n if (level === 'error' || level === 'critical') {\n const errorArg = args.find((arg) => arg instanceof Error);\n if (errorArg instanceof Error) {\n metadata.exception = serializeError(errorArg);\n }\n }\n\n // Log to LogTide\n this.log({\n service: config.service!,\n level,\n message,\n metadata,\n });\n };\n };\n\n // Replace console methods\n console.log = createInterceptor('log', 'info');\n console.info = createInterceptor('info', 'info');\n console.warn = createInterceptor('warn', 'warn');\n console.error = createInterceptor('error', 'error');\n console.debug = createInterceptor('debug', 'debug');\n\n if (this.debugMode) {\n this.originalConsole.log('[LogTide] Console interception started');\n }\n }\n\n /**\n * Stop intercepting console methods and restore originals\n */\n stopConsoleInterception() {\n if (!this.originalConsole) {\n return;\n }\n\n // Restore original console methods\n console.log = this.originalConsole.log;\n console.info = this.originalConsole.info;\n console.warn = this.originalConsole.warn;\n console.error = this.originalConsole.error;\n console.debug = this.originalConsole.debug;\n\n if (this.debugMode) {\n console.log('[LogTide] Console interception stopped');\n }\n\n this.originalConsole = null;\n this.consoleInterceptOptions = null;\n }\n\n /**\n * Check if console interception is active\n */\n isConsoleInterceptionActive(): boolean {\n return this.originalConsole !== null;\n }\n\n // ==================== Payload Processing ====================\n\n /**\n * Check if a string looks like base64 encoded data\n */\n private looksLikeBase64(str: string): boolean {\n if (typeof str !== 'string' || str.length < 100) return false;\n // Check for common base64 patterns: data URLs or long base64 strings\n if (str.startsWith('data:')) return true;\n // Check if it's a long string with only base64 characters\n const base64Regex = /^[A-Za-z0-9+/=]{100,}$/;\n return base64Regex.test(str.replace(/\\s/g, ''));\n }\n\n /**\n * Process a value for payload limits (truncation, base64 removal, etc.)\n */\n private processValue(value: unknown, fieldPath: string): unknown {\n // Check if this field should be excluded\n const fieldName = fieldPath.split('.').pop() || fieldPath;\n if (this.payloadLimits.excludeFields.includes(fieldName)) {\n return '[EXCLUDED]';\n }\n\n if (value === null || value === undefined) {\n return value;\n }\n\n if (typeof value === 'string') {\n // Check for base64 data\n if (this.looksLikeBase64(value)) {\n return '[BASE64 DATA REMOVED]';\n }\n // Truncate if too long\n if (value.length > this.payloadLimits.maxFieldSize) {\n return value.substring(0, this.payloadLimits.maxFieldSize) + this.payloadLimits.truncationMarker;\n }\n return value;\n }\n\n if (Array.isArray(value)) {\n return value.map((item, index) => this.processValue(item, `${fieldPath}[${index}]`));\n }\n\n if (typeof value === 'object') {\n const processed: Record<string, unknown> = {};\n for (const [key, val] of Object.entries(value as Record<string, unknown>)) {\n processed[key] = this.processValue(val, `${fieldPath}.${key}`);\n }\n return processed;\n }\n\n return value;\n }\n\n /**\n * Process metadata to apply payload limits\n */\n private processMetadata(metadata: Record<string, unknown> | undefined): Record<string, unknown> | undefined {\n if (!metadata) return metadata;\n return this.processValue(metadata, 'metadata') as Record<string, unknown>;\n }\n\n /**\n * Ensure log entry doesn't exceed max size\n */\n private enforceMaxLogSize(entry: InternalLogEntry): InternalLogEntry {\n const serialized = JSON.stringify(entry);\n if (serialized.length <= this.payloadLimits.maxLogSize) {\n return entry;\n }\n\n // Log is too large, progressively truncate metadata\n if (this.debugMode) {\n console.warn(`[LogTide] Log entry too large (${serialized.length} bytes), truncating metadata`);\n }\n\n // Create a copy and truncate metadata heavily\n const truncated: InternalLogEntry = {\n ...entry,\n metadata: {\n _truncated: true,\n _originalSize: serialized.length,\n message: entry.message,\n },\n };\n\n return truncated;\n }\n\n // ==================== Logging Methods ====================\n\n private startFlushTimer() {\n this.timer = setInterval(() => {\n this.flush();\n }, this.flushInterval);\n }\n\n log(entry: LogEntry) {\n // Check buffer size limit\n if (this.buffer.length >= this.maxBufferSize) {\n this.metrics.logsDropped++;\n if (this.debugMode) {\n console.warn(`[LogTide] Buffer full, dropping log: ${entry.message}`);\n }\n return;\n }\n\n // Determine trace_id: use entry's trace_id, current context, or auto-generate if enabled\n const traceId = entry.trace_id || this.currentTraceId || (this.autoTraceId ? randomUUID() : undefined);\n\n // Merge and process metadata (applies truncation, exclusion, base64 removal)\n const mergedMetadata = {\n ...this.globalMetadata,\n ...entry.metadata,\n };\n const processedMetadata = this.processMetadata(mergedMetadata);\n\n let internalEntry: InternalLogEntry = {\n ...entry,\n time: entry.time || new Date().toISOString(),\n metadata: processedMetadata,\n trace_id: traceId,\n };\n\n // Enforce max log size\n internalEntry = this.enforceMaxLogSize(internalEntry);\n\n this.buffer.push(internalEntry);\n\n if (this.buffer.length >= this.batchSize) {\n this.flush();\n }\n }\n\n debug(service: string, message: string, metadata?: Record<string, unknown>) {\n this.log({ service, level: 'debug', message, metadata });\n }\n\n info(service: string, message: string, metadata?: Record<string, unknown>) {\n this.log({ service, level: 'info', message, metadata });\n }\n\n warn(service: string, message: string, metadata?: Record<string, unknown>) {\n this.log({ service, level: 'warn', message, metadata });\n }\n\n error(service: string, message: string, metadataOrError?: Record<string, unknown> | Error) {\n let metadata: Record<string, unknown> = {};\n\n if (metadataOrError instanceof Error) {\n metadata = { exception: serializeError(metadataOrError) };\n } else if (metadataOrError) {\n metadata = metadataOrError;\n }\n\n this.log({ service, level: 'error', message, metadata });\n }\n\n critical(service: string, message: string, metadataOrError?: Record<string, unknown> | Error) {\n let metadata: Record<string, unknown> = {};\n\n if (metadataOrError instanceof Error) {\n metadata = { exception: serializeError(metadataOrError) };\n } else if (metadataOrError) {\n metadata = metadataOrError;\n }\n\n this.log({ service, level: 'critical', message, metadata });\n }\n\n // ==================== Flush with Retry & Circuit Breaker ====================\n\n async flush() {\n if (this.buffer.length === 0) return;\n\n // Check circuit breaker\n if (!this.circuitBreaker.canAttempt()) {\n this.metrics.circuitBreakerTrips++;\n if (this.debugMode) {\n console.warn('[LogTide] Circuit breaker OPEN, skipping flush');\n }\n return;\n }\n\n const logs = [...this.buffer];\n this.buffer = [];\n\n const startTime = Date.now();\n let lastError: Error | null = null;\n\n for (let attempt = 0; attempt <= this.maxRetries; attempt++) {\n try {\n const response = await fetch(`${this.apiUrl}/api/v1/ingest`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n 'X-API-Key': this.apiKey,\n },\n body: JSON.stringify({ logs }),\n });\n\n if (!response.ok) {\n const errorText = await response.text();\n throw new Error(`HTTP ${response.status}: ${errorText}`);\n }\n\n // Success\n this.circuitBreaker.recordSuccess();\n this.metrics.logsSent += logs.length;\n\n if (this.enableMetrics) {\n const latency = Date.now() - startTime;\n this.latencies.push(latency);\n if (this.latencies.length > 100) {\n this.latencies.shift();\n }\n this.metrics.avgLatencyMs =\n this.latencies.reduce((a, b) => a + b, 0) / this.latencies.length;\n }\n\n if (this.debugMode) {\n console.log(`[LogTide] Sent ${logs.length} logs successfully`);\n }\n\n return;\n } catch (error) {\n lastError = error instanceof Error ? error : new Error(String(error));\n this.metrics.errors++;\n\n if (attempt < this.maxRetries) {\n this.metrics.retries++;\n const delay = this.retryDelayMs * Math.pow(2, attempt);\n if (this.debugMode) {\n console.warn(\n `[LogTide] Retry ${attempt + 1}/${this.maxRetries} after ${delay}ms: ${lastError.message}`,\n );\n }\n await this.sleep(delay);\n }\n }\n }\n\n // All retries failed\n this.circuitBreaker.recordFailure();\n\n if (this.debugMode) {\n console.error(`[LogTide] Failed to send logs after ${this.maxRetries} retries:`, lastError);\n }\n\n // Re-add logs to buffer if not full\n if (this.buffer.length + logs.length <= this.maxBufferSize) {\n this.buffer.unshift(...logs);\n } else {\n this.metrics.logsDropped += logs.length;\n }\n }\n\n private sleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n }\n\n // ==================== Query Methods ====================\n\n async query(options: QueryOptions = {}): Promise<LogsResponse> {\n const params = new URLSearchParams();\n\n if (options.service) params.append('service', options.service);\n if (options.level) params.append('level', options.level);\n if (options.from) {\n const from = options.from instanceof Date ? options.from.toISOString() : options.from;\n params.append('from', from);\n }\n if (options.to) {\n const to = options.to instanceof Date ? options.to.toISOString() : options.to;\n params.append('to', to);\n }\n if (options.q) params.append('q', options.q);\n if (options.limit) params.append('limit', String(options.limit));\n if (options.offset) params.append('offset', String(options.offset));\n\n const url = `${this.apiUrl}/api/v1/logs?${params.toString()}`;\n\n const response = await fetch(url, {\n headers: {\n 'X-API-Key': this.apiKey,\n },\n });\n\n if (!response.ok) {\n const errorText = await response.text();\n throw new Error(`Query failed: HTTP ${response.status}: ${errorText}`);\n }\n\n return (await response.json()) as LogsResponse;\n }\n\n async getByTraceId(traceId: string): Promise<InternalLogEntry[]> {\n const url = `${this.apiUrl}/api/v1/logs/trace/${traceId}`;\n\n const response = await fetch(url, {\n headers: {\n 'X-API-Key': this.apiKey,\n },\n });\n\n if (!response.ok) {\n const errorText = await response.text();\n throw new Error(`Get by trace ID failed: HTTP ${response.status}: ${errorText}`);\n }\n\n const data = (await response.json()) as { logs?: InternalLogEntry[] };\n return data.logs || [];\n }\n\n async getAggregatedStats(options: AggregatedStatsOptions): Promise<AggregatedStatsResponse> {\n const params = new URLSearchParams();\n\n const from = options.from instanceof Date ? options.from.toISOString() : options.from;\n const to = options.to instanceof Date ? options.to.toISOString() : options.to;\n\n params.append('from', from);\n params.append('to', to);\n if (options.interval) params.append('interval', options.interval);\n if (options.service) params.append('service', options.service);\n\n const url = `${this.apiUrl}/api/v1/logs/aggregated?${params.toString()}`;\n\n const response = await fetch(url, {\n headers: {\n 'X-API-Key': this.apiKey,\n },\n });\n\n if (!response.ok) {\n const errorText = await response.text();\n throw new Error(`Get aggregated stats failed: HTTP ${response.status}: ${errorText}`);\n }\n\n return (await response.json()) as AggregatedStatsResponse;\n }\n\n // ==================== Live Tail (SSE) ====================\n\n stream(options: StreamOptions): () => void {\n const params = new URLSearchParams();\n params.append('token', this.apiKey);\n if (options.service) params.append('service', options.service);\n if (options.level) params.append('level', options.level);\n\n const url = `${this.apiUrl}/api/v1/logs/stream?${params.toString()}`;\n\n const eventSource = new EventSource(url);\n\n eventSource.addEventListener('log', (event: Event) => {\n try {\n const messageEvent = event as MessageEvent;\n const log = JSON.parse(messageEvent.data) as InternalLogEntry;\n options.onLog(log);\n } catch (error) {\n const err = error instanceof Error ? error : new Error(String(error));\n options.onError?.(err);\n }\n });\n\n eventSource.addEventListener('error', () => {\n const error = new Error('SSE connection error');\n options.onError?.(error);\n });\n\n // Return cleanup function\n return () => {\n eventSource.close();\n };\n }\n\n // ==================== Metrics ====================\n\n getMetrics(): ClientMetrics {\n return { ...this.metrics };\n }\n\n resetMetrics() {\n this.metrics = {\n logsSent: 0,\n logsDropped: 0,\n errors: 0,\n retries: 0,\n avgLatencyMs: 0,\n circuitBreakerTrips: 0,\n };\n this.latencies = [];\n }\n\n getCircuitBreakerState(): string {\n return this.circuitBreaker.getState();\n }\n\n // ==================== Cleanup ====================\n\n async close() {\n if (this.timer) {\n clearInterval(this.timer);\n this.timer = null;\n }\n this.stopConsoleInterception();\n await this.flush();\n }\n}\n\nexport default LogTideClient;\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@logtide/sdk-node",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.2",
|
|
4
4
|
"description": "Official Node.js SDK for LogTide (logtide.dev) - Self-hosted log management with advanced features: retry logic, circuit breaker, query API, live streaming, and middleware support",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.cjs",
|