cordova-plugin-unvired-logger 0.0.1
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 +272 -0
- package/package.json +26 -0
- package/plugin.xml +49 -0
- package/src/android/UnviredLogger.java +265 -0
- package/src/browser/Logger.js +242 -0
- package/src/electron/Logger.js +224 -0
- package/src/electron/package.json +31 -0
- package/src/ios/UnviredLogger.swift +291 -0
- package/www/logger.js +174 -0
package/README.md
ADDED
|
@@ -0,0 +1,272 @@
|
|
|
1
|
+
# Cordova Plugin Unvired Logger
|
|
2
|
+
|
|
3
|
+
A comprehensive Cordova plugin that provides advanced logging functionality with log levels, file management, and user-specific log organization. Supports Android, iOS, Electron, and Browser platforms.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
cordova plugin add cordova-plugin-unvired-logger
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Usage
|
|
12
|
+
|
|
13
|
+
### Basic Logging
|
|
14
|
+
|
|
15
|
+
```javascript
|
|
16
|
+
// Info log
|
|
17
|
+
Logger.logInfo("user123", "AuthService", "login", "User login successful",
|
|
18
|
+
function(success) {
|
|
19
|
+
console.log("Log saved:", success);
|
|
20
|
+
},
|
|
21
|
+
function(error) {
|
|
22
|
+
console.error("Logging failed:", error);
|
|
23
|
+
}
|
|
24
|
+
);
|
|
25
|
+
|
|
26
|
+
// Debug log
|
|
27
|
+
Logger.logDebug("user123", "UserService", "getUserData", "Fetching user data from API",
|
|
28
|
+
function(success) {
|
|
29
|
+
console.log("Debug log saved:", success);
|
|
30
|
+
},
|
|
31
|
+
function(error) {
|
|
32
|
+
console.error("Debug logging failed:", error);
|
|
33
|
+
}
|
|
34
|
+
);
|
|
35
|
+
|
|
36
|
+
// Error log
|
|
37
|
+
Logger.logError("user123", "UserService", "getUserData", "Failed to fetch user data: Network error",
|
|
38
|
+
function(success) {
|
|
39
|
+
console.log("Error log saved:", success);
|
|
40
|
+
},
|
|
41
|
+
function(error) {
|
|
42
|
+
console.error("Error logging failed:", error);
|
|
43
|
+
}
|
|
44
|
+
);
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
### Advanced Logging with Level
|
|
48
|
+
|
|
49
|
+
```javascript
|
|
50
|
+
Logger.loggerWithLevel("user123", "debug", "MyClass", "myMethod", "This is a debug message",
|
|
51
|
+
function(success) {
|
|
52
|
+
console.log("Log saved:", success);
|
|
53
|
+
},
|
|
54
|
+
function(error) {
|
|
55
|
+
console.error("Logging failed:", error);
|
|
56
|
+
}
|
|
57
|
+
);
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
### Log Level Management
|
|
61
|
+
|
|
62
|
+
```javascript
|
|
63
|
+
// Set log level to control which messages are logged
|
|
64
|
+
Logger.setLogLevel("debug", // Logs all levels
|
|
65
|
+
function(success) {
|
|
66
|
+
console.log("Log level set to Debug");
|
|
67
|
+
},
|
|
68
|
+
function(error) {
|
|
69
|
+
console.error("Failed to set log level:", error);
|
|
70
|
+
}
|
|
71
|
+
);
|
|
72
|
+
|
|
73
|
+
Logger.setLogLevel("info", // Logs Info and Error only
|
|
74
|
+
function(success) {
|
|
75
|
+
console.log("Log level set to Info");
|
|
76
|
+
},
|
|
77
|
+
function(error) {
|
|
78
|
+
console.error("Failed to set log level:", error);
|
|
79
|
+
}
|
|
80
|
+
);
|
|
81
|
+
|
|
82
|
+
Logger.setLogLevel("error", // Logs Error only
|
|
83
|
+
function(success) {
|
|
84
|
+
console.log("Log level set to Error");
|
|
85
|
+
},
|
|
86
|
+
function(error) {
|
|
87
|
+
console.error("Failed to set log level:", error);
|
|
88
|
+
}
|
|
89
|
+
);
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
### Log File Management
|
|
93
|
+
|
|
94
|
+
```javascript
|
|
95
|
+
// Get log file content
|
|
96
|
+
Logger.getLogFileContent("user123",
|
|
97
|
+
function(content) {
|
|
98
|
+
console.log("Log file content:", content);
|
|
99
|
+
},
|
|
100
|
+
function(error) {
|
|
101
|
+
console.error("Failed to read log file:", error);
|
|
102
|
+
}
|
|
103
|
+
);
|
|
104
|
+
|
|
105
|
+
// Clear log file
|
|
106
|
+
Logger.clearLogFile("user123",
|
|
107
|
+
function(success) {
|
|
108
|
+
console.log("Log file cleared successfully");
|
|
109
|
+
},
|
|
110
|
+
function(error) {
|
|
111
|
+
console.error("Failed to clear log file:", error);
|
|
112
|
+
}
|
|
113
|
+
);
|
|
114
|
+
|
|
115
|
+
// Get backup log file content (when log rotation occurs)
|
|
116
|
+
Logger.getBackupLogFileContent("user123",
|
|
117
|
+
function(content) {
|
|
118
|
+
console.log("Backup log file content:", content);
|
|
119
|
+
},
|
|
120
|
+
function(error) {
|
|
121
|
+
console.error("Failed to read backup log file:", error);
|
|
122
|
+
}
|
|
123
|
+
);
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
### Complete Test Example
|
|
127
|
+
|
|
128
|
+
```javascript
|
|
129
|
+
function testLogger() {
|
|
130
|
+
if (window && Logger) {
|
|
131
|
+
console.log("Testing UnviredLogger plugin...");
|
|
132
|
+
|
|
133
|
+
// Test basic logging
|
|
134
|
+
Logger.logInfo("testuser", "AuthService", "login", "User login successful",
|
|
135
|
+
function(success) {
|
|
136
|
+
console.log("Basic log success:", success);
|
|
137
|
+
|
|
138
|
+
// Test log level setting
|
|
139
|
+
Logger.setLogLevel("debug",
|
|
140
|
+
function() {
|
|
141
|
+
console.log("Log level set to Debug");
|
|
142
|
+
|
|
143
|
+
// Test convenience methods
|
|
144
|
+
Logger.logDebug("testuser", "TestClass", "testMethod", "Debug message test",
|
|
145
|
+
function() {
|
|
146
|
+
console.log("Debug log successful");
|
|
147
|
+
|
|
148
|
+
// Test reading log content
|
|
149
|
+
Logger.getLogFileContent("testuser",
|
|
150
|
+
function(content) {
|
|
151
|
+
console.log("Log file content:", content);
|
|
152
|
+
},
|
|
153
|
+
function(error) {
|
|
154
|
+
console.error("Failed to read log:", error);
|
|
155
|
+
}
|
|
156
|
+
);
|
|
157
|
+
},
|
|
158
|
+
function(error) {
|
|
159
|
+
console.error("Debug log failed:", error);
|
|
160
|
+
}
|
|
161
|
+
);
|
|
162
|
+
},
|
|
163
|
+
function(error) {
|
|
164
|
+
console.error("Failed to set log level:", error);
|
|
165
|
+
}
|
|
166
|
+
);
|
|
167
|
+
},
|
|
168
|
+
function(error) {
|
|
169
|
+
console.error("Basic log failed:", error);
|
|
170
|
+
}
|
|
171
|
+
);
|
|
172
|
+
} else {
|
|
173
|
+
console.warn("UnviredLogger not available.");
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
// Call the test function
|
|
178
|
+
testLogger();
|
|
179
|
+
```
|
|
180
|
+
|
|
181
|
+
## Supported Platforms
|
|
182
|
+
|
|
183
|
+
- **Android**: Native Java implementation with file system access
|
|
184
|
+
- **iOS**: Native Swift implementation with file system access
|
|
185
|
+
- **Electron**: Node.js implementation with file system access
|
|
186
|
+
- **Browser**: JavaScript implementation using localStorage
|
|
187
|
+
|
|
188
|
+
## Features
|
|
189
|
+
|
|
190
|
+
- **Advanced logging**: Log messages with class, method, and log level information
|
|
191
|
+
- **Log levels**: Debug, Info, and Error levels with filtering
|
|
192
|
+
- **User-specific logging**: Logs are organized by user ID
|
|
193
|
+
- **Automatic file creation**: Log files and directories are created automatically
|
|
194
|
+
- **Log rotation**: Automatic backup when log file exceeds 5MB
|
|
195
|
+
- **Timestamped entries**: Each log entry includes local and UTC timestamps
|
|
196
|
+
- **File management**: Read, clear, and backup log files
|
|
197
|
+
- **Cross-platform**: Consistent API across all supported platforms
|
|
198
|
+
- **Convenience methods**: Easy-to-use methods for different log levels
|
|
199
|
+
|
|
200
|
+
## Platform-Specific Details
|
|
201
|
+
|
|
202
|
+
### Android
|
|
203
|
+
- Logs are stored in the app's internal storage: `/data/data/[package]/files/[userId]/AppLogs/`
|
|
204
|
+
- Requires storage permissions for external storage access
|
|
205
|
+
- Automatic log rotation when file size exceeds 5MB
|
|
206
|
+
|
|
207
|
+
### iOS
|
|
208
|
+
- Logs are stored in the app's Documents directory: `Documents/[userId]/AppLogs/`
|
|
209
|
+
- Uses native Swift implementation for optimal performance
|
|
210
|
+
- Automatic log rotation when file size exceeds 5MB
|
|
211
|
+
|
|
212
|
+
### Electron
|
|
213
|
+
- Logs are stored in the app's user data directory: `[userData]/[userId]/log/`
|
|
214
|
+
- Uses Node.js file system APIs
|
|
215
|
+
- Automatic log rotation when file size exceeds 5MB
|
|
216
|
+
|
|
217
|
+
### Browser
|
|
218
|
+
- Logs are stored in browser's localStorage with keys: `unvired_logger_[userId]_log.txt`
|
|
219
|
+
- Fallback implementation when Cordova is not available
|
|
220
|
+
- Automatic content truncation when size exceeds 5MB
|
|
221
|
+
- Console logging for debugging purposes
|
|
222
|
+
|
|
223
|
+
## Log Levels
|
|
224
|
+
|
|
225
|
+
- **Debug**: Detailed information for debugging (only logged when level is set to Debug)
|
|
226
|
+
- **Info**: General information about application flow (logged when level is Info or Debug)
|
|
227
|
+
- **Error**: Error messages and exceptions (always logged)
|
|
228
|
+
|
|
229
|
+
## File Structure
|
|
230
|
+
|
|
231
|
+
Logs are stored in the following structure:
|
|
232
|
+
```
|
|
233
|
+
{userDataPath}/{userId}/AppLogs/log.txt
|
|
234
|
+
{userDataPath}/{userId}/AppLogs/log_backup.txt
|
|
235
|
+
```
|
|
236
|
+
|
|
237
|
+
Where:
|
|
238
|
+
- `userDataPath` is the Electron app's user data directory
|
|
239
|
+
- `userId` is the user identifier you provide
|
|
240
|
+
- `AppLogs` is the log folder name
|
|
241
|
+
- `log.txt` is the current log file
|
|
242
|
+
- `log_backup.txt` is the backup file (created during rotation)
|
|
243
|
+
|
|
244
|
+
## API Reference
|
|
245
|
+
|
|
246
|
+
### Core Methods
|
|
247
|
+
- `log(userId, message, sourceClass?, sourceMethod?, level?, success, error)` - Log a message
|
|
248
|
+
- `setLogLevel(level, success, error)` - Set the logging level
|
|
249
|
+
- `getLogFileContent(userId, success, error)` - Get log file content
|
|
250
|
+
- `clearLogFile(userId, success, error)` - Clear the log file
|
|
251
|
+
- `getBackupLogFileContent(userId, success, error)` - Get backup log file content
|
|
252
|
+
|
|
253
|
+
### Convenience Methods
|
|
254
|
+
- `logDebug(userId, sourceClass, sourceMethod, message, success, error)` - Log debug message
|
|
255
|
+
- `logInfo(userId, sourceClass, sourceMethod, message, success, error)` - Log info message
|
|
256
|
+
- `logError(userId, sourceClass, sourceMethod, message, success, error)` - Log error message
|
|
257
|
+
|
|
258
|
+
### Constants
|
|
259
|
+
- `UnviredLogger.LogLevel.Debug` - Debug log level
|
|
260
|
+
- `UnviredLogger.LogLevel.Info` - Info log level
|
|
261
|
+
- `UnviredLogger.LogLevel.Error` - Error log level
|
|
262
|
+
|
|
263
|
+
## Requirements
|
|
264
|
+
|
|
265
|
+
- Cordova 9.0.0 or higher
|
|
266
|
+
- cordova-electron 1.0.0 or higher
|
|
267
|
+
- Electron 20.0.0 or higher
|
|
268
|
+
- Node.js 14.0.0 or higher
|
|
269
|
+
|
|
270
|
+
## License
|
|
271
|
+
|
|
272
|
+
MIT
|
package/package.json
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "cordova-plugin-unvired-logger",
|
|
3
|
+
"version": "0.0.1",
|
|
4
|
+
"description": "A logger plugin for Electron, Android, Browser, and iOS that appends logs to log.txt files organized by user ID.",
|
|
5
|
+
"cordova": {
|
|
6
|
+
"id": "cordova-plugin-unvired-logger",
|
|
7
|
+
"platforms": [
|
|
8
|
+
"electron",
|
|
9
|
+
"android",
|
|
10
|
+
"browser",
|
|
11
|
+
"ios"
|
|
12
|
+
]
|
|
13
|
+
},
|
|
14
|
+
"keywords": [
|
|
15
|
+
"cordova",
|
|
16
|
+
"electron",
|
|
17
|
+
"android",
|
|
18
|
+
"plugin",
|
|
19
|
+
"logger"
|
|
20
|
+
],
|
|
21
|
+
"author": "Unvired Inc.",
|
|
22
|
+
"license": "MIT",
|
|
23
|
+
"dependencies": {
|
|
24
|
+
"fs": "^0.0.1-security"
|
|
25
|
+
}
|
|
26
|
+
}
|
package/plugin.xml
ADDED
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
|
2
|
+
<plugin id="cordova-plugin-unvired-logger" version="0.0.1"
|
|
3
|
+
xmlns="http://apache.org/cordova/ns/plugins/1.0"
|
|
4
|
+
xmlns:android="http://schemas.android.com/apk/res/android">
|
|
5
|
+
|
|
6
|
+
<name>UnviredLogger</name>
|
|
7
|
+
<description>A logger plugin for Android, iOS, Electron, and Browser that appends logs to log.txt files organized by user ID.</description>
|
|
8
|
+
|
|
9
|
+
<js-module src="www/logger.js" name="UnviredLogger">
|
|
10
|
+
<clobbers target="Logger" />
|
|
11
|
+
</js-module>
|
|
12
|
+
|
|
13
|
+
<platform name="electron">
|
|
14
|
+
<framework src="src/electron"/>
|
|
15
|
+
</platform>
|
|
16
|
+
|
|
17
|
+
<platform name="android">
|
|
18
|
+
<config-file target="res/xml/config.xml" parent="/*">
|
|
19
|
+
<feature name="UnviredLogger">
|
|
20
|
+
<param name="android-package" value="cordova.plugin.unvired.logger.UnviredLogger" />
|
|
21
|
+
</feature>
|
|
22
|
+
</config-file>
|
|
23
|
+
|
|
24
|
+
<source-file src="src/android/UnviredLogger.java" target-dir="src/cordova/plugin/unvired/logger" />
|
|
25
|
+
|
|
26
|
+
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
|
|
27
|
+
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
|
|
28
|
+
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
|
|
29
|
+
</platform>
|
|
30
|
+
|
|
31
|
+
<platform name="ios">
|
|
32
|
+
<config-file target="config.xml" parent="/*">
|
|
33
|
+
<feature name="UnviredLogger">
|
|
34
|
+
<param name="ios-package" value="UnviredLogger" />
|
|
35
|
+
</feature>
|
|
36
|
+
</config-file>
|
|
37
|
+
|
|
38
|
+
<source-file src="src/ios/UnviredLogger.swift" />
|
|
39
|
+
|
|
40
|
+
<framework src="Foundation.framework" />
|
|
41
|
+
<framework src="UIKit.framework" />
|
|
42
|
+
</platform>
|
|
43
|
+
|
|
44
|
+
<platform name="browser">
|
|
45
|
+
<js-module src="src/browser/Logger.js" name="UnviredLoggerBrowser">
|
|
46
|
+
<clobbers target="UnviredLoggerBrowser" />
|
|
47
|
+
</js-module>
|
|
48
|
+
</platform>
|
|
49
|
+
</plugin>
|
|
@@ -0,0 +1,265 @@
|
|
|
1
|
+
package cordova.plugin.unvired.logger;
|
|
2
|
+
|
|
3
|
+
import android.content.Context;
|
|
4
|
+
import android.os.Environment;
|
|
5
|
+
|
|
6
|
+
import org.apache.cordova.CordovaPlugin;
|
|
7
|
+
import org.apache.cordova.CallbackContext;
|
|
8
|
+
import org.json.JSONArray;
|
|
9
|
+
import org.json.JSONException;
|
|
10
|
+
import org.json.JSONObject;
|
|
11
|
+
|
|
12
|
+
import java.io.*;
|
|
13
|
+
import java.text.SimpleDateFormat;
|
|
14
|
+
import java.util.Date;
|
|
15
|
+
import java.util.Locale;
|
|
16
|
+
|
|
17
|
+
public class UnviredLogger extends CordovaPlugin {
|
|
18
|
+
|
|
19
|
+
private static final String LOG_FOLDER_NAME = "AppLogs";
|
|
20
|
+
private static final String LOG_FILE_NAME = "log.txt";
|
|
21
|
+
private static final String BACKUP_LOG_FILE_NAME = "log_backup.txt";
|
|
22
|
+
private static final long MAX_LOG_SIZE = 5 * 1024 * 1024; // 5MB
|
|
23
|
+
|
|
24
|
+
private String defaultLogLevel = "info";
|
|
25
|
+
|
|
26
|
+
@Override
|
|
27
|
+
public boolean execute(String action, JSONArray args, final CallbackContext callbackContext) throws JSONException {
|
|
28
|
+
try {
|
|
29
|
+
switch (action) {
|
|
30
|
+
case "logDebug":
|
|
31
|
+
case "logInfo":
|
|
32
|
+
case "logError":
|
|
33
|
+
case "loggerWithLevel":
|
|
34
|
+
logWithLevel(args, callbackContext);
|
|
35
|
+
return true;
|
|
36
|
+
case "setLogLevel":
|
|
37
|
+
setLogLevel(args, callbackContext);
|
|
38
|
+
return true;
|
|
39
|
+
case "getLogLevel":
|
|
40
|
+
callbackContext.success(defaultLogLevel);
|
|
41
|
+
return true;
|
|
42
|
+
case "getLogFileContent":
|
|
43
|
+
getLogFileContent(args, callbackContext);
|
|
44
|
+
return true;
|
|
45
|
+
case "clearLogFile":
|
|
46
|
+
clearLogFile(args, callbackContext);
|
|
47
|
+
return true;
|
|
48
|
+
case "getBackupLogFileContent":
|
|
49
|
+
getBackupLogFileContent(args, callbackContext);
|
|
50
|
+
return true;
|
|
51
|
+
case "copyLogToBackup":
|
|
52
|
+
copyLogToBackup(args, callbackContext);
|
|
53
|
+
return true;
|
|
54
|
+
case "getLogFileURL":
|
|
55
|
+
getLogFileURL(args, callbackContext);
|
|
56
|
+
return true;
|
|
57
|
+
case "getBackupLogFileURL":
|
|
58
|
+
getBackupLogFileURL(args, callbackContext);
|
|
59
|
+
return true;
|
|
60
|
+
default:
|
|
61
|
+
return false;
|
|
62
|
+
}
|
|
63
|
+
} catch (Exception e) {
|
|
64
|
+
callbackContext.error("Error: " + e.getMessage());
|
|
65
|
+
return false;
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
private void setLogLevel(JSONArray args, CallbackContext callbackContext) {
|
|
70
|
+
try {
|
|
71
|
+
String level = args.getString(0);
|
|
72
|
+
defaultLogLevel = level;
|
|
73
|
+
callbackContext.success();
|
|
74
|
+
} catch (Exception e) {
|
|
75
|
+
callbackContext.error("Failed to set log level: " + e.getMessage());
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
private void logWithLevel(JSONArray args, CallbackContext callbackContext) {
|
|
80
|
+
try {
|
|
81
|
+
JSONObject arg = args.getJSONObject(0);
|
|
82
|
+
String userId = arg.optString("userId");
|
|
83
|
+
String level = arg.optString("level");
|
|
84
|
+
String sourceClass = arg.optString("sourceClass", "");
|
|
85
|
+
String sourceMethod = arg.optString("sourceMethod", "");
|
|
86
|
+
String message = arg.optString("message");
|
|
87
|
+
|
|
88
|
+
if (userId.isEmpty() || level.isEmpty() || message.isEmpty()) {
|
|
89
|
+
callbackContext.error("userId, level, and message are required");
|
|
90
|
+
return;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
// Log level filtering
|
|
94
|
+
if (shouldSkipLog(level)) {
|
|
95
|
+
callbackContext.success();
|
|
96
|
+
return;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
File logFile = getLogFile(userId);
|
|
100
|
+
checkAndRotateLogFile(logFile, userId);
|
|
101
|
+
|
|
102
|
+
String logEntry = formatLogEntry(level, sourceClass, sourceMethod, message);
|
|
103
|
+
appendToFile(logFile, logEntry);
|
|
104
|
+
|
|
105
|
+
callbackContext.success("Logged to " + logFile.getAbsolutePath());
|
|
106
|
+
} catch (Exception e) {
|
|
107
|
+
callbackContext.error("Logging failed: " + e.getMessage());
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
private boolean shouldSkipLog(String level) {
|
|
112
|
+
String normLevel = level.toLowerCase();
|
|
113
|
+
String normDefault = defaultLogLevel.toLowerCase();
|
|
114
|
+
if (normDefault.equals("error") && (normLevel.equals("debug") || normLevel.equals("info"))) return true;
|
|
115
|
+
if (normDefault.equals("info") && normLevel.equals("debug")) return true;
|
|
116
|
+
return false;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
private void getLogFileContent(JSONArray args, CallbackContext callbackContext) {
|
|
120
|
+
try {
|
|
121
|
+
JSONObject arg = args.getJSONObject(0);
|
|
122
|
+
String userId = arg.optString("userId");
|
|
123
|
+
File logFile = getLogFile(userId);
|
|
124
|
+
String content = readFile(logFile);
|
|
125
|
+
callbackContext.success(content);
|
|
126
|
+
} catch (Exception e) {
|
|
127
|
+
callbackContext.error("Failed to read log file: " + e.getMessage());
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
private void clearLogFile(JSONArray args, CallbackContext callbackContext) {
|
|
132
|
+
try {
|
|
133
|
+
JSONObject arg = args.getJSONObject(0);
|
|
134
|
+
String userId = arg.optString("userId");
|
|
135
|
+
File logFile = getLogFile(userId);
|
|
136
|
+
new FileOutputStream(logFile).close();
|
|
137
|
+
callbackContext.success();
|
|
138
|
+
} catch (Exception e) {
|
|
139
|
+
callbackContext.error("Failed to clear log file: " + e.getMessage());
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
private void getBackupLogFileContent(JSONArray args, CallbackContext callbackContext) {
|
|
144
|
+
try {
|
|
145
|
+
JSONObject arg = args.getJSONObject(0);
|
|
146
|
+
String userId = arg.optString("userId");
|
|
147
|
+
File backupFile = getBackupLogFile(userId);
|
|
148
|
+
String content = readFile(backupFile);
|
|
149
|
+
callbackContext.success(content);
|
|
150
|
+
} catch (Exception e) {
|
|
151
|
+
callbackContext.error("Failed to read backup log file: " + e.getMessage());
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
private void copyLogToBackup(JSONArray args, CallbackContext callbackContext) {
|
|
156
|
+
try {
|
|
157
|
+
JSONObject arg = args.getJSONObject(0);
|
|
158
|
+
String userId = arg.optString("userId");
|
|
159
|
+
File logFile = getLogFile(userId);
|
|
160
|
+
File backupFile = getBackupLogFile(userId);
|
|
161
|
+
copyFile(logFile, backupFile);
|
|
162
|
+
callbackContext.success();
|
|
163
|
+
} catch (Exception e) {
|
|
164
|
+
callbackContext.error("Failed to copy log file to backup: " + e.getMessage());
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
private void getLogFileURL(JSONArray args, CallbackContext callbackContext) {
|
|
169
|
+
try {
|
|
170
|
+
JSONObject arg = args.getJSONObject(0);
|
|
171
|
+
String userId = arg.optString("userId");
|
|
172
|
+
File logFile = getLogFile(userId);
|
|
173
|
+
callbackContext.success(logFile.getAbsolutePath());
|
|
174
|
+
} catch (Exception e) {
|
|
175
|
+
callbackContext.error("Failed to get log file URL: " + e.getMessage());
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
private void getBackupLogFileURL(JSONArray args, CallbackContext callbackContext) {
|
|
180
|
+
try {
|
|
181
|
+
JSONObject arg = args.getJSONObject(0);
|
|
182
|
+
String userId = arg.optString("userId");
|
|
183
|
+
File backupFile = getBackupLogFile(userId);
|
|
184
|
+
callbackContext.success(backupFile.getAbsolutePath());
|
|
185
|
+
} catch (Exception e) {
|
|
186
|
+
callbackContext.error("Failed to get backup log file URL: " + e.getMessage());
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
// --- Helper methods ---
|
|
191
|
+
|
|
192
|
+
private File getLogFile(String userId) {
|
|
193
|
+
File dir = getUserLogDir(userId);
|
|
194
|
+
if (!dir.exists()) dir.mkdirs();
|
|
195
|
+
return new File(dir, LOG_FILE_NAME);
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
private File getBackupLogFile(String userId) {
|
|
199
|
+
File dir = getUserLogDir(userId);
|
|
200
|
+
if (!dir.exists()) dir.mkdirs();
|
|
201
|
+
return new File(dir, BACKUP_LOG_FILE_NAME);
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
private File getUserLogDir(String userId) {
|
|
205
|
+
Context ctx = cordova.getActivity().getApplicationContext();
|
|
206
|
+
File userDir = new File(ctx.getFilesDir(), userId + File.separator + LOG_FOLDER_NAME);
|
|
207
|
+
if (!userDir.exists()) userDir.mkdirs();
|
|
208
|
+
return userDir;
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
private void checkAndRotateLogFile(File logFile, String userId) throws IOException {
|
|
212
|
+
if (logFile.exists() && logFile.length() > MAX_LOG_SIZE) {
|
|
213
|
+
File backupFile = getBackupLogFile(userId);
|
|
214
|
+
copyFile(logFile, backupFile);
|
|
215
|
+
new FileOutputStream(logFile).close();
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
private String formatLogEntry(String level, String sourceClass, String sourceMethod, String message) {
|
|
220
|
+
SimpleDateFormat localFormat = new SimpleDateFormat("dd-MM-yyyy HH:mm:ss", Locale.getDefault());
|
|
221
|
+
SimpleDateFormat utcFormat = new SimpleDateFormat("dd-MM-yyyy HH:mm:ss", Locale.US);
|
|
222
|
+
utcFormat.setTimeZone(java.util.TimeZone.getTimeZone("UTC"));
|
|
223
|
+
Date now = new Date();
|
|
224
|
+
String local = localFormat.format(now);
|
|
225
|
+
String utc = utcFormat.format(now);
|
|
226
|
+
String prefix = level.equalsIgnoreCase("error") ? "⭕️⭕️⭕️ " : "";
|
|
227
|
+
return prefix + local + " | UTC:" + utc + " | " + getStringFromLevel(level) + " | " + sourceClass + " | " + sourceMethod + " | " + message + "\n";
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
private String getStringFromLevel(String level) {
|
|
231
|
+
switch (level.toLowerCase()) {
|
|
232
|
+
case "info": return "IMPORTANT";
|
|
233
|
+
case "error": return "ERROR";
|
|
234
|
+
case "debug": return "DEBUG";
|
|
235
|
+
default: return "";
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
private void appendToFile(File file, String data) throws IOException {
|
|
240
|
+
FileWriter fw = new FileWriter(file, true);
|
|
241
|
+
fw.write(data);
|
|
242
|
+
fw.close();
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
private String readFile(File file) throws IOException {
|
|
246
|
+
if (!file.exists()) return "";
|
|
247
|
+
StringBuilder sb = new StringBuilder();
|
|
248
|
+
BufferedReader br = new BufferedReader(new FileReader(file));
|
|
249
|
+
String line;
|
|
250
|
+
while ((line = br.readLine()) != null) sb.append(line).append("\n");
|
|
251
|
+
br.close();
|
|
252
|
+
return sb.toString();
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
private void copyFile(File src, File dest) throws IOException {
|
|
256
|
+
if (!src.exists()) return;
|
|
257
|
+
FileInputStream in = new FileInputStream(src);
|
|
258
|
+
FileOutputStream out = new FileOutputStream(dest);
|
|
259
|
+
byte[] buf = new byte[1024];
|
|
260
|
+
int len;
|
|
261
|
+
while ((len = in.read(buf)) > 0) out.write(buf, 0, len);
|
|
262
|
+
in.close();
|
|
263
|
+
out.close();
|
|
264
|
+
}
|
|
265
|
+
}
|