cordova-plugin-unvired-logger 0.0.10 → 0.0.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/package.json +1 -1
- package/plugin.xml +1 -1
- package/src/android/Logger.java +4 -4
- package/src/browser/Logger.js +7 -7
- package/src/electron/Logger.js +95 -88
- package/src/ios/Logger.swift +4 -4
- package/www/logger.js +1 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "cordova-plugin-unvired-logger",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.11",
|
|
4
4
|
"description": "A logger plugin for Electron, Android, Browser, and iOS that appends logs to log.txt files organized by user ID.",
|
|
5
5
|
"cordova": {
|
|
6
6
|
"id": "cordova-plugin-unvired-logger",
|
package/plugin.xml
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
<?xml version="1.0" encoding="UTF-8"?>
|
|
2
|
-
<plugin id="cordova-plugin-unvired-logger" version="0.0.
|
|
2
|
+
<plugin id="cordova-plugin-unvired-logger" version="0.0.11"
|
|
3
3
|
xmlns="http://apache.org/cordova/ns/plugins/1.0"
|
|
4
4
|
xmlns:android="http://schemas.android.com/apk/res/android">
|
|
5
5
|
|
package/src/android/Logger.java
CHANGED
|
@@ -21,7 +21,7 @@ public class Logger extends CordovaPlugin {
|
|
|
21
21
|
private static final String BACKUP_LOG_FILE_NAME = "log_backup.txt";
|
|
22
22
|
private static final long MAX_LOG_SIZE = 5 * 1024 * 1024; // 5MB
|
|
23
23
|
|
|
24
|
-
private String defaultLogLevel = "
|
|
24
|
+
private String defaultLogLevel = "important";
|
|
25
25
|
|
|
26
26
|
@Override
|
|
27
27
|
public boolean execute(String action, JSONArray args, final CallbackContext callbackContext) throws JSONException {
|
|
@@ -111,8 +111,8 @@ public class Logger extends CordovaPlugin {
|
|
|
111
111
|
private boolean shouldSkipLog(String level) {
|
|
112
112
|
String normLevel = level.toLowerCase();
|
|
113
113
|
String normDefault = defaultLogLevel.toLowerCase();
|
|
114
|
-
if (normDefault.equals("error") && (normLevel.equals("debug") || normLevel.equals("
|
|
115
|
-
if (normDefault.equals("
|
|
114
|
+
if (normDefault.equals("error") && (normLevel.equals("debug") || normLevel.equals("important"))) return true;
|
|
115
|
+
if (normDefault.equals("important") && normLevel.equals("debug")) return true;
|
|
116
116
|
return false;
|
|
117
117
|
}
|
|
118
118
|
|
|
@@ -229,7 +229,7 @@ public class Logger extends CordovaPlugin {
|
|
|
229
229
|
|
|
230
230
|
private String getStringFromLevel(String level) {
|
|
231
231
|
switch (level.toLowerCase()) {
|
|
232
|
-
case "
|
|
232
|
+
case "important": return "IMPORTANT";
|
|
233
233
|
case "error": return "ERROR";
|
|
234
234
|
case "debug": return "DEBUG";
|
|
235
235
|
default: return "";
|
package/src/browser/Logger.js
CHANGED
|
@@ -6,7 +6,7 @@ const MAX_LOG_SIZE = 5 * 1024 * 1024; // 5MB
|
|
|
6
6
|
const LogLevel = {
|
|
7
7
|
Debug: 'debug',
|
|
8
8
|
Error: 'error',
|
|
9
|
-
Info: '
|
|
9
|
+
Info: 'important',
|
|
10
10
|
};
|
|
11
11
|
|
|
12
12
|
let defaultLogLevel = LogLevel.Info;
|
|
@@ -29,12 +29,12 @@ module.exports.logInfo = async function (successCallback, errorCallback, args) {
|
|
|
29
29
|
|
|
30
30
|
module.exports.setLogLevel = function(successCallback, errorCallback, level) {
|
|
31
31
|
// If level is an array (from Cordova), extract the first element
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
successCallback("")
|
|
32
|
+
let levelToSet = Array.isArray(level) ? level[0] : level;
|
|
33
|
+
|
|
34
|
+
// Normalize the level to lowercase for consistency
|
|
35
|
+
defaultLogLevel = (levelToSet || '').toLowerCase();
|
|
36
|
+
|
|
37
|
+
successCallback("");
|
|
38
38
|
}
|
|
39
39
|
|
|
40
40
|
module.exports.getLogLevel = function(successCallback, errorCallback) {
|
package/src/electron/Logger.js
CHANGED
|
@@ -3,6 +3,35 @@ const path = require('path');
|
|
|
3
3
|
const fs = require('fs');
|
|
4
4
|
const fsPromises = fs.promises;
|
|
5
5
|
|
|
6
|
+
// --- Proper async lock for log file operations ---
|
|
7
|
+
let logLockPromise = Promise.resolve();
|
|
8
|
+
let isLocked = false;
|
|
9
|
+
|
|
10
|
+
async function withLogLock(fn) {
|
|
11
|
+
// Wait for any existing lock to complete
|
|
12
|
+
await logLockPromise;
|
|
13
|
+
|
|
14
|
+
// Create a new promise for this operation
|
|
15
|
+
const operationPromise = (async () => {
|
|
16
|
+
try {
|
|
17
|
+
isLocked = true;
|
|
18
|
+
const result = await fn();
|
|
19
|
+
return result;
|
|
20
|
+
} catch (error) {
|
|
21
|
+
console.error('[Logger] Error in log operation:', error);
|
|
22
|
+
// Return error message instead of throwing to prevent unhandled promise rejections
|
|
23
|
+
return `Error in log operation: ${error.message}`;
|
|
24
|
+
} finally {
|
|
25
|
+
isLocked = false;
|
|
26
|
+
}
|
|
27
|
+
})();
|
|
28
|
+
|
|
29
|
+
// Update the lock promise to wait for this operation
|
|
30
|
+
logLockPromise = operationPromise;
|
|
31
|
+
|
|
32
|
+
return operationPromise;
|
|
33
|
+
}
|
|
34
|
+
|
|
6
35
|
const LOG_FOLDER_NAME = 'log';
|
|
7
36
|
const LOG_FILE_NAME = 'log.txt';
|
|
8
37
|
const BACKUP_LOG_FILE_NAME = 'log_backup.txt';
|
|
@@ -10,7 +39,7 @@ const BACKUP_LOG_FILE_NAME = 'log_backup.txt';
|
|
|
10
39
|
const LogLevel = {
|
|
11
40
|
Debug: 'debug',
|
|
12
41
|
Error: 'error',
|
|
13
|
-
Info: '
|
|
42
|
+
Info: 'important',
|
|
14
43
|
};
|
|
15
44
|
|
|
16
45
|
let defaultLogLevel = LogLevel.Info;
|
|
@@ -29,15 +58,11 @@ function logInfo(args) {
|
|
|
29
58
|
}
|
|
30
59
|
|
|
31
60
|
function setLogLevel(level) {
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
defaultLogLevel = level;
|
|
38
|
-
}
|
|
39
|
-
resolve();
|
|
40
|
-
});
|
|
61
|
+
// If level is an array (from Cordova), extract the first element
|
|
62
|
+
let levelToSet = Array.isArray(level) ? level[0] : level;
|
|
63
|
+
|
|
64
|
+
// Normalize the level to lowercase for consistency
|
|
65
|
+
defaultLogLevel = (levelToSet || '').toLowerCase();
|
|
41
66
|
}
|
|
42
67
|
|
|
43
68
|
function getLogLevel() {
|
|
@@ -68,14 +93,10 @@ function getLogFileContent(args) {
|
|
|
68
93
|
}
|
|
69
94
|
|
|
70
95
|
function clearLogFile(args) {
|
|
71
|
-
return
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
resolve();
|
|
76
|
-
} catch (err) {
|
|
77
|
-
reject(new Error(`Failed to clear log file: ${err.message}`));
|
|
78
|
-
}
|
|
96
|
+
return withLogLock(async () => {
|
|
97
|
+
const logPath = getLogFileURL(args);
|
|
98
|
+
await fsPromises.writeFile(logPath, '');
|
|
99
|
+
return 'Log file cleared successfully';
|
|
79
100
|
});
|
|
80
101
|
}
|
|
81
102
|
|
|
@@ -101,69 +122,58 @@ function getBackupLogFileContent(args) {
|
|
|
101
122
|
}
|
|
102
123
|
|
|
103
124
|
function copyLogToBackup(args) {
|
|
104
|
-
return
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
resolve();
|
|
110
|
-
} catch (err) {
|
|
111
|
-
reject(new Error(`Failed to copy log file to backup: ${err.message}`));
|
|
112
|
-
}
|
|
125
|
+
return withLogLock(async () => {
|
|
126
|
+
const logPath = getLogFileURL(args);
|
|
127
|
+
const backupPath = getBackupLogFileURL(args);
|
|
128
|
+
await fsPromises.copyFile(logPath, backupPath);
|
|
129
|
+
return 'Log file copied to backup successfully';
|
|
113
130
|
});
|
|
114
131
|
}
|
|
115
132
|
|
|
116
133
|
function loggerWithLevel(args) {
|
|
117
|
-
return
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
(normalizedDefaultLogLevel === LogLevel.Info && normalizedLevel === LogLevel.Debug)
|
|
136
|
-
) {
|
|
137
|
-
return resolve();
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
await checkAndRotateLogFile(args);
|
|
134
|
+
return withLogLock(async () => {
|
|
135
|
+
if (!args || !args[0]) throw new Error("Invalid arguments provided");
|
|
136
|
+
const { userId, level, sourceClass, sourceMethod, message } = args[0];
|
|
137
|
+
if (!userId) throw new Error("userId is required");
|
|
138
|
+
if (!level) throw new Error("level is required");
|
|
139
|
+
if (!message) throw new Error("message is required");
|
|
140
|
+
|
|
141
|
+
// Normalize log levels for comparison
|
|
142
|
+
const normalizedDefaultLogLevel = (defaultLogLevel || '').toLowerCase();
|
|
143
|
+
const normalizedLevel = (level || '').toLowerCase();
|
|
144
|
+
|
|
145
|
+
// Log level filtering using normalized values
|
|
146
|
+
if (
|
|
147
|
+
(normalizedDefaultLogLevel === LogLevel.Error && (normalizedLevel === LogLevel.Debug || normalizedLevel === LogLevel.Info)) ||
|
|
148
|
+
(normalizedDefaultLogLevel === LogLevel.Info && normalizedLevel === LogLevel.Debug)
|
|
149
|
+
) {
|
|
150
|
+
return;
|
|
151
|
+
}
|
|
141
152
|
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
await fsPromises.appendFile(logPath, data, 'utf8');
|
|
163
|
-
resolve(`Logged to ${logPath}`);
|
|
164
|
-
} catch (err) {
|
|
165
|
-
reject(new Error(`Logging failed: ${err.message}`));
|
|
153
|
+
await checkAndRotateLogFile(args);
|
|
154
|
+
|
|
155
|
+
const logPath = getLogFileURL(args);
|
|
156
|
+
const currentDate = new Date();
|
|
157
|
+
const formatter = new Intl.DateTimeFormat('en-US', {
|
|
158
|
+
day: '2-digit', month: '2-digit', year: 'numeric',
|
|
159
|
+
hour: '2-digit', minute: '2-digit', second: '2-digit'
|
|
160
|
+
});
|
|
161
|
+
const localDateString = formatter.format(currentDate);
|
|
162
|
+
|
|
163
|
+
const dateUtc = new Date(currentDate.toUTCString());
|
|
164
|
+
const utcFormatter = new Intl.DateTimeFormat('en-US', {
|
|
165
|
+
day: '2-digit', month: '2-digit', year: 'numeric',
|
|
166
|
+
hour: '2-digit', minute: '2-digit', second: '2-digit', timeZone: 'UTC'
|
|
167
|
+
});
|
|
168
|
+
const utcDateString = utcFormatter.format(dateUtc);
|
|
169
|
+
|
|
170
|
+
let data = `${localDateString} | UTC:${utcDateString} | ${getStringFromLevel(level)} | ${sourceClass} | ${sourceMethod} | ${message}\n`;
|
|
171
|
+
if (level === LogLevel.Error) {
|
|
172
|
+
data = `⭕️⭕️⭕️ ${data}`;
|
|
166
173
|
}
|
|
174
|
+
console.log(data);
|
|
175
|
+
await fsPromises.appendFile(logPath, data, 'utf8');
|
|
176
|
+
return `Logged to ${logPath}`;
|
|
167
177
|
});
|
|
168
178
|
}
|
|
169
179
|
|
|
@@ -190,21 +200,18 @@ function getStringFromLevel(level) {
|
|
|
190
200
|
}
|
|
191
201
|
|
|
192
202
|
function checkAndRotateLogFile(args) {
|
|
193
|
-
return
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
}
|
|
203
|
+
return withLogLock(async () => {
|
|
204
|
+
const logPath = getLogFileURL(args);
|
|
205
|
+
if (fs.existsSync(logPath)) {
|
|
206
|
+
const stats = await fsPromises.stat(logPath);
|
|
207
|
+
if (stats.size > MAX_LOG_SIZE) {
|
|
208
|
+
const backupPath = getBackupLogFileURL(args);
|
|
209
|
+
await fsPromises.copyFile(logPath, backupPath);
|
|
210
|
+
await fsPromises.writeFile(logPath, '');
|
|
211
|
+
return 'Log file rotated due to size limit';
|
|
203
212
|
}
|
|
204
|
-
resolve();
|
|
205
|
-
} catch (err) {
|
|
206
|
-
reject(new Error(`Failed to rotate log file: ${err.message}`));
|
|
207
213
|
}
|
|
214
|
+
return 'Log file rotation check completed';
|
|
208
215
|
});
|
|
209
216
|
}
|
|
210
217
|
|
package/src/ios/Logger.swift
CHANGED
|
@@ -8,7 +8,7 @@ import UIKit
|
|
|
8
8
|
private let BACKUP_LOG_FILE_NAME = "log_backup.txt"
|
|
9
9
|
private let MAX_LOG_SIZE: Int64 = 5 * 1024 * 1024 // 5MB
|
|
10
10
|
|
|
11
|
-
private var defaultLogLevel: String = "
|
|
11
|
+
private var defaultLogLevel: String = "important"
|
|
12
12
|
|
|
13
13
|
@objc(logDebug:)
|
|
14
14
|
func logDebug(_ command: CDVInvokedUrlCommand) {
|
|
@@ -193,10 +193,10 @@ import UIKit
|
|
|
193
193
|
let normLevel = level.lowercased()
|
|
194
194
|
let normDefault = defaultLogLevel.lowercased()
|
|
195
195
|
|
|
196
|
-
if normDefault == "error" && (normLevel == "debug" || normLevel == "
|
|
196
|
+
if normDefault == "error" && (normLevel == "debug" || normLevel == "important") {
|
|
197
197
|
return true
|
|
198
198
|
}
|
|
199
|
-
if normDefault == "
|
|
199
|
+
if normDefault == "important" && normLevel == "debug" {
|
|
200
200
|
return true
|
|
201
201
|
}
|
|
202
202
|
return false
|
|
@@ -251,7 +251,7 @@ import UIKit
|
|
|
251
251
|
|
|
252
252
|
private func getStringFromLevel(level: String) -> String {
|
|
253
253
|
switch level.lowercased() {
|
|
254
|
-
case "
|
|
254
|
+
case "important": return "IMPORTANT"
|
|
255
255
|
case "error": return "ERROR"
|
|
256
256
|
case "debug": return "DEBUG"
|
|
257
257
|
default: return ""
|