@dra2020/baseclient 1.0.13 → 1.0.14
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/LICENSE +21 -0
- package/README.md +37 -0
- package/dist/all/all.d.ts +36 -0
- package/dist/all/allclient.d.ts +18 -0
- package/dist/base.js +33010 -0
- package/dist/base.js.map +1 -0
- package/dist/baseclient.js +8991 -0
- package/dist/baseclient.js.map +1 -0
- package/dist/context/all.d.ts +1 -0
- package/dist/context/context.d.ts +13 -0
- package/dist/dbabstract/all.d.ts +1 -0
- package/dist/dbabstract/db.d.ts +83 -0
- package/dist/dbdynamo/all.d.ts +1 -0
- package/dist/dbdynamo/dbdynamo.d.ts +190 -0
- package/dist/filterexpr/all.d.ts +1 -0
- package/dist/filterexpr/filterexpr.d.ts +64 -0
- package/dist/fsm/all.d.ts +1 -0
- package/dist/fsm/fsm.d.ts +118 -0
- package/dist/fsmfile/all.d.ts +1 -0
- package/dist/fsmfile/fsmfile.d.ts +47 -0
- package/dist/jsonstream/all.d.ts +1 -0
- package/dist/jsonstream/jsonstream.d.ts +130 -0
- package/dist/lambda/all.d.ts +1 -0
- package/dist/lambda/env.d.ts +10 -0
- package/dist/lambda/lambda.d.ts +18 -0
- package/dist/logabstract/all.d.ts +1 -0
- package/dist/logabstract/log.d.ts +26 -0
- package/dist/logclient/all.d.ts +1 -0
- package/dist/logclient/log.d.ts +6 -0
- package/dist/logserver/all.d.ts +5 -0
- package/dist/logserver/log.d.ts +11 -0
- package/dist/logserver/logaccum.d.ts +154 -0
- package/dist/logserver/logblob.d.ts +24 -0
- package/dist/logserver/logconcat.d.ts +55 -0
- package/dist/logserver/logkey.d.ts +28 -0
- package/dist/memsqs/all.d.ts +4 -0
- package/dist/memsqs/client.d.ts +13 -0
- package/dist/memsqs/loopback.d.ts +11 -0
- package/dist/memsqs/orderedlist.d.ts +19 -0
- package/dist/memsqs/queue.d.ts +84 -0
- package/dist/memsqs/server.d.ts +37 -0
- package/dist/ot-editutil/all.d.ts +2 -0
- package/dist/ot-editutil/oteditutil.d.ts +14 -0
- package/dist/ot-editutil/otmaputil.d.ts +21 -0
- package/dist/ot-js/all.d.ts +9 -0
- package/dist/ot-js/otarray.d.ts +111 -0
- package/dist/ot-js/otclientengine.d.ts +38 -0
- package/dist/ot-js/otcomposite.d.ts +37 -0
- package/dist/ot-js/otcounter.d.ts +17 -0
- package/dist/ot-js/otengine.d.ts +22 -0
- package/dist/ot-js/otmap.d.ts +19 -0
- package/dist/ot-js/otserverengine.d.ts +38 -0
- package/dist/ot-js/otsession.d.ts +111 -0
- package/dist/ot-js/ottypes.d.ts +29 -0
- package/dist/poly/all.d.ts +15 -0
- package/dist/poly/blend.d.ts +1 -0
- package/dist/poly/boundbox.d.ts +16 -0
- package/dist/poly/cartesian.d.ts +5 -0
- package/dist/poly/graham-scan.d.ts +8 -0
- package/dist/poly/hash.d.ts +1 -0
- package/dist/poly/matrix.d.ts +24 -0
- package/dist/poly/minbound.d.ts +1 -0
- package/dist/poly/poly.d.ts +52 -0
- package/dist/poly/polybin.d.ts +5 -0
- package/dist/poly/polylabel.d.ts +7 -0
- package/dist/poly/polypack.d.ts +30 -0
- package/dist/poly/polyround.d.ts +1 -0
- package/dist/poly/polysimplify.d.ts +1 -0
- package/dist/poly/quad.d.ts +48 -0
- package/dist/poly/selfintersect.d.ts +1 -0
- package/dist/poly/shamos.d.ts +1 -0
- package/dist/poly/simplify.d.ts +2 -0
- package/dist/poly/topo.d.ts +46 -0
- package/dist/poly/union.d.ts +48 -0
- package/dist/storage/all.d.ts +4 -0
- package/dist/storage/datablob.d.ts +9 -0
- package/dist/storage/env.d.ts +10 -0
- package/dist/storage/splitsblob.d.ts +13 -0
- package/dist/storage/storage.d.ts +166 -0
- package/dist/storages3/all.d.ts +1 -0
- package/dist/storages3/s3.d.ts +62 -0
- package/dist/util/all.d.ts +5 -0
- package/dist/util/bintrie.d.ts +93 -0
- package/dist/util/countedhash.d.ts +19 -0
- package/dist/util/gradient.d.ts +15 -0
- package/dist/util/indexedarray.d.ts +15 -0
- package/dist/util/util.d.ts +68 -0
- package/docs/context.md +2 -0
- package/docs/dbabstract.md +2 -0
- package/docs/dbdynamo.md +2 -0
- package/docs/fsm.md +243 -0
- package/docs/fsmfile.md +2 -0
- package/docs/jsonstream.md +44 -0
- package/docs/lambda.md +2 -0
- package/docs/logabstract.md +2 -0
- package/docs/logclient.md +2 -0
- package/docs/logserver.md +2 -0
- package/docs/ot-editutil.md +2 -0
- package/docs/ot-js.md +95 -0
- package/docs/poly.md +103 -0
- package/docs/storage.md +2 -0
- package/docs/storages3.md +2 -0
- package/docs/util.md +2 -0
- package/lib/all/all.ts +41 -0
- package/lib/all/allclient.ts +19 -0
- package/lib/context/all.ts +1 -0
- package/lib/context/context.ts +82 -0
- package/lib/dbabstract/all.ts +1 -0
- package/lib/dbabstract/db.ts +246 -0
- package/lib/dbdynamo/all.ts +1 -0
- package/lib/dbdynamo/dbdynamo.ts +1551 -0
- package/lib/filterexpr/all.ts +1 -0
- package/lib/filterexpr/filterexpr.ts +625 -0
- package/lib/fsm/all.ts +1 -0
- package/lib/fsm/fsm.ts +549 -0
- package/lib/fsmfile/all.ts +1 -0
- package/lib/fsmfile/fsmfile.ts +236 -0
- package/lib/jsonstream/all.ts +1 -0
- package/lib/jsonstream/jsonstream.ts +940 -0
- package/lib/lambda/all.ts +1 -0
- package/lib/lambda/env.ts +13 -0
- package/lib/lambda/lambda.ts +120 -0
- package/lib/logabstract/all.ts +1 -0
- package/lib/logabstract/log.ts +55 -0
- package/lib/logclient/all.ts +1 -0
- package/lib/logclient/log.ts +105 -0
- package/lib/logserver/all.ts +5 -0
- package/lib/logserver/log.ts +565 -0
- package/lib/logserver/logaccum.ts +1445 -0
- package/lib/logserver/logblob.ts +84 -0
- package/lib/logserver/logconcat.ts +313 -0
- package/lib/logserver/logkey.ts +125 -0
- package/lib/memsqs/all.ts +4 -0
- package/lib/memsqs/client.ts +268 -0
- package/lib/memsqs/loopback.ts +64 -0
- package/lib/memsqs/orderedlist.ts +74 -0
- package/lib/memsqs/queue.ts +395 -0
- package/lib/memsqs/server.ts +262 -0
- package/lib/ot-editutil/all.ts +2 -0
- package/lib/ot-editutil/oteditutil.ts +180 -0
- package/lib/ot-editutil/otmaputil.ts +209 -0
- package/lib/ot-js/all.ts +9 -0
- package/lib/ot-js/otarray.ts +1168 -0
- package/lib/ot-js/otclientengine.ts +327 -0
- package/lib/ot-js/otcomposite.ts +247 -0
- package/lib/ot-js/otcounter.ts +145 -0
- package/lib/ot-js/otengine.ts +71 -0
- package/lib/ot-js/otmap.ts +144 -0
- package/lib/ot-js/otserverengine.ts +329 -0
- package/lib/ot-js/otsession.ts +199 -0
- package/lib/ot-js/ottypes.ts +98 -0
- package/lib/poly/all.ts +15 -0
- package/lib/poly/blend.ts +27 -0
- package/lib/poly/boundbox.ts +102 -0
- package/lib/poly/cartesian.ts +130 -0
- package/lib/poly/graham-scan.ts +401 -0
- package/lib/poly/hash.ts +15 -0
- package/lib/poly/matrix.ts +309 -0
- package/lib/poly/minbound.ts +211 -0
- package/lib/poly/poly.ts +767 -0
- package/lib/poly/polybin.ts +218 -0
- package/lib/poly/polylabel.ts +204 -0
- package/lib/poly/polypack.ts +458 -0
- package/lib/poly/polyround.ts +30 -0
- package/lib/poly/polysimplify.ts +24 -0
- package/lib/poly/quad.ts +272 -0
- package/lib/poly/selfintersect.ts +87 -0
- package/lib/poly/shamos.ts +297 -0
- package/lib/poly/simplify.ts +119 -0
- package/lib/poly/topo.ts +525 -0
- package/lib/poly/union.ts +371 -0
- package/lib/storage/all.ts +4 -0
- package/lib/storage/datablob.ts +36 -0
- package/lib/storage/env.ts +14 -0
- package/lib/storage/splitsblob.ts +63 -0
- package/lib/storage/storage.ts +604 -0
- package/lib/storages3/all.ts +1 -0
- package/lib/storages3/s3.ts +576 -0
- package/lib/util/all.ts +5 -0
- package/lib/util/bintrie.ts +603 -0
- package/lib/util/countedhash.ts +83 -0
- package/lib/util/gradient.ts +108 -0
- package/lib/util/indexedarray.ts +80 -0
- package/lib/util/util.ts +695 -0
- package/package.json +8 -8
|
@@ -0,0 +1,565 @@
|
|
|
1
|
+
// Node libraries
|
|
2
|
+
import * as fs from 'fs';
|
|
3
|
+
import * as Stream from 'stream';
|
|
4
|
+
|
|
5
|
+
// Shared libraries
|
|
6
|
+
import * as LogAbstract from '../logabstract/all';
|
|
7
|
+
import * as Util from '../util/all';
|
|
8
|
+
import * as Context from '../context/all';
|
|
9
|
+
import * as Storage from '../storage/all';
|
|
10
|
+
import * as FSM from '../fsm/all';
|
|
11
|
+
import * as FF from '../fsmfile/all';
|
|
12
|
+
import * as JS from '../jsonstream/all';
|
|
13
|
+
|
|
14
|
+
export interface LogEnvironment
|
|
15
|
+
{
|
|
16
|
+
context: Context.IContext;
|
|
17
|
+
fsmManager: FSM.FsmManager;
|
|
18
|
+
storageManager: Storage.StorageManager;
|
|
19
|
+
log: LogAbstract.ILog;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
// Max size of log file (approximated)
|
|
23
|
+
const LogContextDefaults: Context.ContextValues = {
|
|
24
|
+
maxlogfilesize: 1000000,
|
|
25
|
+
maxloglatency: 1000 * 60 * 60 * 4, // every four hours
|
|
26
|
+
logtimeresolution: 1000 * 30, // output log timestamp every 30 seconds
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
const FSM_SAVING: number = FSM.FSM_CUSTOM1;
|
|
30
|
+
const FSM_UPLOADING: number = FSM.FSM_CUSTOM2;
|
|
31
|
+
|
|
32
|
+
// Current 'kind's of log entries in use:
|
|
33
|
+
// 'event': some event occurred (event property)
|
|
34
|
+
// 'error': some error happened
|
|
35
|
+
// 'value': some internal state variable has some value (name, value properties)
|
|
36
|
+
// 'sync': synchronous (blocking) time interval (ms property in milliseconds)
|
|
37
|
+
// 'async': elapsed time interval (ms property in milliseconds)
|
|
38
|
+
|
|
39
|
+
// LogManager receives logging requests (in object form) and buffers them to some internal size
|
|
40
|
+
// limit and then saves them out as a storage blob.
|
|
41
|
+
// Blobs are written out in a form that lets a separate offline process aggregate them as necessary.
|
|
42
|
+
// Entries are written as CSV entries with the first lines giving schema definitions for the
|
|
43
|
+
// entries in the file, subsequent entries defining templates with default values for log entries
|
|
44
|
+
// matching a specific schema and subsequent entries providing the data, matching a template.
|
|
45
|
+
// This allows both a flexible logging format as well as a compact representation.
|
|
46
|
+
//
|
|
47
|
+
// Schema are of the form:
|
|
48
|
+
// 'S',SchemaId,P1,P2,P3
|
|
49
|
+
//
|
|
50
|
+
// Templates are of the form:
|
|
51
|
+
// 'T',SchemaId,V1,V2,V3
|
|
52
|
+
//
|
|
53
|
+
// Entries are:
|
|
54
|
+
// 'L',TemplateId,V1,,V3
|
|
55
|
+
//
|
|
56
|
+
// Where "SchemaId" is a small integer and a line that starts with S defines the
|
|
57
|
+
// schema and a line that starts with T references it. A line that starts with L
|
|
58
|
+
// references a template and only specifies the values that differ from the template.
|
|
59
|
+
//
|
|
60
|
+
|
|
61
|
+
// A Schema maps property value to the index in the CSV line, starting with index 2
|
|
62
|
+
type Schema = { [prop: string]: number };
|
|
63
|
+
|
|
64
|
+
// A SchemaMapping indexes by a sequence ID for the Schema
|
|
65
|
+
type SchemaIndex = { [key: number]: Schema };
|
|
66
|
+
|
|
67
|
+
// A schema mapping maps a hash value for the schema to a small integer ID
|
|
68
|
+
type SchemaMapping = { [key: number]: number };
|
|
69
|
+
|
|
70
|
+
interface SchemaResult
|
|
71
|
+
{
|
|
72
|
+
schemaid: number;
|
|
73
|
+
schema: Schema;
|
|
74
|
+
csv: string | null;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
class SchemaManager
|
|
78
|
+
{
|
|
79
|
+
index: SchemaIndex;
|
|
80
|
+
map: SchemaMapping;
|
|
81
|
+
nextid: number;
|
|
82
|
+
|
|
83
|
+
constructor()
|
|
84
|
+
{
|
|
85
|
+
this.clear();
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
clear(): void
|
|
89
|
+
{
|
|
90
|
+
this.index = {};
|
|
91
|
+
this.map = {};
|
|
92
|
+
this.nextid = 0;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
private extractSchema(o: any): Schema
|
|
96
|
+
{
|
|
97
|
+
let s: Schema = {};
|
|
98
|
+
let i: number = 2; // index in CSV line for this value (starts with 'L,schemaid')
|
|
99
|
+
for (let p in o) if (o.hasOwnProperty(p))
|
|
100
|
+
s[p] = i++;
|
|
101
|
+
return s;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
add(o: any): SchemaResult
|
|
105
|
+
{
|
|
106
|
+
let s = this.extractSchema(o);
|
|
107
|
+
let h = Util.hashObject(s);
|
|
108
|
+
let id = this.map[h];
|
|
109
|
+
if (id === undefined)
|
|
110
|
+
{
|
|
111
|
+
id = this.nextid++;
|
|
112
|
+
this.map[h] = id;
|
|
113
|
+
this.index[h] = s;
|
|
114
|
+
|
|
115
|
+
// Build schema string
|
|
116
|
+
let sa: string[] = [];
|
|
117
|
+
sa.push('S');
|
|
118
|
+
sa.push(String(this.nextid-1));
|
|
119
|
+
for (let p in s) if (s.hasOwnProperty(p))
|
|
120
|
+
sa[s[p]] = p;
|
|
121
|
+
return { schemaid: id, schema: s, csv: sa.join(',') };
|
|
122
|
+
}
|
|
123
|
+
return { schemaid: id, schema: s, csv: null };
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
// A template is just an object with associated schema
|
|
128
|
+
interface Template
|
|
129
|
+
{
|
|
130
|
+
sr: SchemaResult;
|
|
131
|
+
o: any;
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
interface TemplateResult
|
|
135
|
+
{
|
|
136
|
+
templateid: number;
|
|
137
|
+
template: Template;
|
|
138
|
+
csv: string | null;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
function equalCount(o1: any, o2: any): number
|
|
142
|
+
{
|
|
143
|
+
let n: number = 0;
|
|
144
|
+
|
|
145
|
+
for (let p in o1) if (o1.hasOwnProperty(p))
|
|
146
|
+
if (typeof o1[p] !== 'number' && o1[p] === o2[p]) n++;
|
|
147
|
+
|
|
148
|
+
return n;
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
class TemplateManager
|
|
152
|
+
{
|
|
153
|
+
templates: Template[];
|
|
154
|
+
|
|
155
|
+
constructor()
|
|
156
|
+
{
|
|
157
|
+
this.clear();
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
clear(): void
|
|
161
|
+
{
|
|
162
|
+
this.templates = [];
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
add(sr: SchemaResult, o: any): TemplateResult
|
|
166
|
+
{
|
|
167
|
+
let tr: TemplateResult = { templateid: -1, template: null, csv: null };
|
|
168
|
+
let bestCount: number = 0;
|
|
169
|
+
let totalCount: number = 0;
|
|
170
|
+
for (let p in o) if (o.hasOwnProperty(p) && typeof o[p] !== 'number')
|
|
171
|
+
totalCount++;
|
|
172
|
+
|
|
173
|
+
for (let i: number = 0; i < this.templates.length; i++)
|
|
174
|
+
{
|
|
175
|
+
let t = this.templates[i];
|
|
176
|
+
if (t.sr.schemaid === sr.schemaid)
|
|
177
|
+
{
|
|
178
|
+
let n = equalCount(t.o, o);
|
|
179
|
+
if (tr.template == null || n > bestCount)
|
|
180
|
+
{
|
|
181
|
+
tr.template = t;
|
|
182
|
+
tr.templateid = i;
|
|
183
|
+
bestCount = n;
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
// Either found no template or found a poor one
|
|
189
|
+
if (tr.template == null || bestCount < totalCount)
|
|
190
|
+
{
|
|
191
|
+
o = Util.shallowCopy(o);
|
|
192
|
+
this.templates.push({ sr: sr, o: o });
|
|
193
|
+
tr.templateid = this.templates.length-1;
|
|
194
|
+
tr.template = this.templates[tr.templateid];
|
|
195
|
+
let sa: string[] = [];
|
|
196
|
+
sa.push('T');
|
|
197
|
+
sa.push(String(sr.schemaid));
|
|
198
|
+
for (let p in o) if (o.hasOwnProperty(p))
|
|
199
|
+
sa[sr.schema[p]] = csvField(o[p]);
|
|
200
|
+
tr.csv = sa.join(',');
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
return tr;
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
class LogInstance
|
|
208
|
+
{
|
|
209
|
+
env: LogEnvironment;
|
|
210
|
+
schemas: string[];
|
|
211
|
+
templates: string[];
|
|
212
|
+
log: string[];
|
|
213
|
+
size: number;
|
|
214
|
+
|
|
215
|
+
constructor(env: LogEnvironment)
|
|
216
|
+
{
|
|
217
|
+
this.env = env;
|
|
218
|
+
this.schemas = [];
|
|
219
|
+
this.log = [];
|
|
220
|
+
this.templates = [];
|
|
221
|
+
this.size = 0;
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
addSchema(s: string): void
|
|
225
|
+
{
|
|
226
|
+
this.schemas.push(s);
|
|
227
|
+
this.size += s.length + 2;
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
addTemplate(s: string): void
|
|
231
|
+
{
|
|
232
|
+
this.templates.push(s);
|
|
233
|
+
this.size += s.length + 2;
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
addLog(s: string): void
|
|
237
|
+
{
|
|
238
|
+
this.log.push(s);
|
|
239
|
+
this.size += s.length + 2;
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
full(): boolean
|
|
243
|
+
{
|
|
244
|
+
return this.size > this.env.context.xnumber('maxlogfilesize');
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
empty(): boolean
|
|
248
|
+
{
|
|
249
|
+
return this.size == 0;
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
class FsmSaveTmp extends FSM.Fsm
|
|
254
|
+
{
|
|
255
|
+
stream: JS.BufferWritable;
|
|
256
|
+
buffer: Buffer;
|
|
257
|
+
lines: string[][];
|
|
258
|
+
curArray: number;
|
|
259
|
+
curIndex: number;
|
|
260
|
+
|
|
261
|
+
constructor(env: LogEnvironment, log: LogInstance)
|
|
262
|
+
{
|
|
263
|
+
super(env);
|
|
264
|
+
this.stream = new JS.BufferWritable();
|
|
265
|
+
this.lines = [ log.schemas, log.templates, log.log ];
|
|
266
|
+
this.curArray = 0;
|
|
267
|
+
this.curIndex = 0;
|
|
268
|
+
this.onError = this.onError.bind(this);
|
|
269
|
+
this.onFinish = this.onFinish.bind(this);
|
|
270
|
+
this.onDrain = this.onDrain.bind(this);
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
start(): void
|
|
274
|
+
{
|
|
275
|
+
this.stream.on('error', this.onError);
|
|
276
|
+
this.stream.on('finish', this.onFinish);
|
|
277
|
+
this.write();
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
write(): void
|
|
281
|
+
{
|
|
282
|
+
if (this.stream)
|
|
283
|
+
{
|
|
284
|
+
let bOK: boolean = true;
|
|
285
|
+
|
|
286
|
+
for (; bOK && this.curArray < this.lines.length; this.curArray++, this.curIndex = 0)
|
|
287
|
+
{
|
|
288
|
+
let a = this.lines[this.curArray];
|
|
289
|
+
for (; bOK && this.curIndex < a.length; this.curIndex++)
|
|
290
|
+
{
|
|
291
|
+
bOK = this.stream.write(a[this.curIndex], 'utf8');
|
|
292
|
+
bOK = this.stream.write('\n', 'utf8') && bOK;
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
if (! bOK)
|
|
296
|
+
break;
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
if (this.curArray == this.lines.length)
|
|
300
|
+
this.stream.end();
|
|
301
|
+
else
|
|
302
|
+
this.stream.once('drain', this.onDrain);
|
|
303
|
+
}
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
onFinish(buffer?: Buffer): void
|
|
307
|
+
{
|
|
308
|
+
this.buffer = buffer;
|
|
309
|
+
if (this.stream)
|
|
310
|
+
this.stream = null;
|
|
311
|
+
if (! this.done)
|
|
312
|
+
this.setState(FSM.FSM_DONE);
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
onDrain(): void
|
|
316
|
+
{
|
|
317
|
+
this.write();
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
onError(): void
|
|
321
|
+
{
|
|
322
|
+
this.setState(FSM.FSM_ERROR);
|
|
323
|
+
this.onFinish();
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
tick(): void
|
|
327
|
+
{
|
|
328
|
+
if (this.ready)
|
|
329
|
+
{
|
|
330
|
+
switch (this.state)
|
|
331
|
+
{
|
|
332
|
+
case FSM.FSM_STARTING:
|
|
333
|
+
this.setState(FSM.FSM_PENDING);
|
|
334
|
+
this.start();
|
|
335
|
+
break;
|
|
336
|
+
}
|
|
337
|
+
}
|
|
338
|
+
}
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
class FsmUpload extends FSM.Fsm
|
|
342
|
+
{
|
|
343
|
+
log: LogInstance;
|
|
344
|
+
name: string;
|
|
345
|
+
fsmTmp: FsmSaveTmp;
|
|
346
|
+
fsmSave: FSM.Fsm;
|
|
347
|
+
|
|
348
|
+
constructor(env: LogEnvironment, name: string, log: LogInstance)
|
|
349
|
+
{
|
|
350
|
+
super(env);
|
|
351
|
+
this.name = name;
|
|
352
|
+
this.log = log;
|
|
353
|
+
}
|
|
354
|
+
|
|
355
|
+
get env(): LogEnvironment { return this._env as LogEnvironment; }
|
|
356
|
+
|
|
357
|
+
upload(buffer: Buffer): FSM.Fsm
|
|
358
|
+
{
|
|
359
|
+
let params: Storage.BlobParams = {
|
|
360
|
+
bucket: 'logs',
|
|
361
|
+
id: this.name,
|
|
362
|
+
saveFromType: 'buffer',
|
|
363
|
+
saveFrom: buffer,
|
|
364
|
+
ContentEncoding: 'gzip'
|
|
365
|
+
};
|
|
366
|
+
let blob = new Storage.StorageBlob(this.env, params);
|
|
367
|
+
blob.setDirty();
|
|
368
|
+
blob.checkSave(this.env.storageManager);
|
|
369
|
+
return blob.fsmSave;
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
tick(): void
|
|
373
|
+
{
|
|
374
|
+
if (this.ready)
|
|
375
|
+
{
|
|
376
|
+
switch (this.state)
|
|
377
|
+
{
|
|
378
|
+
case FSM.FSM_STARTING:
|
|
379
|
+
this.setState(FSM_SAVING);
|
|
380
|
+
this.fsmTmp = new FsmSaveTmp(this.env, this.log);
|
|
381
|
+
this.waitOn(this.fsmTmp);
|
|
382
|
+
break;
|
|
383
|
+
|
|
384
|
+
case FSM_SAVING:
|
|
385
|
+
this.setState(FSM_UPLOADING);
|
|
386
|
+
this.fsmSave = this.upload(this.fsmTmp.buffer);
|
|
387
|
+
this.waitOn(this.fsmSave);
|
|
388
|
+
break;
|
|
389
|
+
|
|
390
|
+
case FSM_UPLOADING:
|
|
391
|
+
this.setState(FSM.FSM_DONE);
|
|
392
|
+
break;
|
|
393
|
+
}
|
|
394
|
+
}
|
|
395
|
+
}
|
|
396
|
+
}
|
|
397
|
+
|
|
398
|
+
function csvField(a: any): string
|
|
399
|
+
{
|
|
400
|
+
let s = String(a);
|
|
401
|
+
let i = s.indexOf('"');
|
|
402
|
+
let j = s.indexOf(',');
|
|
403
|
+
if (i == -1 && j == -1)
|
|
404
|
+
return s;
|
|
405
|
+
return `'${s}'`;
|
|
406
|
+
}
|
|
407
|
+
|
|
408
|
+
class LogManager implements LogAbstract.ILog
|
|
409
|
+
{
|
|
410
|
+
env: LogEnvironment;
|
|
411
|
+
id: string;
|
|
412
|
+
count: number;
|
|
413
|
+
nextid: number;
|
|
414
|
+
schemaManager: SchemaManager;
|
|
415
|
+
templateManager: TemplateManager;
|
|
416
|
+
curLog: LogInstance;
|
|
417
|
+
msLatencyDump: number;
|
|
418
|
+
msLatencyStamp: number;
|
|
419
|
+
stamps: any[];
|
|
420
|
+
toconsole: boolean;
|
|
421
|
+
msExpireDump: number;
|
|
422
|
+
msExpireStamp: number;
|
|
423
|
+
_chatters: string[];
|
|
424
|
+
|
|
425
|
+
constructor(env: LogEnvironment)
|
|
426
|
+
{
|
|
427
|
+
this.env = env;
|
|
428
|
+
env.context.setDefaults(LogContextDefaults);
|
|
429
|
+
this.id = Util.createGuid(); // guid for this server instance
|
|
430
|
+
this.count = 0;
|
|
431
|
+
this.nextid = 0; // to make next log file name unique
|
|
432
|
+
this.stamps = [];
|
|
433
|
+
this.schemaManager = new SchemaManager();
|
|
434
|
+
this.templateManager = new TemplateManager();
|
|
435
|
+
this.curLog = new LogInstance(this.env);
|
|
436
|
+
this.toconsole = env.context.xflag('log_to_console');
|
|
437
|
+
this.msLatencyDump = env.context.xnumber('maxloglatency');
|
|
438
|
+
this.msLatencyStamp = env.context.xnumber('logtimeresolution');
|
|
439
|
+
let msNow = (new Date()).getTime();
|
|
440
|
+
this.msExpireDump = msNow + this.msLatencyDump;
|
|
441
|
+
this.msExpireStamp = msNow + this.msLatencyStamp;
|
|
442
|
+
this._chatters = null;
|
|
443
|
+
}
|
|
444
|
+
|
|
445
|
+
logit(o: any): void
|
|
446
|
+
{
|
|
447
|
+
if (this.toconsole) console.log(JSON.stringify(o));
|
|
448
|
+
// Add to current aggregate
|
|
449
|
+
let sr: SchemaResult = this.schemaManager.add(o);
|
|
450
|
+
if (sr.csv)
|
|
451
|
+
this.curLog.addSchema(sr.csv);
|
|
452
|
+
let tr: TemplateResult = this.templateManager.add(sr, o);
|
|
453
|
+
if (tr.csv)
|
|
454
|
+
this.curLog.addTemplate(tr.csv);
|
|
455
|
+
let sa: string[] = [];
|
|
456
|
+
sa.push('L');
|
|
457
|
+
sa.push(String(tr.templateid));
|
|
458
|
+
for (let p in o) if (o.hasOwnProperty(p))
|
|
459
|
+
{
|
|
460
|
+
if (o[p] !== tr.template.o[p])
|
|
461
|
+
sa[sr.schema[p]] = csvField(o[p]);
|
|
462
|
+
else
|
|
463
|
+
sa[sr.schema[p]] = '';
|
|
464
|
+
}
|
|
465
|
+
this.curLog.addLog(sa.join(','));
|
|
466
|
+
}
|
|
467
|
+
|
|
468
|
+
stampit(): void
|
|
469
|
+
{
|
|
470
|
+
for (let i: number = 0; i < this.stamps.length; i++)
|
|
471
|
+
this.logit(this.stamps[i]);
|
|
472
|
+
}
|
|
473
|
+
|
|
474
|
+
stamp(o: any): void
|
|
475
|
+
{
|
|
476
|
+
this.stamps.push(o);
|
|
477
|
+
}
|
|
478
|
+
|
|
479
|
+
log(o: any, verbosity: number = 0): void
|
|
480
|
+
{
|
|
481
|
+
// Show some restraint
|
|
482
|
+
if (verbosity > this.env.context.xnumber('verbosity'))
|
|
483
|
+
return;
|
|
484
|
+
|
|
485
|
+
let msNow = (new Date()).getTime();
|
|
486
|
+
|
|
487
|
+
if (o.kind === undefined)
|
|
488
|
+
o.kind = 'misc';
|
|
489
|
+
|
|
490
|
+
// Keep count at top of log
|
|
491
|
+
this.count++;
|
|
492
|
+
if (this.curLog.log.length === 0)
|
|
493
|
+
{
|
|
494
|
+
this.logit({ kind: 'misc', _count: this.count });
|
|
495
|
+
this.stampit(); // Ensure every log file has these entries stamped on them
|
|
496
|
+
}
|
|
497
|
+
|
|
498
|
+
// Keep timestamp every 5 seconds when it changes from the setInterval call above
|
|
499
|
+
if (this.msExpireStamp < msNow)
|
|
500
|
+
{
|
|
501
|
+
this.logit({ kind: 'misc', _time: Util.Now() });
|
|
502
|
+
this.msExpireStamp = msNow + this.msLatencyStamp;
|
|
503
|
+
}
|
|
504
|
+
|
|
505
|
+
this.logit(o);
|
|
506
|
+
|
|
507
|
+
if (this.curLog.full() || this.msExpireDump < msNow)
|
|
508
|
+
this.rotateLog();
|
|
509
|
+
}
|
|
510
|
+
|
|
511
|
+
rotateLog(): FSM.Fsm
|
|
512
|
+
{
|
|
513
|
+
let prod = this.env.context.xflag('production') ? 'Prod' : 'Dev';
|
|
514
|
+
let fsm = new FsmUpload(this.env, `Log_${prod}_${Util.Now()}_${this.nextid++}_${this.id}.csv`, this.curLog);
|
|
515
|
+
this.curLog = new LogInstance(this.env);
|
|
516
|
+
this.schemaManager.clear();
|
|
517
|
+
this.templateManager.clear();
|
|
518
|
+
this.msExpireDump = (new Date()).getTime() + this.msLatencyDump;
|
|
519
|
+
return fsm;
|
|
520
|
+
}
|
|
521
|
+
|
|
522
|
+
dump(): FSM.Fsm
|
|
523
|
+
{
|
|
524
|
+
return this.rotateLog();
|
|
525
|
+
}
|
|
526
|
+
|
|
527
|
+
event(o: any, verbosity: number = 0): void
|
|
528
|
+
{
|
|
529
|
+
if (typeof o === 'string') o = { event: o };
|
|
530
|
+
o.kind = 'event';
|
|
531
|
+
this.log(o, verbosity);
|
|
532
|
+
}
|
|
533
|
+
|
|
534
|
+
error(o: any): void
|
|
535
|
+
{
|
|
536
|
+
if (typeof o === 'string') o = { event: o };
|
|
537
|
+
o.kind = 'error';
|
|
538
|
+
this.log(o);
|
|
539
|
+
}
|
|
540
|
+
|
|
541
|
+
value(o: any, verbosity: number = 0): void
|
|
542
|
+
{
|
|
543
|
+
o.kind = 'value';
|
|
544
|
+
this.log(o, verbosity);
|
|
545
|
+
}
|
|
546
|
+
|
|
547
|
+
chatter(s: string): void
|
|
548
|
+
{
|
|
549
|
+
console.log(s);
|
|
550
|
+
if (this._chatters)
|
|
551
|
+
this._chatters.push(s);
|
|
552
|
+
}
|
|
553
|
+
|
|
554
|
+
chatters(): string[]
|
|
555
|
+
{
|
|
556
|
+
if (this._chatters == null)
|
|
557
|
+
this._chatters = [];
|
|
558
|
+
return this._chatters;
|
|
559
|
+
}
|
|
560
|
+
}
|
|
561
|
+
|
|
562
|
+
export function create(env: LogEnvironment): LogAbstract.ILog
|
|
563
|
+
{
|
|
564
|
+
return new LogManager(env);
|
|
565
|
+
}
|