enterprise-logging-system 1.0.12 → 1.0.13
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/dist/backend/controllers/LogController.d.ts +4 -0
- package/dist/backend/controllers/LogController.d.ts.map +1 -1
- package/dist/backend/controllers/LogController.js +98 -2
- package/dist/backend/controllers/LogController.js.map +1 -1
- package/dist/backend/repositories/AccessLogRepository.d.ts +5 -1
- package/dist/backend/repositories/AccessLogRepository.d.ts.map +1 -1
- package/dist/backend/repositories/AccessLogRepository.js +51 -0
- package/dist/backend/repositories/AccessLogRepository.js.map +1 -1
- package/dist/backend/repositories/ChangeLogRepository.d.ts +5 -0
- package/dist/backend/repositories/ChangeLogRepository.d.ts.map +1 -1
- package/dist/backend/repositories/ChangeLogRepository.js +51 -0
- package/dist/backend/repositories/ChangeLogRepository.js.map +1 -1
- package/dist/backend/repositories/ExportLogRepository.d.ts +5 -0
- package/dist/backend/repositories/ExportLogRepository.d.ts.map +1 -1
- package/dist/backend/repositories/ExportLogRepository.js +41 -0
- package/dist/backend/repositories/ExportLogRepository.js.map +1 -1
- package/dist/backend/repositories/SessionLogRepository.d.ts +5 -1
- package/dist/backend/repositories/SessionLogRepository.d.ts.map +1 -1
- package/dist/backend/repositories/SessionLogRepository.js +39 -0
- package/dist/backend/repositories/SessionLogRepository.js.map +1 -1
- package/dist/backend/routes.d.ts +20 -0
- package/dist/backend/routes.d.ts.map +1 -0
- package/dist/backend/routes.js +42 -0
- package/dist/backend/routes.js.map +1 -0
- package/dist/backend/services/LoggingService.d.ts +5 -1
- package/dist/backend/services/LoggingService.d.ts.map +1 -1
- package/dist/backend/services/LoggingService.js +13 -0
- package/dist/backend/services/LoggingService.js.map +1 -1
- package/dist/frontend/activity-monitor/ActivityMonitor.d.ts +69 -5
- package/dist/frontend/activity-monitor/ActivityMonitor.d.ts.map +1 -1
- package/dist/frontend/activity-monitor/ActivityMonitor.js +322 -26
- package/dist/frontend/activity-monitor/ActivityMonitor.js.map +1 -1
- package/dist/frontend/index.d.ts +1 -1
- package/dist/frontend/index.d.ts.map +1 -1
- package/dist/frontend/index.js +4 -1
- package/dist/frontend/index.js.map +1 -1
- package/dist/index.d.ts +31 -7
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +41 -8
- package/dist/index.js.map +1 -1
- package/dist/shared/types/index.d.ts +64 -0
- package/dist/shared/types/index.d.ts.map +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.mountLoggingRoutes = mountLoggingRoutes;
|
|
4
|
+
/**
|
|
5
|
+
* Mount all logging API routes (create + list with search & pagination).
|
|
6
|
+
* Use this in your app after initializing the logging system.
|
|
7
|
+
*
|
|
8
|
+
* Endpoints by log type:
|
|
9
|
+
* - Access logs: POST /pageview, POST /action, GET /access, POST /user/timeline
|
|
10
|
+
* - Session logs: POST /session/start, POST /session/end, POST /heartbeat, POST /activity, GET /sessions, POST /session/details
|
|
11
|
+
* - Change (Audit): POST /change, GET /changes, POST /entity/history
|
|
12
|
+
* - Export logs: POST /export, GET /exports, GET|POST /user/exports
|
|
13
|
+
* - Batch: POST /batch
|
|
14
|
+
*/
|
|
15
|
+
function mountLoggingRoutes(options) {
|
|
16
|
+
const { app, basePath, logController } = options;
|
|
17
|
+
const p = basePath.replace(/\/$/, '');
|
|
18
|
+
// ========== ACCESS LOGS ==========
|
|
19
|
+
app.post(`${p}/pageview`, (req, res) => logController.logPageView(req, res)); // Access log: create page view
|
|
20
|
+
app.post(`${p}/action`, (req, res) => logController.logAction(req, res)); // Access log: create user action
|
|
21
|
+
app.get(`${p}/access`, (req, res) => logController.listAccessLogs(req, res)); // Access logs: list (search & pagination)
|
|
22
|
+
// ========== SESSION LOGS ==========
|
|
23
|
+
app.post(`${p}/session/start`, (req, res) => logController.startSession(req, res)); // Session log: start session
|
|
24
|
+
app.post(`${p}/session/end`, (req, res) => logController.endSession(req, res)); // Session log: end session
|
|
25
|
+
app.post(`${p}/heartbeat`, (req, res) => logController.recordHeartbeat(req, res)); // Session log: heartbeat
|
|
26
|
+
app.post(`${p}/activity`, (req, res) => logController.recordActivity(req, res)); // Session log: record activity
|
|
27
|
+
app.get(`${p}/sessions`, (req, res) => logController.listSessionLogs(req, res)); // Session logs: list (search & pagination)
|
|
28
|
+
app.post(`${p}/session/details`, (req, res) => logController.getSessionDetails(req, res)); // Session logs: get session details
|
|
29
|
+
// ========== CHANGE (AUDIT) LOGS ==========
|
|
30
|
+
app.post(`${p}/change`, (req, res) => logController.logChange(req, res)); // Change (Audit) log: create
|
|
31
|
+
app.get(`${p}/changes`, (req, res) => logController.listChangeLogs(req, res)); // Change (Audit) logs: list (search & pagination)
|
|
32
|
+
app.post(`${p}/entity/history`, (req, res) => logController.getEntityHistory(req, res)); // Change (Audit): entity history
|
|
33
|
+
// ========== EXPORT LOGS ==========
|
|
34
|
+
app.post(`${p}/export`, (req, res) => logController.logExport(req, res)); // Export log: create
|
|
35
|
+
app.get(`${p}/exports`, (req, res) => logController.listExportLogs(req, res)); // Export logs: list (search & pagination)
|
|
36
|
+
app.get(`${p}/user/exports`, (req, res) => logController.getExportHistory(req, res)); // Export logs: user export history
|
|
37
|
+
app.post(`${p}/user/exports`, (req, res) => logController.getExportHistory(req, res)); // Export logs: user export history
|
|
38
|
+
// ========== MIXED / QUERY ==========
|
|
39
|
+
app.post(`${p}/user/timeline`, (req, res) => logController.getUserTimeline(req, res)); // Query: user timeline (access + session + change + export)
|
|
40
|
+
app.post(`${p}/batch`, (req, res) => logController.batchActivities(req, res)); // Batch: multiple events (access, action, etc.)
|
|
41
|
+
}
|
|
42
|
+
//# sourceMappingURL=routes.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"routes.js","sourceRoot":"","sources":["../../src/backend/routes.ts"],"names":[],"mappings":"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"}
|
|
@@ -2,7 +2,7 @@ import type { AccessLog } from '../models/AccessLog';
|
|
|
2
2
|
import type { SessionLog } from '../models/SessionLog';
|
|
3
3
|
import type { ChangeLog } from '../models/ChangeLog';
|
|
4
4
|
import type { ExportLog } from '../models/ExportLog';
|
|
5
|
-
import type { DateRange } from '../../shared/types';
|
|
5
|
+
import type { DateRange, ListResult, AccessLogListQuery, SessionLogListQuery, ChangeLogListQuery, ExportLogListQuery } from '../../shared/types';
|
|
6
6
|
import { AccessLogRepository } from '../repositories/AccessLogRepository';
|
|
7
7
|
import { SessionLogRepository } from '../repositories/SessionLogRepository';
|
|
8
8
|
import { ChangeLogRepository } from '../repositories/ChangeLogRepository';
|
|
@@ -106,5 +106,9 @@ export declare class LoggingService {
|
|
|
106
106
|
activities: AccessLog[];
|
|
107
107
|
}>;
|
|
108
108
|
getExportHistory(userId: string, exportType?: string): Promise<ExportLog[]>;
|
|
109
|
+
listAccessLogs(query: AccessLogListQuery): Promise<ListResult<AccessLog>>;
|
|
110
|
+
listSessionLogs(query: SessionLogListQuery): Promise<ListResult<SessionLog>>;
|
|
111
|
+
listChangeLogs(query: ChangeLogListQuery): Promise<ListResult<ChangeLog>>;
|
|
112
|
+
listExportLogs(query: ExportLogListQuery): Promise<ListResult<ExportLog>>;
|
|
109
113
|
}
|
|
110
114
|
//# sourceMappingURL=LoggingService.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"LoggingService.d.ts","sourceRoot":"","sources":["../../../src/backend/services/LoggingService.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAC;AACrD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAC;AACvD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAC;AACrD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAC;AACrD,OAAO,KAAK,
|
|
1
|
+
{"version":3,"file":"LoggingService.d.ts","sourceRoot":"","sources":["../../../src/backend/services/LoggingService.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAC;AACrD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAC;AACvD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAC;AACrD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAC;AACrD,OAAO,KAAK,EACV,SAAS,EACT,UAAU,EACV,kBAAkB,EAClB,mBAAmB,EACnB,kBAAkB,EAClB,kBAAkB,EACnB,MAAM,oBAAoB,CAAC;AAE5B,OAAO,EAAE,mBAAmB,EAAE,MAAM,qCAAqC,CAAC;AAC1E,OAAO,EAAE,oBAAoB,EAAE,MAAM,sCAAsC,CAAC;AAC5E,OAAO,EAAE,mBAAmB,EAAE,MAAM,qCAAqC,CAAC;AAC1E,OAAO,EAAE,mBAAmB,EAAE,MAAM,qCAAqC,CAAC;AAE1E,qBAAa,cAAc;IAEvB,OAAO,CAAC,aAAa;IACrB,OAAO,CAAC,cAAc;IACtB,OAAO,CAAC,aAAa;IACrB,OAAO,CAAC,aAAa;gBAHb,aAAa,EAAE,mBAAmB,EAClC,cAAc,EAAE,oBAAoB,EACpC,aAAa,EAAE,mBAAmB,EAClC,aAAa,EAAE,mBAAmB;IAItC,WAAW,CAAC,IAAI,EAAE;QACtB,QAAQ,EAAE,MAAM,CAAC;QACjB,MAAM,EAAE,MAAM,CAAC;QACf,QAAQ,EAAE,MAAM,CAAC;QACjB,SAAS,EAAE,MAAM,CAAC;QAClB,SAAS,EAAE,MAAM,CAAC;QAClB,SAAS,EAAE,MAAM,CAAC;QAClB,MAAM,EAAE,MAAM,CAAC;QACf,SAAS,EAAE,MAAM,CAAC;QAClB,OAAO,EAAE,MAAM,CAAC;QAChB,SAAS,EAAE,MAAM,CAAC;QAClB,YAAY,CAAC,EAAE,MAAM,CAAC;QACtB,OAAO,CAAC,EAAE,GAAG,CAAC;QACd,WAAW,CAAC,EAAE,GAAG,CAAC;QAClB,OAAO,CAAC,EAAE,GAAG,CAAC;KACf,GAAG,OAAO,CAAC,SAAS,CAAC;IAWhB,SAAS,CAAC,IAAI,EAAE;QACpB,QAAQ,EAAE,MAAM,CAAC;QACjB,MAAM,EAAE,MAAM,CAAC;QACf,QAAQ,EAAE,MAAM,CAAC;QACjB,SAAS,EAAE,MAAM,CAAC;QAClB,SAAS,EAAE,MAAM,CAAC;QAClB,SAAS,EAAE,MAAM,CAAC;QAClB,YAAY,EAAE,MAAM,CAAC;QACrB,YAAY,EAAE,MAAM,CAAC;QACrB,UAAU,EAAE,MAAM,CAAC;QACnB,YAAY,EAAE,MAAM,CAAC;QACrB,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;QACjC,MAAM,CAAC,EAAE,MAAM,CAAC;QAChB,OAAO,CAAC,EAAE,GAAG,CAAC;KACf,GAAG,OAAO,CAAC,SAAS,CAAC;IAUhB,YAAY,CAAC,IAAI,EAAE;QACvB,QAAQ,EAAE,MAAM,CAAC;QACjB,MAAM,EAAE,MAAM,CAAC;QACf,QAAQ,EAAE,MAAM,CAAC;QACjB,SAAS,EAAE,MAAM,CAAC;QAClB,SAAS,EAAE,MAAM,CAAC;QAClB,SAAS,EAAE,MAAM,CAAC;QAClB,aAAa,CAAC,EAAE,MAAM,CAAC;KACxB,GAAG,OAAO,CAAC,UAAU,CAAC;IASjB,UAAU,CACd,SAAS,EAAE,MAAM,EACjB,MAAM,GAAE,MAAM,GAAG,SAAS,GAAG,OAAgB,GAC5C,OAAO,CAAC,UAAU,GAAG,IAAI,CAAC;IAIvB,cAAc,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,GAAG,IAAI,CAAC;IAI7D,eAAe,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,GAAG,IAAI,CAAC;IAK9D,SAAS,CAAC,IAAI,EAAE;QACpB,QAAQ,EAAE,MAAM,CAAC;QACjB,MAAM,EAAE,MAAM,CAAC;QACf,QAAQ,EAAE,MAAM,CAAC;QACjB,SAAS,EAAE,MAAM,CAAC;QAClB,SAAS,EAAE,MAAM,CAAC;QAClB,SAAS,EAAE,MAAM,CAAC;QAClB,UAAU,EAAE,MAAM,CAAC;QACnB,QAAQ,EAAE,MAAM,CAAC;QACjB,IAAI,EAAE,QAAQ,GAAG,QAAQ,GAAG,QAAQ,GAAG,SAAS,CAAC;QACjD,OAAO,EAAE,KAAK,CAAC;YAAE,KAAK,EAAE,MAAM,CAAC;YAAC,QAAQ,EAAE,GAAG,CAAC;YAAC,QAAQ,EAAE,GAAG,CAAC;YAAC,IAAI,EAAE,MAAM,CAAA;SAAE,CAAC,CAAC;QAC9E,MAAM,CAAC,EAAE,MAAM,CAAC;QAChB,OAAO,CAAC,EAAE,MAAM,CAAC;QACjB,MAAM,EAAE,SAAS,GAAG,SAAS,CAAC;QAC9B,YAAY,CAAC,EAAE,MAAM,CAAC;QACtB,gBAAgB,CAAC,EAAE,MAAM,CAAC;QAC1B,cAAc,CAAC,EAAE,MAAM,CAAC;KACzB,GAAG,OAAO,CAAC,SAAS,CAAC;IAahB,SAAS,CAAC,IAAI,EAAE;QACpB,QAAQ,EAAE,MAAM,CAAC;QACjB,MAAM,EAAE,MAAM,CAAC;QACf,QAAQ,EAAE,MAAM,CAAC;QACjB,SAAS,EAAE,MAAM,CAAC;QAClB,SAAS,EAAE,MAAM,CAAC;QAClB,SAAS,EAAE,MAAM,CAAC;QAClB,UAAU,EAAE,KAAK,GAAG,OAAO,GAAG,KAAK,GAAG,MAAM,CAAC;QAC7C,QAAQ,EAAE,MAAM,CAAC;QACjB,WAAW,EAAE,MAAM,CAAC;QACpB,UAAU,CAAC,EAAE,MAAM,CAAC;QACpB,SAAS,CAAC,EAAE,MAAM,EAAE,CAAC;QACrB,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;QAC9B,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;KACpB,GAAG,OAAO,CAAC,SAAS,CAAC;IAShB,eAAe,CACnB,MAAM,EAAE,MAAM,EACd,SAAS,EAAE,SAAS,GACnB,OAAO,CAAC;QACT,UAAU,EAAE,SAAS,EAAE,CAAC;QACxB,WAAW,EAAE,UAAU,EAAE,CAAC;QAC1B,UAAU,EAAE,SAAS,EAAE,CAAC;QACxB,UAAU,EAAE,SAAS,EAAE,CAAC;KACzB,CAAC;IAWI,gBAAgB,CAAC,UAAU,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,SAAS,EAAE,CAAC;IAI5E,iBAAiB,CACrB,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC;QAAE,OAAO,EAAE,UAAU,GAAG,IAAI,CAAC;QAAC,UAAU,EAAE,SAAS,EAAE,CAAA;KAAE,CAAC;IAS7D,gBAAgB,CAAC,MAAM,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,SAAS,EAAE,CAAC;IAK3E,cAAc,CAAC,KAAK,EAAE,kBAAkB,GAAG,OAAO,CAAC,UAAU,CAAC,SAAS,CAAC,CAAC;IAIzE,eAAe,CAAC,KAAK,EAAE,mBAAmB,GAAG,OAAO,CAAC,UAAU,CAAC,UAAU,CAAC,CAAC;IAI5E,cAAc,CAAC,KAAK,EAAE,kBAAkB,GAAG,OAAO,CAAC,UAAU,CAAC,SAAS,CAAC,CAAC;IAIzE,cAAc,CAAC,KAAK,EAAE,kBAAkB,GAAG,OAAO,CAAC,UAAU,CAAC,SAAS,CAAC,CAAC;CAGhF"}
|
|
@@ -92,6 +92,19 @@ class LoggingService {
|
|
|
92
92
|
async getExportHistory(userId, exportType) {
|
|
93
93
|
return this.exportLogRepo.getUserExports(userId, exportType);
|
|
94
94
|
}
|
|
95
|
+
// List APIs with search and pagination
|
|
96
|
+
async listAccessLogs(query) {
|
|
97
|
+
return this.accessLogRepo.list(query);
|
|
98
|
+
}
|
|
99
|
+
async listSessionLogs(query) {
|
|
100
|
+
return this.sessionLogRepo.list(query);
|
|
101
|
+
}
|
|
102
|
+
async listChangeLogs(query) {
|
|
103
|
+
return this.changeLogRepo.list(query);
|
|
104
|
+
}
|
|
105
|
+
async listExportLogs(query) {
|
|
106
|
+
return this.exportLogRepo.list(query);
|
|
107
|
+
}
|
|
95
108
|
}
|
|
96
109
|
exports.LoggingService = LoggingService;
|
|
97
110
|
//# sourceMappingURL=LoggingService.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"LoggingService.js","sourceRoot":"","sources":["../../../src/backend/services/LoggingService.ts"],"names":[],"mappings":";;;
|
|
1
|
+
{"version":3,"file":"LoggingService.js","sourceRoot":"","sources":["../../../src/backend/services/LoggingService.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
export interface ActivityEvent {
|
|
2
|
-
type: 'PAGE_VIEW' | 'ACTION' | 'NAVIGATION' | 'API_CALL';
|
|
2
|
+
type: 'PAGE_VIEW' | 'ACTION' | 'CHANGE' | 'EXPORT' | 'NAVIGATION' | 'API_CALL';
|
|
3
3
|
name: string;
|
|
4
4
|
data?: Record<string, any>;
|
|
5
5
|
timestamp: Date;
|
|
@@ -13,24 +13,81 @@ export interface PageViewEvent {
|
|
|
13
13
|
previousPage?: string;
|
|
14
14
|
loadTime?: number;
|
|
15
15
|
domReadyTime?: number;
|
|
16
|
+
browser?: BrowserInfo;
|
|
17
|
+
geoLocation?: GeoLocation;
|
|
18
|
+
network?: NetworkInfo;
|
|
16
19
|
}
|
|
17
20
|
export interface ActionEvent {
|
|
18
21
|
actionType: string;
|
|
19
22
|
actionTarget: string;
|
|
20
23
|
actionData?: Record<string, any>;
|
|
24
|
+
pageId?: string;
|
|
25
|
+
}
|
|
26
|
+
export interface ChangeEvent {
|
|
27
|
+
entityType: string;
|
|
28
|
+
entityId: string;
|
|
29
|
+
type: 'CREATE' | 'UPDATE' | 'DELETE' | 'RESTORE';
|
|
30
|
+
changes: Array<{
|
|
31
|
+
field: string;
|
|
32
|
+
oldValue: any;
|
|
33
|
+
newValue: any;
|
|
34
|
+
type: string;
|
|
35
|
+
}>;
|
|
36
|
+
reason?: string;
|
|
37
|
+
comment?: string;
|
|
38
|
+
status: 'SUCCESS' | 'FAILURE';
|
|
39
|
+
errorMessage?: string;
|
|
40
|
+
parentEntityType?: string;
|
|
41
|
+
parentEntityId?: string;
|
|
42
|
+
}
|
|
43
|
+
export interface ExportEvent {
|
|
44
|
+
exportType: 'CSV' | 'EXCEL' | 'PDF' | 'JSON';
|
|
45
|
+
fileName: string;
|
|
46
|
+
recordCount: number;
|
|
47
|
+
entityType?: string;
|
|
48
|
+
entityIds?: string[];
|
|
49
|
+
filters?: Record<string, any>;
|
|
50
|
+
columns?: string[];
|
|
51
|
+
}
|
|
52
|
+
export interface BrowserInfo {
|
|
53
|
+
name: string;
|
|
54
|
+
version: string;
|
|
55
|
+
os: string;
|
|
56
|
+
device: string;
|
|
57
|
+
}
|
|
58
|
+
export interface GeoLocation {
|
|
59
|
+
country?: string;
|
|
60
|
+
region?: string;
|
|
61
|
+
city?: string;
|
|
62
|
+
latitude?: number;
|
|
63
|
+
longitude?: number;
|
|
64
|
+
}
|
|
65
|
+
export interface NetworkInfo {
|
|
66
|
+
connectionType?: string;
|
|
67
|
+
effectiveType?: string;
|
|
68
|
+
downlink?: number;
|
|
69
|
+
rtt?: number;
|
|
21
70
|
}
|
|
22
71
|
export declare class ActivityMonitor {
|
|
23
72
|
private sessionId;
|
|
24
73
|
private userId;
|
|
25
|
-
private
|
|
74
|
+
private tenantId;
|
|
75
|
+
private userRole;
|
|
76
|
+
private baseEndpoint;
|
|
26
77
|
private batchSize;
|
|
27
78
|
private batchInterval;
|
|
28
79
|
private eventQueue;
|
|
29
80
|
private batchTimer?;
|
|
30
|
-
|
|
81
|
+
private heartbeatTimer?;
|
|
82
|
+
private heartbeatInterval;
|
|
83
|
+
constructor(sessionId: string, userId: string, tenantId: string, userRole: string, baseEndpoint?: string);
|
|
31
84
|
private initialize;
|
|
32
|
-
|
|
85
|
+
private startSession;
|
|
86
|
+
private startHeartbeat;
|
|
87
|
+
trackPageView(pageInfo?: Partial<PageViewEvent>): Promise<void>;
|
|
33
88
|
trackAction(action: ActionEvent): void;
|
|
89
|
+
logChange(changeData: ChangeEvent): Promise<void>;
|
|
90
|
+
logExport(exportData: ExportEvent): Promise<void>;
|
|
34
91
|
trackNavigation(from: string, to: string): void;
|
|
35
92
|
trackAPICall(endpoint: string, method: string, status: number, duration: number): void;
|
|
36
93
|
private queueEvent;
|
|
@@ -40,6 +97,13 @@ export declare class ActivityMonitor {
|
|
|
40
97
|
private getCurrentPageId;
|
|
41
98
|
private getPageLoadTime;
|
|
42
99
|
private getDOMReadyTime;
|
|
43
|
-
|
|
100
|
+
private getBrowserInfo;
|
|
101
|
+
private getOS;
|
|
102
|
+
private getDeviceType;
|
|
103
|
+
private getGeoLocation;
|
|
104
|
+
private getIPAddress;
|
|
105
|
+
private getNetworkInfo;
|
|
106
|
+
destroy(): Promise<void>;
|
|
107
|
+
private endSession;
|
|
44
108
|
}
|
|
45
109
|
//# sourceMappingURL=ActivityMonitor.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ActivityMonitor.d.ts","sourceRoot":"","sources":["../../../src/frontend/activity-monitor/ActivityMonitor.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,WAAW,GAAG,QAAQ,GAAG,YAAY,GAAG,UAAU,CAAC;
|
|
1
|
+
{"version":3,"file":"ActivityMonitor.d.ts","sourceRoot":"","sources":["../../../src/frontend/activity-monitor/ActivityMonitor.ts"],"names":[],"mappings":"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"}
|
|
@@ -4,51 +4,226 @@ exports.ActivityMonitor = void 0;
|
|
|
4
4
|
class ActivityMonitor {
|
|
5
5
|
sessionId;
|
|
6
6
|
userId;
|
|
7
|
-
|
|
7
|
+
tenantId;
|
|
8
|
+
userRole;
|
|
9
|
+
baseEndpoint;
|
|
8
10
|
batchSize = 10;
|
|
9
11
|
batchInterval = 5000; // 5 seconds
|
|
10
12
|
eventQueue = [];
|
|
11
13
|
batchTimer;
|
|
12
|
-
|
|
14
|
+
heartbeatTimer;
|
|
15
|
+
heartbeatInterval = 30000; // 30 seconds
|
|
16
|
+
constructor(sessionId, userId, tenantId, userRole, baseEndpoint = '/api/logs') {
|
|
13
17
|
this.sessionId = sessionId;
|
|
14
18
|
this.userId = userId;
|
|
15
|
-
this.
|
|
19
|
+
this.tenantId = tenantId;
|
|
20
|
+
this.userRole = userRole;
|
|
21
|
+
this.baseEndpoint = baseEndpoint;
|
|
16
22
|
this.initialize();
|
|
17
23
|
}
|
|
18
|
-
initialize() {
|
|
24
|
+
async initialize() {
|
|
25
|
+
// Start session on backend
|
|
26
|
+
await this.startSession();
|
|
19
27
|
// Start batch processing
|
|
20
28
|
this.startBatchProcessor();
|
|
21
|
-
//
|
|
29
|
+
// Start heartbeat
|
|
30
|
+
this.startHeartbeat();
|
|
31
|
+
// Track initial page view
|
|
22
32
|
this.trackPageView();
|
|
23
33
|
// Track SPA navigation
|
|
24
34
|
this.trackSPANavigation();
|
|
25
35
|
}
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
36
|
+
// Start session with backend
|
|
37
|
+
async startSession() {
|
|
38
|
+
try {
|
|
39
|
+
const response = await fetch(`${this.baseEndpoint}/session/start`, {
|
|
40
|
+
method: 'POST',
|
|
41
|
+
headers: {
|
|
42
|
+
'Content-Type': 'application/json',
|
|
43
|
+
'x-tenant-id': this.tenantId,
|
|
44
|
+
'x-user-id': this.userId,
|
|
45
|
+
'x-user-role': this.userRole,
|
|
46
|
+
'x-session-id': this.sessionId
|
|
47
|
+
},
|
|
48
|
+
body: JSON.stringify({
|
|
49
|
+
tenantId: this.tenantId,
|
|
50
|
+
userId: this.userId,
|
|
51
|
+
userRole: this.userRole,
|
|
52
|
+
sessionId: this.sessionId,
|
|
53
|
+
ipAddress: await this.getIPAddress(),
|
|
54
|
+
userAgent: navigator.userAgent,
|
|
55
|
+
idleThreshold: 300000 // 5 minutes
|
|
56
|
+
})
|
|
57
|
+
});
|
|
58
|
+
if (!response.ok) {
|
|
59
|
+
console.warn('Failed to start session:', await response.text());
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
catch (error) {
|
|
63
|
+
console.warn('Failed to start session:', error);
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
// Send heartbeat to keep session alive
|
|
67
|
+
startHeartbeat() {
|
|
68
|
+
this.heartbeatTimer = setInterval(async () => {
|
|
69
|
+
try {
|
|
70
|
+
await fetch(`${this.baseEndpoint}/heartbeat`, {
|
|
71
|
+
method: 'POST',
|
|
72
|
+
headers: {
|
|
73
|
+
'Content-Type': 'application/json',
|
|
74
|
+
'x-tenant-id': this.tenantId,
|
|
75
|
+
'x-user-id': this.userId,
|
|
76
|
+
'x-user-role': this.userRole,
|
|
77
|
+
'x-session-id': this.sessionId
|
|
78
|
+
},
|
|
79
|
+
body: JSON.stringify({
|
|
80
|
+
sessionId: this.sessionId
|
|
81
|
+
})
|
|
82
|
+
});
|
|
83
|
+
}
|
|
84
|
+
catch (error) {
|
|
85
|
+
console.warn('Heartbeat failed:', error);
|
|
86
|
+
}
|
|
87
|
+
}, this.heartbeatInterval);
|
|
88
|
+
}
|
|
89
|
+
// Track page view - sends directly (not batched)
|
|
90
|
+
async trackPageView(pageInfo) {
|
|
91
|
+
try {
|
|
92
|
+
const response = await fetch(`${this.baseEndpoint}/pageview`, {
|
|
93
|
+
method: 'POST',
|
|
94
|
+
headers: {
|
|
95
|
+
'Content-Type': 'application/json',
|
|
96
|
+
'x-tenant-id': this.tenantId,
|
|
97
|
+
'x-user-id': this.userId,
|
|
98
|
+
'x-user-role': this.userRole,
|
|
99
|
+
'x-session-id': this.sessionId
|
|
100
|
+
},
|
|
101
|
+
body: JSON.stringify({
|
|
102
|
+
tenantId: this.tenantId,
|
|
103
|
+
userId: this.userId,
|
|
104
|
+
userRole: this.userRole,
|
|
105
|
+
sessionId: this.sessionId,
|
|
106
|
+
ipAddress: await this.getIPAddress(),
|
|
107
|
+
userAgent: navigator.userAgent,
|
|
108
|
+
pageId: pageInfo?.pageId || this.getCurrentPageId(),
|
|
109
|
+
pageTitle: pageInfo?.pageTitle || document.title,
|
|
110
|
+
pageUrl: pageInfo?.pageUrl || window.location.href,
|
|
111
|
+
pageRoute: pageInfo?.pageRoute || window.location.pathname,
|
|
112
|
+
previousPage: pageInfo?.previousPage || document.referrer,
|
|
113
|
+
browser: this.getBrowserInfo(),
|
|
114
|
+
geoLocation: await this.getGeoLocation(),
|
|
115
|
+
network: this.getNetworkInfo(),
|
|
116
|
+
loadTime: pageInfo?.loadTime || this.getPageLoadTime(),
|
|
117
|
+
domReadyTime: pageInfo?.domReadyTime || this.getDOMReadyTime()
|
|
118
|
+
})
|
|
119
|
+
});
|
|
120
|
+
if (!response.ok) {
|
|
121
|
+
console.warn('Failed to log page view:', await response.text());
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
catch (error) {
|
|
125
|
+
console.warn('Failed to log page view:', error);
|
|
126
|
+
}
|
|
42
127
|
}
|
|
128
|
+
// Track user action - batched
|
|
43
129
|
trackAction(action) {
|
|
44
130
|
const event = {
|
|
45
131
|
type: 'ACTION',
|
|
46
132
|
name: 'user_action',
|
|
47
|
-
data:
|
|
133
|
+
data: {
|
|
134
|
+
tenantId: this.tenantId,
|
|
135
|
+
userId: this.userId,
|
|
136
|
+
userRole: this.userRole,
|
|
137
|
+
sessionId: this.sessionId,
|
|
138
|
+
ipAddress: '', // Will be filled by backend
|
|
139
|
+
userAgent: navigator.userAgent,
|
|
140
|
+
activityType: action.actionType || 'USER_ACTION',
|
|
141
|
+
activityName: action.actionTarget || 'Unknown Action',
|
|
142
|
+
actionType: action.actionType || 'CLICK',
|
|
143
|
+
actionTarget: action.actionTarget,
|
|
144
|
+
actionData: action.actionData,
|
|
145
|
+
pageId: action.pageId || this.getCurrentPageId(),
|
|
146
|
+
browser: this.getBrowserInfo()
|
|
147
|
+
},
|
|
48
148
|
timestamp: new Date()
|
|
49
149
|
};
|
|
50
150
|
this.queueEvent(event);
|
|
51
151
|
}
|
|
152
|
+
// Track data change - sends directly (important for audit trail)
|
|
153
|
+
async logChange(changeData) {
|
|
154
|
+
try {
|
|
155
|
+
const response = await fetch(`${this.baseEndpoint}/change`, {
|
|
156
|
+
method: 'POST',
|
|
157
|
+
headers: {
|
|
158
|
+
'Content-Type': 'application/json',
|
|
159
|
+
'x-tenant-id': this.tenantId,
|
|
160
|
+
'x-user-id': this.userId,
|
|
161
|
+
'x-user-role': this.userRole,
|
|
162
|
+
'x-session-id': this.sessionId
|
|
163
|
+
},
|
|
164
|
+
body: JSON.stringify({
|
|
165
|
+
tenantId: this.tenantId,
|
|
166
|
+
userId: this.userId,
|
|
167
|
+
userRole: this.userRole,
|
|
168
|
+
sessionId: this.sessionId,
|
|
169
|
+
ipAddress: await this.getIPAddress(),
|
|
170
|
+
userAgent: navigator.userAgent,
|
|
171
|
+
entityType: changeData.entityType,
|
|
172
|
+
entityId: changeData.entityId,
|
|
173
|
+
type: changeData.type,
|
|
174
|
+
changes: changeData.changes,
|
|
175
|
+
reason: changeData.reason,
|
|
176
|
+
comment: changeData.comment,
|
|
177
|
+
status: changeData.status,
|
|
178
|
+
errorMessage: changeData.errorMessage,
|
|
179
|
+
parentEntityType: changeData.parentEntityType,
|
|
180
|
+
parentEntityId: changeData.parentEntityId
|
|
181
|
+
})
|
|
182
|
+
});
|
|
183
|
+
if (!response.ok) {
|
|
184
|
+
console.warn('Failed to log change:', await response.text());
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
catch (error) {
|
|
188
|
+
console.warn('Failed to log change:', error);
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
// Track data export - sends directly (important for compliance)
|
|
192
|
+
async logExport(exportData) {
|
|
193
|
+
try {
|
|
194
|
+
const response = await fetch(`${this.baseEndpoint}/export`, {
|
|
195
|
+
method: 'POST',
|
|
196
|
+
headers: {
|
|
197
|
+
'Content-Type': 'application/json',
|
|
198
|
+
'x-tenant-id': this.tenantId,
|
|
199
|
+
'x-user-id': this.userId,
|
|
200
|
+
'x-user-role': this.userRole,
|
|
201
|
+
'x-session-id': this.sessionId
|
|
202
|
+
},
|
|
203
|
+
body: JSON.stringify({
|
|
204
|
+
tenantId: this.tenantId,
|
|
205
|
+
userId: this.userId,
|
|
206
|
+
userRole: this.userRole,
|
|
207
|
+
sessionId: this.sessionId,
|
|
208
|
+
ipAddress: await this.getIPAddress(),
|
|
209
|
+
userAgent: navigator.userAgent,
|
|
210
|
+
exportType: exportData.exportType,
|
|
211
|
+
fileName: exportData.fileName,
|
|
212
|
+
recordCount: exportData.recordCount,
|
|
213
|
+
entityType: exportData.entityType,
|
|
214
|
+
entityIds: exportData.entityIds,
|
|
215
|
+
filters: exportData.filters,
|
|
216
|
+
columns: exportData.columns
|
|
217
|
+
})
|
|
218
|
+
});
|
|
219
|
+
if (!response.ok) {
|
|
220
|
+
console.warn('Failed to log export:', await response.text());
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
catch (error) {
|
|
224
|
+
console.warn('Failed to log export:', error);
|
|
225
|
+
}
|
|
226
|
+
}
|
|
52
227
|
trackNavigation(from, to) {
|
|
53
228
|
const event = {
|
|
54
229
|
type: 'NAVIGATION',
|
|
@@ -87,17 +262,27 @@ class ActivityMonitor {
|
|
|
87
262
|
const batch = [...this.eventQueue];
|
|
88
263
|
this.eventQueue = [];
|
|
89
264
|
try {
|
|
90
|
-
await fetch(this.
|
|
265
|
+
const response = await fetch(`${this.baseEndpoint}/batch`, {
|
|
91
266
|
method: 'POST',
|
|
92
267
|
headers: {
|
|
93
268
|
'Content-Type': 'application/json',
|
|
269
|
+
'x-tenant-id': this.tenantId,
|
|
270
|
+
'x-user-id': this.userId,
|
|
271
|
+
'x-user-role': this.userRole,
|
|
272
|
+
'x-session-id': this.sessionId
|
|
94
273
|
},
|
|
95
274
|
body: JSON.stringify({
|
|
96
275
|
sessionId: this.sessionId,
|
|
97
276
|
userId: this.userId,
|
|
98
|
-
events: batch
|
|
277
|
+
events: batch.map(event => ({
|
|
278
|
+
type: event.type,
|
|
279
|
+
data: event.data
|
|
280
|
+
}))
|
|
99
281
|
})
|
|
100
282
|
});
|
|
283
|
+
if (!response.ok) {
|
|
284
|
+
throw new Error(`Batch request failed: ${response.status}`);
|
|
285
|
+
}
|
|
101
286
|
}
|
|
102
287
|
catch (error) {
|
|
103
288
|
console.warn('Failed to send activity batch:', error);
|
|
@@ -145,13 +330,124 @@ class ActivityMonitor {
|
|
|
145
330
|
}
|
|
146
331
|
return 0;
|
|
147
332
|
}
|
|
148
|
-
|
|
333
|
+
getBrowserInfo() {
|
|
334
|
+
const ua = navigator.userAgent;
|
|
335
|
+
return {
|
|
336
|
+
name: navigator.appName,
|
|
337
|
+
version: navigator.appVersion,
|
|
338
|
+
os: this.getOS(),
|
|
339
|
+
device: this.getDeviceType()
|
|
340
|
+
};
|
|
341
|
+
}
|
|
342
|
+
getOS() {
|
|
343
|
+
const userAgent = window.navigator.userAgent;
|
|
344
|
+
const platform = window.navigator.platform;
|
|
345
|
+
const macosPlatforms = ['Macintosh', 'MacIntel', 'MacPPC', 'Mac68K'];
|
|
346
|
+
const windowsPlatforms = ['Win32', 'Win64', 'Windows', 'WinCE'];
|
|
347
|
+
const iosPlatforms = ['iPhone', 'iPad', 'iPod'];
|
|
348
|
+
if (macosPlatforms.indexOf(platform) !== -1) {
|
|
349
|
+
return 'macOS';
|
|
350
|
+
}
|
|
351
|
+
else if (iosPlatforms.indexOf(platform) !== -1) {
|
|
352
|
+
return 'iOS';
|
|
353
|
+
}
|
|
354
|
+
else if (windowsPlatforms.indexOf(platform) !== -1) {
|
|
355
|
+
return 'Windows';
|
|
356
|
+
}
|
|
357
|
+
else if (/Android/.test(userAgent)) {
|
|
358
|
+
return 'Android';
|
|
359
|
+
}
|
|
360
|
+
else if (/Linux/.test(platform)) {
|
|
361
|
+
return 'Linux';
|
|
362
|
+
}
|
|
363
|
+
return 'Unknown';
|
|
364
|
+
}
|
|
365
|
+
getDeviceType() {
|
|
366
|
+
const userAgent = navigator.userAgent;
|
|
367
|
+
if (/tablet|ipad|playbook|silk/i.test(userAgent)) {
|
|
368
|
+
return 'tablet';
|
|
369
|
+
}
|
|
370
|
+
if (/mobile|iphone|ipod|android|blackberry|opera mini|opera mobi|skyfire|maemo|windows phone|palm|iemobile|symbian|symbianos|fennec/i.test(userAgent)) {
|
|
371
|
+
return 'mobile';
|
|
372
|
+
}
|
|
373
|
+
return 'desktop';
|
|
374
|
+
}
|
|
375
|
+
async getGeoLocation() {
|
|
376
|
+
// Note: This requires user permission
|
|
377
|
+
if ('geolocation' in navigator) {
|
|
378
|
+
try {
|
|
379
|
+
const position = await new Promise((resolve, reject) => {
|
|
380
|
+
navigator.geolocation.getCurrentPosition(resolve, reject);
|
|
381
|
+
});
|
|
382
|
+
return {
|
|
383
|
+
latitude: position.coords.latitude,
|
|
384
|
+
longitude: position.coords.longitude
|
|
385
|
+
};
|
|
386
|
+
}
|
|
387
|
+
catch (error) {
|
|
388
|
+
// User denied permission or geolocation failed
|
|
389
|
+
return {};
|
|
390
|
+
}
|
|
391
|
+
}
|
|
392
|
+
return {};
|
|
393
|
+
}
|
|
394
|
+
async getIPAddress() {
|
|
395
|
+
try {
|
|
396
|
+
// This is a simple approach - you might want to use a different service
|
|
397
|
+
const response = await fetch('https://api.ipify.org?format=json');
|
|
398
|
+
const data = await response.json();
|
|
399
|
+
return data.ip || '';
|
|
400
|
+
}
|
|
401
|
+
catch (error) {
|
|
402
|
+
return '';
|
|
403
|
+
}
|
|
404
|
+
}
|
|
405
|
+
getNetworkInfo() {
|
|
406
|
+
if ('connection' in navigator) {
|
|
407
|
+
const conn = navigator.connection;
|
|
408
|
+
return {
|
|
409
|
+
connectionType: conn.type,
|
|
410
|
+
effectiveType: conn.effectiveType,
|
|
411
|
+
downlink: conn.downlink,
|
|
412
|
+
rtt: conn.rtt
|
|
413
|
+
};
|
|
414
|
+
}
|
|
415
|
+
return {};
|
|
416
|
+
}
|
|
417
|
+
async destroy() {
|
|
418
|
+
// Clear timers
|
|
149
419
|
if (this.batchTimer) {
|
|
150
420
|
clearInterval(this.batchTimer);
|
|
151
421
|
}
|
|
422
|
+
if (this.heartbeatTimer) {
|
|
423
|
+
clearInterval(this.heartbeatTimer);
|
|
424
|
+
}
|
|
152
425
|
// Send any remaining events
|
|
153
426
|
if (this.eventQueue.length > 0) {
|
|
154
|
-
this.sendBatch();
|
|
427
|
+
await this.sendBatch();
|
|
428
|
+
}
|
|
429
|
+
// End session on backend
|
|
430
|
+
await this.endSession();
|
|
431
|
+
}
|
|
432
|
+
async endSession() {
|
|
433
|
+
try {
|
|
434
|
+
await fetch(`${this.baseEndpoint}/session/end`, {
|
|
435
|
+
method: 'POST',
|
|
436
|
+
headers: {
|
|
437
|
+
'Content-Type': 'application/json',
|
|
438
|
+
'x-tenant-id': this.tenantId,
|
|
439
|
+
'x-user-id': this.userId,
|
|
440
|
+
'x-user-role': this.userRole,
|
|
441
|
+
'x-session-id': this.sessionId
|
|
442
|
+
},
|
|
443
|
+
body: JSON.stringify({
|
|
444
|
+
sessionId: this.sessionId,
|
|
445
|
+
reason: 'USER'
|
|
446
|
+
})
|
|
447
|
+
});
|
|
448
|
+
}
|
|
449
|
+
catch (error) {
|
|
450
|
+
console.warn('Failed to end session:', error);
|
|
155
451
|
}
|
|
156
452
|
}
|
|
157
453
|
}
|