@push.rocks/smartlog 3.1.10 → 3.1.11
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_ts/00_commitinfo_data.js +1 -1
- package/dist_ts_destination_receiver/index.js +3 -3
- package/npmextra.json +12 -6
- package/package.json +23 -15
- package/readme.md +275 -319
- package/ts/00_commitinfo_data.ts +1 -1
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
*/
|
|
4
4
|
export const commitinfo = {
|
|
5
5
|
name: '@push.rocks/smartlog',
|
|
6
|
-
version: '3.1.
|
|
6
|
+
version: '3.1.11',
|
|
7
7
|
description: 'A minimalistic, distributed, and extensible logging tool supporting centralized log management.'
|
|
8
8
|
};
|
|
9
9
|
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiMDBfY29tbWl0aW5mb19kYXRhLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vdHMvMDBfY29tbWl0aW5mb19kYXRhLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBOztHQUVHO0FBQ0gsTUFBTSxDQUFDLE1BQU0sVUFBVSxHQUFHO0lBQ3hCLElBQUksRUFBRSxzQkFBc0I7SUFDNUIsT0FBTyxFQUFFLFFBQVE7SUFDakIsV0FBVyxFQUFFLGlHQUFpRztDQUMvRyxDQUFBIn0=
|
|
@@ -2,7 +2,7 @@ import * as plugins from './smartlog-destination-receiver.plugins.js';
|
|
|
2
2
|
import {} from '../dist_ts_interfaces/index.js';
|
|
3
3
|
export class SmartlogDestinationReceiver {
|
|
4
4
|
constructor(optionsArg) {
|
|
5
|
-
this.webrequest = new plugins.webrequest.
|
|
5
|
+
this.webrequest = new plugins.webrequest.WebrequestClient();
|
|
6
6
|
this.errorCounter = 0;
|
|
7
7
|
this.options = optionsArg;
|
|
8
8
|
}
|
|
@@ -17,7 +17,7 @@ export class SmartlogDestinationReceiver {
|
|
|
17
17
|
}
|
|
18
18
|
this.errorCounter++;
|
|
19
19
|
});
|
|
20
|
-
return response
|
|
20
|
+
return response;
|
|
21
21
|
}
|
|
22
22
|
}
|
|
23
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
23
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi90c19kZXN0aW5hdGlvbl9yZWNlaXZlci9pbmRleC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEtBQUssT0FBTyxNQUFNLDRDQUE0QyxDQUFDO0FBQ3RFLE9BQU8sRUFJTixNQUFNLGdDQUFnQyxDQUFDO0FBT3hDLE1BQU0sT0FBTywyQkFBMkI7SUFJdEMsWUFBWSxVQUEwRDtRQUY5RCxlQUFVLEdBQUcsSUFBSSxPQUFPLENBQUMsVUFBVSxDQUFDLGdCQUFnQixFQUFFLENBQUM7UUFNdkQsaUJBQVksR0FBRyxDQUFDLENBQUM7UUFIdkIsSUFBSSxDQUFDLE9BQU8sR0FBRyxVQUFVLENBQUM7SUFDNUIsQ0FBQztJQUdNLEtBQUssQ0FBQyxTQUFTLENBQUMsYUFBMEI7UUFDL0MsTUFBTSxRQUFRLEdBQUcsTUFBTSxJQUFJLENBQUMsVUFBVSxDQUFDLFFBQVEsQ0FBQyxJQUFJLENBQUMsT0FBTyxDQUFDLGdCQUFnQixFQUFFO1lBQzdFLElBQUksRUFBRSxPQUFPLENBQUMsU0FBUyxDQUFDLG9CQUFvQixDQUFDLElBQUksQ0FBQyxPQUFPLENBQUMsVUFBVSxDQUFDO1lBQ3JFLFVBQVUsRUFBRSxhQUFhO1NBQzFCLENBQUMsQ0FBQyxLQUFLLENBQUMsR0FBRyxDQUFDLEVBQUU7WUFDYixJQUFJLElBQUksQ0FBQyxZQUFZLEdBQUcsR0FBRyxLQUFLLENBQUMsRUFBRSxDQUFDO2dCQUNsQyxPQUFPLENBQUMsS0FBSyxDQUFDLDBDQUEwQyxDQUFDLENBQUM7Z0JBQzFELE9BQU8sQ0FBQyxLQUFLLENBQUMsZUFBZSxJQUFJLENBQUMsWUFBWSxnQkFBZ0IsQ0FBQyxDQUFBO1lBQ2pFLENBQUM7WUFDRCxJQUFJLENBQUMsWUFBWSxFQUFFLENBQUM7UUFDdEIsQ0FBQyxDQUFDLENBQUM7UUFDSCxPQUFPLFFBQVEsQ0FBQztJQUNsQixDQUFDO0NBQ0YifQ==
|
package/npmextra.json
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
{
|
|
2
|
-
"
|
|
2
|
+
"@git.zone/cli": {
|
|
3
3
|
"projectType": "npm",
|
|
4
4
|
"module": {
|
|
5
5
|
"githost": "code.foss.global",
|
|
@@ -25,13 +25,19 @@
|
|
|
25
25
|
"error tracking",
|
|
26
26
|
"development tools"
|
|
27
27
|
]
|
|
28
|
+
},
|
|
29
|
+
"release": {
|
|
30
|
+
"registries": [
|
|
31
|
+
"https://verdaccio.lossless.digital",
|
|
32
|
+
"https://registry.npmjs.org"
|
|
33
|
+
],
|
|
34
|
+
"accessLevel": "public"
|
|
28
35
|
}
|
|
29
36
|
},
|
|
30
|
-
"
|
|
31
|
-
"npmGlobalTools": [],
|
|
32
|
-
"npmAccessLevel": "public"
|
|
33
|
-
},
|
|
34
|
-
"tsdoc": {
|
|
37
|
+
"@git.zone/tsdoc": {
|
|
35
38
|
"legal": "\n## License and Legal Information\n\nThis repository contains open-source code that is licensed under the MIT License. A copy of the MIT License can be found in the [license](license) file within this repository. \n\n**Please note:** The MIT License does not grant permission to use the trade names, trademarks, service marks, or product names of the project, except as required for reasonable and customary use in describing the origin of the work and reproducing the content of the NOTICE file.\n\n### Trademarks\n\nThis project is owned and maintained by Task Venture Capital GmbH. The names and logos associated with Task Venture Capital GmbH and any related products or services are trademarks of Task Venture Capital GmbH and are not included within the scope of the MIT license granted herein. Use of these trademarks must comply with Task Venture Capital GmbH's Trademark Guidelines, and any usage must be approved in writing by Task Venture Capital GmbH.\n\n### Company Information\n\nTask Venture Capital GmbH \nRegistered at District court Bremen HRB 35230 HB, Germany\n\nFor any legal inquiries or if you require further information, please contact us via email at hello@task.vc.\n\nBy using this repository, you acknowledge that you have read this section, agree to comply with its terms, and understand that the licensing of the code does not imply endorsement by Task Venture Capital GmbH of any derivative works.\n"
|
|
39
|
+
},
|
|
40
|
+
"@ship.zone/szci": {
|
|
41
|
+
"npmGlobalTools": []
|
|
36
42
|
}
|
|
37
43
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@push.rocks/smartlog",
|
|
3
|
-
"version": "3.1.
|
|
3
|
+
"version": "3.1.11",
|
|
4
4
|
"private": false,
|
|
5
5
|
"description": "A minimalistic, distributed, and extensible logging tool supporting centralized log management.",
|
|
6
6
|
"keywords": [
|
|
@@ -35,24 +35,30 @@
|
|
|
35
35
|
},
|
|
36
36
|
"author": "Lossless GmbH",
|
|
37
37
|
"license": "MIT",
|
|
38
|
+
"scripts": {
|
|
39
|
+
"test": "(tstest test/**/*.ts --verbose)",
|
|
40
|
+
"build": "(tsbuild tsfolders)",
|
|
41
|
+
"format": "(gitzone format)",
|
|
42
|
+
"buildDocs": "tsdoc"
|
|
43
|
+
},
|
|
38
44
|
"devDependencies": {
|
|
39
|
-
"@git.zone/tsbuild": "^
|
|
40
|
-
"@git.zone/tsbundle": "^2.
|
|
41
|
-
"@git.zone/tsrun": "^
|
|
42
|
-
"@git.zone/tstest": "^
|
|
45
|
+
"@git.zone/tsbuild": "^4.1.2",
|
|
46
|
+
"@git.zone/tsbundle": "^2.8.3",
|
|
47
|
+
"@git.zone/tsrun": "^2.0.1",
|
|
48
|
+
"@git.zone/tstest": "^3.1.8",
|
|
43
49
|
"@types/node": "^22.15.20"
|
|
44
50
|
},
|
|
45
51
|
"dependencies": {
|
|
46
52
|
"@api.global/typedrequest-interfaces": "^3.0.19",
|
|
47
53
|
"@push.rocks/consolecolor": "^2.0.3",
|
|
48
|
-
"@push.rocks/isounique": "^1.0.
|
|
54
|
+
"@push.rocks/isounique": "^1.0.5",
|
|
49
55
|
"@push.rocks/smartclickhouse": "^2.0.17",
|
|
50
56
|
"@push.rocks/smartfile": "^11.2.7",
|
|
51
|
-
"@push.rocks/smarthash": "^3.2.
|
|
57
|
+
"@push.rocks/smarthash": "^3.2.6",
|
|
52
58
|
"@push.rocks/smartpromise": "^4.2.3",
|
|
53
59
|
"@push.rocks/smarttime": "^4.1.1",
|
|
54
|
-
"@push.rocks/webrequest": "^
|
|
55
|
-
"@tsclass/tsclass": "^9.
|
|
60
|
+
"@push.rocks/webrequest": "^4.0.1",
|
|
61
|
+
"@tsclass/tsclass": "^9.3.0"
|
|
56
62
|
},
|
|
57
63
|
"files": [
|
|
58
64
|
"ts/**/*",
|
|
@@ -75,13 +81,15 @@
|
|
|
75
81
|
"type": "git",
|
|
76
82
|
"url": "https://code.foss.global/push.rocks/smartlog.git"
|
|
77
83
|
},
|
|
84
|
+
"packageManager": "pnpm@10.10.0+sha512.d615db246fe70f25dcfea6d8d73dee782ce23e2245e3c4f6f888249fb568149318637dca73c2c5c8ef2a4ca0d5657fb9567188bfab47f566d1ee6ce987815c39",
|
|
78
85
|
"bugs": {
|
|
79
86
|
"url": "https://code.foss.global/push.rocks/smartlog/issues"
|
|
80
87
|
},
|
|
81
|
-
"
|
|
82
|
-
"
|
|
83
|
-
"
|
|
84
|
-
|
|
85
|
-
|
|
88
|
+
"pnpm": {
|
|
89
|
+
"overrides": {},
|
|
90
|
+
"onlyBuiltDependencies": [
|
|
91
|
+
"esbuild",
|
|
92
|
+
"puppeteer"
|
|
93
|
+
]
|
|
86
94
|
}
|
|
87
|
-
}
|
|
95
|
+
}
|
package/readme.md
CHANGED
|
@@ -6,10 +6,14 @@
|
|
|
6
6
|
|
|
7
7
|
> **smartlog** is a powerful, distributed, and extensible logging system designed for the cloud-native era. Whether you're debugging locally, monitoring production systems, or building complex microservices, smartlog adapts to your needs with style. 🎯
|
|
8
8
|
|
|
9
|
+
## Issue Reporting and Security
|
|
10
|
+
|
|
11
|
+
For reporting bugs, issues, or security vulnerabilities, please visit [community.foss.global/](https://community.foss.global/). This is the central community hub for all issue reporting. Developers who sign and comply with our contribution agreement and go through identification can also get a [code.foss.global/](https://code.foss.global/) account to submit Pull Requests directly.
|
|
12
|
+
|
|
9
13
|
## 🌟 Why smartlog?
|
|
10
14
|
|
|
11
15
|
- **🎨 Beautiful Console Output**: Color-coded, formatted logs that are actually readable
|
|
12
|
-
- **🔌 Extensible Architecture**: Plug in any destination
|
|
16
|
+
- **🔌 Extensible Architecture**: Plug in any destination — databases, files, remote servers
|
|
13
17
|
- **🌍 Distributed by Design**: Built for microservices with correlation and context tracking
|
|
14
18
|
- **⚡ Zero-Config Start**: Works out of the box, scales when you need it
|
|
15
19
|
- **🎭 Interactive CLI Tools**: Spinners and progress bars that handle non-TTY environments gracefully
|
|
@@ -24,9 +28,6 @@ pnpm add @push.rocks/smartlog
|
|
|
24
28
|
|
|
25
29
|
# Using npm
|
|
26
30
|
npm install @push.rocks/smartlog
|
|
27
|
-
|
|
28
|
-
# Using yarn
|
|
29
|
-
yarn add @push.rocks/smartlog
|
|
30
31
|
```
|
|
31
32
|
|
|
32
33
|
## 🚀 Quick Start
|
|
@@ -48,25 +49,32 @@ const logger = new Smartlog({
|
|
|
48
49
|
}
|
|
49
50
|
});
|
|
50
51
|
|
|
51
|
-
// Enable
|
|
52
|
+
// Enable console output
|
|
52
53
|
logger.enableConsole();
|
|
53
54
|
|
|
54
55
|
// Start logging!
|
|
55
|
-
logger.log('info', '🎉 Application started successfully');
|
|
56
|
-
logger.log('error', '💥 Database connection failed', {
|
|
56
|
+
await logger.log('info', '🎉 Application started successfully');
|
|
57
|
+
await logger.log('error', '💥 Database connection failed', {
|
|
57
58
|
errorCode: 'DB_TIMEOUT',
|
|
58
|
-
attemptCount: 3
|
|
59
|
+
attemptCount: 3
|
|
59
60
|
});
|
|
60
61
|
```
|
|
61
62
|
|
|
62
|
-
### Using
|
|
63
|
+
### Using `createForCommitinfo`
|
|
63
64
|
|
|
64
|
-
|
|
65
|
+
If you're integrating with a build system that provides commit info, you can use the static factory method:
|
|
65
66
|
|
|
66
67
|
```typescript
|
|
67
|
-
import {
|
|
68
|
+
import { Smartlog } from '@push.rocks/smartlog';
|
|
68
69
|
|
|
69
|
-
|
|
70
|
+
const logger = Smartlog.createForCommitinfo({
|
|
71
|
+
name: 'my-app',
|
|
72
|
+
version: '1.0.0',
|
|
73
|
+
description: 'My application'
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
logger.enableConsole();
|
|
77
|
+
await logger.log('lifecycle', '🔄 App starting...');
|
|
70
78
|
```
|
|
71
79
|
|
|
72
80
|
## 📚 Core Concepts
|
|
@@ -77,25 +85,42 @@ smartlog supports semantic log levels for different scenarios:
|
|
|
77
85
|
|
|
78
86
|
```typescript
|
|
79
87
|
// Lifecycle events
|
|
80
|
-
logger.log('lifecycle', '🔄 Container starting up...');
|
|
88
|
+
await logger.log('lifecycle', '🔄 Container starting up...');
|
|
81
89
|
|
|
82
90
|
// Success states
|
|
83
|
-
logger.log('success', '✅ Payment processed');
|
|
84
|
-
logger.log('ok', '👍 Health check passed');
|
|
91
|
+
await logger.log('success', '✅ Payment processed');
|
|
92
|
+
await logger.log('ok', '👍 Health check passed');
|
|
85
93
|
|
|
86
94
|
// Information and debugging
|
|
87
|
-
logger.log('info', '📋 User profile updated');
|
|
88
|
-
logger.log('note', '📌 Cache invalidated');
|
|
89
|
-
logger.log('debug', '🔍 Query execution plan', { sql: 'SELECT * FROM users' });
|
|
95
|
+
await logger.log('info', '📋 User profile updated');
|
|
96
|
+
await logger.log('note', '📌 Cache invalidated');
|
|
97
|
+
await logger.log('debug', '🔍 Query execution plan', { sql: 'SELECT * FROM users' });
|
|
90
98
|
|
|
91
99
|
// Warnings and errors
|
|
92
|
-
logger.log('warn', '⚠️ Memory usage above 80%');
|
|
93
|
-
logger.log('error', '❌ Failed to send email');
|
|
100
|
+
await logger.log('warn', '⚠️ Memory usage above 80%');
|
|
101
|
+
await logger.log('error', '❌ Failed to send email');
|
|
94
102
|
|
|
95
103
|
// Verbose output
|
|
96
|
-
logger.log('silly', '🔬 Entering function processPayment()');
|
|
104
|
+
await logger.log('silly', '🔬 Entering function processPayment()');
|
|
97
105
|
```
|
|
98
106
|
|
|
107
|
+
Available levels (from most to least verbose): `silly`, `debug`, `info`, `note`, `ok`, `success`, `warn`, `error`, `lifecycle`
|
|
108
|
+
|
|
109
|
+
### Log Types
|
|
110
|
+
|
|
111
|
+
Each log entry has a type that describes what kind of data it represents:
|
|
112
|
+
|
|
113
|
+
| Type | Description |
|
|
114
|
+
|------|-------------|
|
|
115
|
+
| `log` | Standard log message |
|
|
116
|
+
| `increment` | Counter/metric increment |
|
|
117
|
+
| `gauge` | Gauge measurement |
|
|
118
|
+
| `error` | Error event |
|
|
119
|
+
| `success` | Success event |
|
|
120
|
+
| `value` | Value recording |
|
|
121
|
+
| `finance` | Financial transaction |
|
|
122
|
+
| `compliance` | Compliance event |
|
|
123
|
+
|
|
99
124
|
### Log Groups for Correlation
|
|
100
125
|
|
|
101
126
|
Perfect for tracking request flows through your system:
|
|
@@ -109,36 +134,75 @@ requestGroup.log('debug', 'Validating request body');
|
|
|
109
134
|
requestGroup.log('info', 'Creating user in database');
|
|
110
135
|
requestGroup.log('success', 'User created successfully', { userId: 'usr_123' });
|
|
111
136
|
|
|
112
|
-
// All logs in the group share the same
|
|
137
|
+
// All logs in the group share the same group ID and transaction ID
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
### Log Context
|
|
141
|
+
|
|
142
|
+
Every log carries contextual information about the environment it was created in:
|
|
143
|
+
|
|
144
|
+
```typescript
|
|
145
|
+
interface ILogContext {
|
|
146
|
+
commitinfo?: ICommitInfo; // Build/version info
|
|
147
|
+
company?: string; // Company name
|
|
148
|
+
companyunit?: string; // Team or department
|
|
149
|
+
containerName?: string; // Container/service name
|
|
150
|
+
environment?: 'local' | 'test' | 'staging' | 'production';
|
|
151
|
+
runtime?: 'node' | 'chrome' | 'rust' | 'deno' | 'cloudflare_workers';
|
|
152
|
+
zone?: string; // Deployment zone/region
|
|
153
|
+
}
|
|
113
154
|
```
|
|
114
155
|
|
|
115
156
|
## 🎯 Log Destinations
|
|
116
157
|
|
|
158
|
+
smartlog routes log packages to any number of destinations simultaneously. Each destination implements the `ILogDestination` interface with a single `handleLog` method.
|
|
159
|
+
|
|
117
160
|
### Built-in Destinations
|
|
118
161
|
|
|
119
162
|
#### 🖥️ Local Console (Enhanced)
|
|
120
163
|
|
|
121
|
-
Beautiful,
|
|
164
|
+
Beautiful, color-coded output for local development:
|
|
122
165
|
|
|
123
166
|
```typescript
|
|
124
167
|
import { DestinationLocal } from '@push.rocks/smartlog/destination-local';
|
|
125
168
|
|
|
126
|
-
const localDestination = new DestinationLocal(
|
|
127
|
-
logLevel: 'debug' // Optional: filter by minimum log level
|
|
128
|
-
});
|
|
129
|
-
|
|
169
|
+
const localDestination = new DestinationLocal();
|
|
130
170
|
logger.addLogDestination(localDestination);
|
|
171
|
+
|
|
172
|
+
// Output is color-coded per log level:
|
|
173
|
+
// 🔵 info: blue prefix, white text
|
|
174
|
+
// 🔴 error: red prefix, red text
|
|
175
|
+
// 🟢 ok/success: green prefix, green text
|
|
176
|
+
// 🟠 warn: orange prefix, orange text
|
|
177
|
+
// 🟣 note/debug: pink prefix, pink text
|
|
178
|
+
// 🔵 silly: blue background, blue text
|
|
179
|
+
```
|
|
180
|
+
|
|
181
|
+
The `DestinationLocal` also supports **reduced logging** — a mode where repeated identical log messages are suppressed:
|
|
182
|
+
|
|
183
|
+
```typescript
|
|
184
|
+
const localDest = new DestinationLocal();
|
|
185
|
+
|
|
186
|
+
localDest.logReduced('Waiting for connection...'); // Logged
|
|
187
|
+
localDest.logReduced('Waiting for connection...'); // Suppressed
|
|
188
|
+
localDest.logReduced('Waiting for connection...'); // Suppressed
|
|
189
|
+
localDest.logReduced('Connected!'); // Logged (new message)
|
|
131
190
|
```
|
|
132
191
|
|
|
133
192
|
#### 📁 File Logging
|
|
134
193
|
|
|
135
|
-
Persist logs to files with
|
|
194
|
+
Persist logs to files with timestamped entries:
|
|
136
195
|
|
|
137
196
|
```typescript
|
|
138
197
|
import { SmartlogDestinationFile } from '@push.rocks/smartlog/destination-file';
|
|
139
198
|
|
|
140
|
-
|
|
199
|
+
// Path MUST be absolute
|
|
200
|
+
const fileDestination = new SmartlogDestinationFile('/var/log/myapp/app.log');
|
|
141
201
|
logger.addLogDestination(fileDestination);
|
|
202
|
+
|
|
203
|
+
// Log entries are written as timestamped lines:
|
|
204
|
+
// 2024-01-15T10:30:00.000Z: Application started
|
|
205
|
+
// 2024-01-15T10:30:01.123Z: Processing request
|
|
142
206
|
```
|
|
143
207
|
|
|
144
208
|
#### 🌐 Browser DevTools
|
|
@@ -150,60 +214,54 @@ import { SmartlogDestinationDevtools } from '@push.rocks/smartlog/destination-de
|
|
|
150
214
|
|
|
151
215
|
const devtools = new SmartlogDestinationDevtools();
|
|
152
216
|
logger.addLogDestination(devtools);
|
|
217
|
+
|
|
218
|
+
// Uses CSS styling in browser console for beautiful, categorized output
|
|
219
|
+
// Different colors for error (red), info (pink), ok (green), success (green),
|
|
220
|
+
// warn (orange), and note (blue) levels
|
|
153
221
|
```
|
|
154
222
|
|
|
155
223
|
#### 📊 ClickHouse Analytics
|
|
156
224
|
|
|
157
|
-
Store logs in ClickHouse for powerful analytics:
|
|
225
|
+
Store logs in ClickHouse for powerful time-series analytics:
|
|
158
226
|
|
|
159
227
|
```typescript
|
|
160
228
|
import { SmartlogDestinationClickhouse } from '@push.rocks/smartlog/destination-clickhouse';
|
|
161
229
|
|
|
162
230
|
const clickhouse = await SmartlogDestinationClickhouse.createAndStart({
|
|
163
|
-
|
|
164
|
-
port: 8123,
|
|
231
|
+
url: 'https://analytics.example.com:8123',
|
|
165
232
|
database: 'logs',
|
|
166
|
-
|
|
233
|
+
username: 'logger',
|
|
167
234
|
password: process.env.CLICKHOUSE_PASSWORD
|
|
168
235
|
});
|
|
169
236
|
|
|
170
237
|
logger.addLogDestination(clickhouse);
|
|
171
|
-
|
|
172
|
-
// Query your logs with SQL!
|
|
173
|
-
// SELECT * FROM logs WHERE level = 'error' AND timestamp > now() - INTERVAL 1 HOUR
|
|
174
238
|
```
|
|
175
239
|
|
|
176
240
|
#### 🔗 Remote Receiver
|
|
177
241
|
|
|
178
|
-
Send logs to a centralized logging service:
|
|
242
|
+
Send logs to a centralized logging service with authenticated transport:
|
|
179
243
|
|
|
180
244
|
```typescript
|
|
181
245
|
import { SmartlogDestinationReceiver } from '@push.rocks/smartlog/destination-receiver';
|
|
182
246
|
|
|
183
247
|
const receiver = new SmartlogDestinationReceiver({
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
batchSize: 100, // Send logs in batches
|
|
187
|
-
flushInterval: 5000 // Flush every 5 seconds
|
|
248
|
+
passphrase: process.env.LOG_PASSPHRASE,
|
|
249
|
+
receiverEndpoint: 'https://logs.mycompany.com/ingest'
|
|
188
250
|
});
|
|
189
251
|
|
|
190
252
|
logger.addLogDestination(receiver);
|
|
191
253
|
```
|
|
192
254
|
|
|
255
|
+
Logs are sent as authenticated JSON payloads with SHA-256 hashed passphrases.
|
|
256
|
+
|
|
193
257
|
### 🛠️ Custom Destinations
|
|
194
258
|
|
|
195
|
-
Build your own destination for any logging backend:
|
|
259
|
+
Build your own destination for any logging backend by implementing the `ILogDestination` interface:
|
|
196
260
|
|
|
197
261
|
```typescript
|
|
198
|
-
import { ILogDestination, ILogPackage } from '@push.rocks/smartlog/interfaces';
|
|
262
|
+
import type { ILogDestination, ILogPackage } from '@push.rocks/smartlog/interfaces';
|
|
199
263
|
|
|
200
264
|
class ElasticsearchDestination implements ILogDestination {
|
|
201
|
-
private client: ElasticsearchClient;
|
|
202
|
-
|
|
203
|
-
constructor(config: ElasticsearchConfig) {
|
|
204
|
-
this.client = new ElasticsearchClient(config);
|
|
205
|
-
}
|
|
206
|
-
|
|
207
265
|
async handleLog(logPackage: ILogPackage): Promise<void> {
|
|
208
266
|
await this.client.index({
|
|
209
267
|
index: `logs-${new Date().toISOString().split('T')[0]}`,
|
|
@@ -219,10 +277,7 @@ class ElasticsearchDestination implements ILogDestination {
|
|
|
219
277
|
}
|
|
220
278
|
}
|
|
221
279
|
|
|
222
|
-
|
|
223
|
-
logger.addLogDestination(new ElasticsearchDestination({
|
|
224
|
-
node: 'https://elasticsearch.example.com'
|
|
225
|
-
}));
|
|
280
|
+
logger.addLogDestination(new ElasticsearchDestination());
|
|
226
281
|
```
|
|
227
282
|
|
|
228
283
|
## 🎨 Interactive Console Features
|
|
@@ -241,19 +296,20 @@ spinner.text('🔄 Fetching data from API...');
|
|
|
241
296
|
// ... perform async operation
|
|
242
297
|
spinner.finishSuccess('✅ Data fetched successfully!');
|
|
243
298
|
|
|
244
|
-
//
|
|
245
|
-
spinner
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
299
|
+
// Chain success and move to next task
|
|
300
|
+
spinner.text('📡 Connecting to database');
|
|
301
|
+
// ... connect
|
|
302
|
+
spinner.successAndNext('🔍 Running migrations');
|
|
303
|
+
// ... migrate
|
|
304
|
+
spinner.finishSuccess('🎉 Database ready!');
|
|
250
305
|
|
|
251
306
|
// Customize appearance
|
|
252
307
|
spinner
|
|
253
|
-
.setSpinnerStyle('dots') // dots
|
|
308
|
+
.setSpinnerStyle('dots') // 'dots' | 'line' | 'star' | 'simple'
|
|
254
309
|
.setColor('cyan') // any terminal color
|
|
255
|
-
.setSpeed(80) // animation speed in ms
|
|
256
|
-
|
|
310
|
+
.setSpeed(80); // animation speed in ms
|
|
311
|
+
|
|
312
|
+
spinner.text('🚀 Deploying application...');
|
|
257
313
|
|
|
258
314
|
// Handle failures
|
|
259
315
|
try {
|
|
@@ -274,12 +330,12 @@ import { SmartlogProgressBar } from '@push.rocks/smartlog/source-interactive';
|
|
|
274
330
|
// Create a progress bar
|
|
275
331
|
const progress = new SmartlogProgressBar({
|
|
276
332
|
total: 100,
|
|
277
|
-
width: 40,
|
|
278
|
-
complete: '█',
|
|
279
|
-
incomplete: '░',
|
|
280
|
-
showEta: true,
|
|
281
|
-
showPercent: true,
|
|
282
|
-
showCount: true
|
|
333
|
+
width: 40, // Bar width in characters
|
|
334
|
+
complete: '█', // Fill character
|
|
335
|
+
incomplete: '░', // Empty character
|
|
336
|
+
showEta: true, // Show estimated time remaining
|
|
337
|
+
showPercent: true, // Show percentage
|
|
338
|
+
showCount: true // Show current/total count
|
|
283
339
|
});
|
|
284
340
|
|
|
285
341
|
// Update progress
|
|
@@ -290,22 +346,21 @@ for (let i = 0; i <= 100; i++) {
|
|
|
290
346
|
|
|
291
347
|
progress.complete();
|
|
292
348
|
|
|
293
|
-
//
|
|
349
|
+
// Or use increment for simpler tracking
|
|
294
350
|
const files = await getFiles();
|
|
295
|
-
const
|
|
296
|
-
total: files.length,
|
|
297
|
-
width: 50
|
|
298
|
-
});
|
|
351
|
+
const fileProgress = new SmartlogProgressBar({ total: files.length });
|
|
299
352
|
|
|
300
|
-
for (const
|
|
353
|
+
for (const file of files) {
|
|
301
354
|
await processFile(file);
|
|
302
|
-
|
|
355
|
+
fileProgress.increment();
|
|
303
356
|
}
|
|
357
|
+
|
|
358
|
+
fileProgress.complete();
|
|
304
359
|
```
|
|
305
360
|
|
|
306
361
|
### Non-Interactive Fallback
|
|
307
362
|
|
|
308
|
-
Both spinners and progress bars automatically detect non-interactive environments (CI/CD, Docker logs, piped output) and
|
|
363
|
+
Both spinners and progress bars automatically detect non-interactive environments (CI/CD, Docker logs, piped output) and fall back to simple text output:
|
|
309
364
|
|
|
310
365
|
```
|
|
311
366
|
[Loading] Connecting to database
|
|
@@ -314,86 +369,96 @@ Both spinners and progress bars automatically detect non-interactive environment
|
|
|
314
369
|
Progress: 25% (25/100)
|
|
315
370
|
Progress: 50% (50/100)
|
|
316
371
|
Progress: 100% (100/100)
|
|
317
|
-
|
|
372
|
+
Completed: 100% (100/100)
|
|
318
373
|
```
|
|
319
374
|
|
|
320
|
-
|
|
375
|
+
Detection checks for: TTY capability, CI environment variables (GitHub Actions, Jenkins, GitLab CI, Travis, CircleCI), and `TERM=dumb`.
|
|
321
376
|
|
|
322
|
-
###
|
|
377
|
+
### Backward Compatibility
|
|
323
378
|
|
|
324
|
-
|
|
379
|
+
The `SmartlogSourceOra` class extends `SmartlogSourceInteractive` and provides a compatibility layer for code that previously used the `ora` npm package:
|
|
325
380
|
|
|
326
381
|
```typescript
|
|
327
|
-
|
|
328
|
-
logger.addLogContext({
|
|
329
|
-
requestId: 'req-123',
|
|
330
|
-
userId: 'user-456',
|
|
331
|
-
feature: 'payment-processing'
|
|
332
|
-
});
|
|
382
|
+
import { SmartlogSourceOra } from '@push.rocks/smartlog/source-interactive';
|
|
333
383
|
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
384
|
+
const ora = new SmartlogSourceOra();
|
|
385
|
+
ora.oraInstance.start();
|
|
386
|
+
ora.oraInstance.succeed('Done!');
|
|
337
387
|
```
|
|
338
388
|
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
Create scoped loggers for different components:
|
|
342
|
-
|
|
343
|
-
```typescript
|
|
344
|
-
const dbLogger = logger.createScope('database');
|
|
345
|
-
const apiLogger = logger.createScope('api');
|
|
346
|
-
|
|
347
|
-
dbLogger.log('info', 'Executing query');
|
|
348
|
-
apiLogger.log('info', 'Handling request');
|
|
349
|
-
// Logs include scope information for filtering
|
|
350
|
-
```
|
|
389
|
+
## 🔧 Advanced Features
|
|
351
390
|
|
|
352
|
-
### Minimum Log
|
|
391
|
+
### Minimum Log Level
|
|
353
392
|
|
|
354
|
-
|
|
393
|
+
Set a minimum log level that destinations can use to filter messages:
|
|
355
394
|
|
|
356
395
|
```typescript
|
|
357
396
|
const logger = new Smartlog({
|
|
358
|
-
logContext: { environment: 'production' },
|
|
359
|
-
minimumLogLevel: 'warn' //
|
|
397
|
+
logContext: { environment: 'production', runtime: 'node' },
|
|
398
|
+
minimumLogLevel: 'warn' // Destinations can check this to filter
|
|
360
399
|
});
|
|
361
400
|
|
|
362
|
-
//
|
|
363
|
-
|
|
364
|
-
logger.log('info', 'Regular info');
|
|
365
|
-
|
|
366
|
-
// These will be logged
|
|
367
|
-
logger.log('warn', 'Warning message');
|
|
368
|
-
logger.log('error', 'Error message');
|
|
401
|
+
// The minimumLogLevel is available as a public property
|
|
402
|
+
console.log(logger.minimumLogLevel); // 'warn'
|
|
369
403
|
```
|
|
370
404
|
|
|
371
405
|
### Increment Logging
|
|
372
406
|
|
|
373
|
-
|
|
407
|
+
Track metrics and counters alongside your logs:
|
|
374
408
|
|
|
375
409
|
```typescript
|
|
376
410
|
// Track API calls
|
|
377
411
|
logger.increment('info', 'api.requests', { endpoint: '/users', method: 'GET' });
|
|
378
|
-
logger.increment('info', 'api.requests', { endpoint: '/users', method: 'POST' });
|
|
379
412
|
|
|
380
|
-
// Track
|
|
413
|
+
// Track error types
|
|
381
414
|
logger.increment('error', 'payment.failed', { reason: 'insufficient_funds' });
|
|
382
|
-
logger.increment('error', 'payment.failed', { reason: 'card_declined' });
|
|
383
415
|
```
|
|
384
416
|
|
|
417
|
+
Increment logs are routed to all destinations with `type: 'increment'` so analytics backends can aggregate them.
|
|
418
|
+
|
|
385
419
|
### Capture All Console Output
|
|
386
420
|
|
|
387
|
-
Redirect all console.log and console.error through smartlog:
|
|
421
|
+
Redirect all `console.log` and `console.error` through smartlog:
|
|
388
422
|
|
|
389
423
|
```typescript
|
|
390
|
-
logger.enableConsole({
|
|
391
|
-
captureAll: true
|
|
424
|
+
logger.enableConsole({
|
|
425
|
+
captureAll: true
|
|
392
426
|
});
|
|
393
427
|
|
|
394
|
-
console.log('This goes through smartlog!');
|
|
395
|
-
console.error('This
|
|
396
|
-
|
|
428
|
+
console.log('This goes through smartlog as info!');
|
|
429
|
+
console.error('This goes through smartlog as error!');
|
|
430
|
+
|
|
431
|
+
// Strings containing "Error:" are automatically classified as error level
|
|
432
|
+
// All captured output is prefixed with "LOG =>" to prevent recursion
|
|
433
|
+
```
|
|
434
|
+
|
|
435
|
+
### Log Receiver Server
|
|
436
|
+
|
|
437
|
+
Accept authenticated log packages from remote services:
|
|
438
|
+
|
|
439
|
+
```typescript
|
|
440
|
+
import { SmartlogReceiver } from '@push.rocks/smartlog/receiver';
|
|
441
|
+
|
|
442
|
+
const receiver = new SmartlogReceiver({
|
|
443
|
+
smartlogInstance: logger,
|
|
444
|
+
passphrase: 'shared-secret',
|
|
445
|
+
validatorFunction: async (logPackage) => {
|
|
446
|
+
// Custom validation logic
|
|
447
|
+
return logPackage.context.company === 'MyCompany';
|
|
448
|
+
}
|
|
449
|
+
});
|
|
450
|
+
|
|
451
|
+
// Handle incoming authenticated log packages (e.g., from an HTTP endpoint)
|
|
452
|
+
app.post('/logs', async (req, res) => {
|
|
453
|
+
const result = await receiver.handleAuthenticatedLog(req.body);
|
|
454
|
+
res.json(result); // { status: 'ok' } or { status: 'error' }
|
|
455
|
+
});
|
|
456
|
+
|
|
457
|
+
// Or handle batches
|
|
458
|
+
app.post('/logs/batch', async (req, res) => {
|
|
459
|
+
await receiver.handleManyAuthenticatedLogs(req.body);
|
|
460
|
+
res.json({ status: 'ok' });
|
|
461
|
+
});
|
|
397
462
|
```
|
|
398
463
|
|
|
399
464
|
## 🏗️ Real-World Examples
|
|
@@ -403,6 +468,7 @@ console.error('This too!');
|
|
|
403
468
|
```typescript
|
|
404
469
|
import { Smartlog } from '@push.rocks/smartlog';
|
|
405
470
|
import { SmartlogDestinationClickhouse } from '@push.rocks/smartlog/destination-clickhouse';
|
|
471
|
+
import { DestinationLocal } from '@push.rocks/smartlog/destination-local';
|
|
406
472
|
|
|
407
473
|
// Initialize logger with service context
|
|
408
474
|
const logger = new Smartlog({
|
|
@@ -410,47 +476,39 @@ const logger = new Smartlog({
|
|
|
410
476
|
company: 'TechCorp',
|
|
411
477
|
companyunit: 'Platform',
|
|
412
478
|
containerName: 'user-service',
|
|
413
|
-
environment:
|
|
479
|
+
environment: 'production',
|
|
414
480
|
runtime: 'node',
|
|
415
|
-
zone:
|
|
481
|
+
zone: 'eu-central'
|
|
416
482
|
}
|
|
417
483
|
});
|
|
418
484
|
|
|
419
485
|
// Add ClickHouse for analytics
|
|
420
486
|
const clickhouse = await SmartlogDestinationClickhouse.createAndStart({
|
|
421
|
-
|
|
487
|
+
url: process.env.CLICKHOUSE_URL,
|
|
422
488
|
database: 'microservices_logs'
|
|
423
489
|
});
|
|
424
490
|
logger.addLogDestination(clickhouse);
|
|
425
491
|
|
|
426
|
-
//
|
|
427
|
-
|
|
428
|
-
logger.enableConsole();
|
|
429
|
-
}
|
|
492
|
+
// Add local console for container stdout
|
|
493
|
+
logger.addLogDestination(new DestinationLocal());
|
|
430
494
|
|
|
431
495
|
// Express middleware for request tracking
|
|
432
496
|
app.use((req, res, next) => {
|
|
433
|
-
const
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
// Attach logger to request
|
|
437
|
-
req.logger = logGroup;
|
|
438
|
-
|
|
439
|
-
// Log request
|
|
497
|
+
const logGroup = logger.createLogGroup(req.headers['x-request-id'] || 'unknown');
|
|
498
|
+
|
|
440
499
|
logGroup.log('info', 'Incoming request', {
|
|
441
500
|
method: req.method,
|
|
442
501
|
path: req.path,
|
|
443
502
|
ip: req.ip
|
|
444
503
|
});
|
|
445
|
-
|
|
446
|
-
// Track response
|
|
504
|
+
|
|
447
505
|
res.on('finish', () => {
|
|
448
506
|
logGroup.log('info', 'Request completed', {
|
|
449
507
|
statusCode: res.statusCode,
|
|
450
508
|
duration: Date.now() - req.startTime
|
|
451
509
|
});
|
|
452
510
|
});
|
|
453
|
-
|
|
511
|
+
|
|
454
512
|
next();
|
|
455
513
|
});
|
|
456
514
|
```
|
|
@@ -464,7 +522,8 @@ import { SmartlogSourceInteractive, SmartlogProgressBar } from '@push.rocks/smar
|
|
|
464
522
|
const logger = new Smartlog({
|
|
465
523
|
logContext: {
|
|
466
524
|
containerName: 'migration-tool',
|
|
467
|
-
environment: '
|
|
525
|
+
environment: 'local',
|
|
526
|
+
runtime: 'node'
|
|
468
527
|
}
|
|
469
528
|
});
|
|
470
529
|
|
|
@@ -472,32 +531,29 @@ logger.enableConsole();
|
|
|
472
531
|
|
|
473
532
|
async function migrateDatabase() {
|
|
474
533
|
const spinner = new SmartlogSourceInteractive();
|
|
475
|
-
|
|
476
|
-
// Connect to database
|
|
534
|
+
|
|
477
535
|
spinner.text('🔌 Connecting to database...');
|
|
478
536
|
await connectDB();
|
|
479
537
|
spinner.finishSuccess('✅ Connected to database');
|
|
480
|
-
|
|
481
|
-
// Get migrations
|
|
538
|
+
|
|
482
539
|
spinner.text('📋 Loading migrations...');
|
|
483
540
|
const migrations = await getMigrations();
|
|
484
541
|
spinner.finishSuccess(`✅ Found ${migrations.length} migrations`);
|
|
485
|
-
|
|
486
|
-
// Run migrations with progress bar
|
|
542
|
+
|
|
487
543
|
const progress = new SmartlogProgressBar({
|
|
488
544
|
total: migrations.length,
|
|
489
545
|
width: 40,
|
|
490
546
|
showEta: true
|
|
491
547
|
});
|
|
492
|
-
|
|
548
|
+
|
|
493
549
|
for (const [index, migration] of migrations.entries()) {
|
|
494
|
-
logger.log('info', `Running migration: ${migration.name}`);
|
|
550
|
+
await logger.log('info', `Running migration: ${migration.name}`);
|
|
495
551
|
await runMigration(migration);
|
|
496
552
|
progress.update(index + 1);
|
|
497
553
|
}
|
|
498
|
-
|
|
554
|
+
|
|
499
555
|
progress.complete();
|
|
500
|
-
logger.log('success', '🎉 All migrations completed successfully!');
|
|
556
|
+
await logger.log('success', '🎉 All migrations completed successfully!');
|
|
501
557
|
}
|
|
502
558
|
```
|
|
503
559
|
|
|
@@ -517,10 +573,10 @@ const logger = new Smartlog({
|
|
|
517
573
|
runtime: 'node',
|
|
518
574
|
zone: 'us-east-1'
|
|
519
575
|
},
|
|
520
|
-
minimumLogLevel: 'info'
|
|
576
|
+
minimumLogLevel: 'info'
|
|
521
577
|
});
|
|
522
578
|
|
|
523
|
-
//
|
|
579
|
+
// Color-coded console for container logs
|
|
524
580
|
logger.addLogDestination(new DestinationLocal());
|
|
525
581
|
|
|
526
582
|
// File for audit trail
|
|
@@ -528,221 +584,121 @@ logger.addLogDestination(new SmartlogDestinationFile('/var/log/app/audit.log'));
|
|
|
528
584
|
|
|
529
585
|
// Central logging service
|
|
530
586
|
logger.addLogDestination(new SmartlogDestinationReceiver({
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
batchSize: 100,
|
|
534
|
-
flushInterval: 5000
|
|
587
|
+
passphrase: process.env.LOG_PASSPHRASE,
|
|
588
|
+
receiverEndpoint: 'https://logs.enterprise.com/ingest'
|
|
535
589
|
}));
|
|
536
590
|
|
|
537
|
-
//
|
|
591
|
+
// Custom inline destination for critical alerts
|
|
538
592
|
logger.addLogDestination({
|
|
539
593
|
async handleLog(logPackage) {
|
|
540
594
|
if (logPackage.level === 'error' && logPackage.data?.critical) {
|
|
541
|
-
await
|
|
542
|
-
channel: 'ops-team',
|
|
543
|
-
message: `🚨 Critical error: ${logPackage.message}`,
|
|
544
|
-
data: logPackage
|
|
545
|
-
});
|
|
595
|
+
await sendSlackAlert(`🚨 Critical error: ${logPackage.message}`);
|
|
546
596
|
}
|
|
547
597
|
}
|
|
548
598
|
});
|
|
549
599
|
```
|
|
550
600
|
|
|
551
|
-
##
|
|
552
|
-
|
|
553
|
-
### PM2 Integration
|
|
554
|
-
|
|
555
|
-
```typescript
|
|
556
|
-
// ecosystem.config.js
|
|
557
|
-
module.exports = {
|
|
558
|
-
apps: [{
|
|
559
|
-
name: 'api',
|
|
560
|
-
script: './dist/index.js',
|
|
561
|
-
error_file: '/dev/null', // Disable PM2 error log
|
|
562
|
-
out_file: '/dev/null', // Disable PM2 out log
|
|
563
|
-
merge_logs: true,
|
|
564
|
-
env: {
|
|
565
|
-
NODE_ENV: 'production',
|
|
566
|
-
// smartlog handles all logging
|
|
567
|
-
}
|
|
568
|
-
}]
|
|
569
|
-
};
|
|
570
|
-
```
|
|
571
|
-
|
|
572
|
-
### Docker Integration
|
|
573
|
-
|
|
574
|
-
```dockerfile
|
|
575
|
-
FROM node:18-alpine
|
|
576
|
-
WORKDIR /app
|
|
577
|
-
COPY . .
|
|
578
|
-
RUN pnpm install --production
|
|
579
|
-
|
|
580
|
-
# smartlog handles structured logging
|
|
581
|
-
# No need for special log drivers
|
|
582
|
-
CMD ["node", "dist/index.js"]
|
|
583
|
-
```
|
|
584
|
-
|
|
585
|
-
```yaml
|
|
586
|
-
# docker-compose.yml
|
|
587
|
-
services:
|
|
588
|
-
app:
|
|
589
|
-
build: .
|
|
590
|
-
environment:
|
|
591
|
-
- NODE_ENV=production
|
|
592
|
-
# Logs are structured JSON, perfect for log aggregators
|
|
593
|
-
logging:
|
|
594
|
-
driver: "json-file"
|
|
595
|
-
options:
|
|
596
|
-
max-size: "10m"
|
|
597
|
-
max-file: "3"
|
|
598
|
-
```
|
|
599
|
-
|
|
600
|
-
## 🏆 Best Practices
|
|
601
|
+
## 📖 API Reference
|
|
601
602
|
|
|
602
|
-
###
|
|
603
|
+
### Smartlog Class
|
|
603
604
|
|
|
604
605
|
```typescript
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
logger.log('error', 'Failed to process payment', { orderId, error });
|
|
609
|
-
|
|
610
|
-
// ❌ Bad - everything is 'info'
|
|
611
|
-
logger.log('info', 'Server starting');
|
|
612
|
-
logger.log('info', 'Database connected');
|
|
613
|
-
logger.log('info', 'Error: payment failed');
|
|
614
|
-
```
|
|
606
|
+
class Smartlog {
|
|
607
|
+
// Static factory
|
|
608
|
+
static createForCommitinfo(commitinfo: ICommitInfo): Smartlog;
|
|
615
609
|
|
|
616
|
-
|
|
610
|
+
// Constructor
|
|
611
|
+
constructor(options: {
|
|
612
|
+
logContext: ILogContext;
|
|
613
|
+
minimumLogLevel?: TLogLevel; // default: 'silly'
|
|
614
|
+
});
|
|
617
615
|
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
endpoint: '/api/users',
|
|
622
|
-
statusCode: 500,
|
|
623
|
-
duration: 1234,
|
|
624
|
-
userId: 'usr_123',
|
|
625
|
-
errorCode: 'INTERNAL_ERROR'
|
|
626
|
-
});
|
|
616
|
+
// Logging
|
|
617
|
+
log(level: TLogLevel, message: string, data?: any, correlation?: ILogCorrelation): Promise<void>;
|
|
618
|
+
increment(level: TLogLevel, message: string, data?: any, correlation?: ILogCorrelation): void;
|
|
627
619
|
|
|
628
|
-
//
|
|
629
|
-
|
|
630
|
-
|
|
620
|
+
// Configuration
|
|
621
|
+
enableConsole(options?: { captureAll: boolean }): void;
|
|
622
|
+
addLogDestination(destination: ILogDestination): void;
|
|
631
623
|
|
|
632
|
-
|
|
624
|
+
// Correlation
|
|
625
|
+
createLogGroup(transactionId?: string): LogGroup;
|
|
633
626
|
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
async function processOrder(orderId: string) {
|
|
637
|
-
const logGroup = logger.createLogGroup(orderId);
|
|
638
|
-
|
|
639
|
-
logGroup.log('info', 'Processing order');
|
|
640
|
-
logGroup.log('debug', 'Validating items');
|
|
641
|
-
logGroup.log('info', 'Charging payment');
|
|
642
|
-
logGroup.log('success', 'Order processed');
|
|
643
|
-
}
|
|
627
|
+
// Forwarding (for receiver pattern)
|
|
628
|
+
handleLog(logPackage: ILogPackage): Promise<void>;
|
|
644
629
|
|
|
645
|
-
//
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
logger.log('info', `Charging payment for ${orderId}`);
|
|
630
|
+
// Instance identity
|
|
631
|
+
uniInstanceId: string;
|
|
632
|
+
logContext: ILogContext;
|
|
633
|
+
minimumLogLevel: TLogLevel;
|
|
650
634
|
}
|
|
651
635
|
```
|
|
652
636
|
|
|
653
|
-
###
|
|
637
|
+
### LogGroup Class
|
|
654
638
|
|
|
655
639
|
```typescript
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
// ... other context
|
|
661
|
-
},
|
|
662
|
-
minimumLogLevel: process.env.NODE_ENV === 'production' ? 'info' : 'silly'
|
|
663
|
-
});
|
|
640
|
+
class LogGroup {
|
|
641
|
+
groupId: string; // Auto-generated unique ID
|
|
642
|
+
transactionId: string; // The transaction ID passed at creation
|
|
643
|
+
smartlogRef: Smartlog; // Reference to the parent Smartlog
|
|
664
644
|
|
|
665
|
-
|
|
666
|
-
if (process.env.NODE_ENV === 'production') {
|
|
667
|
-
logger.addLogDestination(clickhouseDestination);
|
|
668
|
-
logger.addLogDestination(alertingDestination);
|
|
669
|
-
} else {
|
|
670
|
-
logger.enableConsole();
|
|
645
|
+
log(level: TLogLevel, message: string, data?: any): void;
|
|
671
646
|
}
|
|
672
647
|
```
|
|
673
648
|
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
### Smartlog Class
|
|
649
|
+
### ILogDestination Interface
|
|
677
650
|
|
|
678
651
|
```typescript
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
// Logging methods
|
|
683
|
-
log(level: TLogLevel, message: string, data?: any, correlation?: ILogCorrelation): void
|
|
684
|
-
increment(level: TLogLevel, key: string, data?: any): void
|
|
685
|
-
|
|
686
|
-
// Configuration
|
|
687
|
-
enableConsole(options?: IConsoleOptions): void
|
|
688
|
-
addLogDestination(destination: ILogDestination): void
|
|
689
|
-
addLogContext(context: Partial<ILogContext>): void
|
|
690
|
-
|
|
691
|
-
// Log groups
|
|
692
|
-
createLogGroup(transactionId?: string): LogGroup
|
|
693
|
-
createScope(scopeName: string): Smartlog
|
|
652
|
+
interface ILogDestination {
|
|
653
|
+
handleLog(logPackage: ILogPackage): Promise<void>;
|
|
694
654
|
}
|
|
695
655
|
```
|
|
696
656
|
|
|
697
|
-
###
|
|
657
|
+
### ILogPackage Interface
|
|
698
658
|
|
|
699
659
|
```typescript
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
| '
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
| 'error' // Error messages
|
|
709
|
-
| 'lifecycle' // Application lifecycle events
|
|
710
|
-
```
|
|
711
|
-
|
|
712
|
-
### Log Package Structure
|
|
713
|
-
|
|
714
|
-
```typescript
|
|
715
|
-
interface ILogPackage {
|
|
716
|
-
timestamp: number;
|
|
717
|
-
level: TLogLevel;
|
|
718
|
-
message: string;
|
|
719
|
-
data?: any;
|
|
720
|
-
context: ILogContext;
|
|
721
|
-
correlation?: ILogCorrelation;
|
|
660
|
+
interface ILogPackage<T = unknown> {
|
|
661
|
+
timestamp: number; // Unix timestamp in milliseconds
|
|
662
|
+
type: TLogType; // 'log' | 'increment' | 'gauge' | ...
|
|
663
|
+
context: ILogContext; // Environment context
|
|
664
|
+
level: TLogLevel; // Log severity
|
|
665
|
+
correlation: ILogCorrelation; // Correlation metadata
|
|
666
|
+
message: string; // The log message
|
|
667
|
+
data?: T; // Optional structured data
|
|
722
668
|
}
|
|
723
669
|
```
|
|
724
670
|
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
## 🤝 Contributing
|
|
671
|
+
### Available Log Levels
|
|
728
672
|
|
|
729
|
-
|
|
673
|
+
| Level | Description | Use Case |
|
|
674
|
+
|-------|-------------|----------|
|
|
675
|
+
| `silly` | Ultra-verbose | Function entry/exit, variable dumps |
|
|
676
|
+
| `debug` | Debug info | Development-time diagnostics |
|
|
677
|
+
| `info` | Informational | Standard operational messages |
|
|
678
|
+
| `note` | Notable events | Important but non-critical events |
|
|
679
|
+
| `ok` | Success confirmation | Health checks, validations |
|
|
680
|
+
| `success` | Major success | Completed operations |
|
|
681
|
+
| `warn` | Warnings | Degraded performance, approaching limits |
|
|
682
|
+
| `error` | Errors | Failures requiring attention |
|
|
683
|
+
| `lifecycle` | Lifecycle events | Start, stop, restart, deploy |
|
|
730
684
|
|
|
731
|
-
##
|
|
685
|
+
## License and Legal Information
|
|
732
686
|
|
|
733
|
-
This repository contains open-source code
|
|
687
|
+
This repository contains open-source code licensed under the MIT License. A copy of the license can be found in the [LICENSE](./LICENSE) file.
|
|
734
688
|
|
|
735
689
|
**Please note:** The MIT License does not grant permission to use the trade names, trademarks, service marks, or product names of the project, except as required for reasonable and customary use in describing the origin of the work and reproducing the content of the NOTICE file.
|
|
736
690
|
|
|
737
691
|
### Trademarks
|
|
738
692
|
|
|
739
|
-
This project is owned and maintained by Task Venture Capital GmbH. The names and logos associated with Task Venture Capital GmbH and any related products or services are trademarks of Task Venture Capital GmbH and are not included within the scope of the MIT license granted herein.
|
|
693
|
+
This project is owned and maintained by Task Venture Capital GmbH. The names and logos associated with Task Venture Capital GmbH and any related products or services are trademarks of Task Venture Capital GmbH or third parties, and are not included within the scope of the MIT license granted herein.
|
|
694
|
+
|
|
695
|
+
Use of these trademarks must comply with Task Venture Capital GmbH's Trademark Guidelines or the guidelines of the respective third-party owners, and any usage must be approved in writing. Third-party trademarks used herein are the property of their respective owners and used only in a descriptive manner, e.g. for an implementation of an API or similar.
|
|
740
696
|
|
|
741
697
|
### Company Information
|
|
742
698
|
|
|
743
|
-
Task Venture Capital GmbH
|
|
744
|
-
Registered at District
|
|
699
|
+
Task Venture Capital GmbH
|
|
700
|
+
Registered at District Court Bremen HRB 35230 HB, Germany
|
|
745
701
|
|
|
746
|
-
For any legal inquiries or
|
|
702
|
+
For any legal inquiries or further information, please contact us via email at hello@task.vc.
|
|
747
703
|
|
|
748
|
-
By using this repository, you acknowledge that you have read this section, agree to comply with its terms, and understand that the licensing of the code does not imply endorsement by Task Venture Capital GmbH of any derivative works.
|
|
704
|
+
By using this repository, you acknowledge that you have read this section, agree to comply with its terms, and understand that the licensing of the code does not imply endorsement by Task Venture Capital GmbH of any derivative works.
|