@nm-logger/logger 1.2.2 → 1.2.4

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 CHANGED
@@ -1,4 +1,4 @@
1
- # @nm-logger/logger v1.2.2
1
+ # @nm-logger/logger v1.2.3
2
2
 
3
3
  Minimal JSON logger for Express:
4
4
 
@@ -12,7 +12,8 @@ Minimal JSON logger for Express:
12
12
  - S3: one JSON file per day per category, append (read+merge+put)
13
13
  - Previous day's local folder is removed when the date changes
14
14
  - `employee_id` taken from `req.user.employee_id || req.user.emp_code || req.user.id`
15
- - `baseDir` can be absolute (e.g. `/home/VE/hiveLogs`)
15
+ - `baseDir` can be absolute (e.g. `/home/logs`)
16
+
16
17
 
17
18
  Basic usage:
18
19
 
@@ -25,17 +26,23 @@ const nm_logger = new Logger(
25
26
  accessKeyId: process.env.AWS_ACCESS_KEY_ID,
26
27
  secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY,
27
28
  region: "us-east-1",
28
- bucket: "nmhive"
29
+ bucket: "bucket-name"
29
30
  },
30
31
  {
31
- baseDir: "/home/logger/logs",
32
+ baseDir: "/home/logs",
32
33
  uploadIntervalMs: 60_000,
33
34
  maskFields: ["aadhaar", "pan"]
34
35
  }
35
36
  );
36
37
 
38
+ Folder permission
39
+
40
+ - mkdir -p /home/logs
41
+ - chmod -R 777 /home/logs
42
+
37
43
  app.use(nm_logger.requestLoggerMiddleware());
38
44
  app.use("/api", routes);
39
45
  app.use(nm_logger.expressMiddleware());
40
46
  nm_logger.attachAxiosLogger(axios);
41
- ```
47
+
48
+ ```
package/package.json CHANGED
@@ -1 +1 @@
1
- {"name":"@nm-logger/logger","version":"1.2.2","description":"Express JSON logger with daily success/error/external logs, S3 append uploads, and configurable baseDir.","main":"index.js","types":"index.d.ts","license":"MIT","dependencies":{"@aws-sdk/client-s3":"^3.600.0","fs-extra":"^11.1.1"}}
1
+ {"name":"@nm-logger/logger","version":"1.2.4","description":"Express JSON logger with daily success/error/external logs, S3 append uploads, and configurable baseDir.","main":"index.js","types":"index.d.ts","license":"MIT","dependencies":{"@aws-sdk/client-s3":"^3.600.0","fs-extra":"^11.1.1"}}
package/src/LogWriter.js CHANGED
@@ -1,2 +1,57 @@
1
- const fs=require("fs-extra");const path=require("path");const{getDatePath,formatDate}=require("./utils");const MAP={success:"daily_logs_success.json",error:"daily_logs_error.json",external:"daily_logs_external.json"};
2
- class LogWriter{constructor(baseDir){this.baseDir=baseDir;}getFilePath(cat="success"){const{Y,M,D}=getDatePath();const fn=MAP[cat]||MAP.success;return path.join(this.baseDir,`${Y}/${M}/${D}/${fn}`);}async writeLog(log,cat="success"){const fp=this.getFilePath(cat);await fs.ensureDir(path.dirname(fp));let w={logs:[]};if(await fs.pathExists(fp)){try{const t=await fs.readFile(fp,"utf8");if(t.trim()){const p=JSON.parse(t);if(Array.isArray(p.logs))w.logs=p.logs;}}catch(_){}}w.logs.push({url:log.url||"",body:log.body||"",params:log.params||"",type:log.type||"",method:log.method||"",error:log.error||"",employee_id:log.employee_id||"",date:log.date||formatDate(new Date())});await fs.writeFile(fp,JSON.stringify(w,null,2),"utf8");return fp;}}module.exports=LogWriter;
1
+ const fs = require("fs-extra");
2
+ const path = require("path");
3
+ const { getDatePath, formatDate } = require("./utils");
4
+
5
+ const MAP = {
6
+ success: "daily_logs_success.json",
7
+ error: "daily_logs_error.json",
8
+ external: "daily_logs_external.json",
9
+ };
10
+
11
+ class LogWriter {
12
+ constructor(baseDir) {
13
+ this.baseDir = baseDir;
14
+ }
15
+
16
+ getFilePath(category = "success") {
17
+ const { Y, M, D } = getDatePath();
18
+ const fileName = MAP[category] || MAP.success;
19
+ return path.join(this.baseDir, `${Y}/${M}/${D}/${fileName}`);
20
+ }
21
+
22
+ async writeLog(log, category = "success") {
23
+ const filePath = this.getFilePath(category);
24
+ await fs.ensureDir(path.dirname(filePath));
25
+
26
+ let wrapper = { logs: [] };
27
+
28
+ if (await fs.pathExists(filePath)) {
29
+ try {
30
+ const txt = await fs.readFile(filePath, "utf8");
31
+ if (txt.trim()) {
32
+ const parsed = JSON.parse(txt);
33
+ if (Array.isArray(parsed.logs)) {
34
+ wrapper.logs = parsed.logs;
35
+ }
36
+ }
37
+ } catch (_) {}
38
+ }
39
+
40
+ wrapper.logs.push({
41
+ url: log.url || "",
42
+ body: log.body || "",
43
+ params: log.params || "",
44
+ response: log.response || "", // 👈 NEW: store external response if present
45
+ type: log.type || "",
46
+ method: log.method || "",
47
+ error: log.error || "",
48
+ employee_id: log.employee_id || "",
49
+ date: log.date || formatDate(new Date()),
50
+ });
51
+
52
+ await fs.writeFile(filePath, JSON.stringify(wrapper, null, 2), "utf8");
53
+ return filePath;
54
+ }
55
+ }
56
+
57
+ module.exports = LogWriter;
package/src/Logger.js CHANGED
@@ -1,11 +1,200 @@
1
- const LogWriter=require("./LogWriter");const Queue=require("./Queue");const S3Uploader=require("./S3Uploader");const DailyWatcher=require("./DailyWatcher");const{getApiType,maskSensitive}=require("./utils");const fs=require("fs-extra");const path=require("path");
2
- class Logger{constructor(s3cfg={},opt={}){let dir="logs";try{if(opt.baseDir){const r=path.resolve(opt.baseDir);fs.ensureDirSync(r);dir=r;}}catch(e){console.error("[@nm-logger] Invalid baseDir, fallback to ./logs",e.message);}this.baseDir=dir;this.logWriter=new LogWriter(this.baseDir);this.queue=new Queue();this.s3=new S3Uploader(s3cfg);this.maskFields=(opt.maskFields||[]).map(x=>String(x).toLowerCase());new DailyWatcher(this.baseDir,this.queue,this.s3,{uploadIntervalMs:opt.uploadIntervalMs||60000});}
3
- mask(v){return maskSensitive(v,this.maskFields);}
4
- buildBaseLog(req,employee_id=""){const url=req&&req.originalUrl||"";const body=req&&req.body||{};const params={params:req&&req.params||{},query:req&&req.query||{}};const mBody=this.mask(body);const mParams=this.mask(params);const method=(req&&req.method||"").toUpperCase();const emp=employee_id||(req&&req.user&&(req.user.employee_id||req.user.emp_code||req.user.id))||"";return{url,body:JSON.stringify(mBody||{}),params:JSON.stringify(mParams||{}),type:getApiType(url),method,error:"",employee_id:emp};}
5
- async logError(err,req,employee_id=""){const base=this.buildBaseLog(req||{},employee_id);const d={...base,error:err&&err.message?err.message:String(err||"")};await this.logWriter.writeLog(d,"error");}
6
- async logRequest(req,employee_id=""){const d=this.buildBaseLog(req,employee_id);await this.logWriter.writeLog(d,"success");}
7
- async logExternalApi({url,method,data,params,error,employeeId}){const mb=this.mask(data||{});const mp=this.mask(params||{});const d={url:url||"",body:JSON.stringify(mb||{}),params:JSON.stringify(mp||{}),type:"external_api",method:(method||"").toUpperCase(),error:error||"",employee_id:employeeId||""};await this.logWriter.writeLog(d,"external");}
8
- expressMiddleware(){return(err,req,res,next)=>{try{this.logError(err,req).catch(()=>{});}catch(_){ }next(err);};}
9
- requestLoggerMiddleware(){return(req,res,next)=>{try{if(!req.__nm_logger_logged){req.__nm_logger_logged=true;this.logRequest(req).catch(()=>{});}}catch(_){ }next();};}
10
- attachAxiosLogger(ax){if(!ax||!ax.interceptors)return;ax.interceptors.response.use(r=>{try{const c=r.config||{};this.logExternalApi({url:c.url,method:c.method,data:c.data,params:c.params,error:null,employeeId:c.employee_id}).catch(()=>{});}catch(_){ }return r;},err=>{try{const c=err.config||{};this.logExternalApi({url:c&&c.url,method:c&&c.method,data:c&&c.data,params:c&&c.params,error:err&&err.message,employeeId:c&&c.employee_id}).catch(()=>{});}catch(_){ }return Promise.reject(err);});}}
11
- module.exports=Logger;
1
+ const LogWriter = require("./LogWriter");
2
+ const Queue = require("./Queue");
3
+ const S3Uploader = require("./S3Uploader");
4
+ const DailyWatcher = require("./DailyWatcher");
5
+ const { getApiType, maskSensitive } = require("./utils");
6
+ const fs = require("fs-extra");
7
+ const path = require("path");
8
+
9
+ class Logger {
10
+ constructor(s3cfg = {}, opt = {}) {
11
+ let dir = null;
12
+
13
+ try {
14
+ if (opt.baseDir) {
15
+ const resolved = path.resolve(opt.baseDir);
16
+ const parent = path.dirname(resolved);
17
+
18
+ // ensure parent + dir exist
19
+ fs.ensureDirSync(parent);
20
+ fs.ensureDirSync(resolved);
21
+
22
+ dir = resolved;
23
+ console.log("[nm-logger] ✔ Using baseDir:", dir);
24
+ }
25
+ } catch (e) {
26
+ console.error("[nm-logger] ❌ baseDir INVALID:", e.message);
27
+ }
28
+
29
+ if (!dir) {
30
+ dir = path.resolve("logs");
31
+ fs.ensureDirSync(dir);
32
+ console.error("[nm-logger] ⚠ Falling back to:", dir);
33
+ }
34
+
35
+ this.baseDir = dir;
36
+ this.logWriter = new LogWriter(this.baseDir);
37
+ this.queue = new Queue();
38
+ this.s3 = new S3Uploader(s3cfg);
39
+ this.maskFields = (opt.maskFields || []).map((x) =>
40
+ String(x).toLowerCase()
41
+ );
42
+
43
+ new DailyWatcher(this.baseDir, this.queue, this.s3, {
44
+ uploadIntervalMs: opt.uploadIntervalMs || 60_000,
45
+ });
46
+ }
47
+
48
+ // Mask helper
49
+ mask(v) {
50
+ return maskSensitive(v, this.maskFields);
51
+ }
52
+
53
+ // Build base log object for success/error logs
54
+ buildBaseLog(req, employee_id = "") {
55
+ const url = req && req.originalUrl ? req.originalUrl : "";
56
+ const body = (req && req.body) || {};
57
+ const params = {
58
+ params: (req && req.params) || {},
59
+ query: (req && req.query) || {},
60
+ };
61
+
62
+ const maskedBody = this.mask(body);
63
+ const maskedParams = this.mask(params);
64
+ const method = (req && req.method ? req.method : "").toUpperCase();
65
+
66
+ const emp =
67
+ employee_id ||
68
+ req?.employee_id ||
69
+ (req &&
70
+ req.user &&
71
+ (req.user.employee_id || req.user.emp_code || req.user.id)) ||
72
+ "";
73
+
74
+ return {
75
+ url,
76
+ body: JSON.stringify(maskedBody || {}),
77
+ params: JSON.stringify(maskedParams || {}),
78
+ type: getApiType(url),
79
+ method,
80
+ error: "",
81
+ employee_id: emp,
82
+ };
83
+ }
84
+
85
+ // ---- Error logging (Express errors) ----
86
+ async logError(err, req, employee_id = "") {
87
+ const base = this.buildBaseLog(req || {}, employee_id);
88
+
89
+ const log = {
90
+ ...base,
91
+ error: err && err.message ? err.message : String(err || ""),
92
+ };
93
+
94
+ await this.logWriter.writeLog(log, "error");
95
+ }
96
+
97
+ // ---- Success logging (normal requests) ----
98
+ async logRequest(req, employee_id = "") {
99
+ const log = this.buildBaseLog(req, employee_id);
100
+ await this.logWriter.writeLog(log, "success");
101
+ }
102
+
103
+ // ---- External API logging (Axios) ----
104
+ async logExternalApi({
105
+ url,
106
+ method,
107
+ data,
108
+ params,
109
+ error,
110
+ employeeId,
111
+ response, // 👈 NEW: store external API response
112
+ }) {
113
+ const maskedBody = this.mask(data || {});
114
+ const maskedParams = this.mask(params || {});
115
+ const maskedResponse = this.mask(response || {});
116
+
117
+ const log = {
118
+ url: url || "",
119
+ body: JSON.stringify(maskedBody || {}),
120
+ params: JSON.stringify(maskedParams || {}),
121
+ response: JSON.stringify(maskedResponse || {}), // 👈 NEW FIELD
122
+ type: "external_api",
123
+ method: (method || "").toUpperCase(),
124
+ error: error || "",
125
+ employee_id: employeeId || "",
126
+ };
127
+
128
+ await this.logWriter.writeLog(log, "external");
129
+ }
130
+
131
+ // ---- Express error middleware ----
132
+ expressMiddleware() {
133
+ return (err, req, res, next) => {
134
+ try {
135
+ this.logError(err, req).catch(() => {});
136
+ } catch (_) {}
137
+ next(err);
138
+ };
139
+ }
140
+
141
+ // ---- Request logger middleware (once per request) ----
142
+ requestLoggerMiddleware() {
143
+ return (req, res, next) => {
144
+ try {
145
+ if (!req.__nm_logger_logged) {
146
+ req.__nm_logger_logged = true;
147
+ this.logRequest(req).catch(() => {});
148
+ }
149
+ } catch (_) {}
150
+ next();
151
+ };
152
+ }
153
+
154
+ // ---- Axios interceptor ----
155
+ attachAxiosLogger(axiosInstance) {
156
+ if (!axiosInstance || !axiosInstance.interceptors) return;
157
+
158
+ // Success response
159
+ axiosInstance.interceptors.response.use(
160
+ (response) => {
161
+ try {
162
+ const cfg = response.config || {};
163
+ this.logExternalApi({
164
+ url: cfg.url,
165
+ method: cfg.method,
166
+ data: cfg.data,
167
+ params: cfg.params,
168
+ response: response.data, // 👈 log external API response body
169
+ error: null,
170
+ employeeId: cfg.employee_id,
171
+ }).catch(() => {});
172
+ } catch (_) {}
173
+
174
+ return response;
175
+ },
176
+
177
+ // Error response
178
+ (error) => {
179
+ try {
180
+ const cfg = (error && error.config) || {};
181
+ const res = error && error.response;
182
+
183
+ this.logExternalApi({
184
+ url: cfg && cfg.url,
185
+ method: cfg && cfg.method,
186
+ data: cfg && cfg.data,
187
+ params: cfg && cfg.params,
188
+ response: res && res.data, // 👈 log response even on error
189
+ error: error && error.message,
190
+ employeeId: cfg && cfg.employee_id,
191
+ }).catch(() => {});
192
+ } catch (_) {}
193
+
194
+ return Promise.reject(error);
195
+ }
196
+ );
197
+ }
198
+ }
199
+
200
+ module.exports = Logger;