@viplance/nestjs-logger 0.3.3 → 0.3.5
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 +6 -5
- package/dist/entities/log.entity.d.ts +1 -0
- package/dist/entities/log.entity.js +1 -0
- package/dist/entities/log.entity.js.map +1 -1
- package/dist/log.interceptor.js +4 -3
- package/dist/log.interceptor.js.map +1 -1
- package/dist/services/log.service.d.ts +3 -0
- package/dist/services/log.service.js +19 -9
- package/dist/services/log.service.js.map +1 -1
- package/package.json +1 -1
- package/public/scripts/common.js +6 -4
- package/public/scripts/details-popup.js +25 -12
- package/public/scripts/json-viewer.js +15 -4
- package/public/styles/index.css +60 -20
- package/src/entities/log.entity.ts +1 -0
- package/src/log.interceptor.ts +2 -2
- package/src/services/log.service.ts +24 -11
package/README.md
CHANGED
|
@@ -61,8 +61,9 @@ Connect the database to store logs.<br />
|
|
|
61
61
|
<br />
|
|
62
62
|
|
|
63
63
|
### The LogService methods:
|
|
64
|
-
- log()
|
|
65
|
-
- error()
|
|
66
|
-
- warn()
|
|
67
|
-
- debug()
|
|
68
|
-
- verbose()
|
|
64
|
+
- log(message: string)
|
|
65
|
+
- error(message: string)
|
|
66
|
+
- warn(message: string)
|
|
67
|
+
- debug(message: string)
|
|
68
|
+
- verbose(message: string)
|
|
69
|
+
- addBreadcrumb(any)
|
|
@@ -16,6 +16,7 @@ function createLogEntity(name) {
|
|
|
16
16
|
count: { type: Number, default: 1 },
|
|
17
17
|
context: { type: String, nullable: true },
|
|
18
18
|
trace: { type: String, nullable: true },
|
|
19
|
+
breadcrumbs: { type: String, nullable: true },
|
|
19
20
|
createdAt: { type: Date },
|
|
20
21
|
updatedAt: { type: Date },
|
|
21
22
|
},
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"log.entity.js","sourceRoot":"","sources":["../../src/entities/log.entity.ts"],"names":[],"mappings":";;AAEA,
|
|
1
|
+
{"version":3,"file":"log.entity.js","sourceRoot":"","sources":["../../src/entities/log.entity.ts"],"names":[],"mappings":";;AAEA,0CAmBC;AArBD,qCAAuC;AAEvC,SAAgB,eAAe,CAAC,IAAY;IAC1C,OAAO,IAAI,sBAAY,CAAC;QACtB,IAAI;QACJ,OAAO,EAAE;YACP,GAAG,EAAE;gBACH,IAAI,EAAE,MAAM;gBACZ,QAAQ,EAAE,IAAI;gBACd,OAAO,EAAE,IAAI;aACd;YACD,IAAI,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE;YACtB,OAAO,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE;YACzB,KAAK,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC,EAAE;YACnC,OAAO,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,IAAI,EAAE;YACzC,KAAK,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,IAAI,EAAE;YACvC,WAAW,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,IAAI,EAAE;YAC7C,SAAS,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE;YACzB,SAAS,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE;SAC1B;KACF,CAAC,CAAC;AACL,CAAC"}
|
package/dist/log.interceptor.js
CHANGED
|
@@ -23,12 +23,13 @@ let LogInterceptor = class LogInterceptor {
|
|
|
23
23
|
intercept(context, next) {
|
|
24
24
|
return next.handle().pipe((0, rxjs_1.tap)({
|
|
25
25
|
error: (error) => {
|
|
26
|
-
var _a;
|
|
27
|
-
// error handler
|
|
26
|
+
var _a, _b;
|
|
28
27
|
(_a = this.logService) === null || _a === void 0 ? void 0 : _a.error(error.message, error.stack, context);
|
|
28
|
+
(_b = this.logService) === null || _b === void 0 ? void 0 : _b.clearBreadcrumbs();
|
|
29
29
|
},
|
|
30
30
|
complete: () => {
|
|
31
|
-
|
|
31
|
+
var _a;
|
|
32
|
+
(_a = this.logService) === null || _a === void 0 ? void 0 : _a.clearBreadcrumbs();
|
|
32
33
|
},
|
|
33
34
|
}));
|
|
34
35
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"log.interceptor.js","sourceRoot":"","sources":["../src/log.interceptor.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;AACA,2CAAoD;AACpD,+BAAuC;AACvC,wDAAoD;AAI7C,IAAM,cAAc,GAApB,MAAM,cAAc;IACzB,YAAiD,UAAsB;QAAtB,eAAU,GAAV,UAAU,CAAY;IAAG,CAAC;IAE3E,SAAS,CAAC,OAA6B,EAAE,IAAiB;QACxD,OAAO,IAAI,CAAC,MAAM,EAAE,CAAC,IAAI,CACvB,IAAA,UAAG,EAAC;YACF,KAAK,EAAE,CAAC,KAAK,EAAE,EAAE;;gBACf,
|
|
1
|
+
{"version":3,"file":"log.interceptor.js","sourceRoot":"","sources":["../src/log.interceptor.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;AACA,2CAAoD;AACpD,+BAAuC;AACvC,wDAAoD;AAI7C,IAAM,cAAc,GAApB,MAAM,cAAc;IACzB,YAAiD,UAAsB;QAAtB,eAAU,GAAV,UAAU,CAAY;IAAG,CAAC;IAE3E,SAAS,CAAC,OAA6B,EAAE,IAAiB;QACxD,OAAO,IAAI,CAAC,MAAM,EAAE,CAAC,IAAI,CACvB,IAAA,UAAG,EAAC;YACF,KAAK,EAAE,CAAC,KAAK,EAAE,EAAE;;gBACf,MAAA,IAAI,CAAC,UAAU,0CAAE,KAAK,CAAC,KAAK,CAAC,OAAO,EAAE,KAAK,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC;gBAC5D,MAAA,IAAI,CAAC,UAAU,0CAAE,gBAAgB,EAAE,CAAC;YACtC,CAAC;YACD,QAAQ,EAAE,GAAG,EAAE;;gBACb,MAAA,IAAI,CAAC,UAAU,0CAAE,gBAAgB,EAAE,CAAC;YACtC,CAAC;SACF,CAAC,CACH,CAAC;IACJ,CAAC;CACF,CAAA;AAhBY,wCAAc;yBAAd,cAAc;IAD1B,IAAA,mBAAU,GAAE;IAEE,WAAA,IAAA,eAAM,EAAC,wBAAU,CAAC,CAAA;qCAA8B,wBAAU;GAD5D,cAAc,CAgB1B"}
|
|
@@ -10,8 +10,11 @@ export declare class LogService implements LoggerService {
|
|
|
10
10
|
static options: LogModuleOptions;
|
|
11
11
|
static Log: EntitySchema;
|
|
12
12
|
static timer: ReturnType<typeof setInterval>;
|
|
13
|
+
breadcrumbs: any[];
|
|
13
14
|
constructor(memoryDbService: MemoryDbService);
|
|
14
15
|
connectDb(options: LogModuleOptions): Promise<DataSource>;
|
|
16
|
+
addBreadcrumb(breadcrumb: any): void;
|
|
17
|
+
clearBreadcrumbs(): void;
|
|
15
18
|
log(message: string, context?: ExecutionContextHost): void;
|
|
16
19
|
error(message: string, trace?: string, context?: ExecutionContextHost): void;
|
|
17
20
|
warn(message: string, context?: ExecutionContextHost): void;
|
|
@@ -21,6 +21,7 @@ const timers_1 = require("timers");
|
|
|
21
21
|
let LogService = LogService_1 = class LogService {
|
|
22
22
|
constructor(memoryDbService) {
|
|
23
23
|
this.memoryDbService = memoryDbService;
|
|
24
|
+
this.breadcrumbs = [];
|
|
24
25
|
}
|
|
25
26
|
async connectDb(options) {
|
|
26
27
|
var _a, _b, _c, _d, _e, _f;
|
|
@@ -41,6 +42,12 @@ let LogService = LogService_1 = class LogService {
|
|
|
41
42
|
LogService_1.timer = (0, timers_1.setInterval)(this.checkRecords, 1000 * 60 * 60); // check one time per hour
|
|
42
43
|
return LogService_1.connection;
|
|
43
44
|
}
|
|
45
|
+
addBreadcrumb(breadcrumb) {
|
|
46
|
+
this.breadcrumbs.push(breadcrumb);
|
|
47
|
+
}
|
|
48
|
+
clearBreadcrumbs() {
|
|
49
|
+
this.breadcrumbs = [];
|
|
50
|
+
}
|
|
44
51
|
log(message, context) {
|
|
45
52
|
this.smartInsert({
|
|
46
53
|
type: types_1.LogType.LOG,
|
|
@@ -88,6 +95,7 @@ let LogService = LogService_1 = class LogService {
|
|
|
88
95
|
"updatedAt",
|
|
89
96
|
"context",
|
|
90
97
|
"trace",
|
|
98
|
+
"breadcrumbs",
|
|
91
99
|
],
|
|
92
100
|
order: { updatedAt: "DESC" },
|
|
93
101
|
});
|
|
@@ -107,6 +115,7 @@ let LogService = LogService_1 = class LogService {
|
|
|
107
115
|
return await connection.update(LogService_1.Log, log._id, {
|
|
108
116
|
context,
|
|
109
117
|
trace: data.trace,
|
|
118
|
+
breadcrumbs: this.breadcrumbs,
|
|
110
119
|
count: log.count + 1,
|
|
111
120
|
updatedAt: currentDate,
|
|
112
121
|
});
|
|
@@ -116,6 +125,7 @@ let LogService = LogService_1 = class LogService {
|
|
|
116
125
|
message: data.message,
|
|
117
126
|
context,
|
|
118
127
|
trace: data.trace,
|
|
128
|
+
breadcrumbs: this.breadcrumbs,
|
|
119
129
|
count: 1,
|
|
120
130
|
createdAt: currentDate,
|
|
121
131
|
updatedAt: currentDate,
|
|
@@ -129,25 +139,25 @@ let LogService = LogService_1 = class LogService {
|
|
|
129
139
|
const res = {};
|
|
130
140
|
const args = context.getArgs();
|
|
131
141
|
for (const arg of args) {
|
|
132
|
-
if (arg.
|
|
133
|
-
res.
|
|
134
|
-
const len = arg.rawHeaders.length - 1;
|
|
135
|
-
for (let i = 0; i < len; i += 2) {
|
|
136
|
-
res.rawHeaders[arg.rawHeaders[i]] = arg.rawHeaders[i + 1];
|
|
137
|
-
}
|
|
142
|
+
if (arg.method) {
|
|
143
|
+
res.method = arg.method;
|
|
138
144
|
}
|
|
139
145
|
if (arg.url) {
|
|
140
146
|
res.url = arg.url;
|
|
141
147
|
}
|
|
142
|
-
if (arg.method) {
|
|
143
|
-
res.method = arg.method;
|
|
144
|
-
}
|
|
145
148
|
if (arg.params) {
|
|
146
149
|
res.params = arg.params;
|
|
147
150
|
}
|
|
148
151
|
if (arg.body) {
|
|
149
152
|
res.body = arg.body;
|
|
150
153
|
}
|
|
154
|
+
if (arg.rawHeaders) {
|
|
155
|
+
res.rawHeaders = {};
|
|
156
|
+
const len = arg.rawHeaders.length - 1;
|
|
157
|
+
for (let i = 0; i < len; i += 2) {
|
|
158
|
+
res.rawHeaders[arg.rawHeaders[i]] = arg.rawHeaders[i + 1];
|
|
159
|
+
}
|
|
160
|
+
}
|
|
151
161
|
}
|
|
152
162
|
return res;
|
|
153
163
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"log.service.js","sourceRoot":"","sources":["../../src/services/log.service.ts"],"names":[],"mappings":";;;;;;;;;;;;;AAAA,2CAAkE;AAClE,2DAAsD;AACtD,0CAA2C;AAC3C,oCAA8D;AAC9D,qCAKiB;AACjB,uDAAyD;AAEzD,mCAAqC;AAG9B,IAAM,UAAU,kBAAhB,MAAM,UAAU;
|
|
1
|
+
{"version":3,"file":"log.service.js","sourceRoot":"","sources":["../../src/services/log.service.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
package/public/scripts/common.js
CHANGED
|
@@ -124,7 +124,7 @@ function getLogHtmlElement(log) {
|
|
|
124
124
|
<div id="${log._id}" class="row">
|
|
125
125
|
<div class="col ${getTypeClass(log.type)}">${log.type}</div>
|
|
126
126
|
<div class="col">
|
|
127
|
-
<div>${log.message}</div>
|
|
127
|
+
<div class="log-info">${log.message}</div>
|
|
128
128
|
<div class="date">${getDate(log.updatedAt)}</div>
|
|
129
129
|
</div>
|
|
130
130
|
<div class="col context">${log.trace || ""}</div>
|
|
@@ -137,9 +137,7 @@ async function getLogs() {
|
|
|
137
137
|
const res = await fetch(`${origin}${pathname}api${search}`);
|
|
138
138
|
|
|
139
139
|
if (res.ok) {
|
|
140
|
-
logs =
|
|
141
|
-
return selectedLogTypes["all"] || selectedLogTypes[log.type];
|
|
142
|
-
});
|
|
140
|
+
logs = await res.json();
|
|
143
141
|
|
|
144
142
|
if (logs.length === 0) {
|
|
145
143
|
document.getElementById("no-logs").style.display = "block";
|
|
@@ -151,6 +149,10 @@ async function getLogs() {
|
|
|
151
149
|
document.querySelector("nav").style.display = "flex";
|
|
152
150
|
}
|
|
153
151
|
|
|
152
|
+
logs = logs.filter((log) => {
|
|
153
|
+
return selectedLogTypes["all"] || selectedLogTypes[log.type];
|
|
154
|
+
});
|
|
155
|
+
|
|
154
156
|
let html = "";
|
|
155
157
|
|
|
156
158
|
logs.forEach((log) => {
|
|
@@ -1,19 +1,19 @@
|
|
|
1
1
|
function showLogDetails(log) {
|
|
2
2
|
const popup = document.getElementById(`popup`);
|
|
3
|
-
|
|
3
|
+
|
|
4
4
|
popup.innerHTML = `
|
|
5
5
|
<div class="content center">
|
|
6
|
-
<div class="container
|
|
7
|
-
<h2 class="${log.type}">${log.type}: ${log.message}</h2>
|
|
8
|
-
<
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
6
|
+
<div class="container">
|
|
7
|
+
<h2 class="popup-title ${log.type}">${log.type}: ${log.message}</h2>
|
|
8
|
+
<div class="mt-05">${getDate(log.updatedAt)}</div>
|
|
9
|
+
${
|
|
10
|
+
log.trace
|
|
11
|
+
? `
|
|
12
|
+
<h3 class="mt-2">Trace</h3>
|
|
13
|
+
<p class="key pl-2"><span>${getTrace(log.trace)}</span></p>
|
|
14
|
+
`
|
|
15
|
+
: ""
|
|
16
|
+
}
|
|
17
17
|
${
|
|
18
18
|
log.context
|
|
19
19
|
? `
|
|
@@ -22,12 +22,25 @@ function showLogDetails(log) {
|
|
|
22
22
|
`
|
|
23
23
|
: ""
|
|
24
24
|
}
|
|
25
|
+
${
|
|
26
|
+
log.breadcrumbs && log.breadcrumbs.length > 0
|
|
27
|
+
? `
|
|
28
|
+
<h3 class="mt-2">Breadcrumbs</h3>
|
|
29
|
+
<p>${jsonViewer(log.breadcrumbs)}</p>
|
|
30
|
+
`
|
|
31
|
+
: ""
|
|
32
|
+
}
|
|
25
33
|
<button class="white mt-2" onclick="closePopup()">Close</button>
|
|
26
34
|
</div>
|
|
27
35
|
<div>`;
|
|
36
|
+
|
|
28
37
|
popup.style.display = "block";
|
|
29
38
|
}
|
|
30
39
|
|
|
40
|
+
function getTrace(trace) {
|
|
41
|
+
return trace.replace(new RegExp(String.fromCharCode(10), "g"), "<br />");
|
|
42
|
+
}
|
|
43
|
+
|
|
31
44
|
function closePopup() {
|
|
32
45
|
const popup = document.getElementById(`popup`);
|
|
33
46
|
popup.style.display = "none";
|
|
@@ -5,21 +5,32 @@ function jsonViewer(json, parentKey) {
|
|
|
5
5
|
|
|
6
6
|
res = `<div>`;
|
|
7
7
|
|
|
8
|
-
if (
|
|
9
|
-
|
|
8
|
+
if (Array.isArray(json)) {
|
|
9
|
+
json.forEach((item) => {
|
|
10
|
+
res += `<div class="key pl-2">${
|
|
11
|
+
typeof item === "object" ? jsonViewer(item) : `<span>${item}</span>`
|
|
12
|
+
}</div>`;
|
|
13
|
+
});
|
|
14
|
+
|
|
15
|
+
return res;
|
|
10
16
|
}
|
|
11
17
|
|
|
12
18
|
const keys = Object.keys(json);
|
|
19
|
+
const showParentKey = parentKey && keys.length > 0; // hide an empty object
|
|
20
|
+
|
|
21
|
+
if (showParentKey) {
|
|
22
|
+
res += `<div class="pl-2"><div>${parentKey}</div>`;
|
|
23
|
+
}
|
|
13
24
|
|
|
14
25
|
for (const key of keys) {
|
|
15
26
|
if (typeof json[key] === "object") {
|
|
16
27
|
res += jsonViewer(json[key], key);
|
|
17
28
|
} else {
|
|
18
|
-
res += `<div class="pl-2">${key}:
|
|
29
|
+
res += `<div class="key pl-2">${key}: <span>${json[key]}</span></div>`;
|
|
19
30
|
}
|
|
20
31
|
}
|
|
21
32
|
|
|
22
|
-
if (
|
|
33
|
+
if (showParentKey) {
|
|
23
34
|
res += `</div>`;
|
|
24
35
|
}
|
|
25
36
|
|
package/public/styles/index.css
CHANGED
|
@@ -3,6 +3,7 @@ body {
|
|
|
3
3
|
background-color: var(--white);
|
|
4
4
|
color: black;
|
|
5
5
|
font-family: Verdana, sans-serif;
|
|
6
|
+
font-size: 14px;
|
|
6
7
|
display: flex;
|
|
7
8
|
flex-direction: column;
|
|
8
9
|
align-items: center;
|
|
@@ -11,19 +12,19 @@ body {
|
|
|
11
12
|
}
|
|
12
13
|
|
|
13
14
|
h1 {
|
|
14
|
-
font-size: 2.
|
|
15
|
+
font-size: 2.6rem;
|
|
15
16
|
font-weight: 400;
|
|
16
17
|
line-height: 3rem;
|
|
17
18
|
}
|
|
18
19
|
|
|
19
20
|
h2 {
|
|
20
|
-
font-size: 1.
|
|
21
|
+
font-size: 1.4rem;
|
|
21
22
|
font-weight: 400;
|
|
22
|
-
line-height:
|
|
23
|
+
line-height: 1.8rem;
|
|
23
24
|
}
|
|
24
25
|
|
|
25
26
|
h3 {
|
|
26
|
-
font-size: 1.
|
|
27
|
+
font-size: 1.1rem;
|
|
27
28
|
font-weight: 400;
|
|
28
29
|
line-height: 2rem;
|
|
29
30
|
}
|
|
@@ -52,12 +53,6 @@ h3 {
|
|
|
52
53
|
max-width: 1600px;
|
|
53
54
|
}
|
|
54
55
|
|
|
55
|
-
@media (max-width: 1620px) {
|
|
56
|
-
.container {
|
|
57
|
-
padding: 0 2rem;
|
|
58
|
-
}
|
|
59
|
-
}
|
|
60
|
-
|
|
61
56
|
#logs {
|
|
62
57
|
margin-top: 4rem;
|
|
63
58
|
}
|
|
@@ -168,14 +163,18 @@ nav ul li:hover {
|
|
|
168
163
|
}
|
|
169
164
|
|
|
170
165
|
/* margins and paddings */
|
|
166
|
+
.mt-05 {
|
|
167
|
+
margin-top: 0.5rem;
|
|
168
|
+
}
|
|
169
|
+
.mt-1 {
|
|
170
|
+
margin-top: 1rem;
|
|
171
|
+
}
|
|
171
172
|
.mt-2 {
|
|
172
173
|
margin-top: 2rem;
|
|
173
174
|
}
|
|
174
|
-
|
|
175
175
|
.mt-3 {
|
|
176
176
|
margin-top: 3rem;
|
|
177
177
|
}
|
|
178
|
-
|
|
179
178
|
.pl-2 {
|
|
180
179
|
box-sizing: border-box;
|
|
181
180
|
padding-left: 2rem;
|
|
@@ -212,7 +211,7 @@ nav ul li:hover {
|
|
|
212
211
|
|
|
213
212
|
.table-header > :nth-child(2),
|
|
214
213
|
.row > :nth-child(2) {
|
|
215
|
-
flex: 0 0
|
|
214
|
+
flex: 0 0 auto;
|
|
216
215
|
}
|
|
217
216
|
.table-header > :nth-child(3),
|
|
218
217
|
.row > :nth-child(3) {
|
|
@@ -225,13 +224,14 @@ nav ul li:hover {
|
|
|
225
224
|
|
|
226
225
|
.row {
|
|
227
226
|
height: 3rem;
|
|
228
|
-
opacity: 0.8;
|
|
229
227
|
font-weight: 100;
|
|
230
228
|
cursor: pointer;
|
|
229
|
+
border-left: 2px solid transparent;
|
|
231
230
|
}
|
|
232
231
|
|
|
233
232
|
.row:hover {
|
|
234
|
-
|
|
233
|
+
border-left: 2px solid;
|
|
234
|
+
border-left-color: var(--dark);
|
|
235
235
|
}
|
|
236
236
|
|
|
237
237
|
.row:nth-child(odd) {
|
|
@@ -244,7 +244,6 @@ nav ul li:hover {
|
|
|
244
244
|
}
|
|
245
245
|
|
|
246
246
|
.context {
|
|
247
|
-
font-size: small;
|
|
248
247
|
color: var(--dark);
|
|
249
248
|
display: -webkit-box;
|
|
250
249
|
-webkit-box-orient: vertical;
|
|
@@ -252,10 +251,20 @@ nav ul li:hover {
|
|
|
252
251
|
-webkit-line-clamp: 2;
|
|
253
252
|
overflow: hidden;
|
|
254
253
|
text-overflow: ellipsis;
|
|
255
|
-
max-height: 2.
|
|
254
|
+
max-height: 2.7rem;
|
|
256
255
|
margin-top: -1rem;
|
|
257
256
|
}
|
|
258
257
|
|
|
258
|
+
.log-info {
|
|
259
|
+
display: -webkit-box;
|
|
260
|
+
-webkit-box-orient: vertical;
|
|
261
|
+
line-clamp: 1;
|
|
262
|
+
-webkit-line-clamp: 1;
|
|
263
|
+
overflow: hidden;
|
|
264
|
+
text-overflow: ellipsis;
|
|
265
|
+
max-height: 1.2rem;
|
|
266
|
+
}
|
|
267
|
+
|
|
259
268
|
.date {
|
|
260
269
|
font-size: small;
|
|
261
270
|
color: var(--dark);
|
|
@@ -282,13 +291,44 @@ nav ul li:hover {
|
|
|
282
291
|
#popup {
|
|
283
292
|
position: fixed;
|
|
284
293
|
display: none;
|
|
285
|
-
|
|
294
|
+
box-sizing: border-box;
|
|
295
|
+
padding: 2rem;
|
|
296
|
+
background-color: rgba(255, 255, 255, 0.95);
|
|
297
|
+
backdrop-filter: blur(5px);
|
|
298
|
+
border: 1px solid var(--light);
|
|
286
299
|
top: 0;
|
|
287
|
-
left:
|
|
288
|
-
width:
|
|
300
|
+
left: 30%;
|
|
301
|
+
width: 50%;
|
|
289
302
|
height: 100%;
|
|
290
303
|
overflow-y: scroll;
|
|
291
304
|
z-index: 1;
|
|
305
|
+
opacity: 0.97;
|
|
292
306
|
}
|
|
293
307
|
|
|
294
308
|
/* JSON viewer */
|
|
309
|
+
.key {
|
|
310
|
+
font-size: 0.9rem;
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
.key span {
|
|
314
|
+
color: var(--dark);
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
@media (max-width: 1620px) {
|
|
318
|
+
header button {
|
|
319
|
+
margin-right: 1rem;
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
.logo {
|
|
323
|
+
margin-left: 1rem;
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
.logo h2 {
|
|
327
|
+
display: none;
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
#popup {
|
|
331
|
+
width: 100%;
|
|
332
|
+
left: 0;
|
|
333
|
+
}
|
|
334
|
+
}
|
|
@@ -14,6 +14,7 @@ export function createLogEntity(name: string) {
|
|
|
14
14
|
count: { type: Number, default: 1 },
|
|
15
15
|
context: { type: String, nullable: true },
|
|
16
16
|
trace: { type: String, nullable: true },
|
|
17
|
+
breadcrumbs: { type: String, nullable: true },
|
|
17
18
|
createdAt: { type: Date },
|
|
18
19
|
updatedAt: { type: Date },
|
|
19
20
|
},
|
package/src/log.interceptor.ts
CHANGED
|
@@ -12,11 +12,11 @@ export class LogInterceptor implements NestInterceptor {
|
|
|
12
12
|
return next.handle().pipe(
|
|
13
13
|
tap({
|
|
14
14
|
error: (error) => {
|
|
15
|
-
// error handler
|
|
16
15
|
this.logService?.error(error.message, error.stack, context);
|
|
16
|
+
this.logService?.clearBreadcrumbs();
|
|
17
17
|
},
|
|
18
18
|
complete: () => {
|
|
19
|
-
|
|
19
|
+
this.logService?.clearBreadcrumbs();
|
|
20
20
|
},
|
|
21
21
|
})
|
|
22
22
|
);
|
|
@@ -19,6 +19,8 @@ export class LogService implements LoggerService {
|
|
|
19
19
|
static Log: EntitySchema = createLogEntity(defaultTable);
|
|
20
20
|
static timer: ReturnType<typeof setInterval>;
|
|
21
21
|
|
|
22
|
+
breadcrumbs: any[] = [];
|
|
23
|
+
|
|
22
24
|
constructor(private readonly memoryDbService: MemoryDbService) {}
|
|
23
25
|
|
|
24
26
|
async connectDb(options: LogModuleOptions): Promise<DataSource> {
|
|
@@ -49,6 +51,14 @@ export class LogService implements LoggerService {
|
|
|
49
51
|
return LogService.connection;
|
|
50
52
|
}
|
|
51
53
|
|
|
54
|
+
addBreadcrumb(breadcrumb: any) {
|
|
55
|
+
this.breadcrumbs.push(breadcrumb);
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
clearBreadcrumbs() {
|
|
59
|
+
this.breadcrumbs = [];
|
|
60
|
+
}
|
|
61
|
+
|
|
52
62
|
log(message: string, context?: ExecutionContextHost) {
|
|
53
63
|
this.smartInsert({
|
|
54
64
|
type: LogType.LOG,
|
|
@@ -101,6 +111,7 @@ export class LogService implements LoggerService {
|
|
|
101
111
|
"updatedAt",
|
|
102
112
|
"context",
|
|
103
113
|
"trace",
|
|
114
|
+
"breadcrumbs",
|
|
104
115
|
],
|
|
105
116
|
order: { updatedAt: "DESC" },
|
|
106
117
|
});
|
|
@@ -130,6 +141,7 @@ export class LogService implements LoggerService {
|
|
|
130
141
|
return await connection.update(LogService.Log, log._id, {
|
|
131
142
|
context,
|
|
132
143
|
trace: data.trace,
|
|
144
|
+
breadcrumbs: this.breadcrumbs,
|
|
133
145
|
count: log.count + 1,
|
|
134
146
|
updatedAt: currentDate,
|
|
135
147
|
});
|
|
@@ -140,6 +152,7 @@ export class LogService implements LoggerService {
|
|
|
140
152
|
message: data.message,
|
|
141
153
|
context,
|
|
142
154
|
trace: data.trace,
|
|
155
|
+
breadcrumbs: this.breadcrumbs,
|
|
143
156
|
count: 1,
|
|
144
157
|
createdAt: currentDate,
|
|
145
158
|
updatedAt: currentDate,
|
|
@@ -155,23 +168,14 @@ export class LogService implements LoggerService {
|
|
|
155
168
|
const args = context.getArgs();
|
|
156
169
|
|
|
157
170
|
for (const arg of args) {
|
|
158
|
-
if (arg.
|
|
159
|
-
res.
|
|
160
|
-
const len = arg.rawHeaders.length - 1;
|
|
161
|
-
|
|
162
|
-
for (let i = 0; i < len; i += 2) {
|
|
163
|
-
res.rawHeaders[arg.rawHeaders[i]] = arg.rawHeaders[i + 1];
|
|
164
|
-
}
|
|
171
|
+
if (arg.method) {
|
|
172
|
+
res.method = arg.method;
|
|
165
173
|
}
|
|
166
174
|
|
|
167
175
|
if (arg.url) {
|
|
168
176
|
res.url = arg.url;
|
|
169
177
|
}
|
|
170
178
|
|
|
171
|
-
if (arg.method) {
|
|
172
|
-
res.method = arg.method;
|
|
173
|
-
}
|
|
174
|
-
|
|
175
179
|
if (arg.params) {
|
|
176
180
|
res.params = arg.params;
|
|
177
181
|
}
|
|
@@ -179,6 +183,15 @@ export class LogService implements LoggerService {
|
|
|
179
183
|
if (arg.body) {
|
|
180
184
|
res.body = arg.body;
|
|
181
185
|
}
|
|
186
|
+
|
|
187
|
+
if (arg.rawHeaders) {
|
|
188
|
+
res.rawHeaders = {};
|
|
189
|
+
const len = arg.rawHeaders.length - 1;
|
|
190
|
+
|
|
191
|
+
for (let i = 0; i < len; i += 2) {
|
|
192
|
+
res.rawHeaders[arg.rawHeaders[i]] = arg.rawHeaders[i + 1];
|
|
193
|
+
}
|
|
194
|
+
}
|
|
182
195
|
}
|
|
183
196
|
|
|
184
197
|
return res;
|