@log-ingestor/mssql 0.0.1 → 0.2.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/LICENSE +21 -0
- package/README.md +164 -0
- package/bin/darwin-arm64/ingestor-darwin +0 -0
- package/bin/linux-amd64/ingestor-linux +0 -0
- package/bin/win/ingestor-win.exe +0 -0
- package/package.json +36 -5
- package/src/config.js +24 -0
- package/src/index.js +9 -0
- package/src/ingestor.js +55 -0
- package/src/logger.js +19 -0
- package/index.js +0 -1
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Arit Vyas
|
|
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,164 @@
|
|
|
1
|
+
# @log-ingestor/mssql
|
|
2
|
+
|
|
3
|
+
Disk-first Node.js logger with automatic ingestion into Microsoft SQL Server — no ELK, no log management headaches.
|
|
4
|
+
|
|
5
|
+
This package is the **MSSQL adapter** for the `log-ingestor` ecosystem.
|
|
6
|
+
It writes structured logs to disk and reliably ingests them into **Microsoft SQL Server** using a high‑performance background ingestor.
|
|
7
|
+
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
## Why this exists
|
|
11
|
+
|
|
12
|
+
Most Node.js applications:
|
|
13
|
+
- Print logs to console
|
|
14
|
+
- Rotate files manually
|
|
15
|
+
- Lose logs on crashes
|
|
16
|
+
- Overpay for ELK
|
|
17
|
+
|
|
18
|
+
This solves that with a simple model:
|
|
19
|
+
|
|
20
|
+
**App → disk → background ingestor → MSSQL**
|
|
21
|
+
|
|
22
|
+
No Kafka. No ELK. No ops pain.
|
|
23
|
+
|
|
24
|
+
---
|
|
25
|
+
|
|
26
|
+
## Features
|
|
27
|
+
|
|
28
|
+
- Structured JSON logging
|
|
29
|
+
- Disk-first (crash-safe)
|
|
30
|
+
- Automatic background ingestion
|
|
31
|
+
- Batch inserts with retry
|
|
32
|
+
- Auto table creation
|
|
33
|
+
- One ingestor per process
|
|
34
|
+
- Production-ready defaults
|
|
35
|
+
|
|
36
|
+
---
|
|
37
|
+
|
|
38
|
+
## Installation
|
|
39
|
+
|
|
40
|
+
```bash
|
|
41
|
+
npm install @log-ingestor/mssql
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
---
|
|
45
|
+
|
|
46
|
+
## Basic Usage
|
|
47
|
+
|
|
48
|
+
```js
|
|
49
|
+
const { createLogger } = require("@log-ingestor/mssql");
|
|
50
|
+
|
|
51
|
+
const logger = createLogger({
|
|
52
|
+
service: {
|
|
53
|
+
name: "order-service",
|
|
54
|
+
version: "1.0.0"
|
|
55
|
+
},
|
|
56
|
+
logging: {
|
|
57
|
+
logDir: "./logs"
|
|
58
|
+
},
|
|
59
|
+
db: {
|
|
60
|
+
type: "mssql",
|
|
61
|
+
connection: process.env.MSSQL_CONNECTION
|
|
62
|
+
},
|
|
63
|
+
batch: {
|
|
64
|
+
size: 200
|
|
65
|
+
}
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
logger.info("order created", { orderId: 123 });
|
|
69
|
+
logger.error("payment failed", { reason: "timeout" });
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
That’s it.
|
|
73
|
+
The ingestor starts automatically in the background.
|
|
74
|
+
|
|
75
|
+
---
|
|
76
|
+
|
|
77
|
+
## How it works
|
|
78
|
+
|
|
79
|
+
1. Logs are written as JSON lines to disk
|
|
80
|
+
2. A background ingestor binary starts automatically
|
|
81
|
+
3. Logs are batched and inserted into MSSQL
|
|
82
|
+
4. Retries happen automatically on failure
|
|
83
|
+
|
|
84
|
+
Your app never blocks on DB writes.
|
|
85
|
+
|
|
86
|
+
---
|
|
87
|
+
|
|
88
|
+
## Configuration
|
|
89
|
+
|
|
90
|
+
### Logger options
|
|
91
|
+
|
|
92
|
+
```ts
|
|
93
|
+
{
|
|
94
|
+
service: {
|
|
95
|
+
name: string,
|
|
96
|
+
version?: string
|
|
97
|
+
},
|
|
98
|
+
logging: {
|
|
99
|
+
logDir?: string // default: ./logs
|
|
100
|
+
},
|
|
101
|
+
db: {
|
|
102
|
+
type: "mssql",
|
|
103
|
+
connection: string,
|
|
104
|
+
table?: string // default: unified_logs
|
|
105
|
+
},
|
|
106
|
+
batch?: {
|
|
107
|
+
size?: number // default: 200
|
|
108
|
+
maxRetries?: number // default: 3
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
---
|
|
114
|
+
|
|
115
|
+
## Output format (example)
|
|
116
|
+
|
|
117
|
+
```json
|
|
118
|
+
{
|
|
119
|
+
"logId": "uuid",
|
|
120
|
+
"timestamp": "2026-01-05T10:20:30.000Z",
|
|
121
|
+
"level": "INFO",
|
|
122
|
+
"service": {
|
|
123
|
+
"name": "order-service",
|
|
124
|
+
"version": "1.0.0"
|
|
125
|
+
},
|
|
126
|
+
"message": "order created",
|
|
127
|
+
"data": {
|
|
128
|
+
"orderId": 123
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
---
|
|
134
|
+
|
|
135
|
+
## Internal components
|
|
136
|
+
|
|
137
|
+
- **@log-ingestor/core** – shared logger logic
|
|
138
|
+
- **@log-ingestor/mssql** – MSSQL ingestion adapter
|
|
139
|
+
- **Ingestor binary** – high-performance background worker
|
|
140
|
+
|
|
141
|
+
---
|
|
142
|
+
|
|
143
|
+
## What this is NOT
|
|
144
|
+
|
|
145
|
+
- Not a console logger
|
|
146
|
+
- Not a replacement for application metrics
|
|
147
|
+
- Not an ELK stack
|
|
148
|
+
|
|
149
|
+
This is for **durable, queryable application logs**.
|
|
150
|
+
|
|
151
|
+
---
|
|
152
|
+
|
|
153
|
+
## Roadmap
|
|
154
|
+
|
|
155
|
+
- PostgreSQL adapter
|
|
156
|
+
- MySQL adapter
|
|
157
|
+
- MongoDB adapter
|
|
158
|
+
- DynamoDB adapter
|
|
159
|
+
|
|
160
|
+
---
|
|
161
|
+
|
|
162
|
+
## License
|
|
163
|
+
|
|
164
|
+
MIT
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
package/package.json
CHANGED
|
@@ -1,11 +1,42 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@log-ingestor/mssql",
|
|
3
|
-
"version": "0.0
|
|
4
|
-
"description": "
|
|
3
|
+
"version": "0.2.0",
|
|
4
|
+
"description": "Disk-first structured logger for Node.js with local ingestion to Microsoft SQL Server (MSSQL)",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"private": false,
|
|
7
|
-
"main": "index.js",
|
|
7
|
+
"main": "src/index.js",
|
|
8
8
|
"dependencies": {
|
|
9
|
-
"@log-ingestor/core": "^0.0
|
|
9
|
+
"@log-ingestor/core": "^0.2.0"
|
|
10
|
+
},
|
|
11
|
+
"files": [
|
|
12
|
+
"src",
|
|
13
|
+
"bin",
|
|
14
|
+
"README.md",
|
|
15
|
+
"LICENSE"
|
|
16
|
+
],
|
|
17
|
+
"keywords": [
|
|
18
|
+
"logger",
|
|
19
|
+
"logging",
|
|
20
|
+
"structured-logging",
|
|
21
|
+
"disk-logging",
|
|
22
|
+
"database-logging",
|
|
23
|
+
"node-logger",
|
|
24
|
+
"mssql",
|
|
25
|
+
"sql-server",
|
|
26
|
+
"enterprise-logging",
|
|
27
|
+
"backend-logging",
|
|
28
|
+
"durable-logging"
|
|
29
|
+
],
|
|
30
|
+
"author": "Arit Vyas <aritvyas@hotmail.com>",
|
|
31
|
+
"repository": {
|
|
32
|
+
"type": "git",
|
|
33
|
+
"url": "https://github.com/aritvyas/unified-logger-sdk.git"
|
|
34
|
+
},
|
|
35
|
+
"bugs": {
|
|
36
|
+
"url": "https://github.com/aritvyas/unified-logger-sdk/issues"
|
|
37
|
+
},
|
|
38
|
+
"homepage": "https://github.com/aritvyas/unified-logger-sdk#readme",
|
|
39
|
+
"engines": {
|
|
40
|
+
"node": ">=16"
|
|
10
41
|
}
|
|
11
|
-
}
|
|
42
|
+
}
|
package/src/config.js
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
function buildIngestorConfig({ logDir, db, batch }) {
|
|
2
|
+
if (!logDir) {
|
|
3
|
+
throw new Error("logDir is required");
|
|
4
|
+
}
|
|
5
|
+
|
|
6
|
+
if (!db?.type || !db?.connection) {
|
|
7
|
+
throw new Error("db.type and db.connection are required");
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
return {
|
|
11
|
+
logDir,
|
|
12
|
+
db: {
|
|
13
|
+
type: db.type,
|
|
14
|
+
connection: db.connection,
|
|
15
|
+
table: db.table || "unified_logs"
|
|
16
|
+
},
|
|
17
|
+
batch: {
|
|
18
|
+
size: batch?.size || 200,
|
|
19
|
+
maxRetries: batch?.maxRetries || 3
|
|
20
|
+
}
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
module.exports = { buildIngestorConfig };
|
package/src/index.js
ADDED
package/src/ingestor.js
ADDED
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
const os = require("os");
|
|
2
|
+
const fs = require("fs");
|
|
3
|
+
const path = require("path");
|
|
4
|
+
const { spawn } = require("child_process");
|
|
5
|
+
|
|
6
|
+
function resolveBinary() {
|
|
7
|
+
const platform = os.platform();
|
|
8
|
+
const arch = os.arch();
|
|
9
|
+
|
|
10
|
+
let binDir, binName;
|
|
11
|
+
|
|
12
|
+
if (platform === "win32") {
|
|
13
|
+
binDir = "win";
|
|
14
|
+
binName = "ingestor-win.exe";
|
|
15
|
+
} else if (platform === "linux" && arch === "x64") {
|
|
16
|
+
binDir = "linux-amd64";
|
|
17
|
+
binName = "ingestor-linux";
|
|
18
|
+
} else if (platform === "darwin" && arch === "arm64") {
|
|
19
|
+
binDir = "darwin-arm64";
|
|
20
|
+
binName = "ingestor-darwin";
|
|
21
|
+
} else {
|
|
22
|
+
throw new Error(`Unsupported platform: ${platform} ${arch}`);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
const pkgRoot = path.resolve(__dirname, "..");
|
|
26
|
+
const binPath = path.join(pkgRoot, "bin", binDir, binName);
|
|
27
|
+
|
|
28
|
+
if (!fs.existsSync(binPath)) {
|
|
29
|
+
throw new Error(`Ingestor binary not found at ${binPath}`);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
return binPath;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
function startIngestor(config) {
|
|
36
|
+
const bin = resolveBinary();
|
|
37
|
+
const cfgPath = path.join(process.cwd(), "ingestor.config.json");
|
|
38
|
+
|
|
39
|
+
fs.writeFileSync(cfgPath, JSON.stringify(config, null, 2));
|
|
40
|
+
|
|
41
|
+
const internalDir = path.join(process.cwd(), "logs", "_internal");
|
|
42
|
+
fs.mkdirSync(internalDir, { recursive: true });
|
|
43
|
+
|
|
44
|
+
const errLog = path.join(internalDir, "ingestor.err.log");
|
|
45
|
+
|
|
46
|
+
const proc = spawn(bin, [cfgPath], {
|
|
47
|
+
windowsHide: true,
|
|
48
|
+
stdio: ["ignore", "ignore", fs.openSync(errLog, "a")],
|
|
49
|
+
detached: true
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
proc.unref();
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
module.exports = { startIngestor };
|
package/src/logger.js
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
const { BaseLogger } = require("@log-ingestor/core");
|
|
2
|
+
const { startIngestor } = require("./ingestor");
|
|
3
|
+
const { buildIngestorConfig } = require("./config");
|
|
4
|
+
|
|
5
|
+
class Logger extends BaseLogger {
|
|
6
|
+
constructor(options) {
|
|
7
|
+
super(options);
|
|
8
|
+
|
|
9
|
+
const ingestorConfig = buildIngestorConfig({
|
|
10
|
+
logDir: options.logging?.logDir || "./logs",
|
|
11
|
+
db: options.db,
|
|
12
|
+
batch: options.batch
|
|
13
|
+
});
|
|
14
|
+
|
|
15
|
+
startIngestor(ingestorConfig);
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
module.exports = { Logger };
|
package/index.js
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
module.exports = {};
|