@rodit/rodit-auth-be 9.11.14

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.
@@ -0,0 +1,160 @@
1
+ /**
2
+ * Logging service
3
+ * Copyright (c) 2026 Discernible IO. All rights reserved.
4
+ */
5
+
6
+ const winston = require("winston");
7
+ const config = require('./configsdk');
8
+
9
+ const SERVICE_NAME = config.get("SERVICE_NAME");
10
+
11
+ // Custom format to standardize and enhance logs for monitoring
12
+ const monitoringFormat = winston.format.combine(
13
+ // Convert errors to serializable objects with proper stack traces
14
+ winston.format((info) => {
15
+ // Handle Error objects
16
+ if (info.error instanceof Error) {
17
+ info.error = {
18
+ message: info.error.message,
19
+ stack: info.error.stack,
20
+ name: info.error.name
21
+ };
22
+ }
23
+ // Standardize log level names to uppercase
24
+ if (info.level) {
25
+ info.level = info.level.toUpperCase();
26
+ }
27
+ // Add standard fields if not present
28
+ info.service_name = SERVICE_NAME;
29
+ info.context = info.context || {};
30
+ // Add hostname for better filtering
31
+ info.hostname = require('os').hostname();
32
+ return info;
33
+ })(),
34
+ // Convert to JSON with proper spacing
35
+ winston.format.json()
36
+ );
37
+
38
+ // Create the default logger: stdout JSON only (no file transports)
39
+ let currentLogger = winston.createLogger({
40
+ level: config.get("LOG_LEVEL", "debug"), // Configurable via config with fallback
41
+ format: monitoringFormat,
42
+ defaultMeta: { service_name: SERVICE_NAME },
43
+ levels: winston.config.npm.levels,
44
+ transports: [
45
+ new winston.transports.Console({
46
+ format: monitoringFormat
47
+ })
48
+ ],
49
+ });
50
+
51
+ // Add helper methods for consistent context logging
52
+ function attachHelpers(baseLogger) {
53
+ baseLogger.logWithContext = (level, message, context = {}, error = null) => {
54
+ baseLogger.log({
55
+ level,
56
+ message,
57
+ context,
58
+ ...(error && { error })
59
+ });
60
+ };
61
+
62
+ ['error', 'warn', 'info', 'debug'].forEach(level => {
63
+ baseLogger[`${level}WithContext`] = (message, context = {}, error = null) => {
64
+ baseLogger.logWithContext(level, message, context, error);
65
+ };
66
+
67
+ // Add conditional logging helpers to avoid verbose if-statements
68
+ baseLogger[`${level}If`] = (condition, message, context = {}, error = null) => {
69
+ if (condition) {
70
+ if (level === 'error') {
71
+ baseLogger[level](message, context, error);
72
+ } else {
73
+ baseLogger[level](message, context);
74
+ }
75
+ }
76
+ };
77
+
78
+ });
79
+
80
+ // Add metric function for monitoring style metrics
81
+ baseLogger.metric = (name, value, labels = {}) => {
82
+ baseLogger.debug(`METRIC: ${name}=${value}`, {
83
+ context: {
84
+ metric_name: name,
85
+ metric_value: value,
86
+ metric_labels: labels,
87
+ metric_type: 'gauge'
88
+ }
89
+ });
90
+ };
91
+
92
+ // Add helper to log error and metrics in a standardized way to avoid duplication
93
+ baseLogger.logErrorWithMetrics = (message, context = {}, error = null, metricName = 'error_count', metricLabels = {}) => {
94
+ baseLogger.errorWithContext(message, context, error);
95
+ baseLogger.metric(metricName, 1, {
96
+ error_type: error?.name || "Unknown",
97
+ error_message: error?.message?.substring(0, 100) || "Unknown",
98
+ ...metricLabels
99
+ });
100
+ };
101
+
102
+ /**
103
+ * Creates a standardized context object for logging
104
+ */
105
+ baseLogger.createLogContext = function(component, event, data = {}, error = null) {
106
+ return {
107
+ component,
108
+ event,
109
+ ...(error && { error: typeof error === 'string' ? error : error.message }),
110
+ ...data
111
+ };
112
+ };
113
+
114
+
115
+ return baseLogger;
116
+ }
117
+
118
+ currentLogger = attachHelpers(currentLogger);
119
+
120
+ // Allow consumers to inject their own logger that implements { error, warn, info, debug, log }
121
+ function setLogger(customLogger) {
122
+ if (!customLogger || typeof customLogger !== 'object') {
123
+ throw new Error('setLogger(customLogger) requires a logger object');
124
+ }
125
+ const required = ['error', 'warn', 'info', 'debug', 'log'];
126
+ const missing = required.filter(m => typeof customLogger[m] !== 'function');
127
+ if (missing.length) {
128
+ throw new Error(`Injected logger is missing methods: ${missing.join(', ')}`);
129
+ }
130
+ const previous = currentLogger;
131
+ currentLogger = attachHelpers(customLogger);
132
+ return previous;
133
+ }
134
+
135
+ // Export a stable facade that delegates to the current logger
136
+ const FORWARDED_METHODS = [
137
+ 'error',
138
+ 'warn',
139
+ 'info',
140
+ 'debug',
141
+ 'logWithContext',
142
+ 'errorWithContext',
143
+ 'warnWithContext',
144
+ 'infoWithContext',
145
+ 'debugWithContext',
146
+ 'metric',
147
+ 'logErrorWithMetrics',
148
+ 'createLogContext',
149
+ ];
150
+
151
+ const facade = {
152
+ setLogger,
153
+ get SERVICE_NAME() { return SERVICE_NAME; },
154
+ };
155
+
156
+ FORWARDED_METHODS.forEach((methodName) => {
157
+ facade[methodName] = (...args) => currentLogger[methodName](...args);
158
+ });
159
+
160
+ module.exports = facade;