devlogs-browser 1.1.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/README.md +48 -0
- package/dist/client.d.ts +22 -0
- package/dist/devlogs.cjs.js +305 -0
- package/dist/devlogs.cjs.js.map +1 -0
- package/dist/devlogs.esm.js +297 -0
- package/dist/devlogs.esm.js.map +1 -0
- package/dist/devlogs.iife.js +310 -0
- package/dist/devlogs.iife.js.map +1 -0
- package/dist/formatter.d.ts +5 -0
- package/dist/index.d.ts +30 -0
- package/dist/interceptor.d.ts +42 -0
- package/dist/types.d.ts +63 -0
- package/dist/url-parser.d.ts +15 -0
- package/package.json +32 -0
package/README.md
ADDED
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
# devlogs-browser
|
|
2
|
+
|
|
3
|
+
Browser logging library for DevLogs - forwards console logs to OpenSearch.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install devlogs-browser
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Usage
|
|
12
|
+
|
|
13
|
+
```javascript
|
|
14
|
+
import * as devlogs from 'devlogs-browser';
|
|
15
|
+
|
|
16
|
+
devlogs.init({
|
|
17
|
+
url: 'http://admin:admin@localhost:9200',
|
|
18
|
+
index: 'devlogs-myapp',
|
|
19
|
+
area: 'frontend'
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
// Now console.log/warn/error/info are forwarded to OpenSearch
|
|
23
|
+
console.log('Hello from browser!');
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
## Production Deployment
|
|
27
|
+
|
|
28
|
+
Devlogs is a development tool and should not run in production:
|
|
29
|
+
|
|
30
|
+
### Option 1: Conditional initialization
|
|
31
|
+
|
|
32
|
+
```javascript
|
|
33
|
+
if (process.env.NODE_ENV === 'development') {
|
|
34
|
+
devlogs.init({ url: '...', index: '...' });
|
|
35
|
+
}
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
### Option 2: Don't import at all
|
|
39
|
+
|
|
40
|
+
Only import devlogs in development - bundlers will tree-shake it out of production builds.
|
|
41
|
+
|
|
42
|
+
## API
|
|
43
|
+
|
|
44
|
+
- `init(options)` - Initialize and intercept console methods
|
|
45
|
+
- `destroy()` - Restore original console methods
|
|
46
|
+
- `setArea(area)` - Set the current area
|
|
47
|
+
- `setOperationId(id)` - Set the current operation ID
|
|
48
|
+
- `withOperation(fn, options)` - Run function with operation context
|
package/dist/client.d.ts
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type { DevlogsConfig, LogDocument } from './types';
|
|
2
|
+
/**
|
|
3
|
+
* Lightweight OpenSearch client for browser environments.
|
|
4
|
+
*
|
|
5
|
+
* Features:
|
|
6
|
+
* - Uses native fetch API (no dependencies)
|
|
7
|
+
* - Circuit breaker pattern: shows single error on connection failure
|
|
8
|
+
* - Fire-and-forget logging (non-blocking)
|
|
9
|
+
*/
|
|
10
|
+
export declare class DevlogsOpenSearchClient {
|
|
11
|
+
private readonly baseUrl;
|
|
12
|
+
private readonly authHeader;
|
|
13
|
+
private readonly indexName;
|
|
14
|
+
private circuitOpen;
|
|
15
|
+
private errorShown;
|
|
16
|
+
constructor(config: DevlogsConfig);
|
|
17
|
+
/**
|
|
18
|
+
* Index a log document. Fire-and-forget - does not await response.
|
|
19
|
+
*/
|
|
20
|
+
index(doc: LogDocument): void;
|
|
21
|
+
private handleConnectionError;
|
|
22
|
+
}
|
|
@@ -0,0 +1,305 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Parse a DEVLOGS URL into configuration components.
|
|
5
|
+
*
|
|
6
|
+
* Supports format: http://user:pass@host:port or https://user:pass@host:port
|
|
7
|
+
*
|
|
8
|
+
* Defaults:
|
|
9
|
+
* - scheme: http
|
|
10
|
+
* - host: localhost
|
|
11
|
+
* - port: 9200 for http, 443 for https
|
|
12
|
+
* - user: admin
|
|
13
|
+
* - password: admin
|
|
14
|
+
* - index: devlogs-0001
|
|
15
|
+
*/
|
|
16
|
+
function parseDevlogsUrl(url, index) {
|
|
17
|
+
const parsed = new URL(url);
|
|
18
|
+
const scheme = parsed.protocol.replace(':', '');
|
|
19
|
+
return {
|
|
20
|
+
scheme,
|
|
21
|
+
host: parsed.hostname || 'localhost',
|
|
22
|
+
port: parsed.port
|
|
23
|
+
? parseInt(parsed.port, 10)
|
|
24
|
+
: (scheme === 'https' ? 443 : 9200),
|
|
25
|
+
user: parsed.username || 'admin',
|
|
26
|
+
password: parsed.password || 'admin',
|
|
27
|
+
index: index || 'devlogs-0001',
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Python logging level numbers for compatibility
|
|
33
|
+
*/
|
|
34
|
+
const LEVEL_MAP = {
|
|
35
|
+
debug: 10,
|
|
36
|
+
info: 20,
|
|
37
|
+
log: 20, // Treat console.log as INFO level
|
|
38
|
+
warn: 30,
|
|
39
|
+
error: 40,
|
|
40
|
+
};
|
|
41
|
+
/**
|
|
42
|
+
* Normalize console method name to standard log level
|
|
43
|
+
*/
|
|
44
|
+
function normalizeLevel(method) {
|
|
45
|
+
if (method === 'warn')
|
|
46
|
+
return 'warning';
|
|
47
|
+
if (method === 'log')
|
|
48
|
+
return 'info';
|
|
49
|
+
return method;
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Format console arguments into a single message string
|
|
53
|
+
*/
|
|
54
|
+
function formatMessage(args) {
|
|
55
|
+
return args
|
|
56
|
+
.map((arg) => {
|
|
57
|
+
if (typeof arg === 'string') {
|
|
58
|
+
return arg;
|
|
59
|
+
}
|
|
60
|
+
if (arg instanceof Error) {
|
|
61
|
+
return `${arg.name}: ${arg.message}`;
|
|
62
|
+
}
|
|
63
|
+
try {
|
|
64
|
+
return JSON.stringify(arg);
|
|
65
|
+
}
|
|
66
|
+
catch {
|
|
67
|
+
return String(arg);
|
|
68
|
+
}
|
|
69
|
+
})
|
|
70
|
+
.join(' ');
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Extract features from console arguments if an object is provided
|
|
74
|
+
*/
|
|
75
|
+
function extractFeatures(args, contextFeatures) {
|
|
76
|
+
const features = {
|
|
77
|
+
userAgent: navigator.userAgent,
|
|
78
|
+
...contextFeatures,
|
|
79
|
+
};
|
|
80
|
+
// If last argument is a plain object, merge it as features
|
|
81
|
+
const lastArg = args[args.length - 1];
|
|
82
|
+
if (lastArg &&
|
|
83
|
+
typeof lastArg === 'object' &&
|
|
84
|
+
!Array.isArray(lastArg) &&
|
|
85
|
+
!(lastArg instanceof Error)) {
|
|
86
|
+
Object.assign(features, lastArg);
|
|
87
|
+
}
|
|
88
|
+
return features;
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* Format a log entry into the devlogs document schema
|
|
92
|
+
*/
|
|
93
|
+
function formatLogDocument(method, args, context) {
|
|
94
|
+
return {
|
|
95
|
+
doc_type: 'log_entry',
|
|
96
|
+
timestamp: new Date().toISOString(),
|
|
97
|
+
level: normalizeLevel(method),
|
|
98
|
+
levelno: LEVEL_MAP[method],
|
|
99
|
+
logger_name: context.loggerName,
|
|
100
|
+
message: formatMessage(args),
|
|
101
|
+
pathname: context.pathname,
|
|
102
|
+
lineno: null,
|
|
103
|
+
funcName: null,
|
|
104
|
+
area: context.area,
|
|
105
|
+
operation_id: context.operationId,
|
|
106
|
+
features: extractFeatures(args, context.features),
|
|
107
|
+
};
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
/**
|
|
111
|
+
* Store original console methods before interception.
|
|
112
|
+
* These are used for:
|
|
113
|
+
* 1. Calling the original console so browser devtools still work
|
|
114
|
+
* 2. Error reporting from the client without causing infinite loops
|
|
115
|
+
*/
|
|
116
|
+
const originalConsole = {
|
|
117
|
+
log: console.log.bind(console),
|
|
118
|
+
warn: console.warn.bind(console),
|
|
119
|
+
error: console.error.bind(console),
|
|
120
|
+
debug: console.debug.bind(console),
|
|
121
|
+
info: console.info.bind(console),
|
|
122
|
+
};
|
|
123
|
+
const METHODS = ['log', 'warn', 'error', 'debug', 'info'];
|
|
124
|
+
/**
|
|
125
|
+
* Current logging context - shared across all console calls
|
|
126
|
+
*/
|
|
127
|
+
let currentContext = {
|
|
128
|
+
area: null,
|
|
129
|
+
operationId: null,
|
|
130
|
+
loggerName: 'browser',
|
|
131
|
+
pathname: typeof window !== 'undefined' ? window.location.pathname : '/',
|
|
132
|
+
features: {},
|
|
133
|
+
};
|
|
134
|
+
/**
|
|
135
|
+
* Get the current logging context
|
|
136
|
+
*/
|
|
137
|
+
function getContext() {
|
|
138
|
+
return { ...currentContext };
|
|
139
|
+
}
|
|
140
|
+
/**
|
|
141
|
+
* Update the logging context
|
|
142
|
+
*/
|
|
143
|
+
function setContext(updates) {
|
|
144
|
+
currentContext = { ...currentContext, ...updates };
|
|
145
|
+
}
|
|
146
|
+
/**
|
|
147
|
+
* Set the application area
|
|
148
|
+
*/
|
|
149
|
+
function setArea(area) {
|
|
150
|
+
currentContext.area = area;
|
|
151
|
+
}
|
|
152
|
+
/**
|
|
153
|
+
* Set the operation ID for correlation
|
|
154
|
+
*/
|
|
155
|
+
function setOperationId(operationId) {
|
|
156
|
+
currentContext.operationId = operationId;
|
|
157
|
+
}
|
|
158
|
+
/**
|
|
159
|
+
* Set custom features to include in all logs
|
|
160
|
+
*/
|
|
161
|
+
function setFeatures(features) {
|
|
162
|
+
currentContext.features = features;
|
|
163
|
+
}
|
|
164
|
+
/**
|
|
165
|
+
* Execute a function with a temporary operation ID
|
|
166
|
+
*/
|
|
167
|
+
function withOperation(operationId, fn) {
|
|
168
|
+
const previousId = currentContext.operationId;
|
|
169
|
+
currentContext.operationId = operationId;
|
|
170
|
+
try {
|
|
171
|
+
return fn();
|
|
172
|
+
}
|
|
173
|
+
finally {
|
|
174
|
+
currentContext.operationId = previousId;
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
/**
|
|
178
|
+
* Intercept console methods to forward logs to the index.
|
|
179
|
+
* Original console methods are still called so devtools work normally.
|
|
180
|
+
*/
|
|
181
|
+
function interceptConsole(client) {
|
|
182
|
+
METHODS.forEach((method) => {
|
|
183
|
+
console[method] = (...args) => {
|
|
184
|
+
// Always call the original console method first
|
|
185
|
+
originalConsole[method](...args);
|
|
186
|
+
// Format and send to index
|
|
187
|
+
const doc = formatLogDocument(method, args, getContext());
|
|
188
|
+
client.index(doc);
|
|
189
|
+
};
|
|
190
|
+
});
|
|
191
|
+
}
|
|
192
|
+
/**
|
|
193
|
+
* Restore original console methods
|
|
194
|
+
*/
|
|
195
|
+
function restoreConsole() {
|
|
196
|
+
METHODS.forEach((method) => {
|
|
197
|
+
console[method] = originalConsole[method];
|
|
198
|
+
});
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
/**
|
|
202
|
+
* Lightweight OpenSearch client for browser environments.
|
|
203
|
+
*
|
|
204
|
+
* Features:
|
|
205
|
+
* - Uses native fetch API (no dependencies)
|
|
206
|
+
* - Circuit breaker pattern: shows single error on connection failure
|
|
207
|
+
* - Fire-and-forget logging (non-blocking)
|
|
208
|
+
*/
|
|
209
|
+
class DevlogsOpenSearchClient {
|
|
210
|
+
constructor(config) {
|
|
211
|
+
this.circuitOpen = false;
|
|
212
|
+
this.errorShown = false;
|
|
213
|
+
this.baseUrl = `${config.scheme}://${config.host}:${config.port}`;
|
|
214
|
+
this.authHeader = `Basic ${btoa(`${config.user}:${config.password}`)}`;
|
|
215
|
+
this.indexName = config.index;
|
|
216
|
+
}
|
|
217
|
+
/**
|
|
218
|
+
* Index a log document. Fire-and-forget - does not await response.
|
|
219
|
+
*/
|
|
220
|
+
index(doc) {
|
|
221
|
+
if (this.circuitOpen) {
|
|
222
|
+
return;
|
|
223
|
+
}
|
|
224
|
+
fetch(`${this.baseUrl}/${this.indexName}/_doc`, {
|
|
225
|
+
method: 'POST',
|
|
226
|
+
headers: {
|
|
227
|
+
'Authorization': this.authHeader,
|
|
228
|
+
'Content-Type': 'application/json',
|
|
229
|
+
},
|
|
230
|
+
body: JSON.stringify(doc),
|
|
231
|
+
}).catch((error) => {
|
|
232
|
+
this.handleConnectionError(error);
|
|
233
|
+
});
|
|
234
|
+
}
|
|
235
|
+
handleConnectionError(error) {
|
|
236
|
+
this.circuitOpen = true;
|
|
237
|
+
if (!this.errorShown) {
|
|
238
|
+
this.errorShown = true;
|
|
239
|
+
originalConsole.error('[devlogs] Unable to connect to index:', error);
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
let initialized = false;
|
|
245
|
+
let client = null;
|
|
246
|
+
/**
|
|
247
|
+
* Initialize the devlogs browser client.
|
|
248
|
+
*
|
|
249
|
+
* This intercepts console.log/warn/error/debug/info and forwards
|
|
250
|
+
* all log messages to the OpenSearch index.
|
|
251
|
+
*
|
|
252
|
+
* @example
|
|
253
|
+
* ```js
|
|
254
|
+
* devlogs.init({
|
|
255
|
+
* url: 'http://admin:admin@localhost:9200',
|
|
256
|
+
* area: 'frontend',
|
|
257
|
+
* loggerName: 'my-app'
|
|
258
|
+
* });
|
|
259
|
+
*
|
|
260
|
+
* console.log('App started'); // Forwarded to index
|
|
261
|
+
* ```
|
|
262
|
+
*/
|
|
263
|
+
function init(options) {
|
|
264
|
+
if (initialized) {
|
|
265
|
+
originalConsole.warn('[devlogs] Already initialized');
|
|
266
|
+
return;
|
|
267
|
+
}
|
|
268
|
+
const config = parseDevlogsUrl(options.url, options.index);
|
|
269
|
+
client = new DevlogsOpenSearchClient(config);
|
|
270
|
+
setContext({
|
|
271
|
+
area: options.area || null,
|
|
272
|
+
operationId: options.operationId || null,
|
|
273
|
+
loggerName: options.loggerName || 'browser',
|
|
274
|
+
pathname: typeof window !== 'undefined' ? window.location.pathname : '/',
|
|
275
|
+
features: {},
|
|
276
|
+
});
|
|
277
|
+
interceptConsole(client);
|
|
278
|
+
initialized = true;
|
|
279
|
+
}
|
|
280
|
+
/**
|
|
281
|
+
* Disable devlogs and restore original console methods.
|
|
282
|
+
*/
|
|
283
|
+
function destroy() {
|
|
284
|
+
if (!initialized) {
|
|
285
|
+
return;
|
|
286
|
+
}
|
|
287
|
+
restoreConsole();
|
|
288
|
+
client = null;
|
|
289
|
+
initialized = false;
|
|
290
|
+
}
|
|
291
|
+
/**
|
|
292
|
+
* Check if devlogs is currently initialized
|
|
293
|
+
*/
|
|
294
|
+
function isInitialized() {
|
|
295
|
+
return initialized;
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
exports.destroy = destroy;
|
|
299
|
+
exports.init = init;
|
|
300
|
+
exports.isInitialized = isInitialized;
|
|
301
|
+
exports.setArea = setArea;
|
|
302
|
+
exports.setFeatures = setFeatures;
|
|
303
|
+
exports.setOperationId = setOperationId;
|
|
304
|
+
exports.withOperation = withOperation;
|
|
305
|
+
//# sourceMappingURL=devlogs.cjs.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"devlogs.cjs.js","sources":["../src/url-parser.ts","../src/formatter.ts","../src/interceptor.ts","../src/client.ts","../src/index.ts"],"sourcesContent":[null,null,null,null,null],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,297 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Parse a DEVLOGS URL into configuration components.
|
|
3
|
+
*
|
|
4
|
+
* Supports format: http://user:pass@host:port or https://user:pass@host:port
|
|
5
|
+
*
|
|
6
|
+
* Defaults:
|
|
7
|
+
* - scheme: http
|
|
8
|
+
* - host: localhost
|
|
9
|
+
* - port: 9200 for http, 443 for https
|
|
10
|
+
* - user: admin
|
|
11
|
+
* - password: admin
|
|
12
|
+
* - index: devlogs-0001
|
|
13
|
+
*/
|
|
14
|
+
function parseDevlogsUrl(url, index) {
|
|
15
|
+
const parsed = new URL(url);
|
|
16
|
+
const scheme = parsed.protocol.replace(':', '');
|
|
17
|
+
return {
|
|
18
|
+
scheme,
|
|
19
|
+
host: parsed.hostname || 'localhost',
|
|
20
|
+
port: parsed.port
|
|
21
|
+
? parseInt(parsed.port, 10)
|
|
22
|
+
: (scheme === 'https' ? 443 : 9200),
|
|
23
|
+
user: parsed.username || 'admin',
|
|
24
|
+
password: parsed.password || 'admin',
|
|
25
|
+
index: index || 'devlogs-0001',
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Python logging level numbers for compatibility
|
|
31
|
+
*/
|
|
32
|
+
const LEVEL_MAP = {
|
|
33
|
+
debug: 10,
|
|
34
|
+
info: 20,
|
|
35
|
+
log: 20, // Treat console.log as INFO level
|
|
36
|
+
warn: 30,
|
|
37
|
+
error: 40,
|
|
38
|
+
};
|
|
39
|
+
/**
|
|
40
|
+
* Normalize console method name to standard log level
|
|
41
|
+
*/
|
|
42
|
+
function normalizeLevel(method) {
|
|
43
|
+
if (method === 'warn')
|
|
44
|
+
return 'warning';
|
|
45
|
+
if (method === 'log')
|
|
46
|
+
return 'info';
|
|
47
|
+
return method;
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Format console arguments into a single message string
|
|
51
|
+
*/
|
|
52
|
+
function formatMessage(args) {
|
|
53
|
+
return args
|
|
54
|
+
.map((arg) => {
|
|
55
|
+
if (typeof arg === 'string') {
|
|
56
|
+
return arg;
|
|
57
|
+
}
|
|
58
|
+
if (arg instanceof Error) {
|
|
59
|
+
return `${arg.name}: ${arg.message}`;
|
|
60
|
+
}
|
|
61
|
+
try {
|
|
62
|
+
return JSON.stringify(arg);
|
|
63
|
+
}
|
|
64
|
+
catch {
|
|
65
|
+
return String(arg);
|
|
66
|
+
}
|
|
67
|
+
})
|
|
68
|
+
.join(' ');
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Extract features from console arguments if an object is provided
|
|
72
|
+
*/
|
|
73
|
+
function extractFeatures(args, contextFeatures) {
|
|
74
|
+
const features = {
|
|
75
|
+
userAgent: navigator.userAgent,
|
|
76
|
+
...contextFeatures,
|
|
77
|
+
};
|
|
78
|
+
// If last argument is a plain object, merge it as features
|
|
79
|
+
const lastArg = args[args.length - 1];
|
|
80
|
+
if (lastArg &&
|
|
81
|
+
typeof lastArg === 'object' &&
|
|
82
|
+
!Array.isArray(lastArg) &&
|
|
83
|
+
!(lastArg instanceof Error)) {
|
|
84
|
+
Object.assign(features, lastArg);
|
|
85
|
+
}
|
|
86
|
+
return features;
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* Format a log entry into the devlogs document schema
|
|
90
|
+
*/
|
|
91
|
+
function formatLogDocument(method, args, context) {
|
|
92
|
+
return {
|
|
93
|
+
doc_type: 'log_entry',
|
|
94
|
+
timestamp: new Date().toISOString(),
|
|
95
|
+
level: normalizeLevel(method),
|
|
96
|
+
levelno: LEVEL_MAP[method],
|
|
97
|
+
logger_name: context.loggerName,
|
|
98
|
+
message: formatMessage(args),
|
|
99
|
+
pathname: context.pathname,
|
|
100
|
+
lineno: null,
|
|
101
|
+
funcName: null,
|
|
102
|
+
area: context.area,
|
|
103
|
+
operation_id: context.operationId,
|
|
104
|
+
features: extractFeatures(args, context.features),
|
|
105
|
+
};
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
/**
|
|
109
|
+
* Store original console methods before interception.
|
|
110
|
+
* These are used for:
|
|
111
|
+
* 1. Calling the original console so browser devtools still work
|
|
112
|
+
* 2. Error reporting from the client without causing infinite loops
|
|
113
|
+
*/
|
|
114
|
+
const originalConsole = {
|
|
115
|
+
log: console.log.bind(console),
|
|
116
|
+
warn: console.warn.bind(console),
|
|
117
|
+
error: console.error.bind(console),
|
|
118
|
+
debug: console.debug.bind(console),
|
|
119
|
+
info: console.info.bind(console),
|
|
120
|
+
};
|
|
121
|
+
const METHODS = ['log', 'warn', 'error', 'debug', 'info'];
|
|
122
|
+
/**
|
|
123
|
+
* Current logging context - shared across all console calls
|
|
124
|
+
*/
|
|
125
|
+
let currentContext = {
|
|
126
|
+
area: null,
|
|
127
|
+
operationId: null,
|
|
128
|
+
loggerName: 'browser',
|
|
129
|
+
pathname: typeof window !== 'undefined' ? window.location.pathname : '/',
|
|
130
|
+
features: {},
|
|
131
|
+
};
|
|
132
|
+
/**
|
|
133
|
+
* Get the current logging context
|
|
134
|
+
*/
|
|
135
|
+
function getContext() {
|
|
136
|
+
return { ...currentContext };
|
|
137
|
+
}
|
|
138
|
+
/**
|
|
139
|
+
* Update the logging context
|
|
140
|
+
*/
|
|
141
|
+
function setContext(updates) {
|
|
142
|
+
currentContext = { ...currentContext, ...updates };
|
|
143
|
+
}
|
|
144
|
+
/**
|
|
145
|
+
* Set the application area
|
|
146
|
+
*/
|
|
147
|
+
function setArea(area) {
|
|
148
|
+
currentContext.area = area;
|
|
149
|
+
}
|
|
150
|
+
/**
|
|
151
|
+
* Set the operation ID for correlation
|
|
152
|
+
*/
|
|
153
|
+
function setOperationId(operationId) {
|
|
154
|
+
currentContext.operationId = operationId;
|
|
155
|
+
}
|
|
156
|
+
/**
|
|
157
|
+
* Set custom features to include in all logs
|
|
158
|
+
*/
|
|
159
|
+
function setFeatures(features) {
|
|
160
|
+
currentContext.features = features;
|
|
161
|
+
}
|
|
162
|
+
/**
|
|
163
|
+
* Execute a function with a temporary operation ID
|
|
164
|
+
*/
|
|
165
|
+
function withOperation(operationId, fn) {
|
|
166
|
+
const previousId = currentContext.operationId;
|
|
167
|
+
currentContext.operationId = operationId;
|
|
168
|
+
try {
|
|
169
|
+
return fn();
|
|
170
|
+
}
|
|
171
|
+
finally {
|
|
172
|
+
currentContext.operationId = previousId;
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
/**
|
|
176
|
+
* Intercept console methods to forward logs to the index.
|
|
177
|
+
* Original console methods are still called so devtools work normally.
|
|
178
|
+
*/
|
|
179
|
+
function interceptConsole(client) {
|
|
180
|
+
METHODS.forEach((method) => {
|
|
181
|
+
console[method] = (...args) => {
|
|
182
|
+
// Always call the original console method first
|
|
183
|
+
originalConsole[method](...args);
|
|
184
|
+
// Format and send to index
|
|
185
|
+
const doc = formatLogDocument(method, args, getContext());
|
|
186
|
+
client.index(doc);
|
|
187
|
+
};
|
|
188
|
+
});
|
|
189
|
+
}
|
|
190
|
+
/**
|
|
191
|
+
* Restore original console methods
|
|
192
|
+
*/
|
|
193
|
+
function restoreConsole() {
|
|
194
|
+
METHODS.forEach((method) => {
|
|
195
|
+
console[method] = originalConsole[method];
|
|
196
|
+
});
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
/**
|
|
200
|
+
* Lightweight OpenSearch client for browser environments.
|
|
201
|
+
*
|
|
202
|
+
* Features:
|
|
203
|
+
* - Uses native fetch API (no dependencies)
|
|
204
|
+
* - Circuit breaker pattern: shows single error on connection failure
|
|
205
|
+
* - Fire-and-forget logging (non-blocking)
|
|
206
|
+
*/
|
|
207
|
+
class DevlogsOpenSearchClient {
|
|
208
|
+
constructor(config) {
|
|
209
|
+
this.circuitOpen = false;
|
|
210
|
+
this.errorShown = false;
|
|
211
|
+
this.baseUrl = `${config.scheme}://${config.host}:${config.port}`;
|
|
212
|
+
this.authHeader = `Basic ${btoa(`${config.user}:${config.password}`)}`;
|
|
213
|
+
this.indexName = config.index;
|
|
214
|
+
}
|
|
215
|
+
/**
|
|
216
|
+
* Index a log document. Fire-and-forget - does not await response.
|
|
217
|
+
*/
|
|
218
|
+
index(doc) {
|
|
219
|
+
if (this.circuitOpen) {
|
|
220
|
+
return;
|
|
221
|
+
}
|
|
222
|
+
fetch(`${this.baseUrl}/${this.indexName}/_doc`, {
|
|
223
|
+
method: 'POST',
|
|
224
|
+
headers: {
|
|
225
|
+
'Authorization': this.authHeader,
|
|
226
|
+
'Content-Type': 'application/json',
|
|
227
|
+
},
|
|
228
|
+
body: JSON.stringify(doc),
|
|
229
|
+
}).catch((error) => {
|
|
230
|
+
this.handleConnectionError(error);
|
|
231
|
+
});
|
|
232
|
+
}
|
|
233
|
+
handleConnectionError(error) {
|
|
234
|
+
this.circuitOpen = true;
|
|
235
|
+
if (!this.errorShown) {
|
|
236
|
+
this.errorShown = true;
|
|
237
|
+
originalConsole.error('[devlogs] Unable to connect to index:', error);
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
let initialized = false;
|
|
243
|
+
let client = null;
|
|
244
|
+
/**
|
|
245
|
+
* Initialize the devlogs browser client.
|
|
246
|
+
*
|
|
247
|
+
* This intercepts console.log/warn/error/debug/info and forwards
|
|
248
|
+
* all log messages to the OpenSearch index.
|
|
249
|
+
*
|
|
250
|
+
* @example
|
|
251
|
+
* ```js
|
|
252
|
+
* devlogs.init({
|
|
253
|
+
* url: 'http://admin:admin@localhost:9200',
|
|
254
|
+
* area: 'frontend',
|
|
255
|
+
* loggerName: 'my-app'
|
|
256
|
+
* });
|
|
257
|
+
*
|
|
258
|
+
* console.log('App started'); // Forwarded to index
|
|
259
|
+
* ```
|
|
260
|
+
*/
|
|
261
|
+
function init(options) {
|
|
262
|
+
if (initialized) {
|
|
263
|
+
originalConsole.warn('[devlogs] Already initialized');
|
|
264
|
+
return;
|
|
265
|
+
}
|
|
266
|
+
const config = parseDevlogsUrl(options.url, options.index);
|
|
267
|
+
client = new DevlogsOpenSearchClient(config);
|
|
268
|
+
setContext({
|
|
269
|
+
area: options.area || null,
|
|
270
|
+
operationId: options.operationId || null,
|
|
271
|
+
loggerName: options.loggerName || 'browser',
|
|
272
|
+
pathname: typeof window !== 'undefined' ? window.location.pathname : '/',
|
|
273
|
+
features: {},
|
|
274
|
+
});
|
|
275
|
+
interceptConsole(client);
|
|
276
|
+
initialized = true;
|
|
277
|
+
}
|
|
278
|
+
/**
|
|
279
|
+
* Disable devlogs and restore original console methods.
|
|
280
|
+
*/
|
|
281
|
+
function destroy() {
|
|
282
|
+
if (!initialized) {
|
|
283
|
+
return;
|
|
284
|
+
}
|
|
285
|
+
restoreConsole();
|
|
286
|
+
client = null;
|
|
287
|
+
initialized = false;
|
|
288
|
+
}
|
|
289
|
+
/**
|
|
290
|
+
* Check if devlogs is currently initialized
|
|
291
|
+
*/
|
|
292
|
+
function isInitialized() {
|
|
293
|
+
return initialized;
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
export { destroy, init, isInitialized, setArea, setFeatures, setOperationId, withOperation };
|
|
297
|
+
//# sourceMappingURL=devlogs.esm.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"devlogs.esm.js","sources":["../src/url-parser.ts","../src/formatter.ts","../src/interceptor.ts","../src/client.ts","../src/index.ts"],"sourcesContent":[null,null,null,null,null],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,310 @@
|
|
|
1
|
+
var devlogs = (function (exports) {
|
|
2
|
+
'use strict';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Parse a DEVLOGS URL into configuration components.
|
|
6
|
+
*
|
|
7
|
+
* Supports format: http://user:pass@host:port or https://user:pass@host:port
|
|
8
|
+
*
|
|
9
|
+
* Defaults:
|
|
10
|
+
* - scheme: http
|
|
11
|
+
* - host: localhost
|
|
12
|
+
* - port: 9200 for http, 443 for https
|
|
13
|
+
* - user: admin
|
|
14
|
+
* - password: admin
|
|
15
|
+
* - index: devlogs-0001
|
|
16
|
+
*/
|
|
17
|
+
function parseDevlogsUrl(url, index) {
|
|
18
|
+
const parsed = new URL(url);
|
|
19
|
+
const scheme = parsed.protocol.replace(':', '');
|
|
20
|
+
return {
|
|
21
|
+
scheme,
|
|
22
|
+
host: parsed.hostname || 'localhost',
|
|
23
|
+
port: parsed.port
|
|
24
|
+
? parseInt(parsed.port, 10)
|
|
25
|
+
: (scheme === 'https' ? 443 : 9200),
|
|
26
|
+
user: parsed.username || 'admin',
|
|
27
|
+
password: parsed.password || 'admin',
|
|
28
|
+
index: index || 'devlogs-0001',
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Python logging level numbers for compatibility
|
|
34
|
+
*/
|
|
35
|
+
const LEVEL_MAP = {
|
|
36
|
+
debug: 10,
|
|
37
|
+
info: 20,
|
|
38
|
+
log: 20, // Treat console.log as INFO level
|
|
39
|
+
warn: 30,
|
|
40
|
+
error: 40,
|
|
41
|
+
};
|
|
42
|
+
/**
|
|
43
|
+
* Normalize console method name to standard log level
|
|
44
|
+
*/
|
|
45
|
+
function normalizeLevel(method) {
|
|
46
|
+
if (method === 'warn')
|
|
47
|
+
return 'warning';
|
|
48
|
+
if (method === 'log')
|
|
49
|
+
return 'info';
|
|
50
|
+
return method;
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Format console arguments into a single message string
|
|
54
|
+
*/
|
|
55
|
+
function formatMessage(args) {
|
|
56
|
+
return args
|
|
57
|
+
.map((arg) => {
|
|
58
|
+
if (typeof arg === 'string') {
|
|
59
|
+
return arg;
|
|
60
|
+
}
|
|
61
|
+
if (arg instanceof Error) {
|
|
62
|
+
return `${arg.name}: ${arg.message}`;
|
|
63
|
+
}
|
|
64
|
+
try {
|
|
65
|
+
return JSON.stringify(arg);
|
|
66
|
+
}
|
|
67
|
+
catch {
|
|
68
|
+
return String(arg);
|
|
69
|
+
}
|
|
70
|
+
})
|
|
71
|
+
.join(' ');
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* Extract features from console arguments if an object is provided
|
|
75
|
+
*/
|
|
76
|
+
function extractFeatures(args, contextFeatures) {
|
|
77
|
+
const features = {
|
|
78
|
+
userAgent: navigator.userAgent,
|
|
79
|
+
...contextFeatures,
|
|
80
|
+
};
|
|
81
|
+
// If last argument is a plain object, merge it as features
|
|
82
|
+
const lastArg = args[args.length - 1];
|
|
83
|
+
if (lastArg &&
|
|
84
|
+
typeof lastArg === 'object' &&
|
|
85
|
+
!Array.isArray(lastArg) &&
|
|
86
|
+
!(lastArg instanceof Error)) {
|
|
87
|
+
Object.assign(features, lastArg);
|
|
88
|
+
}
|
|
89
|
+
return features;
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* Format a log entry into the devlogs document schema
|
|
93
|
+
*/
|
|
94
|
+
function formatLogDocument(method, args, context) {
|
|
95
|
+
return {
|
|
96
|
+
doc_type: 'log_entry',
|
|
97
|
+
timestamp: new Date().toISOString(),
|
|
98
|
+
level: normalizeLevel(method),
|
|
99
|
+
levelno: LEVEL_MAP[method],
|
|
100
|
+
logger_name: context.loggerName,
|
|
101
|
+
message: formatMessage(args),
|
|
102
|
+
pathname: context.pathname,
|
|
103
|
+
lineno: null,
|
|
104
|
+
funcName: null,
|
|
105
|
+
area: context.area,
|
|
106
|
+
operation_id: context.operationId,
|
|
107
|
+
features: extractFeatures(args, context.features),
|
|
108
|
+
};
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
/**
|
|
112
|
+
* Store original console methods before interception.
|
|
113
|
+
* These are used for:
|
|
114
|
+
* 1. Calling the original console so browser devtools still work
|
|
115
|
+
* 2. Error reporting from the client without causing infinite loops
|
|
116
|
+
*/
|
|
117
|
+
const originalConsole = {
|
|
118
|
+
log: console.log.bind(console),
|
|
119
|
+
warn: console.warn.bind(console),
|
|
120
|
+
error: console.error.bind(console),
|
|
121
|
+
debug: console.debug.bind(console),
|
|
122
|
+
info: console.info.bind(console),
|
|
123
|
+
};
|
|
124
|
+
const METHODS = ['log', 'warn', 'error', 'debug', 'info'];
|
|
125
|
+
/**
|
|
126
|
+
* Current logging context - shared across all console calls
|
|
127
|
+
*/
|
|
128
|
+
let currentContext = {
|
|
129
|
+
area: null,
|
|
130
|
+
operationId: null,
|
|
131
|
+
loggerName: 'browser',
|
|
132
|
+
pathname: typeof window !== 'undefined' ? window.location.pathname : '/',
|
|
133
|
+
features: {},
|
|
134
|
+
};
|
|
135
|
+
/**
|
|
136
|
+
* Get the current logging context
|
|
137
|
+
*/
|
|
138
|
+
function getContext() {
|
|
139
|
+
return { ...currentContext };
|
|
140
|
+
}
|
|
141
|
+
/**
|
|
142
|
+
* Update the logging context
|
|
143
|
+
*/
|
|
144
|
+
function setContext(updates) {
|
|
145
|
+
currentContext = { ...currentContext, ...updates };
|
|
146
|
+
}
|
|
147
|
+
/**
|
|
148
|
+
* Set the application area
|
|
149
|
+
*/
|
|
150
|
+
function setArea(area) {
|
|
151
|
+
currentContext.area = area;
|
|
152
|
+
}
|
|
153
|
+
/**
|
|
154
|
+
* Set the operation ID for correlation
|
|
155
|
+
*/
|
|
156
|
+
function setOperationId(operationId) {
|
|
157
|
+
currentContext.operationId = operationId;
|
|
158
|
+
}
|
|
159
|
+
/**
|
|
160
|
+
* Set custom features to include in all logs
|
|
161
|
+
*/
|
|
162
|
+
function setFeatures(features) {
|
|
163
|
+
currentContext.features = features;
|
|
164
|
+
}
|
|
165
|
+
/**
|
|
166
|
+
* Execute a function with a temporary operation ID
|
|
167
|
+
*/
|
|
168
|
+
function withOperation(operationId, fn) {
|
|
169
|
+
const previousId = currentContext.operationId;
|
|
170
|
+
currentContext.operationId = operationId;
|
|
171
|
+
try {
|
|
172
|
+
return fn();
|
|
173
|
+
}
|
|
174
|
+
finally {
|
|
175
|
+
currentContext.operationId = previousId;
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
/**
|
|
179
|
+
* Intercept console methods to forward logs to the index.
|
|
180
|
+
* Original console methods are still called so devtools work normally.
|
|
181
|
+
*/
|
|
182
|
+
function interceptConsole(client) {
|
|
183
|
+
METHODS.forEach((method) => {
|
|
184
|
+
console[method] = (...args) => {
|
|
185
|
+
// Always call the original console method first
|
|
186
|
+
originalConsole[method](...args);
|
|
187
|
+
// Format and send to index
|
|
188
|
+
const doc = formatLogDocument(method, args, getContext());
|
|
189
|
+
client.index(doc);
|
|
190
|
+
};
|
|
191
|
+
});
|
|
192
|
+
}
|
|
193
|
+
/**
|
|
194
|
+
* Restore original console methods
|
|
195
|
+
*/
|
|
196
|
+
function restoreConsole() {
|
|
197
|
+
METHODS.forEach((method) => {
|
|
198
|
+
console[method] = originalConsole[method];
|
|
199
|
+
});
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
/**
|
|
203
|
+
* Lightweight OpenSearch client for browser environments.
|
|
204
|
+
*
|
|
205
|
+
* Features:
|
|
206
|
+
* - Uses native fetch API (no dependencies)
|
|
207
|
+
* - Circuit breaker pattern: shows single error on connection failure
|
|
208
|
+
* - Fire-and-forget logging (non-blocking)
|
|
209
|
+
*/
|
|
210
|
+
class DevlogsOpenSearchClient {
|
|
211
|
+
constructor(config) {
|
|
212
|
+
this.circuitOpen = false;
|
|
213
|
+
this.errorShown = false;
|
|
214
|
+
this.baseUrl = `${config.scheme}://${config.host}:${config.port}`;
|
|
215
|
+
this.authHeader = `Basic ${btoa(`${config.user}:${config.password}`)}`;
|
|
216
|
+
this.indexName = config.index;
|
|
217
|
+
}
|
|
218
|
+
/**
|
|
219
|
+
* Index a log document. Fire-and-forget - does not await response.
|
|
220
|
+
*/
|
|
221
|
+
index(doc) {
|
|
222
|
+
if (this.circuitOpen) {
|
|
223
|
+
return;
|
|
224
|
+
}
|
|
225
|
+
fetch(`${this.baseUrl}/${this.indexName}/_doc`, {
|
|
226
|
+
method: 'POST',
|
|
227
|
+
headers: {
|
|
228
|
+
'Authorization': this.authHeader,
|
|
229
|
+
'Content-Type': 'application/json',
|
|
230
|
+
},
|
|
231
|
+
body: JSON.stringify(doc),
|
|
232
|
+
}).catch((error) => {
|
|
233
|
+
this.handleConnectionError(error);
|
|
234
|
+
});
|
|
235
|
+
}
|
|
236
|
+
handleConnectionError(error) {
|
|
237
|
+
this.circuitOpen = true;
|
|
238
|
+
if (!this.errorShown) {
|
|
239
|
+
this.errorShown = true;
|
|
240
|
+
originalConsole.error('[devlogs] Unable to connect to index:', error);
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
let initialized = false;
|
|
246
|
+
let client = null;
|
|
247
|
+
/**
|
|
248
|
+
* Initialize the devlogs browser client.
|
|
249
|
+
*
|
|
250
|
+
* This intercepts console.log/warn/error/debug/info and forwards
|
|
251
|
+
* all log messages to the OpenSearch index.
|
|
252
|
+
*
|
|
253
|
+
* @example
|
|
254
|
+
* ```js
|
|
255
|
+
* devlogs.init({
|
|
256
|
+
* url: 'http://admin:admin@localhost:9200',
|
|
257
|
+
* area: 'frontend',
|
|
258
|
+
* loggerName: 'my-app'
|
|
259
|
+
* });
|
|
260
|
+
*
|
|
261
|
+
* console.log('App started'); // Forwarded to index
|
|
262
|
+
* ```
|
|
263
|
+
*/
|
|
264
|
+
function init(options) {
|
|
265
|
+
if (initialized) {
|
|
266
|
+
originalConsole.warn('[devlogs] Already initialized');
|
|
267
|
+
return;
|
|
268
|
+
}
|
|
269
|
+
const config = parseDevlogsUrl(options.url, options.index);
|
|
270
|
+
client = new DevlogsOpenSearchClient(config);
|
|
271
|
+
setContext({
|
|
272
|
+
area: options.area || null,
|
|
273
|
+
operationId: options.operationId || null,
|
|
274
|
+
loggerName: options.loggerName || 'browser',
|
|
275
|
+
pathname: typeof window !== 'undefined' ? window.location.pathname : '/',
|
|
276
|
+
features: {},
|
|
277
|
+
});
|
|
278
|
+
interceptConsole(client);
|
|
279
|
+
initialized = true;
|
|
280
|
+
}
|
|
281
|
+
/**
|
|
282
|
+
* Disable devlogs and restore original console methods.
|
|
283
|
+
*/
|
|
284
|
+
function destroy() {
|
|
285
|
+
if (!initialized) {
|
|
286
|
+
return;
|
|
287
|
+
}
|
|
288
|
+
restoreConsole();
|
|
289
|
+
client = null;
|
|
290
|
+
initialized = false;
|
|
291
|
+
}
|
|
292
|
+
/**
|
|
293
|
+
* Check if devlogs is currently initialized
|
|
294
|
+
*/
|
|
295
|
+
function isInitialized() {
|
|
296
|
+
return initialized;
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
exports.destroy = destroy;
|
|
300
|
+
exports.init = init;
|
|
301
|
+
exports.isInitialized = isInitialized;
|
|
302
|
+
exports.setArea = setArea;
|
|
303
|
+
exports.setFeatures = setFeatures;
|
|
304
|
+
exports.setOperationId = setOperationId;
|
|
305
|
+
exports.withOperation = withOperation;
|
|
306
|
+
|
|
307
|
+
return exports;
|
|
308
|
+
|
|
309
|
+
})({});
|
|
310
|
+
//# sourceMappingURL=devlogs.iife.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"devlogs.iife.js","sources":["../src/url-parser.ts","../src/formatter.ts","../src/interceptor.ts","../src/client.ts","../src/index.ts"],"sourcesContent":[null,null,null,null,null],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import type { DevlogsOptions } from './types';
|
|
2
|
+
import { setArea, setOperationId, setFeatures, withOperation } from './interceptor';
|
|
3
|
+
/**
|
|
4
|
+
* Initialize the devlogs browser client.
|
|
5
|
+
*
|
|
6
|
+
* This intercepts console.log/warn/error/debug/info and forwards
|
|
7
|
+
* all log messages to the OpenSearch index.
|
|
8
|
+
*
|
|
9
|
+
* @example
|
|
10
|
+
* ```js
|
|
11
|
+
* devlogs.init({
|
|
12
|
+
* url: 'http://admin:admin@localhost:9200',
|
|
13
|
+
* area: 'frontend',
|
|
14
|
+
* loggerName: 'my-app'
|
|
15
|
+
* });
|
|
16
|
+
*
|
|
17
|
+
* console.log('App started'); // Forwarded to index
|
|
18
|
+
* ```
|
|
19
|
+
*/
|
|
20
|
+
export declare function init(options: DevlogsOptions): void;
|
|
21
|
+
/**
|
|
22
|
+
* Disable devlogs and restore original console methods.
|
|
23
|
+
*/
|
|
24
|
+
export declare function destroy(): void;
|
|
25
|
+
/**
|
|
26
|
+
* Check if devlogs is currently initialized
|
|
27
|
+
*/
|
|
28
|
+
export declare function isInitialized(): boolean;
|
|
29
|
+
export { setArea, setOperationId, setFeatures, withOperation };
|
|
30
|
+
export type { DevlogsOptions, LogContext, LogDocument } from './types';
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import type { LogContext, OriginalConsole } from './types';
|
|
2
|
+
import type { DevlogsOpenSearchClient } from './client';
|
|
3
|
+
/**
|
|
4
|
+
* Store original console methods before interception.
|
|
5
|
+
* These are used for:
|
|
6
|
+
* 1. Calling the original console so browser devtools still work
|
|
7
|
+
* 2. Error reporting from the client without causing infinite loops
|
|
8
|
+
*/
|
|
9
|
+
export declare const originalConsole: OriginalConsole;
|
|
10
|
+
/**
|
|
11
|
+
* Get the current logging context
|
|
12
|
+
*/
|
|
13
|
+
export declare function getContext(): LogContext;
|
|
14
|
+
/**
|
|
15
|
+
* Update the logging context
|
|
16
|
+
*/
|
|
17
|
+
export declare function setContext(updates: Partial<LogContext>): void;
|
|
18
|
+
/**
|
|
19
|
+
* Set the application area
|
|
20
|
+
*/
|
|
21
|
+
export declare function setArea(area: string | null): void;
|
|
22
|
+
/**
|
|
23
|
+
* Set the operation ID for correlation
|
|
24
|
+
*/
|
|
25
|
+
export declare function setOperationId(operationId: string | null): void;
|
|
26
|
+
/**
|
|
27
|
+
* Set custom features to include in all logs
|
|
28
|
+
*/
|
|
29
|
+
export declare function setFeatures(features: Record<string, unknown>): void;
|
|
30
|
+
/**
|
|
31
|
+
* Execute a function with a temporary operation ID
|
|
32
|
+
*/
|
|
33
|
+
export declare function withOperation<T>(operationId: string, fn: () => T): T;
|
|
34
|
+
/**
|
|
35
|
+
* Intercept console methods to forward logs to the index.
|
|
36
|
+
* Original console methods are still called so devtools work normally.
|
|
37
|
+
*/
|
|
38
|
+
export declare function interceptConsole(client: DevlogsOpenSearchClient): void;
|
|
39
|
+
/**
|
|
40
|
+
* Restore original console methods
|
|
41
|
+
*/
|
|
42
|
+
export declare function restoreConsole(): void;
|
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Configuration parsed from the DEVLOGS URL
|
|
3
|
+
*/
|
|
4
|
+
export interface DevlogsConfig {
|
|
5
|
+
scheme: 'http' | 'https';
|
|
6
|
+
host: string;
|
|
7
|
+
port: number;
|
|
8
|
+
user: string;
|
|
9
|
+
password: string;
|
|
10
|
+
index: string;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Options for initializing the devlogs client
|
|
14
|
+
*/
|
|
15
|
+
export interface DevlogsOptions {
|
|
16
|
+
/** OpenSearch URL in format: http://user:pass@host:port */
|
|
17
|
+
url: string;
|
|
18
|
+
/** Index name (default: devlogs-0001) */
|
|
19
|
+
index?: string;
|
|
20
|
+
/** Application area/subsystem identifier */
|
|
21
|
+
area?: string;
|
|
22
|
+
/** Operation ID for log correlation */
|
|
23
|
+
operationId?: string;
|
|
24
|
+
/** Logger name (default: browser) */
|
|
25
|
+
loggerName?: string;
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Current logging context
|
|
29
|
+
*/
|
|
30
|
+
export interface LogContext {
|
|
31
|
+
area: string | null;
|
|
32
|
+
operationId: string | null;
|
|
33
|
+
loggerName: string;
|
|
34
|
+
pathname: string;
|
|
35
|
+
features: Record<string, unknown>;
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Log document matching the devlogs schema
|
|
39
|
+
*/
|
|
40
|
+
export interface LogDocument {
|
|
41
|
+
doc_type: 'log_entry';
|
|
42
|
+
timestamp: string;
|
|
43
|
+
level: string;
|
|
44
|
+
levelno: number;
|
|
45
|
+
logger_name: string;
|
|
46
|
+
message: string;
|
|
47
|
+
pathname: string;
|
|
48
|
+
lineno: number | null;
|
|
49
|
+
funcName: string | null;
|
|
50
|
+
area: string | null;
|
|
51
|
+
operation_id: string | null;
|
|
52
|
+
features: Record<string, unknown>;
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Console method names that we intercept
|
|
56
|
+
*/
|
|
57
|
+
export type ConsoleMethod = 'log' | 'warn' | 'error' | 'debug' | 'info';
|
|
58
|
+
/**
|
|
59
|
+
* Mapping of console methods to their original implementations
|
|
60
|
+
*/
|
|
61
|
+
export type OriginalConsole = {
|
|
62
|
+
[K in ConsoleMethod]: (...args: unknown[]) => void;
|
|
63
|
+
};
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { DevlogsConfig } from './types';
|
|
2
|
+
/**
|
|
3
|
+
* Parse a DEVLOGS URL into configuration components.
|
|
4
|
+
*
|
|
5
|
+
* Supports format: http://user:pass@host:port or https://user:pass@host:port
|
|
6
|
+
*
|
|
7
|
+
* Defaults:
|
|
8
|
+
* - scheme: http
|
|
9
|
+
* - host: localhost
|
|
10
|
+
* - port: 9200 for http, 443 for https
|
|
11
|
+
* - user: admin
|
|
12
|
+
* - password: admin
|
|
13
|
+
* - index: devlogs-0001
|
|
14
|
+
*/
|
|
15
|
+
export declare function parseDevlogsUrl(url: string, index?: string): DevlogsConfig;
|
package/package.json
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "devlogs-browser",
|
|
3
|
+
"version": "1.1.1",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"description": "Browser logging library for DevLogs - forwards console logs to OpenSearch",
|
|
6
|
+
"main": "dist/devlogs.cjs.js",
|
|
7
|
+
"module": "dist/devlogs.esm.js",
|
|
8
|
+
"browser": "dist/devlogs.iife.js",
|
|
9
|
+
"types": "dist/index.d.ts",
|
|
10
|
+
"files": [
|
|
11
|
+
"dist"
|
|
12
|
+
],
|
|
13
|
+
"scripts": {
|
|
14
|
+
"build": "rollup -c",
|
|
15
|
+
"dev": "rollup -c -w",
|
|
16
|
+
"typecheck": "tsc --noEmit"
|
|
17
|
+
},
|
|
18
|
+
"devDependencies": {
|
|
19
|
+
"@rollup/plugin-typescript": "^11.1.6",
|
|
20
|
+
"rollup": "^4.9.0",
|
|
21
|
+
"tslib": "^2.6.2",
|
|
22
|
+
"typescript": "^5.3.0"
|
|
23
|
+
},
|
|
24
|
+
"keywords": [
|
|
25
|
+
"logging",
|
|
26
|
+
"devlogs",
|
|
27
|
+
"opensearch",
|
|
28
|
+
"browser",
|
|
29
|
+
"console"
|
|
30
|
+
],
|
|
31
|
+
"license": "MIT"
|
|
32
|
+
}
|