@factorypure/logger 1.0.6 → 1.0.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.ts +6 -5
- package/dist/index.js +68 -16
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { AsyncLocalStorage } from
|
|
2
|
-
import { CloudWatchLogs } from
|
|
3
|
-
import Notify from
|
|
4
|
-
import { NextFunction, Request, Response } from
|
|
1
|
+
import { AsyncLocalStorage } from 'async_hooks';
|
|
2
|
+
import { CloudWatchLogs } from '../node_modules/@aws-sdk/client-cloudwatch-logs/dist-types/CloudWatchLogs';
|
|
3
|
+
import Notify from '../node_modules/@factorypure/notify/dist/index';
|
|
4
|
+
import { NextFunction, Request, Response } from 'express';
|
|
5
5
|
declare class LogStream {
|
|
6
6
|
#private;
|
|
7
7
|
logStreamName: string;
|
|
@@ -21,7 +21,7 @@ export default class LoggerClient {
|
|
|
21
21
|
asyncLocalStorage?: AsyncLocalStorage<string>;
|
|
22
22
|
notifyClient?: Notify;
|
|
23
23
|
fatalErrorSlackChannel: string;
|
|
24
|
-
constructor({ logGroupName, cloudWatchClient, asyncLocalStorage, notifyClient, fatalErrorSlackChannel }: LoggerOptions);
|
|
24
|
+
constructor({ logGroupName, cloudWatchClient, asyncLocalStorage, notifyClient, fatalErrorSlackChannel, }: LoggerOptions);
|
|
25
25
|
createLogStream(logStreamName: string): LogStream;
|
|
26
26
|
}
|
|
27
27
|
type LoggerOptions = {
|
|
@@ -34,6 +34,7 @@ type LoggerOptions = {
|
|
|
34
34
|
export declare const attachRequestId: (asyncLocalStorage: AsyncLocalStorage<any>, user?: {
|
|
35
35
|
id: number;
|
|
36
36
|
}) => (req: Request, _res: Response, next: NextFunction) => void;
|
|
37
|
+
export declare function runInContext<T>(asyncLocalStorage: AsyncLocalStorage<any>, fn: (...args: any[]) => T): T;
|
|
37
38
|
export declare const logCrashes: () => void;
|
|
38
39
|
export declare const reportCrashes: (logger: LogStream) => void;
|
|
39
40
|
export {};
|
package/dist/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import fs from
|
|
1
|
+
import fs from 'fs';
|
|
2
2
|
class LogStream {
|
|
3
3
|
logStreamName;
|
|
4
4
|
initialized;
|
|
@@ -14,10 +14,12 @@ class LogStream {
|
|
|
14
14
|
}
|
|
15
15
|
async #createLogStream() {
|
|
16
16
|
let failed = false;
|
|
17
|
-
await this.logger.cloudWatchClient
|
|
17
|
+
await this.logger.cloudWatchClient
|
|
18
|
+
?.createLogStream({
|
|
18
19
|
logGroupName: this.logger.logGroupName,
|
|
19
20
|
logStreamName: this.logStreamName,
|
|
20
|
-
})
|
|
21
|
+
})
|
|
22
|
+
.catch((err) => {
|
|
21
23
|
if (err.__type !== 'ResourceAlreadyExistsException') {
|
|
22
24
|
console.error(err);
|
|
23
25
|
failed = true;
|
|
@@ -30,7 +32,9 @@ class LogStream {
|
|
|
30
32
|
info = (...messages) => {
|
|
31
33
|
const requestId = this.logger.asyncLocalStorage?.getStore();
|
|
32
34
|
if (!this.initialized) {
|
|
33
|
-
this.#init()
|
|
35
|
+
this.#init()
|
|
36
|
+
.then(() => this.info(...messages))
|
|
37
|
+
.catch(console.error);
|
|
34
38
|
return;
|
|
35
39
|
}
|
|
36
40
|
for (const message of messages) {
|
|
@@ -42,7 +46,9 @@ class LogStream {
|
|
|
42
46
|
warn = (...messages) => {
|
|
43
47
|
const requestId = this.logger.asyncLocalStorage?.getStore();
|
|
44
48
|
if (!this.initialized) {
|
|
45
|
-
this.#init()
|
|
49
|
+
this.#init()
|
|
50
|
+
.then(() => this.info(...messages))
|
|
51
|
+
.catch(console.error);
|
|
46
52
|
return;
|
|
47
53
|
}
|
|
48
54
|
for (const message of messages) {
|
|
@@ -54,7 +60,9 @@ class LogStream {
|
|
|
54
60
|
error = (...errors) => {
|
|
55
61
|
const requestId = this.logger.asyncLocalStorage?.getStore();
|
|
56
62
|
if (!this.initialized) {
|
|
57
|
-
this.#init()
|
|
63
|
+
this.#init()
|
|
64
|
+
.then(() => this.error(...errors))
|
|
65
|
+
.catch(console.error);
|
|
58
66
|
return;
|
|
59
67
|
}
|
|
60
68
|
for (const error of errors) {
|
|
@@ -72,14 +80,52 @@ class LogStream {
|
|
|
72
80
|
this.error(error);
|
|
73
81
|
this.#sendNotifications({
|
|
74
82
|
channels: [this.logger.fatalErrorSlackChannel],
|
|
75
|
-
text: `[${this.logger.logGroupName}]
|
|
83
|
+
text: `[${this.logger.logGroupName}] ${error.message}`,
|
|
84
|
+
blocks: [
|
|
85
|
+
{
|
|
86
|
+
type: 'section',
|
|
87
|
+
text: {
|
|
88
|
+
type: 'mrkdwn',
|
|
89
|
+
text: `*Fatal Error:*\n\`\`\`${error.message}\`\`\``,
|
|
90
|
+
},
|
|
91
|
+
},
|
|
92
|
+
{
|
|
93
|
+
type: 'section',
|
|
94
|
+
text: {
|
|
95
|
+
type: 'mrkdwn',
|
|
96
|
+
text: `*Log Group Name:*\n\`\`\`${this.logger.logGroupName}\`\`\``,
|
|
97
|
+
},
|
|
98
|
+
},
|
|
99
|
+
{
|
|
100
|
+
type: 'section',
|
|
101
|
+
text: {
|
|
102
|
+
type: 'mrkdwn',
|
|
103
|
+
text: `*Timestamp:*\n\`\`\`${new Date().toISOString()}\`\`\``,
|
|
104
|
+
},
|
|
105
|
+
},
|
|
106
|
+
{
|
|
107
|
+
type: 'section',
|
|
108
|
+
text: {
|
|
109
|
+
type: 'mrkdwn',
|
|
110
|
+
text: `*Request Context:*\n\`\`\`<https://us-east-1.console.aws.amazon.com/cloudwatch/home?region=us-east-1#logsV2:log-groups/log-group/${this.logger.logGroupName}/log-events$3Fstart$3D${Date.now() - 60000 * 15}$26end$3D${Date.now() + 60000 * 15}$26filterPattern$3D${requestId || ''}|${requestId || 'N/A'}>\`\`\``,
|
|
111
|
+
},
|
|
112
|
+
},
|
|
113
|
+
{
|
|
114
|
+
type: 'section',
|
|
115
|
+
text: {
|
|
116
|
+
type: 'mrkdwn',
|
|
117
|
+
text: `*Stack Trace:*\n\`\`\`${error.stack}\`\`\``,
|
|
118
|
+
},
|
|
119
|
+
},
|
|
120
|
+
],
|
|
76
121
|
mrkdwn: '',
|
|
77
122
|
store_id: 1,
|
|
78
123
|
});
|
|
79
124
|
};
|
|
80
125
|
async #putEvent(message) {
|
|
81
126
|
if (this.logger.cloudWatchClient) {
|
|
82
|
-
return this.logger.cloudWatchClient
|
|
127
|
+
return this.logger.cloudWatchClient
|
|
128
|
+
.putLogEvents({
|
|
83
129
|
logGroupName: this.logger.logGroupName,
|
|
84
130
|
logStreamName: this.logStreamName,
|
|
85
131
|
logEvents: [
|
|
@@ -88,7 +134,8 @@ class LogStream {
|
|
|
88
134
|
timestamp: Date.now(),
|
|
89
135
|
},
|
|
90
136
|
],
|
|
91
|
-
})
|
|
137
|
+
})
|
|
138
|
+
.catch(console.error);
|
|
92
139
|
}
|
|
93
140
|
}
|
|
94
141
|
async #sendNotifications(options) {
|
|
@@ -110,7 +157,7 @@ export default class LoggerClient {
|
|
|
110
157
|
asyncLocalStorage;
|
|
111
158
|
notifyClient;
|
|
112
159
|
fatalErrorSlackChannel;
|
|
113
|
-
constructor({ logGroupName, cloudWatchClient, asyncLocalStorage, notifyClient, fatalErrorSlackChannel = 'fatal-error-log' }) {
|
|
160
|
+
constructor({ logGroupName, cloudWatchClient, asyncLocalStorage, notifyClient, fatalErrorSlackChannel = 'fatal-error-log', }) {
|
|
114
161
|
this.logGroupName = logGroupName;
|
|
115
162
|
this.initialized = false;
|
|
116
163
|
this.cloudWatchClient = cloudWatchClient;
|
|
@@ -129,9 +176,11 @@ export default class LoggerClient {
|
|
|
129
176
|
}
|
|
130
177
|
async #createLogGroup() {
|
|
131
178
|
let failed = false;
|
|
132
|
-
await this.cloudWatchClient
|
|
179
|
+
await this.cloudWatchClient
|
|
180
|
+
?.createLogGroup({
|
|
133
181
|
logGroupName: this.logGroupName,
|
|
134
|
-
})
|
|
182
|
+
})
|
|
183
|
+
.catch((err) => {
|
|
135
184
|
if (err.__type !== 'ResourceAlreadyExistsException') {
|
|
136
185
|
console.error(err);
|
|
137
186
|
failed = true;
|
|
@@ -144,18 +193,21 @@ export default class LoggerClient {
|
|
|
144
193
|
}
|
|
145
194
|
export const attachRequestId = (asyncLocalStorage, user) => {
|
|
146
195
|
return (req, _res, next) => {
|
|
147
|
-
const availableCharacters =
|
|
196
|
+
const availableCharacters = 'qwertyuiopasdfghjklzxcvbnmQWERTYUIOPASDFGHJKLZXCVBNM0987654321';
|
|
148
197
|
let id = user ? `userId-${user.id}:` : 'system-request:';
|
|
149
198
|
let uniqueKey = '';
|
|
150
199
|
while (uniqueKey.length < 10) {
|
|
151
|
-
uniqueKey +=
|
|
152
|
-
availableCharacters[Math.floor(Math.random() * availableCharacters.length)];
|
|
200
|
+
uniqueKey += availableCharacters[Math.floor(Math.random() * availableCharacters.length)];
|
|
153
201
|
}
|
|
154
202
|
id = id + uniqueKey;
|
|
155
|
-
req.headers[
|
|
203
|
+
req.headers['X-Request-Id'] = id;
|
|
156
204
|
asyncLocalStorage.run(id, next);
|
|
157
205
|
};
|
|
158
206
|
};
|
|
207
|
+
export function runInContext(asyncLocalStorage, fn) {
|
|
208
|
+
const contextId = Math.random().toString(36).slice(2, 12);
|
|
209
|
+
return asyncLocalStorage.run(contextId, fn);
|
|
210
|
+
}
|
|
159
211
|
export const logCrashes = () => {
|
|
160
212
|
process.on('uncaughtException', (err) => {
|
|
161
213
|
console.error(err);
|