@mastra/loggers 1.3.2 → 1.3.3-alpha.1
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/docs/SKILL.md +1 -1
- package/dist/docs/assets/SOURCE_MAP.json +1 -1
- package/dist/docs/references/reference-core-mastra-class.md +3 -1
- package/dist/docs/references/reference-file-based-agents-logger.md +1 -1
- package/dist/http/index.cjs +3 -3
- package/dist/http/index.cjs.map +1 -1
- package/dist/http/index.js +3 -3
- package/dist/http/index.js.map +1 -1
- package/dist/upstash/index.cjs +12 -7
- package/dist/upstash/index.cjs.map +1 -1
- package/dist/upstash/index.d.ts +1 -1
- package/dist/upstash/index.d.ts.map +1 -1
- package/dist/upstash/index.js +12 -7
- package/dist/upstash/index.js.map +1 -1
- package/package.json +7 -7
package/dist/docs/SKILL.md
CHANGED
|
@@ -85,6 +85,8 @@ Visit the [Configuration reference](https://mastra.ai/reference/configuration) f
|
|
|
85
85
|
|
|
86
86
|
**scorers** (`Record<string, Scorer>`): Scorers for evaluating agent responses and workflow outputs. Registration also makes a scorer resolvable by ID, which is required to persist its scores. See Score persistence (Default: `{}`)
|
|
87
87
|
|
|
88
|
+
**classifiers** (`Record<string, Classifier>`): Classifiers for typed fixed-option evaluation. Registered classifiers can be retrieved by key or ID. See Classifier (Default: `{}`)
|
|
89
|
+
|
|
88
90
|
**processors** (`Record<string, Processor>`): Input/output processors for transforming agent inputs and outputs (Default: `{}`)
|
|
89
91
|
|
|
90
92
|
**gateways** (`Record<string, MastraModelGateway>`): Custom model gateways to register for accessing AI models through alternative providers or private deployments. Structured as a key-value pair, with keys being the registry key (used for getGateway()) and values being gateway instances. (Default: `{}`)
|
|
@@ -131,7 +133,7 @@ Visit the [Configuration reference](https://mastra.ai/reference/configuration) f
|
|
|
131
133
|
|
|
132
134
|
**recovery** (`MastraRecoveryConfig`): Boot-time recovery behavior for orphaned agent and workflow runs. See Crash recovery. (Default: `{ durableAgents: 'off' }`)
|
|
133
135
|
|
|
134
|
-
**recovery.durableAgents** (`'auto' | 'off'`): Set to 'auto' to automatically re-drive orphaned RUNNING durable agent runs on server boot. Recovery re-issues LLM calls and re-executes tool calls, so tools must be idempotent. See Crash recovery.
|
|
136
|
+
**recovery.durableAgents** (`'auto' | 'off'`): Set to 'auto' to automatically re-drive orphaned RUNNING durable agent runs on server boot. This also controls the default snapshot-persistence policy for durable agents: running checkpoints are only written when set to 'auto' (or when an agent sets a custom shouldPersistSnapshot that includes running). Recovery re-issues LLM calls and re-executes tool calls, so tools must be idempotent. See Crash recovery.
|
|
135
137
|
|
|
136
138
|
## Methods
|
|
137
139
|
|
|
@@ -23,7 +23,7 @@ export default new PinoLogger({
|
|
|
23
23
|
})
|
|
24
24
|
```
|
|
25
25
|
|
|
26
|
-
Mastra registers the logger before storage, observability, and file-based agents
|
|
26
|
+
Mastra registers the logger before storage, observability, and file-based agents. Those primitives log through this logger as they're wired up.
|
|
27
27
|
|
|
28
28
|
## Precedence with code
|
|
29
29
|
|
package/dist/http/index.cjs
CHANGED
|
@@ -25,9 +25,9 @@ var HttpTransport = class extends _mastra_core_logger.LoggerTransport {
|
|
|
25
25
|
this.flushInterval = options.flushInterval || 1e4;
|
|
26
26
|
this.timeout = options.timeout || 3e4;
|
|
27
27
|
this.retryOptions = {
|
|
28
|
-
maxRetries: options.retryOptions?.maxRetries
|
|
29
|
-
retryDelay: options.retryOptions?.retryDelay
|
|
30
|
-
exponentialBackoff: options.retryOptions?.exponentialBackoff
|
|
28
|
+
maxRetries: options.retryOptions?.maxRetries ?? 3,
|
|
29
|
+
retryDelay: options.retryOptions?.retryDelay ?? 1e3,
|
|
30
|
+
exponentialBackoff: options.retryOptions?.exponentialBackoff ?? true
|
|
31
31
|
};
|
|
32
32
|
this.logBuffer = [];
|
|
33
33
|
this.lastFlush = Date.now();
|
package/dist/http/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.cjs","names":["LoggerTransport"],"sources":["../../src/http/index.ts"],"sourcesContent":["import { LoggerTransport } from '@mastra/core/logger';\nimport type { BaseLogMessage, LogLevel } from '@mastra/core/logger';\n\ninterface RetryOptions {\n maxRetries?: number;\n retryDelay?: number;\n exponentialBackoff?: boolean;\n}\n\ninterface HttpTransportOptions {\n url: string;\n method?: 'POST' | 'PUT' | 'PATCH';\n headers?: Record<string, string>;\n batchSize?: number;\n flushInterval?: number;\n timeout?: number;\n retryOptions?: RetryOptions;\n}\n\nexport class HttpTransport extends LoggerTransport {\n private url: string;\n private method: string;\n private headers: Record<string, string>;\n private batchSize: number;\n private flushInterval: number;\n private timeout: number;\n private retryOptions: Required<RetryOptions>;\n private logBuffer: BaseLogMessage[];\n private lastFlush: number;\n private flushIntervalId: NodeJS.Timeout;\n\n constructor(options: HttpTransportOptions) {\n super({ objectMode: true });\n\n if (!options.url) {\n throw new Error('HTTP URL is required');\n }\n\n this.url = options.url;\n this.method = options.method || 'POST';\n this.headers = {\n 'Content-Type': 'application/json',\n ...options.headers,\n };\n this.batchSize = options.batchSize || 100;\n this.flushInterval = options.flushInterval || 10000;\n this.timeout = options.timeout || 30000;\n this.retryOptions = {\n maxRetries: options.retryOptions?.maxRetries
|
|
1
|
+
{"version":3,"file":"index.cjs","names":["LoggerTransport"],"sources":["../../src/http/index.ts"],"sourcesContent":["import { LoggerTransport } from '@mastra/core/logger';\nimport type { BaseLogMessage, LogLevel } from '@mastra/core/logger';\n\ninterface RetryOptions {\n maxRetries?: number;\n retryDelay?: number;\n exponentialBackoff?: boolean;\n}\n\ninterface HttpTransportOptions {\n url: string;\n method?: 'POST' | 'PUT' | 'PATCH';\n headers?: Record<string, string>;\n batchSize?: number;\n flushInterval?: number;\n timeout?: number;\n retryOptions?: RetryOptions;\n}\n\nexport class HttpTransport extends LoggerTransport {\n private url: string;\n private method: string;\n private headers: Record<string, string>;\n private batchSize: number;\n private flushInterval: number;\n private timeout: number;\n private retryOptions: Required<RetryOptions>;\n private logBuffer: BaseLogMessage[];\n private lastFlush: number;\n private flushIntervalId: NodeJS.Timeout;\n\n constructor(options: HttpTransportOptions) {\n super({ objectMode: true });\n\n if (!options.url) {\n throw new Error('HTTP URL is required');\n }\n\n this.url = options.url;\n this.method = options.method || 'POST';\n this.headers = {\n 'Content-Type': 'application/json',\n ...options.headers,\n };\n this.batchSize = options.batchSize || 100;\n this.flushInterval = options.flushInterval || 10000;\n this.timeout = options.timeout || 30000;\n this.retryOptions = {\n maxRetries: options.retryOptions?.maxRetries ?? 3,\n retryDelay: options.retryOptions?.retryDelay ?? 1000,\n exponentialBackoff: options.retryOptions?.exponentialBackoff ?? true,\n };\n\n this.logBuffer = [];\n this.lastFlush = Date.now();\n\n // Start flush interval\n this.flushIntervalId = setInterval(() => {\n this._flush().catch(err => {\n console.error('Error flushing logs to HTTP endpoint:', err);\n });\n }, this.flushInterval);\n }\n\n private async makeHttpRequest(data: any, retryCount = 0): Promise<Response> {\n const controller = new AbortController();\n const timeoutId = setTimeout(() => controller.abort(), this.timeout);\n\n try {\n const body = JSON.stringify({ logs: data });\n\n const response = await fetch(this.url, {\n method: this.method,\n headers: this.headers,\n body,\n signal: controller.signal,\n });\n\n clearTimeout(timeoutId);\n\n if (!response.ok) {\n throw new Error(`HTTP ${response.status}: ${response.statusText}`);\n }\n\n return response;\n } catch (error) {\n clearTimeout(timeoutId);\n\n if (retryCount < this.retryOptions.maxRetries) {\n const delay = this.retryOptions.exponentialBackoff\n ? this.retryOptions.retryDelay * Math.pow(2, retryCount)\n : this.retryOptions.retryDelay;\n\n await new Promise(resolve => setTimeout(resolve, delay));\n return this.makeHttpRequest(data, retryCount + 1);\n }\n\n throw error;\n }\n }\n\n async _flush(): Promise<void> {\n if (this.logBuffer.length === 0) {\n return;\n }\n\n const now = Date.now();\n const logs = this.logBuffer.splice(0, this.batchSize);\n\n try {\n await this.makeHttpRequest(logs);\n this.lastFlush = now;\n } catch (error) {\n // On error, put logs back in the buffer\n this.logBuffer.unshift(...logs);\n throw error;\n }\n }\n\n _write(chunk: any, encoding?: string, callback?: (error?: Error | null) => void): boolean {\n if (typeof callback === 'function') {\n this._transform(chunk, encoding || 'utf8', callback);\n return true;\n }\n\n this._transform(chunk, encoding || 'utf8', (error: Error | null) => {\n if (error) console.error('Transform error in write:', error);\n });\n return true;\n }\n\n _transform(chunk: string, _enc: string, cb: Function): void {\n try {\n // Parse the log line if it's a string\n const log = typeof chunk === 'string' ? JSON.parse(chunk) : chunk;\n\n // Add timestamp if not present\n if (!log.time) {\n log.time = Date.now();\n }\n\n // Add to buffer\n this.logBuffer.push(log);\n\n // Flush if buffer reaches batch size\n if (this.logBuffer.length >= this.batchSize) {\n this._flush().catch(err => {\n console.error('Error flushing logs to HTTP endpoint:', err);\n });\n }\n\n // Pass through the log\n cb(null, chunk);\n } catch (error) {\n cb(error);\n }\n }\n\n _destroy(err: Error, cb: Function): void {\n clearInterval(this.flushIntervalId);\n\n // Final flush\n if (this.logBuffer.length > 0) {\n this._flush()\n .then(() => cb(err))\n .catch(flushErr => {\n console.error('Error in final flush:', flushErr);\n cb(err || flushErr);\n });\n } else {\n cb(err);\n }\n }\n\n async listLogs(params?: {\n fromDate?: Date;\n toDate?: Date;\n logLevel?: LogLevel;\n filters?: Record<string, any>;\n returnPaginationResults?: boolean;\n page?: number;\n perPage?: number;\n }): Promise<{\n logs: BaseLogMessage[];\n total: number;\n page: number;\n perPage: number;\n hasMore: boolean;\n }> {\n // HttpTransport is write-only by default\n // Subclasses can override this method to implement log retrieval\n console.warn(\n 'HttpTransport.listLogs: This transport is write-only. Override this method to implement log retrieval.',\n );\n\n return {\n logs: [],\n total: 0,\n page: params?.page ?? 1,\n perPage: params?.perPage ?? 100,\n hasMore: false,\n };\n }\n\n async listLogsByRunId({\n runId: _runId,\n fromDate: _fromDate,\n toDate: _toDate,\n logLevel: _logLevel,\n filters: _filters,\n page,\n perPage,\n }: {\n runId: string;\n fromDate?: Date;\n toDate?: Date;\n logLevel?: LogLevel;\n filters?: Record<string, any>;\n page?: number;\n perPage?: number;\n }): Promise<{\n logs: BaseLogMessage[];\n total: number;\n page: number;\n perPage: number;\n hasMore: boolean;\n }> {\n // HttpTransport is write-only by default\n // Subclasses can override this method to implement log retrieval\n console.warn(\n 'HttpTransport.listLogsByRunId: This transport is write-only. Override this method to implement log retrieval.',\n );\n\n return {\n logs: [],\n total: 0,\n page: page ?? 1,\n perPage: perPage ?? 100,\n hasMore: false,\n };\n }\n\n // Utility methods\n public getBufferedLogs(): BaseLogMessage[] {\n return [...this.logBuffer];\n }\n\n public clearBuffer(): void {\n this.logBuffer = [];\n }\n\n public getLastFlushTime(): number {\n return this.lastFlush;\n }\n}\n"],"mappings":"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"}
|
package/dist/http/index.js
CHANGED
|
@@ -24,9 +24,9 @@ var HttpTransport = class extends LoggerTransport {
|
|
|
24
24
|
this.flushInterval = options.flushInterval || 1e4;
|
|
25
25
|
this.timeout = options.timeout || 3e4;
|
|
26
26
|
this.retryOptions = {
|
|
27
|
-
maxRetries: options.retryOptions?.maxRetries
|
|
28
|
-
retryDelay: options.retryOptions?.retryDelay
|
|
29
|
-
exponentialBackoff: options.retryOptions?.exponentialBackoff
|
|
27
|
+
maxRetries: options.retryOptions?.maxRetries ?? 3,
|
|
28
|
+
retryDelay: options.retryOptions?.retryDelay ?? 1e3,
|
|
29
|
+
exponentialBackoff: options.retryOptions?.exponentialBackoff ?? true
|
|
30
30
|
};
|
|
31
31
|
this.logBuffer = [];
|
|
32
32
|
this.lastFlush = Date.now();
|
package/dist/http/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":[],"sources":["../../src/http/index.ts"],"sourcesContent":["import { LoggerTransport } from '@mastra/core/logger';\nimport type { BaseLogMessage, LogLevel } from '@mastra/core/logger';\n\ninterface RetryOptions {\n maxRetries?: number;\n retryDelay?: number;\n exponentialBackoff?: boolean;\n}\n\ninterface HttpTransportOptions {\n url: string;\n method?: 'POST' | 'PUT' | 'PATCH';\n headers?: Record<string, string>;\n batchSize?: number;\n flushInterval?: number;\n timeout?: number;\n retryOptions?: RetryOptions;\n}\n\nexport class HttpTransport extends LoggerTransport {\n private url: string;\n private method: string;\n private headers: Record<string, string>;\n private batchSize: number;\n private flushInterval: number;\n private timeout: number;\n private retryOptions: Required<RetryOptions>;\n private logBuffer: BaseLogMessage[];\n private lastFlush: number;\n private flushIntervalId: NodeJS.Timeout;\n\n constructor(options: HttpTransportOptions) {\n super({ objectMode: true });\n\n if (!options.url) {\n throw new Error('HTTP URL is required');\n }\n\n this.url = options.url;\n this.method = options.method || 'POST';\n this.headers = {\n 'Content-Type': 'application/json',\n ...options.headers,\n };\n this.batchSize = options.batchSize || 100;\n this.flushInterval = options.flushInterval || 10000;\n this.timeout = options.timeout || 30000;\n this.retryOptions = {\n maxRetries: options.retryOptions?.maxRetries
|
|
1
|
+
{"version":3,"file":"index.js","names":[],"sources":["../../src/http/index.ts"],"sourcesContent":["import { LoggerTransport } from '@mastra/core/logger';\nimport type { BaseLogMessage, LogLevel } from '@mastra/core/logger';\n\ninterface RetryOptions {\n maxRetries?: number;\n retryDelay?: number;\n exponentialBackoff?: boolean;\n}\n\ninterface HttpTransportOptions {\n url: string;\n method?: 'POST' | 'PUT' | 'PATCH';\n headers?: Record<string, string>;\n batchSize?: number;\n flushInterval?: number;\n timeout?: number;\n retryOptions?: RetryOptions;\n}\n\nexport class HttpTransport extends LoggerTransport {\n private url: string;\n private method: string;\n private headers: Record<string, string>;\n private batchSize: number;\n private flushInterval: number;\n private timeout: number;\n private retryOptions: Required<RetryOptions>;\n private logBuffer: BaseLogMessage[];\n private lastFlush: number;\n private flushIntervalId: NodeJS.Timeout;\n\n constructor(options: HttpTransportOptions) {\n super({ objectMode: true });\n\n if (!options.url) {\n throw new Error('HTTP URL is required');\n }\n\n this.url = options.url;\n this.method = options.method || 'POST';\n this.headers = {\n 'Content-Type': 'application/json',\n ...options.headers,\n };\n this.batchSize = options.batchSize || 100;\n this.flushInterval = options.flushInterval || 10000;\n this.timeout = options.timeout || 30000;\n this.retryOptions = {\n maxRetries: options.retryOptions?.maxRetries ?? 3,\n retryDelay: options.retryOptions?.retryDelay ?? 1000,\n exponentialBackoff: options.retryOptions?.exponentialBackoff ?? true,\n };\n\n this.logBuffer = [];\n this.lastFlush = Date.now();\n\n // Start flush interval\n this.flushIntervalId = setInterval(() => {\n this._flush().catch(err => {\n console.error('Error flushing logs to HTTP endpoint:', err);\n });\n }, this.flushInterval);\n }\n\n private async makeHttpRequest(data: any, retryCount = 0): Promise<Response> {\n const controller = new AbortController();\n const timeoutId = setTimeout(() => controller.abort(), this.timeout);\n\n try {\n const body = JSON.stringify({ logs: data });\n\n const response = await fetch(this.url, {\n method: this.method,\n headers: this.headers,\n body,\n signal: controller.signal,\n });\n\n clearTimeout(timeoutId);\n\n if (!response.ok) {\n throw new Error(`HTTP ${response.status}: ${response.statusText}`);\n }\n\n return response;\n } catch (error) {\n clearTimeout(timeoutId);\n\n if (retryCount < this.retryOptions.maxRetries) {\n const delay = this.retryOptions.exponentialBackoff\n ? this.retryOptions.retryDelay * Math.pow(2, retryCount)\n : this.retryOptions.retryDelay;\n\n await new Promise(resolve => setTimeout(resolve, delay));\n return this.makeHttpRequest(data, retryCount + 1);\n }\n\n throw error;\n }\n }\n\n async _flush(): Promise<void> {\n if (this.logBuffer.length === 0) {\n return;\n }\n\n const now = Date.now();\n const logs = this.logBuffer.splice(0, this.batchSize);\n\n try {\n await this.makeHttpRequest(logs);\n this.lastFlush = now;\n } catch (error) {\n // On error, put logs back in the buffer\n this.logBuffer.unshift(...logs);\n throw error;\n }\n }\n\n _write(chunk: any, encoding?: string, callback?: (error?: Error | null) => void): boolean {\n if (typeof callback === 'function') {\n this._transform(chunk, encoding || 'utf8', callback);\n return true;\n }\n\n this._transform(chunk, encoding || 'utf8', (error: Error | null) => {\n if (error) console.error('Transform error in write:', error);\n });\n return true;\n }\n\n _transform(chunk: string, _enc: string, cb: Function): void {\n try {\n // Parse the log line if it's a string\n const log = typeof chunk === 'string' ? JSON.parse(chunk) : chunk;\n\n // Add timestamp if not present\n if (!log.time) {\n log.time = Date.now();\n }\n\n // Add to buffer\n this.logBuffer.push(log);\n\n // Flush if buffer reaches batch size\n if (this.logBuffer.length >= this.batchSize) {\n this._flush().catch(err => {\n console.error('Error flushing logs to HTTP endpoint:', err);\n });\n }\n\n // Pass through the log\n cb(null, chunk);\n } catch (error) {\n cb(error);\n }\n }\n\n _destroy(err: Error, cb: Function): void {\n clearInterval(this.flushIntervalId);\n\n // Final flush\n if (this.logBuffer.length > 0) {\n this._flush()\n .then(() => cb(err))\n .catch(flushErr => {\n console.error('Error in final flush:', flushErr);\n cb(err || flushErr);\n });\n } else {\n cb(err);\n }\n }\n\n async listLogs(params?: {\n fromDate?: Date;\n toDate?: Date;\n logLevel?: LogLevel;\n filters?: Record<string, any>;\n returnPaginationResults?: boolean;\n page?: number;\n perPage?: number;\n }): Promise<{\n logs: BaseLogMessage[];\n total: number;\n page: number;\n perPage: number;\n hasMore: boolean;\n }> {\n // HttpTransport is write-only by default\n // Subclasses can override this method to implement log retrieval\n console.warn(\n 'HttpTransport.listLogs: This transport is write-only. Override this method to implement log retrieval.',\n );\n\n return {\n logs: [],\n total: 0,\n page: params?.page ?? 1,\n perPage: params?.perPage ?? 100,\n hasMore: false,\n };\n }\n\n async listLogsByRunId({\n runId: _runId,\n fromDate: _fromDate,\n toDate: _toDate,\n logLevel: _logLevel,\n filters: _filters,\n page,\n perPage,\n }: {\n runId: string;\n fromDate?: Date;\n toDate?: Date;\n logLevel?: LogLevel;\n filters?: Record<string, any>;\n page?: number;\n perPage?: number;\n }): Promise<{\n logs: BaseLogMessage[];\n total: number;\n page: number;\n perPage: number;\n hasMore: boolean;\n }> {\n // HttpTransport is write-only by default\n // Subclasses can override this method to implement log retrieval\n console.warn(\n 'HttpTransport.listLogsByRunId: This transport is write-only. Override this method to implement log retrieval.',\n );\n\n return {\n logs: [],\n total: 0,\n page: page ?? 1,\n perPage: perPage ?? 100,\n hasMore: false,\n };\n }\n\n // Utility methods\n public getBufferedLogs(): BaseLogMessage[] {\n return [...this.logBuffer];\n }\n\n public clearBuffer(): void {\n this.logBuffer = [];\n }\n\n public getLastFlushTime(): number {\n return this.lastFlush;\n }\n}\n"],"mappings":"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"}
|
package/dist/upstash/index.cjs
CHANGED
|
@@ -28,14 +28,14 @@ var UpstashTransport = class extends _mastra_core_logger.LoggerTransport {
|
|
|
28
28
|
});
|
|
29
29
|
}, this.flushInterval);
|
|
30
30
|
}
|
|
31
|
-
async
|
|
31
|
+
async executeUpstashCommands(commands) {
|
|
32
32
|
const response = await fetch(`${this.upstashUrl}/pipeline`, {
|
|
33
33
|
method: "POST",
|
|
34
34
|
headers: {
|
|
35
35
|
Authorization: `Bearer ${this.upstashToken}`,
|
|
36
36
|
"Content-Type": "application/json"
|
|
37
37
|
},
|
|
38
|
-
body: JSON.stringify(
|
|
38
|
+
body: JSON.stringify(commands)
|
|
39
39
|
});
|
|
40
40
|
if (!response.ok) throw new Error(`Failed to execute Upstash command: ${response.statusText}`);
|
|
41
41
|
return response.json();
|
|
@@ -45,13 +45,18 @@ var UpstashTransport = class extends _mastra_core_logger.LoggerTransport {
|
|
|
45
45
|
const now = Date.now();
|
|
46
46
|
const logs = this.logBuffer.splice(0, this.batchSize);
|
|
47
47
|
try {
|
|
48
|
-
const
|
|
48
|
+
const commands = [[
|
|
49
49
|
"LPUSH",
|
|
50
50
|
this.listName,
|
|
51
51
|
...logs.map((log) => JSON.stringify(log))
|
|
52
|
-
];
|
|
53
|
-
if (this.maxListLength > 0)
|
|
54
|
-
|
|
52
|
+
]];
|
|
53
|
+
if (this.maxListLength > 0) commands.push([
|
|
54
|
+
"LTRIM",
|
|
55
|
+
this.listName,
|
|
56
|
+
0,
|
|
57
|
+
this.maxListLength - 1
|
|
58
|
+
]);
|
|
59
|
+
await this.executeUpstashCommands(commands);
|
|
55
60
|
this.lastFlush = now;
|
|
56
61
|
} catch (error) {
|
|
57
62
|
this.logBuffer.unshift(...logs);
|
|
@@ -97,7 +102,7 @@ var UpstashTransport = class extends _mastra_core_logger.LoggerTransport {
|
|
|
97
102
|
0,
|
|
98
103
|
-1
|
|
99
104
|
];
|
|
100
|
-
let filteredLogs = ((await this.
|
|
105
|
+
let filteredLogs = ((await this.executeUpstashCommands([command]))?.[0]?.result?.map((log) => {
|
|
101
106
|
try {
|
|
102
107
|
return JSON.parse(log);
|
|
103
108
|
} catch {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.cjs","names":["LoggerTransport"],"sources":["../../src/upstash/index.ts"],"sourcesContent":["import { LoggerTransport } from '@mastra/core/logger';\nimport type { BaseLogMessage, LogLevel } from '@mastra/core/logger';\n\nexport class UpstashTransport extends LoggerTransport {\n upstashUrl: string;\n upstashToken: string;\n listName: string;\n maxListLength: number;\n batchSize: number;\n flushInterval: number;\n logBuffer: any[];\n lastFlush: number;\n flushIntervalId: NodeJS.Timeout;\n\n constructor(opts: {\n listName?: string;\n maxListLength?: number;\n batchSize?: number;\n upstashUrl: string;\n flushInterval?: number;\n upstashToken: string;\n }) {\n super({ objectMode: true });\n\n if (!opts.upstashUrl || !opts.upstashToken) {\n throw new Error('Upstash URL and token are required');\n }\n\n this.upstashUrl = opts.upstashUrl;\n this.upstashToken = opts.upstashToken;\n this.listName = opts.listName || 'application-logs';\n this.maxListLength = opts.maxListLength || 10000;\n this.batchSize = opts.batchSize || 100;\n this.flushInterval = opts.flushInterval || 10000;\n\n this.logBuffer = [];\n this.lastFlush = Date.now();\n\n // Start flush interval\n this.flushIntervalId = setInterval(() => {\n this._flush().catch(err => {\n console.error('Error flushing logs to Upstash:', err);\n });\n }, this.flushInterval);\n }\n\n private async executeUpstashCommand(command: any[]): Promise<any> {\n const response = await fetch(`${this.upstashUrl}/pipeline`, {\n method: 'POST',\n headers: {\n Authorization: `Bearer ${this.upstashToken}`,\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify([command]),\n });\n\n if (!response.ok) {\n throw new Error(`Failed to execute Upstash command: ${response.statusText}`);\n }\n\n return response.json();\n }\n\n async _flush() {\n if (this.logBuffer.length === 0) {\n return;\n }\n\n const now = Date.now();\n const logs = this.logBuffer.splice(0, this.batchSize);\n\n try {\n // Prepare the Upstash Redis command\n const command = ['LPUSH', this.listName, ...logs.map(log => JSON.stringify(log))];\n\n // Trim the list if it exceeds maxListLength\n if (this.maxListLength > 0) {\n command.push('LTRIM', this.listName, 0 as any, (this.maxListLength - 1) as any);\n }\n\n // Send logs to Upstash Redis\n await this.executeUpstashCommand(command);\n this.lastFlush = now;\n } catch (error) {\n // On error, put logs back in the buffer\n this.logBuffer.unshift(...logs);\n throw error;\n }\n }\n\n _write(chunk: any, encoding?: string, callback?: (error?: Error | null) => void): boolean {\n if (typeof callback === 'function') {\n this._transform(chunk, encoding || 'utf8', callback);\n return true;\n }\n\n this._transform(chunk, encoding || 'utf8', (error: Error | null) => {\n if (error) console.error('Transform error in write:', error);\n });\n return true;\n }\n\n _transform(chunk: string, _enc: string, cb: Function) {\n try {\n // Parse the log line if it's a string\n const log = typeof chunk === 'string' ? JSON.parse(chunk) : chunk;\n\n // Add timestamp if not present\n if (!log.time) {\n log.time = Date.now();\n }\n\n // Add to buffer\n this.logBuffer.push(log);\n\n // Flush if buffer reaches batch size\n if (this.logBuffer.length >= this.batchSize) {\n this._flush().catch(err => {\n console.error('Error flushing logs to Upstash:', err);\n });\n }\n\n // Pass through the log\n cb(null, chunk);\n } catch (error) {\n cb(error);\n }\n }\n\n _destroy(err: Error, cb: Function) {\n clearInterval(this.flushIntervalId);\n\n // Final flush\n if (this.logBuffer.length > 0) {\n this._flush()\n .then(() => cb(err))\n .catch(flushErr => {\n console.error('Error in final flush:', flushErr);\n cb(err || flushErr);\n });\n } else {\n cb(err);\n }\n }\n\n async listLogs(params?: {\n fromDate?: Date;\n toDate?: Date;\n logLevel?: LogLevel;\n filters?: Record<string, any>;\n returnPaginationResults?: boolean; // default true\n page?: number;\n perPage?: number;\n }): Promise<{\n logs: BaseLogMessage[];\n total: number;\n page: number;\n perPage: number;\n hasMore: boolean;\n }> {\n try {\n // Get all logs from the list\n const command = ['LRANGE', this.listName, 0, -1];\n const response = await this.executeUpstashCommand(command);\n\n const logs =\n (response?.[0]?.result?.map((log: string) => {\n try {\n // Parse the logs from JSON strings back to objects\n return JSON.parse(log);\n } catch {\n return {};\n }\n }) as BaseLogMessage[]) || [];\n\n let filteredLogs = logs.filter(record => record !== null && typeof record === 'object');\n\n const {\n fromDate,\n toDate,\n logLevel,\n filters,\n returnPaginationResults: returnPaginationResultsInput,\n page: pageInput,\n perPage: perPageInput,\n } = params || {};\n\n const page = pageInput === 0 ? 1 : (pageInput ?? 1);\n const perPage = perPageInput ?? 100;\n const returnPaginationResults = returnPaginationResultsInput ?? true;\n\n if (filters) {\n filteredLogs = filteredLogs.filter(log =>\n Object.entries(filters || {}).every(([key, value]) => log[key as keyof BaseLogMessage] === value),\n );\n }\n\n if (logLevel) {\n filteredLogs = filteredLogs.filter(log => log.level === logLevel);\n }\n\n if (fromDate) {\n filteredLogs = filteredLogs.filter(log => new Date(log.time)?.getTime() >= fromDate!.getTime());\n }\n\n if (toDate) {\n filteredLogs = filteredLogs.filter(log => new Date(log.time)?.getTime() <= toDate!.getTime());\n }\n\n if (!returnPaginationResults) {\n return {\n logs: filteredLogs,\n total: filteredLogs.length,\n page,\n perPage: filteredLogs.length,\n hasMore: false,\n };\n }\n\n const total = filteredLogs.length;\n const resolvedPerPage = perPage || 100;\n const start = (page - 1) * resolvedPerPage;\n const end = start + resolvedPerPage;\n const paginatedLogs = filteredLogs.slice(start, end);\n const hasMore = end < total;\n\n return {\n logs: paginatedLogs,\n total,\n page,\n perPage: resolvedPerPage,\n hasMore,\n };\n } catch (error) {\n console.error('Error getting logs from Upstash:', error);\n return {\n logs: [],\n total: 0,\n page: params?.page ?? 1,\n perPage: params?.perPage ?? 100,\n hasMore: false,\n };\n }\n }\n\n async listLogsByRunId({\n runId,\n fromDate,\n toDate,\n logLevel,\n filters,\n page: pageInput,\n perPage: perPageInput,\n }: {\n runId: string;\n fromDate?: Date;\n toDate?: Date;\n logLevel?: LogLevel;\n filters?: Record<string, any>;\n page?: number;\n perPage?: number;\n }): Promise<{\n logs: BaseLogMessage[];\n total: number;\n page: number;\n perPage: number;\n hasMore: boolean;\n }> {\n try {\n const page = pageInput === 0 ? 1 : (pageInput ?? 1);\n const perPage = perPageInput ?? 100;\n const allLogs = await this.listLogs({ fromDate, toDate, logLevel, filters, returnPaginationResults: false });\n const logs = (allLogs?.logs?.filter((log: any) => log.runId === runId) || []) as BaseLogMessage[];\n const total = logs.length;\n const resolvedPerPage = perPage || 100;\n const start = (page - 1) * resolvedPerPage;\n const end = start + resolvedPerPage;\n const paginatedLogs = logs.slice(start, end);\n const hasMore = end < total;\n\n return {\n logs: paginatedLogs,\n total,\n page,\n perPage: resolvedPerPage,\n hasMore,\n };\n } catch (error) {\n console.error('Error getting logs by runId from Upstash:', error);\n return {\n logs: [],\n total: 0,\n page: pageInput ?? 1,\n perPage: perPageInput ?? 100,\n hasMore: false,\n };\n }\n }\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.cjs","names":["LoggerTransport"],"sources":["../../src/upstash/index.ts"],"sourcesContent":["import { LoggerTransport } from '@mastra/core/logger';\nimport type { BaseLogMessage, LogLevel } from '@mastra/core/logger';\n\nexport class UpstashTransport extends LoggerTransport {\n upstashUrl: string;\n upstashToken: string;\n listName: string;\n maxListLength: number;\n batchSize: number;\n flushInterval: number;\n logBuffer: any[];\n lastFlush: number;\n flushIntervalId: NodeJS.Timeout;\n\n constructor(opts: {\n listName?: string;\n maxListLength?: number;\n batchSize?: number;\n upstashUrl: string;\n flushInterval?: number;\n upstashToken: string;\n }) {\n super({ objectMode: true });\n\n if (!opts.upstashUrl || !opts.upstashToken) {\n throw new Error('Upstash URL and token are required');\n }\n\n this.upstashUrl = opts.upstashUrl;\n this.upstashToken = opts.upstashToken;\n this.listName = opts.listName || 'application-logs';\n this.maxListLength = opts.maxListLength || 10000;\n this.batchSize = opts.batchSize || 100;\n this.flushInterval = opts.flushInterval || 10000;\n\n this.logBuffer = [];\n this.lastFlush = Date.now();\n\n // Start flush interval\n this.flushIntervalId = setInterval(() => {\n this._flush().catch(err => {\n console.error('Error flushing logs to Upstash:', err);\n });\n }, this.flushInterval);\n }\n\n private async executeUpstashCommands(commands: any[][]): Promise<any> {\n const response = await fetch(`${this.upstashUrl}/pipeline`, {\n method: 'POST',\n headers: {\n Authorization: `Bearer ${this.upstashToken}`,\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify(commands),\n });\n\n if (!response.ok) {\n throw new Error(`Failed to execute Upstash command: ${response.statusText}`);\n }\n\n return response.json();\n }\n\n async _flush() {\n if (this.logBuffer.length === 0) {\n return;\n }\n\n const now = Date.now();\n const logs = this.logBuffer.splice(0, this.batchSize);\n\n try {\n const commands: any[][] = [['LPUSH', this.listName, ...logs.map(log => JSON.stringify(log))]];\n\n // Trim the list if it exceeds maxListLength (must be a separate pipeline command)\n if (this.maxListLength > 0) {\n commands.push(['LTRIM', this.listName, 0, this.maxListLength - 1]);\n }\n\n await this.executeUpstashCommands(commands);\n this.lastFlush = now;\n } catch (error) {\n // On error, put logs back in the buffer\n this.logBuffer.unshift(...logs);\n throw error;\n }\n }\n\n _write(chunk: any, encoding?: string, callback?: (error?: Error | null) => void): boolean {\n if (typeof callback === 'function') {\n this._transform(chunk, encoding || 'utf8', callback);\n return true;\n }\n\n this._transform(chunk, encoding || 'utf8', (error: Error | null) => {\n if (error) console.error('Transform error in write:', error);\n });\n return true;\n }\n\n _transform(chunk: string, _enc: string, cb: Function) {\n try {\n // Parse the log line if it's a string\n const log = typeof chunk === 'string' ? JSON.parse(chunk) : chunk;\n\n // Add timestamp if not present\n if (!log.time) {\n log.time = Date.now();\n }\n\n // Add to buffer\n this.logBuffer.push(log);\n\n // Flush if buffer reaches batch size\n if (this.logBuffer.length >= this.batchSize) {\n this._flush().catch(err => {\n console.error('Error flushing logs to Upstash:', err);\n });\n }\n\n // Pass through the log\n cb(null, chunk);\n } catch (error) {\n cb(error);\n }\n }\n\n _destroy(err: Error, cb: Function) {\n clearInterval(this.flushIntervalId);\n\n // Final flush\n if (this.logBuffer.length > 0) {\n this._flush()\n .then(() => cb(err))\n .catch(flushErr => {\n console.error('Error in final flush:', flushErr);\n cb(err || flushErr);\n });\n } else {\n cb(err);\n }\n }\n\n async listLogs(params?: {\n fromDate?: Date;\n toDate?: Date;\n logLevel?: LogLevel;\n filters?: Record<string, any>;\n returnPaginationResults?: boolean; // default true\n page?: number;\n perPage?: number;\n }): Promise<{\n logs: BaseLogMessage[];\n total: number;\n page: number;\n perPage: number;\n hasMore: boolean;\n }> {\n try {\n // Get all logs from the list\n const command = ['LRANGE', this.listName, 0, -1];\n const response = await this.executeUpstashCommands([command]);\n\n const logs =\n (response?.[0]?.result?.map((log: string) => {\n try {\n // Parse the logs from JSON strings back to objects\n return JSON.parse(log);\n } catch {\n return {};\n }\n }) as BaseLogMessage[]) || [];\n\n let filteredLogs = logs.filter(record => record !== null && typeof record === 'object');\n\n const {\n fromDate,\n toDate,\n logLevel,\n filters,\n returnPaginationResults: returnPaginationResultsInput,\n page: pageInput,\n perPage: perPageInput,\n } = params || {};\n\n const page = pageInput === 0 ? 1 : (pageInput ?? 1);\n const perPage = perPageInput ?? 100;\n const returnPaginationResults = returnPaginationResultsInput ?? true;\n\n if (filters) {\n filteredLogs = filteredLogs.filter(log =>\n Object.entries(filters || {}).every(([key, value]) => log[key as keyof BaseLogMessage] === value),\n );\n }\n\n if (logLevel) {\n filteredLogs = filteredLogs.filter(log => log.level === logLevel);\n }\n\n if (fromDate) {\n filteredLogs = filteredLogs.filter(log => new Date(log.time)?.getTime() >= fromDate!.getTime());\n }\n\n if (toDate) {\n filteredLogs = filteredLogs.filter(log => new Date(log.time)?.getTime() <= toDate!.getTime());\n }\n\n if (!returnPaginationResults) {\n return {\n logs: filteredLogs,\n total: filteredLogs.length,\n page,\n perPage: filteredLogs.length,\n hasMore: false,\n };\n }\n\n const total = filteredLogs.length;\n const resolvedPerPage = perPage || 100;\n const start = (page - 1) * resolvedPerPage;\n const end = start + resolvedPerPage;\n const paginatedLogs = filteredLogs.slice(start, end);\n const hasMore = end < total;\n\n return {\n logs: paginatedLogs,\n total,\n page,\n perPage: resolvedPerPage,\n hasMore,\n };\n } catch (error) {\n console.error('Error getting logs from Upstash:', error);\n return {\n logs: [],\n total: 0,\n page: params?.page ?? 1,\n perPage: params?.perPage ?? 100,\n hasMore: false,\n };\n }\n }\n\n async listLogsByRunId({\n runId,\n fromDate,\n toDate,\n logLevel,\n filters,\n page: pageInput,\n perPage: perPageInput,\n }: {\n runId: string;\n fromDate?: Date;\n toDate?: Date;\n logLevel?: LogLevel;\n filters?: Record<string, any>;\n page?: number;\n perPage?: number;\n }): Promise<{\n logs: BaseLogMessage[];\n total: number;\n page: number;\n perPage: number;\n hasMore: boolean;\n }> {\n try {\n const page = pageInput === 0 ? 1 : (pageInput ?? 1);\n const perPage = perPageInput ?? 100;\n const allLogs = await this.listLogs({ fromDate, toDate, logLevel, filters, returnPaginationResults: false });\n const logs = (allLogs?.logs?.filter((log: any) => log.runId === runId) || []) as BaseLogMessage[];\n const total = logs.length;\n const resolvedPerPage = perPage || 100;\n const start = (page - 1) * resolvedPerPage;\n const end = start + resolvedPerPage;\n const paginatedLogs = logs.slice(start, end);\n const hasMore = end < total;\n\n return {\n logs: paginatedLogs,\n total,\n page,\n perPage: resolvedPerPage,\n hasMore,\n };\n } catch (error) {\n console.error('Error getting logs by runId from Upstash:', error);\n return {\n logs: [],\n total: 0,\n page: pageInput ?? 1,\n perPage: perPageInput ?? 100,\n hasMore: false,\n };\n }\n }\n}\n"],"mappings":"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"}
|
package/dist/upstash/index.d.ts
CHANGED
|
@@ -18,7 +18,7 @@ export declare class UpstashTransport extends LoggerTransport {
|
|
|
18
18
|
flushInterval?: number;
|
|
19
19
|
upstashToken: string;
|
|
20
20
|
});
|
|
21
|
-
private
|
|
21
|
+
private executeUpstashCommands;
|
|
22
22
|
_flush(): Promise<void>;
|
|
23
23
|
_write(chunk: any, encoding?: string, callback?: (error?: Error | null) => void): boolean;
|
|
24
24
|
_transform(chunk: string, _enc: string, cb: Function): void;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/upstash/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AACtD,OAAO,KAAK,EAAE,cAAc,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AAEpE,qBAAa,gBAAiB,SAAQ,eAAe;IACnD,UAAU,EAAE,MAAM,CAAC;IACnB,YAAY,EAAE,MAAM,CAAC;IACrB,QAAQ,EAAE,MAAM,CAAC;IACjB,aAAa,EAAE,MAAM,CAAC;IACtB,SAAS,EAAE,MAAM,CAAC;IAClB,aAAa,EAAE,MAAM,CAAC;IACtB,SAAS,EAAE,GAAG,EAAE,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,eAAe,EAAE,MAAM,CAAC,OAAO,CAAC;IAEhC,YAAY,IAAI,EAAE;QAChB,QAAQ,CAAC,EAAE,MAAM,CAAC;QAClB,aAAa,CAAC,EAAE,MAAM,CAAC;QACvB,SAAS,CAAC,EAAE,MAAM,CAAC;QACnB,UAAU,EAAE,MAAM,CAAC;QACnB,aAAa,CAAC,EAAE,MAAM,CAAC;QACvB,YAAY,EAAE,MAAM,CAAC;KACtB,EAuBA;YAEa,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/upstash/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AACtD,OAAO,KAAK,EAAE,cAAc,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AAEpE,qBAAa,gBAAiB,SAAQ,eAAe;IACnD,UAAU,EAAE,MAAM,CAAC;IACnB,YAAY,EAAE,MAAM,CAAC;IACrB,QAAQ,EAAE,MAAM,CAAC;IACjB,aAAa,EAAE,MAAM,CAAC;IACtB,SAAS,EAAE,MAAM,CAAC;IAClB,aAAa,EAAE,MAAM,CAAC;IACtB,SAAS,EAAE,GAAG,EAAE,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,eAAe,EAAE,MAAM,CAAC,OAAO,CAAC;IAEhC,YAAY,IAAI,EAAE;QAChB,QAAQ,CAAC,EAAE,MAAM,CAAC;QAClB,aAAa,CAAC,EAAE,MAAM,CAAC;QACvB,SAAS,CAAC,EAAE,MAAM,CAAC;QACnB,UAAU,EAAE,MAAM,CAAC;QACnB,aAAa,CAAC,EAAE,MAAM,CAAC;QACvB,YAAY,EAAE,MAAM,CAAC;KACtB,EAuBA;YAEa,sBAAsB;IAiB9B,MAAM,kBAuBX;IAED,MAAM,CAAC,KAAK,EAAE,GAAG,EAAE,QAAQ,CAAC,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,CAAC,KAAK,CAAC,EAAE,KAAK,GAAG,IAAI,KAAK,IAAI,GAAG,OAAO,CAUxF;IAED,UAAU,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,QAAQ,QAyBnD;IAED,QAAQ,CAAC,GAAG,EAAE,KAAK,EAAE,EAAE,EAAE,QAAQ,QAchC;IAEK,QAAQ,CAAC,MAAM,CAAC,EAAE;QACtB,QAAQ,CAAC,EAAE,IAAI,CAAC;QAChB,MAAM,CAAC,EAAE,IAAI,CAAC;QACd,QAAQ,CAAC,EAAE,QAAQ,CAAC;QACpB,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;QAC9B,uBAAuB,CAAC,EAAE,OAAO,CAAC;QAClC,IAAI,CAAC,EAAE,MAAM,CAAC;QACd,OAAO,CAAC,EAAE,MAAM,CAAC;KAClB,GAAG,OAAO,CAAC;QACV,IAAI,EAAE,cAAc,EAAE,CAAC;QACvB,KAAK,EAAE,MAAM,CAAC;QACd,IAAI,EAAE,MAAM,CAAC;QACb,OAAO,EAAE,MAAM,CAAC;QAChB,OAAO,EAAE,OAAO,CAAC;KAClB,CAAC,CAoFD;IAEK,eAAe,CAAC,EACpB,KAAK,EACL,QAAQ,EACR,MAAM,EACN,QAAQ,EACR,OAAO,EACP,IAAI,EAAE,SAAS,EACf,OAAO,EAAE,YAAY,GACtB,EAAE;QACD,KAAK,EAAE,MAAM,CAAC;QACd,QAAQ,CAAC,EAAE,IAAI,CAAC;QAChB,MAAM,CAAC,EAAE,IAAI,CAAC;QACd,QAAQ,CAAC,EAAE,QAAQ,CAAC;QACpB,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;QAC9B,IAAI,CAAC,EAAE,MAAM,CAAC;QACd,OAAO,CAAC,EAAE,MAAM,CAAC;KAClB,GAAG,OAAO,CAAC;QACV,IAAI,EAAE,cAAc,EAAE,CAAC;QACvB,KAAK,EAAE,MAAM,CAAC;QACd,IAAI,EAAE,MAAM,CAAC;QACb,OAAO,EAAE,MAAM,CAAC;QAChB,OAAO,EAAE,OAAO,CAAC;KAClB,CAAC,CA8BD;CACF"}
|
package/dist/upstash/index.js
CHANGED
|
@@ -27,14 +27,14 @@ var UpstashTransport = class extends LoggerTransport {
|
|
|
27
27
|
});
|
|
28
28
|
}, this.flushInterval);
|
|
29
29
|
}
|
|
30
|
-
async
|
|
30
|
+
async executeUpstashCommands(commands) {
|
|
31
31
|
const response = await fetch(`${this.upstashUrl}/pipeline`, {
|
|
32
32
|
method: "POST",
|
|
33
33
|
headers: {
|
|
34
34
|
Authorization: `Bearer ${this.upstashToken}`,
|
|
35
35
|
"Content-Type": "application/json"
|
|
36
36
|
},
|
|
37
|
-
body: JSON.stringify(
|
|
37
|
+
body: JSON.stringify(commands)
|
|
38
38
|
});
|
|
39
39
|
if (!response.ok) throw new Error(`Failed to execute Upstash command: ${response.statusText}`);
|
|
40
40
|
return response.json();
|
|
@@ -44,13 +44,18 @@ var UpstashTransport = class extends LoggerTransport {
|
|
|
44
44
|
const now = Date.now();
|
|
45
45
|
const logs = this.logBuffer.splice(0, this.batchSize);
|
|
46
46
|
try {
|
|
47
|
-
const
|
|
47
|
+
const commands = [[
|
|
48
48
|
"LPUSH",
|
|
49
49
|
this.listName,
|
|
50
50
|
...logs.map((log) => JSON.stringify(log))
|
|
51
|
-
];
|
|
52
|
-
if (this.maxListLength > 0)
|
|
53
|
-
|
|
51
|
+
]];
|
|
52
|
+
if (this.maxListLength > 0) commands.push([
|
|
53
|
+
"LTRIM",
|
|
54
|
+
this.listName,
|
|
55
|
+
0,
|
|
56
|
+
this.maxListLength - 1
|
|
57
|
+
]);
|
|
58
|
+
await this.executeUpstashCommands(commands);
|
|
54
59
|
this.lastFlush = now;
|
|
55
60
|
} catch (error) {
|
|
56
61
|
this.logBuffer.unshift(...logs);
|
|
@@ -96,7 +101,7 @@ var UpstashTransport = class extends LoggerTransport {
|
|
|
96
101
|
0,
|
|
97
102
|
-1
|
|
98
103
|
];
|
|
99
|
-
let filteredLogs = ((await this.
|
|
104
|
+
let filteredLogs = ((await this.executeUpstashCommands([command]))?.[0]?.result?.map((log) => {
|
|
100
105
|
try {
|
|
101
106
|
return JSON.parse(log);
|
|
102
107
|
} catch {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":[],"sources":["../../src/upstash/index.ts"],"sourcesContent":["import { LoggerTransport } from '@mastra/core/logger';\nimport type { BaseLogMessage, LogLevel } from '@mastra/core/logger';\n\nexport class UpstashTransport extends LoggerTransport {\n upstashUrl: string;\n upstashToken: string;\n listName: string;\n maxListLength: number;\n batchSize: number;\n flushInterval: number;\n logBuffer: any[];\n lastFlush: number;\n flushIntervalId: NodeJS.Timeout;\n\n constructor(opts: {\n listName?: string;\n maxListLength?: number;\n batchSize?: number;\n upstashUrl: string;\n flushInterval?: number;\n upstashToken: string;\n }) {\n super({ objectMode: true });\n\n if (!opts.upstashUrl || !opts.upstashToken) {\n throw new Error('Upstash URL and token are required');\n }\n\n this.upstashUrl = opts.upstashUrl;\n this.upstashToken = opts.upstashToken;\n this.listName = opts.listName || 'application-logs';\n this.maxListLength = opts.maxListLength || 10000;\n this.batchSize = opts.batchSize || 100;\n this.flushInterval = opts.flushInterval || 10000;\n\n this.logBuffer = [];\n this.lastFlush = Date.now();\n\n // Start flush interval\n this.flushIntervalId = setInterval(() => {\n this._flush().catch(err => {\n console.error('Error flushing logs to Upstash:', err);\n });\n }, this.flushInterval);\n }\n\n private async executeUpstashCommand(command: any[]): Promise<any> {\n const response = await fetch(`${this.upstashUrl}/pipeline`, {\n method: 'POST',\n headers: {\n Authorization: `Bearer ${this.upstashToken}`,\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify([command]),\n });\n\n if (!response.ok) {\n throw new Error(`Failed to execute Upstash command: ${response.statusText}`);\n }\n\n return response.json();\n }\n\n async _flush() {\n if (this.logBuffer.length === 0) {\n return;\n }\n\n const now = Date.now();\n const logs = this.logBuffer.splice(0, this.batchSize);\n\n try {\n // Prepare the Upstash Redis command\n const command = ['LPUSH', this.listName, ...logs.map(log => JSON.stringify(log))];\n\n // Trim the list if it exceeds maxListLength\n if (this.maxListLength > 0) {\n command.push('LTRIM', this.listName, 0 as any, (this.maxListLength - 1) as any);\n }\n\n // Send logs to Upstash Redis\n await this.executeUpstashCommand(command);\n this.lastFlush = now;\n } catch (error) {\n // On error, put logs back in the buffer\n this.logBuffer.unshift(...logs);\n throw error;\n }\n }\n\n _write(chunk: any, encoding?: string, callback?: (error?: Error | null) => void): boolean {\n if (typeof callback === 'function') {\n this._transform(chunk, encoding || 'utf8', callback);\n return true;\n }\n\n this._transform(chunk, encoding || 'utf8', (error: Error | null) => {\n if (error) console.error('Transform error in write:', error);\n });\n return true;\n }\n\n _transform(chunk: string, _enc: string, cb: Function) {\n try {\n // Parse the log line if it's a string\n const log = typeof chunk === 'string' ? JSON.parse(chunk) : chunk;\n\n // Add timestamp if not present\n if (!log.time) {\n log.time = Date.now();\n }\n\n // Add to buffer\n this.logBuffer.push(log);\n\n // Flush if buffer reaches batch size\n if (this.logBuffer.length >= this.batchSize) {\n this._flush().catch(err => {\n console.error('Error flushing logs to Upstash:', err);\n });\n }\n\n // Pass through the log\n cb(null, chunk);\n } catch (error) {\n cb(error);\n }\n }\n\n _destroy(err: Error, cb: Function) {\n clearInterval(this.flushIntervalId);\n\n // Final flush\n if (this.logBuffer.length > 0) {\n this._flush()\n .then(() => cb(err))\n .catch(flushErr => {\n console.error('Error in final flush:', flushErr);\n cb(err || flushErr);\n });\n } else {\n cb(err);\n }\n }\n\n async listLogs(params?: {\n fromDate?: Date;\n toDate?: Date;\n logLevel?: LogLevel;\n filters?: Record<string, any>;\n returnPaginationResults?: boolean; // default true\n page?: number;\n perPage?: number;\n }): Promise<{\n logs: BaseLogMessage[];\n total: number;\n page: number;\n perPage: number;\n hasMore: boolean;\n }> {\n try {\n // Get all logs from the list\n const command = ['LRANGE', this.listName, 0, -1];\n const response = await this.executeUpstashCommand(command);\n\n const logs =\n (response?.[0]?.result?.map((log: string) => {\n try {\n // Parse the logs from JSON strings back to objects\n return JSON.parse(log);\n } catch {\n return {};\n }\n }) as BaseLogMessage[]) || [];\n\n let filteredLogs = logs.filter(record => record !== null && typeof record === 'object');\n\n const {\n fromDate,\n toDate,\n logLevel,\n filters,\n returnPaginationResults: returnPaginationResultsInput,\n page: pageInput,\n perPage: perPageInput,\n } = params || {};\n\n const page = pageInput === 0 ? 1 : (pageInput ?? 1);\n const perPage = perPageInput ?? 100;\n const returnPaginationResults = returnPaginationResultsInput ?? true;\n\n if (filters) {\n filteredLogs = filteredLogs.filter(log =>\n Object.entries(filters || {}).every(([key, value]) => log[key as keyof BaseLogMessage] === value),\n );\n }\n\n if (logLevel) {\n filteredLogs = filteredLogs.filter(log => log.level === logLevel);\n }\n\n if (fromDate) {\n filteredLogs = filteredLogs.filter(log => new Date(log.time)?.getTime() >= fromDate!.getTime());\n }\n\n if (toDate) {\n filteredLogs = filteredLogs.filter(log => new Date(log.time)?.getTime() <= toDate!.getTime());\n }\n\n if (!returnPaginationResults) {\n return {\n logs: filteredLogs,\n total: filteredLogs.length,\n page,\n perPage: filteredLogs.length,\n hasMore: false,\n };\n }\n\n const total = filteredLogs.length;\n const resolvedPerPage = perPage || 100;\n const start = (page - 1) * resolvedPerPage;\n const end = start + resolvedPerPage;\n const paginatedLogs = filteredLogs.slice(start, end);\n const hasMore = end < total;\n\n return {\n logs: paginatedLogs,\n total,\n page,\n perPage: resolvedPerPage,\n hasMore,\n };\n } catch (error) {\n console.error('Error getting logs from Upstash:', error);\n return {\n logs: [],\n total: 0,\n page: params?.page ?? 1,\n perPage: params?.perPage ?? 100,\n hasMore: false,\n };\n }\n }\n\n async listLogsByRunId({\n runId,\n fromDate,\n toDate,\n logLevel,\n filters,\n page: pageInput,\n perPage: perPageInput,\n }: {\n runId: string;\n fromDate?: Date;\n toDate?: Date;\n logLevel?: LogLevel;\n filters?: Record<string, any>;\n page?: number;\n perPage?: number;\n }): Promise<{\n logs: BaseLogMessage[];\n total: number;\n page: number;\n perPage: number;\n hasMore: boolean;\n }> {\n try {\n const page = pageInput === 0 ? 1 : (pageInput ?? 1);\n const perPage = perPageInput ?? 100;\n const allLogs = await this.listLogs({ fromDate, toDate, logLevel, filters, returnPaginationResults: false });\n const logs = (allLogs?.logs?.filter((log: any) => log.runId === runId) || []) as BaseLogMessage[];\n const total = logs.length;\n const resolvedPerPage = perPage || 100;\n const start = (page - 1) * resolvedPerPage;\n const end = start + resolvedPerPage;\n const paginatedLogs = logs.slice(start, end);\n const hasMore = end < total;\n\n return {\n logs: paginatedLogs,\n total,\n page,\n perPage: resolvedPerPage,\n hasMore,\n };\n } catch (error) {\n console.error('Error getting logs by runId from Upstash:', error);\n return {\n logs: [],\n total: 0,\n page: pageInput ?? 1,\n perPage: perPageInput ?? 100,\n hasMore: false,\n };\n }\n }\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","names":[],"sources":["../../src/upstash/index.ts"],"sourcesContent":["import { LoggerTransport } from '@mastra/core/logger';\nimport type { BaseLogMessage, LogLevel } from '@mastra/core/logger';\n\nexport class UpstashTransport extends LoggerTransport {\n upstashUrl: string;\n upstashToken: string;\n listName: string;\n maxListLength: number;\n batchSize: number;\n flushInterval: number;\n logBuffer: any[];\n lastFlush: number;\n flushIntervalId: NodeJS.Timeout;\n\n constructor(opts: {\n listName?: string;\n maxListLength?: number;\n batchSize?: number;\n upstashUrl: string;\n flushInterval?: number;\n upstashToken: string;\n }) {\n super({ objectMode: true });\n\n if (!opts.upstashUrl || !opts.upstashToken) {\n throw new Error('Upstash URL and token are required');\n }\n\n this.upstashUrl = opts.upstashUrl;\n this.upstashToken = opts.upstashToken;\n this.listName = opts.listName || 'application-logs';\n this.maxListLength = opts.maxListLength || 10000;\n this.batchSize = opts.batchSize || 100;\n this.flushInterval = opts.flushInterval || 10000;\n\n this.logBuffer = [];\n this.lastFlush = Date.now();\n\n // Start flush interval\n this.flushIntervalId = setInterval(() => {\n this._flush().catch(err => {\n console.error('Error flushing logs to Upstash:', err);\n });\n }, this.flushInterval);\n }\n\n private async executeUpstashCommands(commands: any[][]): Promise<any> {\n const response = await fetch(`${this.upstashUrl}/pipeline`, {\n method: 'POST',\n headers: {\n Authorization: `Bearer ${this.upstashToken}`,\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify(commands),\n });\n\n if (!response.ok) {\n throw new Error(`Failed to execute Upstash command: ${response.statusText}`);\n }\n\n return response.json();\n }\n\n async _flush() {\n if (this.logBuffer.length === 0) {\n return;\n }\n\n const now = Date.now();\n const logs = this.logBuffer.splice(0, this.batchSize);\n\n try {\n const commands: any[][] = [['LPUSH', this.listName, ...logs.map(log => JSON.stringify(log))]];\n\n // Trim the list if it exceeds maxListLength (must be a separate pipeline command)\n if (this.maxListLength > 0) {\n commands.push(['LTRIM', this.listName, 0, this.maxListLength - 1]);\n }\n\n await this.executeUpstashCommands(commands);\n this.lastFlush = now;\n } catch (error) {\n // On error, put logs back in the buffer\n this.logBuffer.unshift(...logs);\n throw error;\n }\n }\n\n _write(chunk: any, encoding?: string, callback?: (error?: Error | null) => void): boolean {\n if (typeof callback === 'function') {\n this._transform(chunk, encoding || 'utf8', callback);\n return true;\n }\n\n this._transform(chunk, encoding || 'utf8', (error: Error | null) => {\n if (error) console.error('Transform error in write:', error);\n });\n return true;\n }\n\n _transform(chunk: string, _enc: string, cb: Function) {\n try {\n // Parse the log line if it's a string\n const log = typeof chunk === 'string' ? JSON.parse(chunk) : chunk;\n\n // Add timestamp if not present\n if (!log.time) {\n log.time = Date.now();\n }\n\n // Add to buffer\n this.logBuffer.push(log);\n\n // Flush if buffer reaches batch size\n if (this.logBuffer.length >= this.batchSize) {\n this._flush().catch(err => {\n console.error('Error flushing logs to Upstash:', err);\n });\n }\n\n // Pass through the log\n cb(null, chunk);\n } catch (error) {\n cb(error);\n }\n }\n\n _destroy(err: Error, cb: Function) {\n clearInterval(this.flushIntervalId);\n\n // Final flush\n if (this.logBuffer.length > 0) {\n this._flush()\n .then(() => cb(err))\n .catch(flushErr => {\n console.error('Error in final flush:', flushErr);\n cb(err || flushErr);\n });\n } else {\n cb(err);\n }\n }\n\n async listLogs(params?: {\n fromDate?: Date;\n toDate?: Date;\n logLevel?: LogLevel;\n filters?: Record<string, any>;\n returnPaginationResults?: boolean; // default true\n page?: number;\n perPage?: number;\n }): Promise<{\n logs: BaseLogMessage[];\n total: number;\n page: number;\n perPage: number;\n hasMore: boolean;\n }> {\n try {\n // Get all logs from the list\n const command = ['LRANGE', this.listName, 0, -1];\n const response = await this.executeUpstashCommands([command]);\n\n const logs =\n (response?.[0]?.result?.map((log: string) => {\n try {\n // Parse the logs from JSON strings back to objects\n return JSON.parse(log);\n } catch {\n return {};\n }\n }) as BaseLogMessage[]) || [];\n\n let filteredLogs = logs.filter(record => record !== null && typeof record === 'object');\n\n const {\n fromDate,\n toDate,\n logLevel,\n filters,\n returnPaginationResults: returnPaginationResultsInput,\n page: pageInput,\n perPage: perPageInput,\n } = params || {};\n\n const page = pageInput === 0 ? 1 : (pageInput ?? 1);\n const perPage = perPageInput ?? 100;\n const returnPaginationResults = returnPaginationResultsInput ?? true;\n\n if (filters) {\n filteredLogs = filteredLogs.filter(log =>\n Object.entries(filters || {}).every(([key, value]) => log[key as keyof BaseLogMessage] === value),\n );\n }\n\n if (logLevel) {\n filteredLogs = filteredLogs.filter(log => log.level === logLevel);\n }\n\n if (fromDate) {\n filteredLogs = filteredLogs.filter(log => new Date(log.time)?.getTime() >= fromDate!.getTime());\n }\n\n if (toDate) {\n filteredLogs = filteredLogs.filter(log => new Date(log.time)?.getTime() <= toDate!.getTime());\n }\n\n if (!returnPaginationResults) {\n return {\n logs: filteredLogs,\n total: filteredLogs.length,\n page,\n perPage: filteredLogs.length,\n hasMore: false,\n };\n }\n\n const total = filteredLogs.length;\n const resolvedPerPage = perPage || 100;\n const start = (page - 1) * resolvedPerPage;\n const end = start + resolvedPerPage;\n const paginatedLogs = filteredLogs.slice(start, end);\n const hasMore = end < total;\n\n return {\n logs: paginatedLogs,\n total,\n page,\n perPage: resolvedPerPage,\n hasMore,\n };\n } catch (error) {\n console.error('Error getting logs from Upstash:', error);\n return {\n logs: [],\n total: 0,\n page: params?.page ?? 1,\n perPage: params?.perPage ?? 100,\n hasMore: false,\n };\n }\n }\n\n async listLogsByRunId({\n runId,\n fromDate,\n toDate,\n logLevel,\n filters,\n page: pageInput,\n perPage: perPageInput,\n }: {\n runId: string;\n fromDate?: Date;\n toDate?: Date;\n logLevel?: LogLevel;\n filters?: Record<string, any>;\n page?: number;\n perPage?: number;\n }): Promise<{\n logs: BaseLogMessage[];\n total: number;\n page: number;\n perPage: number;\n hasMore: boolean;\n }> {\n try {\n const page = pageInput === 0 ? 1 : (pageInput ?? 1);\n const perPage = perPageInput ?? 100;\n const allLogs = await this.listLogs({ fromDate, toDate, logLevel, filters, returnPaginationResults: false });\n const logs = (allLogs?.logs?.filter((log: any) => log.runId === runId) || []) as BaseLogMessage[];\n const total = logs.length;\n const resolvedPerPage = perPage || 100;\n const start = (page - 1) * resolvedPerPage;\n const end = start + resolvedPerPage;\n const paginatedLogs = logs.slice(start, end);\n const hasMore = end < total;\n\n return {\n logs: paginatedLogs,\n total,\n page,\n perPage: resolvedPerPage,\n hasMore,\n };\n } catch (error) {\n console.error('Error getting logs by runId from Upstash:', error);\n return {\n logs: [],\n total: 0,\n page: pageInput ?? 1,\n perPage: perPageInput ?? 100,\n hasMore: false,\n };\n }\n }\n}\n"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mastra/loggers",
|
|
3
|
-
"version": "1.3.
|
|
3
|
+
"version": "1.3.3-alpha.1",
|
|
4
4
|
"description": "",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"files": [
|
|
@@ -69,16 +69,16 @@
|
|
|
69
69
|
},
|
|
70
70
|
"devDependencies": {
|
|
71
71
|
"@types/node": "22.20.1",
|
|
72
|
-
"@vitest/coverage-v8": "4.1.
|
|
73
|
-
"@vitest/ui": "4.1.
|
|
72
|
+
"@vitest/coverage-v8": "4.1.11",
|
|
73
|
+
"@vitest/ui": "4.1.11",
|
|
74
74
|
"eslint": "^10.7.0",
|
|
75
75
|
"tsdown": "0.22.9",
|
|
76
76
|
"tsx": "^4.23.1",
|
|
77
77
|
"typescript": "^7.0.2",
|
|
78
|
-
"vitest": "4.1.
|
|
79
|
-
"@internal/lint": "0.0.
|
|
80
|
-
"@
|
|
81
|
-
"@
|
|
78
|
+
"vitest": "4.1.11",
|
|
79
|
+
"@internal/lint": "0.0.137",
|
|
80
|
+
"@internal/types-builder": "0.0.112",
|
|
81
|
+
"@mastra/core": "1.72.0-alpha.10"
|
|
82
82
|
},
|
|
83
83
|
"peerDependencies": {
|
|
84
84
|
"@mastra/core": ">=1.0.0-0 <2.0.0-0"
|