@urga-panel/ur-panels-core 1.0.20 → 1.0.22
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/ServiceManager.js +34 -16
- package/dist/index.d.ts +2 -0
- package/dist/index.js +2 -0
- package/dist/services/abstract/authServices/AuthService.js +2 -3
- package/dist/services/abstract/pageServices/controllers/NSPageControllerService.js +2 -2
- package/dist/services/abstract/webviewServices/WVFrontService.js +3 -3
- package/dist/services/main/httpServices/RequestHandlerService.js +4 -4
- package/dist/services/main/logService/LogService.d.ts +31 -0
- package/dist/services/main/logService/LogService.js +131 -0
- package/dist/services/main/logService/index.d.ts +7 -0
- package/dist/services/main/logService/index.js +4 -0
- package/dist/services/main/logService/transports/ConsoleTransport.d.ts +16 -0
- package/dist/services/main/logService/transports/ConsoleTransport.js +62 -0
- package/dist/services/main/logService/transports/DatabaseTransport.d.ts +28 -0
- package/dist/services/main/logService/transports/DatabaseTransport.js +90 -0
- package/dist/services/main/logService/types.d.ts +23 -0
- package/dist/services/main/logService/types.js +1 -0
- package/dist/services/main/logService/utils/parseEnvConfig.d.ts +27 -0
- package/dist/services/main/logService/utils/parseEnvConfig.js +60 -0
- package/dist/services/main/remoteApiControllerService/RemoteApiControllerService.js +2 -2
- package/dist/services/main/testServices/TestService2.js +1 -1
- package/dist/types/Service.d.ts +17 -12
- package/dist/types/Service.js +31 -7
- package/dist/types/ServiceOts.d.ts +1 -0
- package/package.json +1 -1
- package/src/ServiceManager.ts +35 -16
- package/src/index.ts +4 -0
- package/src/services/abstract/authServices/AuthService.ts +2 -3
- package/src/services/abstract/pageServices/controllers/NSPageControllerService.ts +2 -2
- package/src/services/abstract/webviewServices/WVFrontService.ts +3 -3
- package/src/services/main/httpServices/RequestHandlerService.ts +4 -4
- package/src/services/main/logService/LogService.ts +151 -0
- package/src/services/main/logService/index.ts +7 -0
- package/src/services/main/logService/transports/ConsoleTransport.ts +73 -0
- package/src/services/main/logService/transports/DatabaseTransport.ts +116 -0
- package/src/services/main/logService/types.ts +26 -0
- package/src/services/main/logService/utils/parseEnvConfig.ts +78 -0
- package/src/services/main/remoteApiControllerService/RemoteApiControllerService.ts +2 -2
- package/src/services/main/testServices/TestService2.ts +1 -1
- package/src/types/Service.ts +54 -14
- package/src/types/ServiceOts.ts +1 -0
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
import { ILogEntry, ILogTransport } from "../types";
|
|
2
|
+
import { LogLevel } from "../../../../types/Service";
|
|
3
|
+
|
|
4
|
+
export interface DatabaseTransportOptions {
|
|
5
|
+
levels?: LogLevel[];
|
|
6
|
+
minLevel?: LogLevel;
|
|
7
|
+
getDatabaseService: () => any; // DatabaseService'i almak için callback
|
|
8
|
+
collectionName?: string; // Varsayılan: "logs"
|
|
9
|
+
batchSize?: number; // Toplu yazma için
|
|
10
|
+
flushInterval?: number; // ms cinsinden
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export class DatabaseTransport implements ILogTransport {
|
|
14
|
+
name = "DatabaseTransport";
|
|
15
|
+
levels?: LogLevel[];
|
|
16
|
+
minLevel?: LogLevel;
|
|
17
|
+
|
|
18
|
+
private getDatabaseService: () => any;
|
|
19
|
+
private collectionName: string;
|
|
20
|
+
private batchSize: number;
|
|
21
|
+
private flushInterval: number;
|
|
22
|
+
private logBuffer: ILogEntry[] = [];
|
|
23
|
+
private flushTimer?: NodeJS.Timeout;
|
|
24
|
+
|
|
25
|
+
private logLevelOrder: Record<LogLevel, number> = {
|
|
26
|
+
debug: 0,
|
|
27
|
+
info: 1,
|
|
28
|
+
success: 2,
|
|
29
|
+
warn: 3,
|
|
30
|
+
error: 4
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
constructor(options: DatabaseTransportOptions) {
|
|
34
|
+
this.getDatabaseService = options.getDatabaseService;
|
|
35
|
+
this.collectionName = options.collectionName || "logs";
|
|
36
|
+
this.batchSize = options.batchSize || 10;
|
|
37
|
+
this.flushInterval = options.flushInterval || 5000; // 5 saniye
|
|
38
|
+
|
|
39
|
+
if (options.levels) this.levels = options.levels;
|
|
40
|
+
if (options.minLevel) this.minLevel = options.minLevel;
|
|
41
|
+
|
|
42
|
+
// Periyodik flush başlat
|
|
43
|
+
this.startFlushTimer();
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
shouldLog(entry: ILogEntry): boolean {
|
|
47
|
+
// Eğer spesifik level'lar belirtilmişse
|
|
48
|
+
if (this.levels && this.levels.length > 0) {
|
|
49
|
+
return this.levels.includes(entry.level);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
// Eğer minimum level belirtilmişse
|
|
53
|
+
if (this.minLevel) {
|
|
54
|
+
return this.logLevelOrder[entry.level] >= this.logLevelOrder[this.minLevel];
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
// Varsayılan: sadece warn ve error
|
|
58
|
+
return entry.level === 'warn' || entry.level === 'error';
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
async log(entry: ILogEntry): Promise<void> {
|
|
62
|
+
// Buffer'a ekle
|
|
63
|
+
this.logBuffer.push(entry);
|
|
64
|
+
|
|
65
|
+
// Eğer buffer dolmuşsa hemen flush et
|
|
66
|
+
if (this.logBuffer.length >= this.batchSize) {
|
|
67
|
+
await this.flush();
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
async flush(): Promise<void> {
|
|
72
|
+
if (this.logBuffer.length === 0) return;
|
|
73
|
+
|
|
74
|
+
try {
|
|
75
|
+
const dbService = this.getDatabaseService();
|
|
76
|
+
if (!dbService || !dbService.client) {
|
|
77
|
+
console.error('[DatabaseTransport] DatabaseService not ready');
|
|
78
|
+
return;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
const db = dbService.client.db();
|
|
82
|
+
const logsCollection = db.collection(this.collectionName);
|
|
83
|
+
|
|
84
|
+
const documents = this.logBuffer.map(entry => ({
|
|
85
|
+
timestamp: entry.timestamp,
|
|
86
|
+
level: entry.level,
|
|
87
|
+
service: entry.tag,
|
|
88
|
+
namespace: entry.namespace,
|
|
89
|
+
message: entry.message,
|
|
90
|
+
args: entry.args,
|
|
91
|
+
createdAt: new Date()
|
|
92
|
+
}));
|
|
93
|
+
|
|
94
|
+
await logsCollection.insertMany(documents);
|
|
95
|
+
this.logBuffer = []; // Buffer'ı temizle
|
|
96
|
+
} catch (error) {
|
|
97
|
+
console.error('[DatabaseTransport] Failed to write logs:', error);
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
async close(): Promise<void> {
|
|
102
|
+
// Timer'ı durdur
|
|
103
|
+
if (this.flushTimer) {
|
|
104
|
+
clearInterval(this.flushTimer);
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
// Kalan log'ları flush et
|
|
108
|
+
await this.flush();
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
private startFlushTimer(): void {
|
|
112
|
+
this.flushTimer = setInterval(async () => {
|
|
113
|
+
await this.flush();
|
|
114
|
+
}, this.flushInterval);
|
|
115
|
+
}
|
|
116
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { LogLevel } from "../../../types/Service";
|
|
2
|
+
|
|
3
|
+
export interface ILogEntry {
|
|
4
|
+
timestamp: Date;
|
|
5
|
+
level: LogLevel;
|
|
6
|
+
tag: string;
|
|
7
|
+
namespace?: string;
|
|
8
|
+
message: string;
|
|
9
|
+
args: any[];
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export interface ILogTransport {
|
|
13
|
+
name: string;
|
|
14
|
+
levels?: LogLevel[]; // Eğer belirtilirse, sadece bu level'ları logla
|
|
15
|
+
minLevel?: LogLevel; // Eğer belirtilirse, bu level ve üstü
|
|
16
|
+
shouldLog(entry: ILogEntry): boolean; // Transport log'u kabul ediyor mu?
|
|
17
|
+
log(entry: ILogEntry): void | Promise<void>;
|
|
18
|
+
flush?(): void | Promise<void>;
|
|
19
|
+
close?(): void | Promise<void>;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export interface LogServiceConfig {
|
|
23
|
+
transports: ILogTransport[];
|
|
24
|
+
minLevel?: LogLevel;
|
|
25
|
+
enabledNamespaces?: string[]; // ['template:kurs', 'DatabaseService']
|
|
26
|
+
}
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import { LogLevel } from "../../../../types/Service";
|
|
2
|
+
import { LogServiceConfig } from "../types";
|
|
3
|
+
import { ConsoleTransport } from "../transports/ConsoleTransport";
|
|
4
|
+
|
|
5
|
+
export interface EnvLogConfig {
|
|
6
|
+
LOG_LEVEL?: string;
|
|
7
|
+
LOG_CONSOLE_LEVELS?: string;
|
|
8
|
+
LOG_NAMESPACES?: string;
|
|
9
|
+
LOG_DATABASE_ENABLED?: string;
|
|
10
|
+
LOG_DATABASE_LEVELS?: string;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Environment variable'lardan LogService config'i oluşturur
|
|
15
|
+
*
|
|
16
|
+
* Örnek .env:
|
|
17
|
+
* LOG_LEVEL=info
|
|
18
|
+
* LOG_CONSOLE_LEVELS=debug,info,success,warn,error
|
|
19
|
+
* LOG_NAMESPACES=DatabaseService,AuthService
|
|
20
|
+
* LOG_DATABASE_ENABLED=true
|
|
21
|
+
* LOG_DATABASE_LEVELS=warn,error
|
|
22
|
+
*/
|
|
23
|
+
export function parseLogConfigFromEnv(env: EnvLogConfig): Partial<LogServiceConfig> {
|
|
24
|
+
const config: Partial<LogServiceConfig> = {
|
|
25
|
+
transports: []
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
// Minimum log level
|
|
29
|
+
if (env.LOG_LEVEL) {
|
|
30
|
+
const level = env.LOG_LEVEL.toLowerCase();
|
|
31
|
+
if (['debug', 'info', 'success', 'warn', 'error'].includes(level)) {
|
|
32
|
+
config.minLevel = level as LogLevel;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
// Namespace filtreleme
|
|
37
|
+
if (env.LOG_NAMESPACES) {
|
|
38
|
+
config.enabledNamespaces = env.LOG_NAMESPACES
|
|
39
|
+
.split(',')
|
|
40
|
+
.map(s => s.trim())
|
|
41
|
+
.filter(s => s.length > 0);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
// ConsoleTransport (varsayılan olarak her zaman var)
|
|
45
|
+
let consoleLevels: LogLevel[] | undefined;
|
|
46
|
+
if (env.LOG_CONSOLE_LEVELS) {
|
|
47
|
+
consoleLevels = env.LOG_CONSOLE_LEVELS
|
|
48
|
+
.split(',')
|
|
49
|
+
.map(s => s.trim().toLowerCase())
|
|
50
|
+
.filter(s => ['debug', 'info', 'success', 'warn', 'error'].includes(s)) as LogLevel[];
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
config.transports!.push(new ConsoleTransport({
|
|
54
|
+
levels: consoleLevels
|
|
55
|
+
}));
|
|
56
|
+
|
|
57
|
+
return config;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* DatabaseTransport için config döner
|
|
62
|
+
*/
|
|
63
|
+
export function getDatabaseTransportConfigFromEnv(env: EnvLogConfig): { enabled: boolean, levels?: LogLevel[] } {
|
|
64
|
+
const enabled = env.LOG_DATABASE_ENABLED === 'true';
|
|
65
|
+
|
|
66
|
+
let levels: LogLevel[] | undefined;
|
|
67
|
+
if (env.LOG_DATABASE_LEVELS) {
|
|
68
|
+
levels = env.LOG_DATABASE_LEVELS
|
|
69
|
+
.split(',')
|
|
70
|
+
.map(s => s.trim().toLowerCase())
|
|
71
|
+
.filter(s => ['debug', 'info', 'success', 'warn', 'error'].includes(s)) as LogLevel[];
|
|
72
|
+
} else {
|
|
73
|
+
// Varsayılan: sadece warn ve error
|
|
74
|
+
levels = ['warn', 'error'];
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
return { enabled, levels };
|
|
78
|
+
}
|
|
@@ -46,11 +46,11 @@ export class RemoteApiControllerService extends Service {
|
|
|
46
46
|
}
|
|
47
47
|
addApi(apiName: string, serviceRef: any, apiConfig: apiConfig): void {
|
|
48
48
|
if (this.apis[apiName]) {
|
|
49
|
-
|
|
49
|
+
this.log.warn(`API ${apiName} already exists. Overwriting.`);
|
|
50
50
|
}
|
|
51
51
|
this.apis[apiName] = apiConfig;
|
|
52
52
|
this.apis[apiName].serviceRef = serviceRef;
|
|
53
|
-
|
|
53
|
+
this.log.info(`API ${apiName} added with config:`, apiConfig);
|
|
54
54
|
|
|
55
55
|
// Create a service for each API
|
|
56
56
|
Object.keys(this.apis).forEach(async apiName => {
|
|
@@ -13,7 +13,7 @@ export class Test2Service extends Service {
|
|
|
13
13
|
serviceInfo: { name: string; requiredServices: string[]; };
|
|
14
14
|
constructor(ots:Test2Ots) {
|
|
15
15
|
super({...ots});
|
|
16
|
-
|
|
16
|
+
this.log.info("Test2Service initialized");
|
|
17
17
|
}
|
|
18
18
|
|
|
19
19
|
protected async onSetup(options?: ServiceSetupOptions): Promise<ServiceResponse> {
|
package/src/types/Service.ts
CHANGED
|
@@ -2,6 +2,21 @@ import { ServiceOts } from "./ServiceOts";
|
|
|
2
2
|
import { ServiceResponse } from "./ServiceResponse";
|
|
3
3
|
import { ServiceSetupOptions } from "./ServiceSetupOptions";
|
|
4
4
|
|
|
5
|
+
export type LogLevel = 'debug' | 'info' | 'success' | 'warn' | 'error';
|
|
6
|
+
|
|
7
|
+
export interface ServiceLogger {
|
|
8
|
+
debug: (...args: any[]) => void;
|
|
9
|
+
info: (...args: any[]) => void;
|
|
10
|
+
success: (...args: any[]) => void;
|
|
11
|
+
warn: (...args: any[]) => void;
|
|
12
|
+
error: (...args: any[]) => void;
|
|
13
|
+
// Backward compatibility
|
|
14
|
+
OK: (...args: any[]) => void;
|
|
15
|
+
ERROR: (...args: any[]) => void;
|
|
16
|
+
WARN: (...args: any[]) => void;
|
|
17
|
+
l: (...args: any[]) => void;
|
|
18
|
+
}
|
|
19
|
+
|
|
5
20
|
export abstract class Service {
|
|
6
21
|
|
|
7
22
|
static serviceInfo: {
|
|
@@ -9,12 +24,8 @@ export abstract class Service {
|
|
|
9
24
|
requiredServices: string[];
|
|
10
25
|
}
|
|
11
26
|
public tag: string = "";
|
|
12
|
-
public
|
|
13
|
-
|
|
14
|
-
ERROR: Function,
|
|
15
|
-
l: Function,
|
|
16
|
-
WARN: Function
|
|
17
|
-
}
|
|
27
|
+
public namespace?: string;
|
|
28
|
+
public log: ServiceLogger;
|
|
18
29
|
|
|
19
30
|
protected abstract onSetup(options?: ServiceSetupOptions):Promise<ServiceResponse>;
|
|
20
31
|
protected abstract onStart(): Promise<ServiceResponse>;
|
|
@@ -40,22 +51,51 @@ export abstract class Service {
|
|
|
40
51
|
|
|
41
52
|
constructor(private opts: ServiceOts) {
|
|
42
53
|
this.tag = opts.tag;
|
|
54
|
+
this.namespace = opts.namespace;
|
|
55
|
+
|
|
43
56
|
if (!opts.usedService["LogService"]) {
|
|
44
|
-
//console.error("LogService not found for", opts.tag);
|
|
45
57
|
this.log = this.logSetup();
|
|
46
58
|
return;
|
|
47
59
|
}
|
|
48
60
|
else {
|
|
49
|
-
|
|
50
|
-
this.log = (opts.usedService["LogService"] as unknown as any).logSetupForService(this.tag);
|
|
61
|
+
this.log = (opts.usedService["LogService"] as unknown as any).logSetupForService(this.tag, this.namespace);
|
|
51
62
|
}
|
|
52
63
|
}
|
|
53
|
-
|
|
64
|
+
|
|
65
|
+
private getLogPrefix(): string {
|
|
66
|
+
if (this.namespace) {
|
|
67
|
+
return `[${this.namespace}:${this.tag}]`;
|
|
68
|
+
}
|
|
69
|
+
return `[${this.tag}]`;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
private formatMessage(level: LogLevel, ...args: any[]): any[] {
|
|
73
|
+
const timestamp = new Date().toLocaleTimeString('tr-TR', { hour12: false });
|
|
74
|
+
const prefix = this.getLogPrefix();
|
|
75
|
+
|
|
76
|
+
const icons: Record<LogLevel, string> = {
|
|
77
|
+
debug: '🔍',
|
|
78
|
+
info: 'ℹ️',
|
|
79
|
+
success: '✅',
|
|
80
|
+
warn: '⚠️',
|
|
81
|
+
error: '❌'
|
|
82
|
+
};
|
|
83
|
+
|
|
84
|
+
return [`${icons[level]} ${timestamp} ${prefix}`, ...args];
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
logSetup(): ServiceLogger {
|
|
54
88
|
return {
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
89
|
+
debug: (...args: any[]) => console.log(...this.formatMessage('debug', ...args)),
|
|
90
|
+
info: (...args: any[]) => console.log(...this.formatMessage('info', ...args)),
|
|
91
|
+
success: (...args: any[]) => console.log(...this.formatMessage('success', ...args)),
|
|
92
|
+
warn: (...args: any[]) => console.warn(...this.formatMessage('warn', ...args)),
|
|
93
|
+
error: (...args: any[]) => console.error(...this.formatMessage('error', ...args)),
|
|
94
|
+
// Backward compatibility
|
|
95
|
+
OK: (...args: any[]) => console.log(...this.formatMessage('success', ...args)),
|
|
96
|
+
ERROR: (...args: any[]) => console.error(...this.formatMessage('error', ...args)),
|
|
97
|
+
WARN: (...args: any[]) => console.warn(...this.formatMessage('warn', ...args)),
|
|
98
|
+
l: (...args: any[]) => console.log(...this.formatMessage('info', ...args)),
|
|
59
99
|
}
|
|
60
100
|
}
|
|
61
101
|
}
|