@dynamic-labs/logger 0.0.0-exp20240808.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 +3746 -0
- package/LICENSE +21 -0
- package/README.md +18 -0
- package/_virtual/_tslib.cjs +36 -0
- package/_virtual/_tslib.js +32 -0
- package/package.json +31 -0
- package/src/index.cjs +214 -0
- package/src/index.d.ts +48 -0
- package/src/index.js +203 -0
- package/src/types.cjs +13 -0
- package/src/types.d.ts +13 -0
- package/src/types.js +11 -0
- package/src/utils/deepMerge.cjs +57 -0
- package/src/utils/deepMerge.d.ts +1 -0
- package/src/utils/deepMerge.js +53 -0
- package/src/utils/processArgs.cjs +21 -0
- package/src/utils/processArgs.d.ts +10 -0
- package/src/utils/processArgs.js +17 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2022 Dynamic Labs, Inc.
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
# logger
|
|
2
|
+
|
|
3
|
+
Generic logger that wraps console.log with support of log levels and formatting messages.
|
|
4
|
+
|
|
5
|
+
Features:
|
|
6
|
+
|
|
7
|
+
1. Create a new named logger `new Logger(name, LogLevel.INFO)`
|
|
8
|
+
2. Formats log messages: `[name] [level]: message`
|
|
9
|
+
3. Supports additional arguments just like console log
|
|
10
|
+
4. Change the loglevel with `logger.setLogLevel(LogLevel)`
|
|
11
|
+
|
|
12
|
+
## Building
|
|
13
|
+
|
|
14
|
+
Run `nx build logger` to build the library.
|
|
15
|
+
|
|
16
|
+
## Running unit tests
|
|
17
|
+
|
|
18
|
+
Run `nx test logger` to execute the unit tests via [Jest](https://jestjs.io).
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
'use client'
|
|
2
|
+
'use strict';
|
|
3
|
+
|
|
4
|
+
Object.defineProperty(exports, '__esModule', { value: true });
|
|
5
|
+
|
|
6
|
+
/******************************************************************************
|
|
7
|
+
Copyright (c) Microsoft Corporation.
|
|
8
|
+
|
|
9
|
+
Permission to use, copy, modify, and/or distribute this software for any
|
|
10
|
+
purpose with or without fee is hereby granted.
|
|
11
|
+
|
|
12
|
+
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
|
|
13
|
+
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
|
|
14
|
+
AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
|
|
15
|
+
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
|
|
16
|
+
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
|
17
|
+
OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
|
18
|
+
PERFORMANCE OF THIS SOFTWARE.
|
|
19
|
+
***************************************************************************** */
|
|
20
|
+
|
|
21
|
+
function __awaiter(thisArg, _arguments, P, generator) {
|
|
22
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
23
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
24
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
25
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
26
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
27
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
28
|
+
});
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
typeof SuppressedError === "function" ? SuppressedError : function (error, suppressed, message) {
|
|
32
|
+
var e = new Error(message);
|
|
33
|
+
return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e;
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
exports.__awaiter = __awaiter;
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
'use client'
|
|
2
|
+
/******************************************************************************
|
|
3
|
+
Copyright (c) Microsoft Corporation.
|
|
4
|
+
|
|
5
|
+
Permission to use, copy, modify, and/or distribute this software for any
|
|
6
|
+
purpose with or without fee is hereby granted.
|
|
7
|
+
|
|
8
|
+
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
|
|
9
|
+
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
|
|
10
|
+
AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
|
|
11
|
+
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
|
|
12
|
+
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
|
13
|
+
OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
|
14
|
+
PERFORMANCE OF THIS SOFTWARE.
|
|
15
|
+
***************************************************************************** */
|
|
16
|
+
|
|
17
|
+
function __awaiter(thisArg, _arguments, P, generator) {
|
|
18
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
19
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
20
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
21
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
22
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
23
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
24
|
+
});
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
typeof SuppressedError === "function" ? SuppressedError : function (error, suppressed, message) {
|
|
28
|
+
var e = new Error(message);
|
|
29
|
+
return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e;
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
export { __awaiter };
|
package/package.json
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@dynamic-labs/logger",
|
|
3
|
+
"version": "0.0.0-exp20240808.0",
|
|
4
|
+
"repository": {
|
|
5
|
+
"type": "git",
|
|
6
|
+
"url": "git+https://github.com/dynamic-labs/dynamic-auth.git",
|
|
7
|
+
"directory": "packages/logger"
|
|
8
|
+
},
|
|
9
|
+
"description": "A simple client side logging library used in Dynamic SDK",
|
|
10
|
+
"bugs": {
|
|
11
|
+
"url": "https://github.com/dynamic-labs/DynamicAuth/issues"
|
|
12
|
+
},
|
|
13
|
+
"homepage": "https://github.com/dynamic-labs/DynamicAuth/main/packages/logger#readme",
|
|
14
|
+
"author": "Dynamic Labs, Inc.",
|
|
15
|
+
"license": "MIT",
|
|
16
|
+
"main": "./src/index.cjs",
|
|
17
|
+
"module": "./src/index.js",
|
|
18
|
+
"types": "./src/index.d.ts",
|
|
19
|
+
"type": "module",
|
|
20
|
+
"exports": {
|
|
21
|
+
".": {
|
|
22
|
+
"types": "./src/index.d.ts",
|
|
23
|
+
"import": "./src/index.js",
|
|
24
|
+
"require": "./src/index.cjs"
|
|
25
|
+
},
|
|
26
|
+
"./package.json": "./package.json"
|
|
27
|
+
},
|
|
28
|
+
"peerDependencies": {
|
|
29
|
+
"eventemitter3": "5.0.1"
|
|
30
|
+
}
|
|
31
|
+
}
|
package/src/index.cjs
ADDED
|
@@ -0,0 +1,214 @@
|
|
|
1
|
+
'use client'
|
|
2
|
+
'use strict';
|
|
3
|
+
|
|
4
|
+
Object.defineProperty(exports, '__esModule', { value: true });
|
|
5
|
+
|
|
6
|
+
var _tslib = require('../_virtual/_tslib.cjs');
|
|
7
|
+
var EventEmitter = require('eventemitter3');
|
|
8
|
+
var types = require('./types.cjs');
|
|
9
|
+
var deepMerge = require('./utils/deepMerge.cjs');
|
|
10
|
+
var processArgs = require('./utils/processArgs.cjs');
|
|
11
|
+
|
|
12
|
+
function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
|
|
13
|
+
|
|
14
|
+
var EventEmitter__default = /*#__PURE__*/_interopDefaultLegacy(EventEmitter);
|
|
15
|
+
|
|
16
|
+
/* eslint-disable @typescript-eslint/no-explicit-any, no-console */
|
|
17
|
+
const IGNORE_MESSAGES = ['Failed to send logs to server'];
|
|
18
|
+
const messageQueue = [];
|
|
19
|
+
class Logger {
|
|
20
|
+
constructor(name, level) {
|
|
21
|
+
this.name = name;
|
|
22
|
+
this.meta = undefined;
|
|
23
|
+
if (level === undefined && process.env['NODE_ENV'] !== 'production') {
|
|
24
|
+
this.level = types.LogLevel.DEBUG;
|
|
25
|
+
}
|
|
26
|
+
else if (level === undefined) {
|
|
27
|
+
this.level = types.LogLevel.WARN;
|
|
28
|
+
}
|
|
29
|
+
else {
|
|
30
|
+
this.level = level;
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
static setEmitErrors(emit) {
|
|
34
|
+
if (emit !== undefined) {
|
|
35
|
+
Logger.globalKeys.emitErrors = emit;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
static setEnvironmentId(environmentId) {
|
|
39
|
+
if (environmentId !== undefined) {
|
|
40
|
+
Logger.globalKeys.environmentId = environmentId;
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
setMetaData(key, value) {
|
|
44
|
+
if (!this.meta) {
|
|
45
|
+
this.meta = {};
|
|
46
|
+
}
|
|
47
|
+
const data = {};
|
|
48
|
+
key.split('.').reduce((acc, k, i, arr) => {
|
|
49
|
+
if (i === arr.length - 1) {
|
|
50
|
+
acc[k] = value;
|
|
51
|
+
}
|
|
52
|
+
else {
|
|
53
|
+
if (!acc[k]) {
|
|
54
|
+
acc[k] = {};
|
|
55
|
+
}
|
|
56
|
+
return acc[k];
|
|
57
|
+
}
|
|
58
|
+
}, data);
|
|
59
|
+
this.meta = deepMerge.deepMerge(this.meta, data);
|
|
60
|
+
}
|
|
61
|
+
getNameArray(name) {
|
|
62
|
+
return Array.isArray(name) ? name : [name];
|
|
63
|
+
}
|
|
64
|
+
createLogger(name, level) {
|
|
65
|
+
return new Logger([...this.getNameArray(this.name), ...this.getNameArray(name)], level !== null && level !== void 0 ? level : this.level);
|
|
66
|
+
}
|
|
67
|
+
get logLevel() {
|
|
68
|
+
return types.LogLevel[this.level];
|
|
69
|
+
}
|
|
70
|
+
setLogLevel(level) {
|
|
71
|
+
if (level in types.LogLevel && typeof level === 'string') {
|
|
72
|
+
this.level = types.LogLevel[level];
|
|
73
|
+
}
|
|
74
|
+
else if (level in types.LogLevel && typeof level === 'number') {
|
|
75
|
+
this.level = level;
|
|
76
|
+
}
|
|
77
|
+
else {
|
|
78
|
+
throw new Error(`Invalid log level: ${level}`);
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
formatMessage(level, message) {
|
|
82
|
+
var _a;
|
|
83
|
+
if (message instanceof Error) {
|
|
84
|
+
message = message.stack;
|
|
85
|
+
}
|
|
86
|
+
else if (
|
|
87
|
+
// Handle Error-Like Objects
|
|
88
|
+
message instanceof Object &&
|
|
89
|
+
Object.prototype.hasOwnProperty.call(message, 'stack')) {
|
|
90
|
+
message = message.stack;
|
|
91
|
+
}
|
|
92
|
+
else if (message instanceof Object) {
|
|
93
|
+
message = JSON.stringify(message);
|
|
94
|
+
}
|
|
95
|
+
const names = (Array.isArray(this.name) ? this.name : [this.name]).map((name) => `[${name}]`);
|
|
96
|
+
return `${names.join('')} [${(_a = types.LogLevel[level]) !== null && _a !== void 0 ? _a : 'TROUBLESHOOTING'}]: ${message}`;
|
|
97
|
+
}
|
|
98
|
+
captureAndSend(level, message, ...args) {
|
|
99
|
+
return _tslib.__awaiter(this, void 0, void 0, function* () {
|
|
100
|
+
if (Logger.globalKeys.emitErrors &&
|
|
101
|
+
!IGNORE_MESSAGES.includes(message === null || message === void 0 ? void 0 : message.toString()) &&
|
|
102
|
+
typeof window !== 'undefined') {
|
|
103
|
+
this.emitHttpLogs(level, message, { args });
|
|
104
|
+
}
|
|
105
|
+
});
|
|
106
|
+
}
|
|
107
|
+
emitHttpLogs(level, message, { args = [], transformMeta = (meta) => meta }) {
|
|
108
|
+
messageQueue.push({ args, level, message });
|
|
109
|
+
if (messageQueue.length === 1) {
|
|
110
|
+
/**
|
|
111
|
+
* Batching the logs to send them in a single request
|
|
112
|
+
* https://developer.mozilla.org/en-US/docs/Web/API/HTML_DOM_API/Microtask_guide#batching_operations
|
|
113
|
+
*
|
|
114
|
+
* Essentially, multiple calls to log in the same event loop will be batched into a single request
|
|
115
|
+
*/
|
|
116
|
+
queueMicrotask(() => _tslib.__awaiter(this, void 0, void 0, function* () {
|
|
117
|
+
var _a, _b;
|
|
118
|
+
const messages = [];
|
|
119
|
+
messageQueue.forEach((msg) => {
|
|
120
|
+
var _a, _b, _c, _d, _e;
|
|
121
|
+
const body = {};
|
|
122
|
+
const { objectArgs, remainingArgs } = processArgs.processArgs(msg);
|
|
123
|
+
Object.assign(body, ...objectArgs);
|
|
124
|
+
Object.assign(body, {
|
|
125
|
+
level: types.LogLevel[msg.level],
|
|
126
|
+
message: [msg.message, ...remainingArgs].join(' '),
|
|
127
|
+
meta: transformMeta(this.meta),
|
|
128
|
+
url: {
|
|
129
|
+
hostname: (_a = window.location) === null || _a === void 0 ? void 0 : _a.hostname,
|
|
130
|
+
origin: (_b = window.location) === null || _b === void 0 ? void 0 : _b.origin,
|
|
131
|
+
pathname: (_c = window.location) === null || _c === void 0 ? void 0 : _c.pathname,
|
|
132
|
+
port: (_d = window.location) === null || _d === void 0 ? void 0 : _d.port,
|
|
133
|
+
protocol: (_e = window.location) === null || _e === void 0 ? void 0 : _e.protocol,
|
|
134
|
+
},
|
|
135
|
+
});
|
|
136
|
+
messages.push(body);
|
|
137
|
+
});
|
|
138
|
+
try {
|
|
139
|
+
if (!((_a = Logger.globalKeys) === null || _a === void 0 ? void 0 : _a.environmentId)) {
|
|
140
|
+
throw new Error('Environment ID not set');
|
|
141
|
+
}
|
|
142
|
+
yield fetch(`https://logs.dynamicauth.com/api/v1/${(_b = Logger.globalKeys) === null || _b === void 0 ? void 0 : _b.environmentId}`, {
|
|
143
|
+
body: JSON.stringify(messages),
|
|
144
|
+
headers: {
|
|
145
|
+
'Content-Type': 'application/json',
|
|
146
|
+
},
|
|
147
|
+
method: 'POST',
|
|
148
|
+
mode: 'cors',
|
|
149
|
+
referrerPolicy: 'origin-when-cross-origin',
|
|
150
|
+
});
|
|
151
|
+
}
|
|
152
|
+
catch (error) {
|
|
153
|
+
this.debug('Failed to send logs to server', error);
|
|
154
|
+
}
|
|
155
|
+
messageQueue.length = 0;
|
|
156
|
+
}));
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
/**
|
|
160
|
+
* Emits an INFO type message to the backend for analysis and debugging
|
|
161
|
+
*/
|
|
162
|
+
instrument(message, options) {
|
|
163
|
+
return this.emitHttpLogs(types.LogLevel.INFO, message, {
|
|
164
|
+
args: [options],
|
|
165
|
+
// Don't send any meta to avoid storing PII
|
|
166
|
+
transformMeta: () => undefined,
|
|
167
|
+
});
|
|
168
|
+
}
|
|
169
|
+
log(level, message, ...args) {
|
|
170
|
+
const enableTroubleshootMode = typeof window !== 'undefined' &&
|
|
171
|
+
(window === null || window === void 0 ? void 0 : window.dynamic_enableTroubleshootMode) === true;
|
|
172
|
+
if (!enableTroubleshootMode &&
|
|
173
|
+
(level < this.level || level === types.LogLevel.MUTE)) {
|
|
174
|
+
return;
|
|
175
|
+
}
|
|
176
|
+
const fmtMsg = this.formatMessage(level, message);
|
|
177
|
+
switch (level) {
|
|
178
|
+
case types.LogLevel.WARN:
|
|
179
|
+
console.warn(fmtMsg, ...args);
|
|
180
|
+
break;
|
|
181
|
+
case types.LogLevel.ERROR:
|
|
182
|
+
console.error(fmtMsg, ...args);
|
|
183
|
+
break;
|
|
184
|
+
default:
|
|
185
|
+
console.log(fmtMsg, ...args);
|
|
186
|
+
}
|
|
187
|
+
if (level === types.LogLevel.ERROR) {
|
|
188
|
+
this.captureAndSend(level, message, ...args);
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
debug(message, ...args) {
|
|
192
|
+
this.log(types.LogLevel.DEBUG, message, ...args);
|
|
193
|
+
}
|
|
194
|
+
info(message, ...args) {
|
|
195
|
+
this.log(types.LogLevel.INFO, message, ...args);
|
|
196
|
+
}
|
|
197
|
+
warn(message, ...args) {
|
|
198
|
+
this.log(types.LogLevel.WARN, message, ...args);
|
|
199
|
+
}
|
|
200
|
+
error(message, ...args) {
|
|
201
|
+
Logger.events.emit('error', message);
|
|
202
|
+
this.log(types.LogLevel.ERROR, message, ...args);
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
Logger.globalKeys = {
|
|
206
|
+
emitErrors: true,
|
|
207
|
+
};
|
|
208
|
+
Logger.events = new EventEmitter__default["default"]();
|
|
209
|
+
|
|
210
|
+
Object.defineProperty(exports, 'LogLevel', {
|
|
211
|
+
enumerable: true,
|
|
212
|
+
get: function () { return types.LogLevel; }
|
|
213
|
+
});
|
|
214
|
+
exports.Logger = Logger;
|
package/src/index.d.ts
ADDED
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import EventEmitter from 'eventemitter3';
|
|
2
|
+
import { LogLevel, Message } from './types';
|
|
3
|
+
export { LogLevel, type Message } from './types';
|
|
4
|
+
type EmitHttpOptions = {
|
|
5
|
+
args?: any[];
|
|
6
|
+
transformMeta?: (meta: Record<string, any> | undefined) => Record<string, any> | undefined;
|
|
7
|
+
};
|
|
8
|
+
export type InstrumentOptions = {
|
|
9
|
+
extraArgs?: NonNullable<EmitHttpOptions['args']>;
|
|
10
|
+
/** Identifies which resource is being instrumented */
|
|
11
|
+
key: string;
|
|
12
|
+
/** Instrumentation does not use meta so this needs to be explicit */
|
|
13
|
+
environmentId: string;
|
|
14
|
+
/** Measurement in MS the operation took to complete */
|
|
15
|
+
time: number;
|
|
16
|
+
appName?: string;
|
|
17
|
+
userId?: string;
|
|
18
|
+
primaryWalletId?: string;
|
|
19
|
+
};
|
|
20
|
+
export declare class Logger {
|
|
21
|
+
private name;
|
|
22
|
+
private level;
|
|
23
|
+
private static globalKeys;
|
|
24
|
+
private meta;
|
|
25
|
+
constructor(name: string | string[], level?: LogLevel);
|
|
26
|
+
static setEmitErrors(emit?: boolean): void;
|
|
27
|
+
static setEnvironmentId(environmentId?: string): void;
|
|
28
|
+
static events: EventEmitter<{
|
|
29
|
+
error: Message;
|
|
30
|
+
}, any>;
|
|
31
|
+
setMetaData(key: string, value: any): void;
|
|
32
|
+
private getNameArray;
|
|
33
|
+
createLogger(name: string | string[], level?: LogLevel): Logger;
|
|
34
|
+
get logLevel(): string;
|
|
35
|
+
setLogLevel(level: LogLevel | keyof typeof LogLevel): void;
|
|
36
|
+
private formatMessage;
|
|
37
|
+
private captureAndSend;
|
|
38
|
+
emitHttpLogs(level: LogLevel, message: Message, { args, transformMeta }: EmitHttpOptions): void;
|
|
39
|
+
/**
|
|
40
|
+
* Emits an INFO type message to the backend for analysis and debugging
|
|
41
|
+
*/
|
|
42
|
+
instrument(message: Message, options: InstrumentOptions & Record<string, unknown>): void;
|
|
43
|
+
log(level: LogLevel, message: Message, ...args: any[]): void;
|
|
44
|
+
debug(message: Message, ...args: any[]): void;
|
|
45
|
+
info(message: Message, ...args: any[]): void;
|
|
46
|
+
warn(message: Message, ...args: any[]): void;
|
|
47
|
+
error(message: Message, ...args: any[]): void;
|
|
48
|
+
}
|
package/src/index.js
ADDED
|
@@ -0,0 +1,203 @@
|
|
|
1
|
+
'use client'
|
|
2
|
+
import { __awaiter } from '../_virtual/_tslib.js';
|
|
3
|
+
import EventEmitter from 'eventemitter3';
|
|
4
|
+
import { LogLevel } from './types.js';
|
|
5
|
+
export { LogLevel } from './types.js';
|
|
6
|
+
import { deepMerge } from './utils/deepMerge.js';
|
|
7
|
+
import { processArgs } from './utils/processArgs.js';
|
|
8
|
+
|
|
9
|
+
/* eslint-disable @typescript-eslint/no-explicit-any, no-console */
|
|
10
|
+
const IGNORE_MESSAGES = ['Failed to send logs to server'];
|
|
11
|
+
const messageQueue = [];
|
|
12
|
+
class Logger {
|
|
13
|
+
constructor(name, level) {
|
|
14
|
+
this.name = name;
|
|
15
|
+
this.meta = undefined;
|
|
16
|
+
if (level === undefined && process.env['NODE_ENV'] !== 'production') {
|
|
17
|
+
this.level = LogLevel.DEBUG;
|
|
18
|
+
}
|
|
19
|
+
else if (level === undefined) {
|
|
20
|
+
this.level = LogLevel.WARN;
|
|
21
|
+
}
|
|
22
|
+
else {
|
|
23
|
+
this.level = level;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
static setEmitErrors(emit) {
|
|
27
|
+
if (emit !== undefined) {
|
|
28
|
+
Logger.globalKeys.emitErrors = emit;
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
static setEnvironmentId(environmentId) {
|
|
32
|
+
if (environmentId !== undefined) {
|
|
33
|
+
Logger.globalKeys.environmentId = environmentId;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
setMetaData(key, value) {
|
|
37
|
+
if (!this.meta) {
|
|
38
|
+
this.meta = {};
|
|
39
|
+
}
|
|
40
|
+
const data = {};
|
|
41
|
+
key.split('.').reduce((acc, k, i, arr) => {
|
|
42
|
+
if (i === arr.length - 1) {
|
|
43
|
+
acc[k] = value;
|
|
44
|
+
}
|
|
45
|
+
else {
|
|
46
|
+
if (!acc[k]) {
|
|
47
|
+
acc[k] = {};
|
|
48
|
+
}
|
|
49
|
+
return acc[k];
|
|
50
|
+
}
|
|
51
|
+
}, data);
|
|
52
|
+
this.meta = deepMerge(this.meta, data);
|
|
53
|
+
}
|
|
54
|
+
getNameArray(name) {
|
|
55
|
+
return Array.isArray(name) ? name : [name];
|
|
56
|
+
}
|
|
57
|
+
createLogger(name, level) {
|
|
58
|
+
return new Logger([...this.getNameArray(this.name), ...this.getNameArray(name)], level !== null && level !== void 0 ? level : this.level);
|
|
59
|
+
}
|
|
60
|
+
get logLevel() {
|
|
61
|
+
return LogLevel[this.level];
|
|
62
|
+
}
|
|
63
|
+
setLogLevel(level) {
|
|
64
|
+
if (level in LogLevel && typeof level === 'string') {
|
|
65
|
+
this.level = LogLevel[level];
|
|
66
|
+
}
|
|
67
|
+
else if (level in LogLevel && typeof level === 'number') {
|
|
68
|
+
this.level = level;
|
|
69
|
+
}
|
|
70
|
+
else {
|
|
71
|
+
throw new Error(`Invalid log level: ${level}`);
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
formatMessage(level, message) {
|
|
75
|
+
var _a;
|
|
76
|
+
if (message instanceof Error) {
|
|
77
|
+
message = message.stack;
|
|
78
|
+
}
|
|
79
|
+
else if (
|
|
80
|
+
// Handle Error-Like Objects
|
|
81
|
+
message instanceof Object &&
|
|
82
|
+
Object.prototype.hasOwnProperty.call(message, 'stack')) {
|
|
83
|
+
message = message.stack;
|
|
84
|
+
}
|
|
85
|
+
else if (message instanceof Object) {
|
|
86
|
+
message = JSON.stringify(message);
|
|
87
|
+
}
|
|
88
|
+
const names = (Array.isArray(this.name) ? this.name : [this.name]).map((name) => `[${name}]`);
|
|
89
|
+
return `${names.join('')} [${(_a = LogLevel[level]) !== null && _a !== void 0 ? _a : 'TROUBLESHOOTING'}]: ${message}`;
|
|
90
|
+
}
|
|
91
|
+
captureAndSend(level, message, ...args) {
|
|
92
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
93
|
+
if (Logger.globalKeys.emitErrors &&
|
|
94
|
+
!IGNORE_MESSAGES.includes(message === null || message === void 0 ? void 0 : message.toString()) &&
|
|
95
|
+
typeof window !== 'undefined') {
|
|
96
|
+
this.emitHttpLogs(level, message, { args });
|
|
97
|
+
}
|
|
98
|
+
});
|
|
99
|
+
}
|
|
100
|
+
emitHttpLogs(level, message, { args = [], transformMeta = (meta) => meta }) {
|
|
101
|
+
messageQueue.push({ args, level, message });
|
|
102
|
+
if (messageQueue.length === 1) {
|
|
103
|
+
/**
|
|
104
|
+
* Batching the logs to send them in a single request
|
|
105
|
+
* https://developer.mozilla.org/en-US/docs/Web/API/HTML_DOM_API/Microtask_guide#batching_operations
|
|
106
|
+
*
|
|
107
|
+
* Essentially, multiple calls to log in the same event loop will be batched into a single request
|
|
108
|
+
*/
|
|
109
|
+
queueMicrotask(() => __awaiter(this, void 0, void 0, function* () {
|
|
110
|
+
var _a, _b;
|
|
111
|
+
const messages = [];
|
|
112
|
+
messageQueue.forEach((msg) => {
|
|
113
|
+
var _a, _b, _c, _d, _e;
|
|
114
|
+
const body = {};
|
|
115
|
+
const { objectArgs, remainingArgs } = processArgs(msg);
|
|
116
|
+
Object.assign(body, ...objectArgs);
|
|
117
|
+
Object.assign(body, {
|
|
118
|
+
level: LogLevel[msg.level],
|
|
119
|
+
message: [msg.message, ...remainingArgs].join(' '),
|
|
120
|
+
meta: transformMeta(this.meta),
|
|
121
|
+
url: {
|
|
122
|
+
hostname: (_a = window.location) === null || _a === void 0 ? void 0 : _a.hostname,
|
|
123
|
+
origin: (_b = window.location) === null || _b === void 0 ? void 0 : _b.origin,
|
|
124
|
+
pathname: (_c = window.location) === null || _c === void 0 ? void 0 : _c.pathname,
|
|
125
|
+
port: (_d = window.location) === null || _d === void 0 ? void 0 : _d.port,
|
|
126
|
+
protocol: (_e = window.location) === null || _e === void 0 ? void 0 : _e.protocol,
|
|
127
|
+
},
|
|
128
|
+
});
|
|
129
|
+
messages.push(body);
|
|
130
|
+
});
|
|
131
|
+
try {
|
|
132
|
+
if (!((_a = Logger.globalKeys) === null || _a === void 0 ? void 0 : _a.environmentId)) {
|
|
133
|
+
throw new Error('Environment ID not set');
|
|
134
|
+
}
|
|
135
|
+
yield fetch(`https://logs.dynamicauth.com/api/v1/${(_b = Logger.globalKeys) === null || _b === void 0 ? void 0 : _b.environmentId}`, {
|
|
136
|
+
body: JSON.stringify(messages),
|
|
137
|
+
headers: {
|
|
138
|
+
'Content-Type': 'application/json',
|
|
139
|
+
},
|
|
140
|
+
method: 'POST',
|
|
141
|
+
mode: 'cors',
|
|
142
|
+
referrerPolicy: 'origin-when-cross-origin',
|
|
143
|
+
});
|
|
144
|
+
}
|
|
145
|
+
catch (error) {
|
|
146
|
+
this.debug('Failed to send logs to server', error);
|
|
147
|
+
}
|
|
148
|
+
messageQueue.length = 0;
|
|
149
|
+
}));
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
/**
|
|
153
|
+
* Emits an INFO type message to the backend for analysis and debugging
|
|
154
|
+
*/
|
|
155
|
+
instrument(message, options) {
|
|
156
|
+
return this.emitHttpLogs(LogLevel.INFO, message, {
|
|
157
|
+
args: [options],
|
|
158
|
+
// Don't send any meta to avoid storing PII
|
|
159
|
+
transformMeta: () => undefined,
|
|
160
|
+
});
|
|
161
|
+
}
|
|
162
|
+
log(level, message, ...args) {
|
|
163
|
+
const enableTroubleshootMode = typeof window !== 'undefined' &&
|
|
164
|
+
(window === null || window === void 0 ? void 0 : window.dynamic_enableTroubleshootMode) === true;
|
|
165
|
+
if (!enableTroubleshootMode &&
|
|
166
|
+
(level < this.level || level === LogLevel.MUTE)) {
|
|
167
|
+
return;
|
|
168
|
+
}
|
|
169
|
+
const fmtMsg = this.formatMessage(level, message);
|
|
170
|
+
switch (level) {
|
|
171
|
+
case LogLevel.WARN:
|
|
172
|
+
console.warn(fmtMsg, ...args);
|
|
173
|
+
break;
|
|
174
|
+
case LogLevel.ERROR:
|
|
175
|
+
console.error(fmtMsg, ...args);
|
|
176
|
+
break;
|
|
177
|
+
default:
|
|
178
|
+
console.log(fmtMsg, ...args);
|
|
179
|
+
}
|
|
180
|
+
if (level === LogLevel.ERROR) {
|
|
181
|
+
this.captureAndSend(level, message, ...args);
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
debug(message, ...args) {
|
|
185
|
+
this.log(LogLevel.DEBUG, message, ...args);
|
|
186
|
+
}
|
|
187
|
+
info(message, ...args) {
|
|
188
|
+
this.log(LogLevel.INFO, message, ...args);
|
|
189
|
+
}
|
|
190
|
+
warn(message, ...args) {
|
|
191
|
+
this.log(LogLevel.WARN, message, ...args);
|
|
192
|
+
}
|
|
193
|
+
error(message, ...args) {
|
|
194
|
+
Logger.events.emit('error', message);
|
|
195
|
+
this.log(LogLevel.ERROR, message, ...args);
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
Logger.globalKeys = {
|
|
199
|
+
emitErrors: true,
|
|
200
|
+
};
|
|
201
|
+
Logger.events = new EventEmitter();
|
|
202
|
+
|
|
203
|
+
export { Logger };
|
package/src/types.cjs
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
'use client'
|
|
2
|
+
'use strict';
|
|
3
|
+
|
|
4
|
+
Object.defineProperty(exports, '__esModule', { value: true });
|
|
5
|
+
|
|
6
|
+
exports.LogLevel = void 0;
|
|
7
|
+
(function (LogLevel) {
|
|
8
|
+
LogLevel[LogLevel["DEBUG"] = 0] = "DEBUG";
|
|
9
|
+
LogLevel[LogLevel["INFO"] = 1] = "INFO";
|
|
10
|
+
LogLevel[LogLevel["WARN"] = 2] = "WARN";
|
|
11
|
+
LogLevel[LogLevel["ERROR"] = 3] = "ERROR";
|
|
12
|
+
LogLevel[LogLevel["MUTE"] = 99] = "MUTE";
|
|
13
|
+
})(exports.LogLevel || (exports.LogLevel = {}));
|
package/src/types.d.ts
ADDED
package/src/types.js
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
'use client'
|
|
2
|
+
var LogLevel;
|
|
3
|
+
(function (LogLevel) {
|
|
4
|
+
LogLevel[LogLevel["DEBUG"] = 0] = "DEBUG";
|
|
5
|
+
LogLevel[LogLevel["INFO"] = 1] = "INFO";
|
|
6
|
+
LogLevel[LogLevel["WARN"] = 2] = "WARN";
|
|
7
|
+
LogLevel[LogLevel["ERROR"] = 3] = "ERROR";
|
|
8
|
+
LogLevel[LogLevel["MUTE"] = 99] = "MUTE";
|
|
9
|
+
})(LogLevel || (LogLevel = {}));
|
|
10
|
+
|
|
11
|
+
export { LogLevel };
|