-
Notifications
You must be signed in to change notification settings - Fork 0
/
CachedLogger.ts
146 lines (129 loc) · 4.67 KB
/
CachedLogger.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
/** @module log */
import { ConfigParams } from 'pip-services-commons-node';
import { ErrorDescription } from 'pip-services-commons-node';
import { ErrorDescriptionFactory } from 'pip-services-commons-node';
import { LogLevel } from './LogLevel';
import { Logger } from './Logger';
import { LogMessage } from './LogMessage';
import { LogLevelConverter } from './LogLevelConverter';
/**
* Abstract logger that caches captured log messages in memory and periodically dumps them.
* Child classes implement saving cached messages to their specified destinations.
*
* ### Configuration parameters ###
*
* - level: maximum log level to capture
* - source: source (context) name
* - options:
* - interval: interval in milliseconds to save log messages (default: 10 seconds)
* - max_cache_size: maximum number of messages stored in this cache (default: 100)
*
* ### References ###
*
* - <code>\*:context-info:\*:\*:1.0</code> (optional) [[ContextInfo]] to detect the context id
* and specify counters source
*
* @see [[ILogger]]
* @see [[Logger]]
* @see [[LogMessage]]
*/
export abstract class CachedLogger extends Logger {
protected _cache: LogMessage[] = [];
protected _updated: boolean = false;
protected _lastDumpTime: number = new Date().getTime();
protected _maxCacheSize: number = 100;
protected _interval: number = 10000;
/**
* Creates a new instance of the logger.
*/
public constructor() {
super();
}
/**
* Writes a log message to the logger destination.
*
* @param level a log level.
* @param correlationId (optional) transaction id to trace execution through call chain.
* @param error an error object associated with this message.
* @param message a human-readable message to log.
*/
protected write(level: LogLevel, correlationId: string, error: Error, message: string): void {
let errorDesc: ErrorDescription = error != null ? ErrorDescriptionFactory.create(error) : null;
let logMessage: LogMessage = <LogMessage>{
time: new Date(),
level: LogLevelConverter.toString(level),
source: this._source,
correlation_id: correlationId,
error: errorDesc,
message: message
};
this._cache.push(logMessage);
this.update();
}
/**
* Saves log messages from the cache.
*
* @param messages a list with log messages
* @param callback callback function that receives error or null for success.
*/
protected abstract save(messages: LogMessage[], callback: (err: any) => void): void;
/**
* Configures component by passing configuration parameters.
*
* @param config configuration parameters to be set.
*/
public configure(config: ConfigParams): void {
super.configure(config);
this._interval = config.getAsLongWithDefault("options.interval", this._interval);
this._maxCacheSize = config.getAsIntegerWithDefault("options.max_cache_size", this._maxCacheSize);
}
/**
* Clears (removes) all cached log messages.
*/
public clear(): void {
this._cache = [];
this._updated = false;
}
/**
* Dumps (writes) the currently cached log messages.
*
* @see [[write]]
*/
public dump(): void {
if (this._updated) {
if (!this._updated) return;
let messages = this._cache;
this._cache = [];
this.save(messages, (err) => {
if (err) {
// Adds messages back to the cache
messages.push(...this._cache);
this._cache = messages;
// Truncate cache
let deleteCount = this._cache.length - this._maxCacheSize;
if (deleteCount > 0)
this._cache.splice(0, deleteCount);
}
});
this._updated = false;
this._lastDumpTime = new Date().getTime();
}
}
/**
* Makes message cache as updated
* and dumps it when timeout expires.
*
* @see [[dump]]
*/
protected update(): void {
this._updated = true;
let now = new Date().getTime();
if (now > this._lastDumpTime + this._interval) {
try {
this.dump();
} catch (ex) {
// Todo: decide what to do
}
}
}
}