@onezlinks/session-logger 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +22 -0
- package/LICENSE +21 -0
- package/README.md +648 -0
- package/package.json +52 -0
- package/src/cleanup.js +82 -0
- package/src/constants.js +74 -0
- package/src/context.js +343 -0
- package/src/file-logger.js +76 -0
- package/src/formatter.js +55 -0
- package/src/index.js +74 -0
- package/types/index.d.ts +208 -0
package/src/index.js
ADDED
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @onezlinks/session-logger — Public API
|
|
3
|
+
* Session-based file logger with AsyncLocalStorage context propagation
|
|
4
|
+
*
|
|
5
|
+
* @module @onezlinks/session-logger
|
|
6
|
+
* @version 1.0.0
|
|
7
|
+
* @description Hybrid API: Wrapper (safe) + Manual (flexible) patterns
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
// Re-export all public APIs from context
|
|
11
|
+
const {
|
|
12
|
+
// Wrapper Pattern (Recommended)
|
|
13
|
+
withSession,
|
|
14
|
+
|
|
15
|
+
// Manual Pattern (Advanced)
|
|
16
|
+
startSession,
|
|
17
|
+
endSession,
|
|
18
|
+
|
|
19
|
+
// Context Inspection
|
|
20
|
+
getSessionContext,
|
|
21
|
+
|
|
22
|
+
// Logging Functions
|
|
23
|
+
log,
|
|
24
|
+
info,
|
|
25
|
+
error,
|
|
26
|
+
warn,
|
|
27
|
+
|
|
28
|
+
// Special Formatters
|
|
29
|
+
logCost,
|
|
30
|
+
logDuration,
|
|
31
|
+
logMetric
|
|
32
|
+
} = require('./context')
|
|
33
|
+
|
|
34
|
+
// Re-export cleanup utility
|
|
35
|
+
const { cleanOldLogs } = require('./cleanup')
|
|
36
|
+
|
|
37
|
+
// Re-export constants for advanced usage
|
|
38
|
+
const { CONFIG, COMMON_TAGS } = require('./constants')
|
|
39
|
+
|
|
40
|
+
module.exports = {
|
|
41
|
+
// ═══════════════════════════════════════════════════════════════
|
|
42
|
+
// Wrapper Pattern (Recommended for Production)
|
|
43
|
+
// ═══════════════════════════════════════════════════════════════
|
|
44
|
+
withSession,
|
|
45
|
+
|
|
46
|
+
// ═══════════════════════════════════════════════════════════════
|
|
47
|
+
// Manual Pattern (Advanced — for Complex Flow)
|
|
48
|
+
// ═══════════════════════════════════════════════════════════════
|
|
49
|
+
startSession,
|
|
50
|
+
endSession,
|
|
51
|
+
|
|
52
|
+
// ═══════════════════════════════════════════════════════════════
|
|
53
|
+
// Context & Logging
|
|
54
|
+
// ═══════════════════════════════════════════════════════════════
|
|
55
|
+
getSessionContext,
|
|
56
|
+
log,
|
|
57
|
+
info,
|
|
58
|
+
error,
|
|
59
|
+
warn,
|
|
60
|
+
logCost,
|
|
61
|
+
logDuration,
|
|
62
|
+
logMetric,
|
|
63
|
+
|
|
64
|
+
// ═══════════════════════════════════════════════════════════════
|
|
65
|
+
// Utilities
|
|
66
|
+
// ═══════════════════════════════════════════════════════════════
|
|
67
|
+
cleanOldLogs,
|
|
68
|
+
|
|
69
|
+
// ═══════════════════════════════════════════════════════════════
|
|
70
|
+
// Constants (Advanced Usage)
|
|
71
|
+
// ═══════════════════════════════════════════════════════════════
|
|
72
|
+
CONFIG,
|
|
73
|
+
COMMON_TAGS
|
|
74
|
+
}
|
package/types/index.d.ts
ADDED
|
@@ -0,0 +1,208 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @onezlinks/session-logger — TypeScript Definitions
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
// ═══════════════════════════════════════════════════════════════
|
|
6
|
+
// Types
|
|
7
|
+
// ═══════════════════════════════════════════════════════════════
|
|
8
|
+
|
|
9
|
+
export interface SessionOptions {
|
|
10
|
+
/** Unique session identifier (e.g. UUID, MongoDB ObjectId) */
|
|
11
|
+
sessionId: string
|
|
12
|
+
|
|
13
|
+
/** Log category — used as subdirectory name (e.g. 'ai-pipeline', 'order') */
|
|
14
|
+
category: string
|
|
15
|
+
|
|
16
|
+
/** Additional metadata included in session header */
|
|
17
|
+
metadata?: Record<string, string | number>
|
|
18
|
+
|
|
19
|
+
/** Override base log directory (default: CONFIG.LOG_BASE_DIR) */
|
|
20
|
+
logDir?: string
|
|
21
|
+
|
|
22
|
+
/** Enable file logging (default: true) */
|
|
23
|
+
enableFile?: boolean
|
|
24
|
+
|
|
25
|
+
/** Enable stdout/stderr output (default: true) */
|
|
26
|
+
enableStdout?: boolean
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export interface SessionContext {
|
|
30
|
+
sessionId: string
|
|
31
|
+
category: string
|
|
32
|
+
metadata: Record<string, string | number>
|
|
33
|
+
fileConsole: Console | null
|
|
34
|
+
logPath: string | null
|
|
35
|
+
errLogPath: string | null
|
|
36
|
+
startTime: number
|
|
37
|
+
stats: SessionStats
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
export interface SessionStats {
|
|
41
|
+
logs: number
|
|
42
|
+
errors: number
|
|
43
|
+
warnings: number
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
export interface CostData {
|
|
47
|
+
totalUSD: number
|
|
48
|
+
totalTHB: number
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
export interface CleanupResult {
|
|
52
|
+
deleted: string[]
|
|
53
|
+
errors: string[]
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
export interface SessionConfig {
|
|
57
|
+
/** Base directory for all session logs (env: SESSION_LOG_DIR, default: 'logs') */
|
|
58
|
+
readonly LOG_BASE_DIR: string
|
|
59
|
+
|
|
60
|
+
/** Days to retain logs before cleanup (env: SESSION_LOG_RETENTION_DAYS, default: 30) */
|
|
61
|
+
readonly LOG_RETENTION_DAYS: number
|
|
62
|
+
|
|
63
|
+
/** Enable/disable file logging (env: SESSION_LOG_TO_FILE, default: true) */
|
|
64
|
+
readonly ENABLE_FILE: boolean
|
|
65
|
+
|
|
66
|
+
/** Enable/disable stdout output (env: SESSION_LOG_TO_STDOUT, default: true) */
|
|
67
|
+
readonly ENABLE_STDOUT: boolean
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
// ═══════════════════════════════════════════════════════════════
|
|
71
|
+
// Wrapper Pattern (Recommended)
|
|
72
|
+
// ═══════════════════════════════════════════════════════════════
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* Run async function within session logger context.
|
|
76
|
+
* Automatically initializes and finalizes the session.
|
|
77
|
+
*
|
|
78
|
+
* @example
|
|
79
|
+
* await withSession({
|
|
80
|
+
* sessionId: order._id.toString(),
|
|
81
|
+
* category: 'ai-pipeline',
|
|
82
|
+
* metadata: { orderId: order._id }
|
|
83
|
+
* }, async () => {
|
|
84
|
+
* log('Pipeline', 'Processing started')
|
|
85
|
+
* // ... your logic
|
|
86
|
+
* })
|
|
87
|
+
*/
|
|
88
|
+
export function withSession<T>(options: SessionOptions, asyncFn: () => Promise<T>): Promise<T>
|
|
89
|
+
|
|
90
|
+
// ═══════════════════════════════════════════════════════════════
|
|
91
|
+
// Manual Pattern (Advanced)
|
|
92
|
+
// ═══════════════════════════════════════════════════════════════
|
|
93
|
+
|
|
94
|
+
/**
|
|
95
|
+
* Start a session logger context.
|
|
96
|
+
* ⚠️ Must call endSession() in a finally block.
|
|
97
|
+
*/
|
|
98
|
+
export function startSession(options: SessionOptions): void
|
|
99
|
+
|
|
100
|
+
/**
|
|
101
|
+
* End current session logger context.
|
|
102
|
+
* ⚠️ Must be called in a finally block after startSession().
|
|
103
|
+
*/
|
|
104
|
+
export function endSession(): Promise<void>
|
|
105
|
+
|
|
106
|
+
// ═══════════════════════════════════════════════════════════════
|
|
107
|
+
// Context Inspection
|
|
108
|
+
// ═══════════════════════════════════════════════════════════════
|
|
109
|
+
|
|
110
|
+
/**
|
|
111
|
+
* Get current session context, or null if not inside a session.
|
|
112
|
+
*/
|
|
113
|
+
export function getSessionContext(): SessionContext | null
|
|
114
|
+
|
|
115
|
+
// ═══════════════════════════════════════════════════════════════
|
|
116
|
+
// Logging Functions
|
|
117
|
+
// ═══════════════════════════════════════════════════════════════
|
|
118
|
+
|
|
119
|
+
/**
|
|
120
|
+
* Log an info message.
|
|
121
|
+
* Falls back to console.log when outside a session context.
|
|
122
|
+
*/
|
|
123
|
+
export function log(tag: string, message: string, ...args: unknown[]): void
|
|
124
|
+
|
|
125
|
+
/**
|
|
126
|
+
* Alias for log() — semantic clarity.
|
|
127
|
+
*/
|
|
128
|
+
export function info(tag: string, message: string, ...args: unknown[]): void
|
|
129
|
+
|
|
130
|
+
/**
|
|
131
|
+
* Log an error message.
|
|
132
|
+
* Falls back to console.error when outside a session context.
|
|
133
|
+
*/
|
|
134
|
+
export function error(tag: string, message: string, ...args: unknown[]): void
|
|
135
|
+
|
|
136
|
+
/**
|
|
137
|
+
* Log a warning message.
|
|
138
|
+
* Falls back to console.warn when outside a session context.
|
|
139
|
+
*/
|
|
140
|
+
export function warn(tag: string, message: string, ...args: unknown[]): void
|
|
141
|
+
|
|
142
|
+
// ═══════════════════════════════════════════════════════════════
|
|
143
|
+
// Special Formatters
|
|
144
|
+
// ═══════════════════════════════════════════════════════════════
|
|
145
|
+
|
|
146
|
+
/**
|
|
147
|
+
* Log cost/billing data with consistent formatting.
|
|
148
|
+
*/
|
|
149
|
+
export function logCost(
|
|
150
|
+
tag: string,
|
|
151
|
+
costData: CostData,
|
|
152
|
+
inputUnits?: number,
|
|
153
|
+
outputUnits?: number,
|
|
154
|
+
cachedUnits?: number
|
|
155
|
+
): void
|
|
156
|
+
|
|
157
|
+
/**
|
|
158
|
+
* Log duration/performance metrics.
|
|
159
|
+
*/
|
|
160
|
+
export function logDuration(tag: string, durationMs: number, label?: string): void
|
|
161
|
+
|
|
162
|
+
/**
|
|
163
|
+
* Log custom metrics with optional unit.
|
|
164
|
+
*/
|
|
165
|
+
export function logMetric(tag: string, metricName: string, value: number | string, unit?: string): void
|
|
166
|
+
|
|
167
|
+
// ═══════════════════════════════════════════════════════════════
|
|
168
|
+
// Utilities
|
|
169
|
+
// ═══════════════════════════════════════════════════════════════
|
|
170
|
+
|
|
171
|
+
/**
|
|
172
|
+
* Clean up old log files beyond retention period.
|
|
173
|
+
*/
|
|
174
|
+
export function cleanOldLogs(category?: string, daysToKeep?: number): Promise<CleanupResult>
|
|
175
|
+
|
|
176
|
+
// ═══════════════════════════════════════════════════════════════
|
|
177
|
+
// Constants
|
|
178
|
+
// ═══════════════════════════════════════════════════════════════
|
|
179
|
+
|
|
180
|
+
/** Configuration with lazy environment variable evaluation */
|
|
181
|
+
export const CONFIG: SessionConfig
|
|
182
|
+
|
|
183
|
+
/** Common tag suggestions (reference only — not enforced) */
|
|
184
|
+
export const COMMON_TAGS: {
|
|
185
|
+
readonly PIPELINE: 'Pipeline'
|
|
186
|
+
readonly QUALITY: 'Quality'
|
|
187
|
+
readonly OCR: 'OCR'
|
|
188
|
+
readonly OPENAI: 'OpenAI'
|
|
189
|
+
readonly CLIENT: 'Client'
|
|
190
|
+
readonly REDEMPTION: 'Redemption'
|
|
191
|
+
readonly POINTS: 'Points'
|
|
192
|
+
readonly VALIDATION: 'Validation'
|
|
193
|
+
readonly NOTIFICATION: 'Notification'
|
|
194
|
+
readonly SURVEY: 'Survey'
|
|
195
|
+
readonly STORAGE: 'Storage'
|
|
196
|
+
readonly ANALYTICS: 'Analytics'
|
|
197
|
+
readonly ORDER: 'Order'
|
|
198
|
+
readonly PAYMENT: 'Payment'
|
|
199
|
+
readonly INVENTORY: 'Inventory'
|
|
200
|
+
readonly SHIPPING: 'Shipping'
|
|
201
|
+
readonly MESSAGE: 'Message'
|
|
202
|
+
readonly WEBHOOK: 'Webhook'
|
|
203
|
+
readonly RESPONSE: 'Response'
|
|
204
|
+
readonly BROADCAST: 'Broadcast'
|
|
205
|
+
readonly DATABASE: 'Database'
|
|
206
|
+
readonly CACHE: 'Cache'
|
|
207
|
+
readonly WORKER: 'Worker'
|
|
208
|
+
}
|