@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,84 @@
|
|
|
1
|
+
import * as zlib from 'zlib';
|
|
2
|
+
|
|
3
|
+
// Shared libraries
|
|
4
|
+
import * as Util from '../util/all';
|
|
5
|
+
import * as Context from '../context/all';
|
|
6
|
+
import * as LogAbstract from '../logabstract/all';
|
|
7
|
+
import * as FSM from '../fsm/all';
|
|
8
|
+
import * as Storage from '../storage/all';
|
|
9
|
+
|
|
10
|
+
import { LogKey } from './logkey';
|
|
11
|
+
|
|
12
|
+
interface Environment
|
|
13
|
+
{
|
|
14
|
+
context: Context.IContext;
|
|
15
|
+
log: LogAbstract.ILog;
|
|
16
|
+
fsmManager: FSM.FsmManager;
|
|
17
|
+
storageManager: Storage.StorageManager;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export class LogBlob extends Storage.StorageBlob
|
|
21
|
+
{
|
|
22
|
+
key: LogKey;
|
|
23
|
+
|
|
24
|
+
constructor(env: Environment, params: Storage.BlobParams)
|
|
25
|
+
{
|
|
26
|
+
if (params.bucket === undefined) params.bucket = 'logs';
|
|
27
|
+
super(env, params);
|
|
28
|
+
this.key = LogKey.create(this.params.id);
|
|
29
|
+
this.filter = this.filter.bind(this);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
get env(): Environment { return this._env as Environment; }
|
|
33
|
+
|
|
34
|
+
get result(): string { return this.params.loadTo as string }
|
|
35
|
+
|
|
36
|
+
static createForDownload(env: Environment, id: string): LogBlob
|
|
37
|
+
{
|
|
38
|
+
let blob = new LogBlob(env, { id: id, loadToType: 'string' });
|
|
39
|
+
blob.startLoad(env.storageManager);
|
|
40
|
+
return blob;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
static createForUpload(env: Environment, id: string, data: string): LogBlob
|
|
44
|
+
{
|
|
45
|
+
let params: Storage.BlobParams = {
|
|
46
|
+
id: id,
|
|
47
|
+
ContentEncoding: 'gzip',
|
|
48
|
+
ContentType: 'application/json',
|
|
49
|
+
saveFromType: 'string',
|
|
50
|
+
saveFrom: data
|
|
51
|
+
};
|
|
52
|
+
let blob = new LogBlob(env, params);
|
|
53
|
+
blob.setDirty();
|
|
54
|
+
blob.checkSave(env.storageManager);
|
|
55
|
+
return blob;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
static createForDelete(env: Environment, id: string): LogBlob
|
|
59
|
+
{
|
|
60
|
+
let blob = new LogBlob(env, { id: id });
|
|
61
|
+
blob.startDelete(env.storageManager);
|
|
62
|
+
return blob;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
static createForLs(env: Environment): LogBlob
|
|
66
|
+
{
|
|
67
|
+
let blob = new LogBlob(env, { id: '' });
|
|
68
|
+
blob.startList(env.storageManager);
|
|
69
|
+
return blob;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
filter(s: string): boolean
|
|
73
|
+
{
|
|
74
|
+
let key = LogKey.create(s);
|
|
75
|
+
if (key == null) return false;
|
|
76
|
+
let mode = this.env.context.xflag('production') ? 'Prod' : 'Dev';
|
|
77
|
+
return key.mode === mode;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
asString(): string
|
|
81
|
+
{
|
|
82
|
+
return this.params.loadTo as string;
|
|
83
|
+
}
|
|
84
|
+
}
|
|
@@ -0,0 +1,313 @@
|
|
|
1
|
+
import * as fs from 'fs';
|
|
2
|
+
import * as stream from 'stream';
|
|
3
|
+
import * as zlib from 'zlib';
|
|
4
|
+
|
|
5
|
+
// Shared libraries
|
|
6
|
+
import * as Util from '../util/all';
|
|
7
|
+
import * as Context from '../context/all';
|
|
8
|
+
import * as LogAbstract from '../logabstract/all';
|
|
9
|
+
import * as FSM from '../fsm/all';
|
|
10
|
+
import * as Storage from '../storage/all';
|
|
11
|
+
|
|
12
|
+
import { LogBlob } from './logblob';
|
|
13
|
+
|
|
14
|
+
interface Environment
|
|
15
|
+
{
|
|
16
|
+
context: Context.IContext;
|
|
17
|
+
log: LogAbstract.ILog;
|
|
18
|
+
fsmManager: FSM.FsmManager;
|
|
19
|
+
storageManager: Storage.StorageManager;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
let UniqueState = FSM.FSM_CUSTOM1;
|
|
23
|
+
const FSM_BLOB = UniqueState++;
|
|
24
|
+
const FSM_QUERYING = UniqueState++;
|
|
25
|
+
const FSM_LISTING = UniqueState++;
|
|
26
|
+
const FSM_AGGREGATING = UniqueState++;
|
|
27
|
+
const FSM_SAVING = UniqueState++;
|
|
28
|
+
const FSM_LOADING = UniqueState++;
|
|
29
|
+
const FSM_DELETING = UniqueState++;
|
|
30
|
+
const FSM_FILTERING = UniqueState++;
|
|
31
|
+
|
|
32
|
+
const reLog = /^Log_([^_]*)_(\d{4}-\d{2}-\d{2}T\d{2}:)\d{2}:\d{2}.\d{3}Z_(\d+)_[^\.]+.csv$/;
|
|
33
|
+
const reLine = /^(.),(\d+),(.*)$/;
|
|
34
|
+
|
|
35
|
+
// The compaction process involves:
|
|
36
|
+
// 1. Listing the log files.
|
|
37
|
+
// 2. Grouping into sets to compact/concat.
|
|
38
|
+
// 3. Downloading the files and concatenating them.
|
|
39
|
+
// 4. Uploading the concatenated file.
|
|
40
|
+
// 5. Deleting the files used to construct the aggregate.
|
|
41
|
+
//
|
|
42
|
+
// The motivation for this is that further processing on the logs and log bucket will be
|
|
43
|
+
// much more efficient with a smaller number of larger files. In particular, the lambda
|
|
44
|
+
// instances result in lots of small log files.
|
|
45
|
+
//
|
|
46
|
+
|
|
47
|
+
function logToKey(env: Environment, log: string): string
|
|
48
|
+
{
|
|
49
|
+
// Log is of form:
|
|
50
|
+
// {Log,Agg}_{Prod,Dev}_YYYY-MM-DDTHH:MM:SS.UUUZ_{count}_{guid}.{csv,json}
|
|
51
|
+
// We are only concerned with Log_{Prod|Dev}_{datetime}_0_*.csv
|
|
52
|
+
// That is, we just want the small single instance log files.
|
|
53
|
+
// The key includes Log_Prod_YYYY-MM-DDTHH:
|
|
54
|
+
|
|
55
|
+
let prod = env.context.xflag('production') ? 'Prod' : 'Dev';
|
|
56
|
+
let a = reLog.exec(log);
|
|
57
|
+
if (a && a.length == 4 && a[3] == '0' && a[1] === prod)
|
|
58
|
+
return `Log_${a[1]}_${a[2]}`;
|
|
59
|
+
return null;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
export class FsmCompact extends FSM.Fsm
|
|
63
|
+
{
|
|
64
|
+
blobLs: LogBlob;
|
|
65
|
+
clusters: { [key: string]: string[] };
|
|
66
|
+
|
|
67
|
+
constructor(env: Environment)
|
|
68
|
+
{
|
|
69
|
+
super(env);
|
|
70
|
+
this.clusters = {};
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
get env(): Environment { return this._env as Environment }
|
|
74
|
+
|
|
75
|
+
gatherLogList(logs: string[]): void
|
|
76
|
+
{
|
|
77
|
+
logs.forEach((log: string) => {
|
|
78
|
+
let key = logToKey(this.env, log);
|
|
79
|
+
if (key)
|
|
80
|
+
{
|
|
81
|
+
let cluster = this.clusters[key];
|
|
82
|
+
if (cluster === undefined)
|
|
83
|
+
{
|
|
84
|
+
cluster = [];
|
|
85
|
+
this.clusters[key] = cluster;
|
|
86
|
+
}
|
|
87
|
+
cluster.push(log);
|
|
88
|
+
}
|
|
89
|
+
});
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
tick(): void
|
|
93
|
+
{
|
|
94
|
+
if (this.ready && this.isDependentError)
|
|
95
|
+
this.setState(FSM.FSM_ERROR);
|
|
96
|
+
else if (this.ready)
|
|
97
|
+
{
|
|
98
|
+
switch (this.state)
|
|
99
|
+
{
|
|
100
|
+
case FSM.FSM_STARTING:
|
|
101
|
+
this.blobLs = LogBlob.createForLs(this.env);
|
|
102
|
+
this.waitOn(this.blobLs.fsmArray);
|
|
103
|
+
this.setState(FSM_LISTING);
|
|
104
|
+
break;
|
|
105
|
+
|
|
106
|
+
case FSM_LISTING:
|
|
107
|
+
this.gatherLogList(this.blobLs.keys);
|
|
108
|
+
this.blobLs.resetList();
|
|
109
|
+
if (this.blobLs.fsmList.done)
|
|
110
|
+
this.setState(FSM_FILTERING);
|
|
111
|
+
else
|
|
112
|
+
this.waitOn(this.blobLs.fsmList);
|
|
113
|
+
break;
|
|
114
|
+
|
|
115
|
+
case FSM_FILTERING:
|
|
116
|
+
Object.keys(this.clusters).forEach((key: string) => {
|
|
117
|
+
let cluster = this.clusters[key];
|
|
118
|
+
if (cluster.length < 10)
|
|
119
|
+
delete this.clusters[key];
|
|
120
|
+
});
|
|
121
|
+
this.env.log.chatter(`logconcat: compacting ${Util.countKeys(this.clusters)} log clusters`);
|
|
122
|
+
this.setState(FSM_AGGREGATING);
|
|
123
|
+
break;
|
|
124
|
+
|
|
125
|
+
case FSM_AGGREGATING:
|
|
126
|
+
for (let key in this.clusters) if (this.clusters.hasOwnProperty(key))
|
|
127
|
+
{
|
|
128
|
+
let cluster = this.clusters[key];
|
|
129
|
+
this.waitOn(new FsmCompactOne(this.env, key, cluster));
|
|
130
|
+
delete this.clusters[key];
|
|
131
|
+
break; // one at a time
|
|
132
|
+
}
|
|
133
|
+
if (this.ready)
|
|
134
|
+
this.setState(FSM.FSM_DONE);
|
|
135
|
+
break;
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
// This is a little tricky because file format is wacky. Numeric value after 'S' in schema line is just
|
|
142
|
+
// the schema number (redundant to implicit ordering). The numeric value after 'T' in template line is
|
|
143
|
+
// a reference to the schema used on that line. The template number is implicit in the ordering. And then
|
|
144
|
+
// the number after 'L' in a log line is a reference to this implicit template numbering order.
|
|
145
|
+
|
|
146
|
+
class Permuter
|
|
147
|
+
{
|
|
148
|
+
tag: string; // 'T' or 'S'
|
|
149
|
+
entries: { [key: string]: { key: string, to: string, from: string } };
|
|
150
|
+
mapper: { [from: string]: string };
|
|
151
|
+
length: number;
|
|
152
|
+
|
|
153
|
+
constructor(tag: string)
|
|
154
|
+
{
|
|
155
|
+
this.tag = tag;
|
|
156
|
+
this.entries = {};
|
|
157
|
+
this.mapper = {};
|
|
158
|
+
this.length = 0;
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
reset(): void
|
|
162
|
+
{
|
|
163
|
+
Object.keys(this.entries).forEach((key: string) => {
|
|
164
|
+
let entry = this.entries[key];
|
|
165
|
+
entry.from = null;
|
|
166
|
+
});
|
|
167
|
+
this.mapper = {};
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
add(fields: string[]): void
|
|
171
|
+
{
|
|
172
|
+
if (fields.length != 4)
|
|
173
|
+
throw 'Permuter:add: unexpected line format';
|
|
174
|
+
let key = this.tag === 'S' ? fields[3] : `${fields[2]},${fields[3]}`;
|
|
175
|
+
let entry = this.entries[key];
|
|
176
|
+
if (entry === undefined)
|
|
177
|
+
{
|
|
178
|
+
entry = { key: key, to: String(this.length++), from: this.tag === 'S' ? fields[2] : String(Util.countKeys(this.mapper)) };
|
|
179
|
+
this.entries[key] = entry;
|
|
180
|
+
}
|
|
181
|
+
else
|
|
182
|
+
{
|
|
183
|
+
if (entry.from != null)
|
|
184
|
+
throw 'Permuter:add: unexpected duplicate field entry';
|
|
185
|
+
else
|
|
186
|
+
entry.from = this.tag === 'S' ? fields[2] : String(Util.countKeys(this.mapper));
|
|
187
|
+
}
|
|
188
|
+
this.mapper[entry.from] = entry.to;
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
map(from: string): string
|
|
192
|
+
{
|
|
193
|
+
return this.mapper[from];
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
asCSV(): string[]
|
|
197
|
+
{
|
|
198
|
+
let entryarray = Object.keys(this.entries).map((key: string) => { return this.entries[key] });
|
|
199
|
+
entryarray.sort((e1: any, e2: any) => { return Number(e1.to) < Number(e2.to) ? -1 : 1 });
|
|
200
|
+
return entryarray.map((e: any) => {
|
|
201
|
+
if (this.tag === 'S')
|
|
202
|
+
return new Array(this.tag, e.to, e.key).join(',');
|
|
203
|
+
else
|
|
204
|
+
return new Array(this.tag, e.key).join(',');
|
|
205
|
+
});
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
export class FsmCompactOne extends FSM.Fsm
|
|
210
|
+
{
|
|
211
|
+
key: string;
|
|
212
|
+
cluster: string[];
|
|
213
|
+
blobs: LogBlob[];
|
|
214
|
+
csv: string[];
|
|
215
|
+
schemas: Permuter;
|
|
216
|
+
templates: Permuter;
|
|
217
|
+
|
|
218
|
+
constructor(env: Environment, key: string, cluster: string[])
|
|
219
|
+
{
|
|
220
|
+
super(env);
|
|
221
|
+
this.key = key;
|
|
222
|
+
this.cluster = cluster;
|
|
223
|
+
this.csv = [];
|
|
224
|
+
this.schemas = new Permuter('S');
|
|
225
|
+
this.templates = new Permuter('T');
|
|
226
|
+
this.env.log.chatter(`logconcat: compacting ${this.key} with ${this.cluster.length} log files`);
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
get env(): Environment { return this._env as Environment }
|
|
230
|
+
|
|
231
|
+
loadBlobs(): void
|
|
232
|
+
{
|
|
233
|
+
this.blobs.forEach((blob: LogBlob) => {
|
|
234
|
+
let lines = blob.result.split('\n');
|
|
235
|
+
lines.forEach((line: string) => {
|
|
236
|
+
let a = reLine.exec(line);
|
|
237
|
+
if (a && a.length == 4)
|
|
238
|
+
{
|
|
239
|
+
switch (a[1])
|
|
240
|
+
{
|
|
241
|
+
case 'S': this.schemas.add(a); break;
|
|
242
|
+
case 'T': a[2] = this.schemas.map(a[2]); this.templates.add(a); break;
|
|
243
|
+
case 'L': a[2] = this.templates.map(a[2]); this.csv.push(a.slice(1).join(',')); break;
|
|
244
|
+
default:
|
|
245
|
+
throw 'FsmCompactOne: unexpected line in csv file';
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
});
|
|
249
|
+
this.schemas.reset();
|
|
250
|
+
this.templates.reset();
|
|
251
|
+
});
|
|
252
|
+
this.blobs = [];
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
saveBlobs(): void
|
|
256
|
+
{
|
|
257
|
+
let csv = [...this.schemas.asCSV(), ...this.templates.asCSV(), ...this.csv];
|
|
258
|
+
let key = `${this.key}00:00.000Z_0_${Util.createGuid()}.csv`;
|
|
259
|
+
this.env.log.chatter(`logconcat: uploading ${key}`);
|
|
260
|
+
let blob = LogBlob.createForUpload(this.env, key, csv.join('\n'));
|
|
261
|
+
this.waitOn(blob.fsmLoad);
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
deleteBlobs(): void
|
|
265
|
+
{
|
|
266
|
+
this.cluster.forEach((log: string) => {
|
|
267
|
+
let blob = LogBlob.createForDelete(this.env, log);
|
|
268
|
+
this.waitOn(blob.fsmDel);
|
|
269
|
+
});
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
tick(): void
|
|
273
|
+
{
|
|
274
|
+
if (this.ready && this.isDependentError)
|
|
275
|
+
{
|
|
276
|
+
this.env.log.error('logconcat: failure building log cluster');
|
|
277
|
+
this.env.log.chatter('logconcat: failure building log cluster');
|
|
278
|
+
this.setState(FSM.FSM_ERROR);
|
|
279
|
+
}
|
|
280
|
+
else if (this.ready)
|
|
281
|
+
{
|
|
282
|
+
switch (this.state)
|
|
283
|
+
{
|
|
284
|
+
case FSM.FSM_STARTING:
|
|
285
|
+
this.blobs = [];
|
|
286
|
+
this.cluster.forEach((log: string) => {
|
|
287
|
+
let blob = LogBlob.createForDownload(this.env, log);
|
|
288
|
+
this.blobs.push(blob);
|
|
289
|
+
this.waitOn(blob.fsmLoad);
|
|
290
|
+
});
|
|
291
|
+
this.setState(FSM_LOADING);
|
|
292
|
+
break;
|
|
293
|
+
|
|
294
|
+
case FSM_LOADING:
|
|
295
|
+
this.loadBlobs();
|
|
296
|
+
this.saveBlobs();
|
|
297
|
+
this.setState(FSM_SAVING);
|
|
298
|
+
break;
|
|
299
|
+
|
|
300
|
+
case FSM_SAVING:
|
|
301
|
+
this.deleteBlobs();
|
|
302
|
+
this.setState(FSM_DELETING);
|
|
303
|
+
break;
|
|
304
|
+
|
|
305
|
+
case FSM_DELETING:
|
|
306
|
+
this.env.log.chatter(`logconcat: compacted ${this.key}`);
|
|
307
|
+
this.setState(FSM.FSM_DONE);
|
|
308
|
+
break;
|
|
309
|
+
}
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
export function dateToKey(d: Date): string
|
|
2
|
+
{
|
|
3
|
+
let m = d.getUTCMonth() + 1;
|
|
4
|
+
let day = d.getUTCDate();
|
|
5
|
+
let yyyy = d.getFullYear();
|
|
6
|
+
let sm = m < 10 ? `0${m}` : String(m);
|
|
7
|
+
let sd = day < 10 ? `0${day}` : String(day);
|
|
8
|
+
|
|
9
|
+
return `${yyyy}.${sm}.${sd}`;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export function dateToMonthKey(d: Date): string
|
|
13
|
+
{
|
|
14
|
+
let m = d.getUTCMonth() + 1;
|
|
15
|
+
let yyyy = d.getFullYear();
|
|
16
|
+
let sm = m < 10 ? `0${m}` : String(m);
|
|
17
|
+
|
|
18
|
+
return `${yyyy}.${sm}`;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export function dateToYearKey(d: Date): string
|
|
22
|
+
{
|
|
23
|
+
return String(d.getFullYear());
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export class LogKey
|
|
27
|
+
{
|
|
28
|
+
kind: string;
|
|
29
|
+
mode: string;
|
|
30
|
+
date: string;
|
|
31
|
+
dateKey: string;
|
|
32
|
+
monthKey: string;
|
|
33
|
+
yearKey: string;
|
|
34
|
+
count: string;
|
|
35
|
+
instance: string;
|
|
36
|
+
ext: string;
|
|
37
|
+
|
|
38
|
+
constructor()
|
|
39
|
+
{
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
static root(): LogKey
|
|
43
|
+
{
|
|
44
|
+
let key = new LogKey();
|
|
45
|
+
key.kind = 'Agg';
|
|
46
|
+
return key;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
static create(s: string): LogKey
|
|
50
|
+
{
|
|
51
|
+
let key = new LogKey();
|
|
52
|
+
if (s == null || s == '') return null;
|
|
53
|
+
let iExt = s.lastIndexOf('.');
|
|
54
|
+
let ext = s.substring(iExt+1);
|
|
55
|
+
s = s.substring(0, iExt);
|
|
56
|
+
let a = s.split('_');
|
|
57
|
+
if (a.length == 5)
|
|
58
|
+
{
|
|
59
|
+
key.kind = a[0]; key.mode = a[1]; key.date = a[2]; key.count = a[3]; key.instance = a[4]; key.ext = ext;
|
|
60
|
+
}
|
|
61
|
+
else if (a.length == 3)
|
|
62
|
+
{
|
|
63
|
+
key.kind = a[0]; key.mode = a[1]; key.date = a[2]; key.ext = ext;
|
|
64
|
+
}
|
|
65
|
+
else
|
|
66
|
+
{
|
|
67
|
+
key.kind = 'unknown'; key.dateKey = 'unknown'; key.instance = s;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
if (key.kind === 'Log')
|
|
71
|
+
{
|
|
72
|
+
let d = new Date(key.date);
|
|
73
|
+
key.dateKey = dateToKey(d);
|
|
74
|
+
key.monthKey = dateToMonthKey(d);
|
|
75
|
+
key.yearKey = dateToYearKey(d);
|
|
76
|
+
}
|
|
77
|
+
else if (key.date)
|
|
78
|
+
{
|
|
79
|
+
let keys = key.date.split('.');
|
|
80
|
+
if (keys.length > 0)
|
|
81
|
+
key.yearKey = keys[0];
|
|
82
|
+
if (keys.length > 1)
|
|
83
|
+
key.monthKey = `${keys[0]}.${keys[1]}`;
|
|
84
|
+
if (keys.length > 2)
|
|
85
|
+
key.dateKey = key.date;
|
|
86
|
+
}
|
|
87
|
+
return key;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
yearClosed(): boolean { return (Number(this.yearKey) < Number(nowKey.yearKey)) }
|
|
91
|
+
monthClosed(): boolean { return (Number(this.monthKey) < Number(nowKey.monthKey)) }
|
|
92
|
+
dateClosed(): boolean { return this.dateKey !== nowKey.dateKey }
|
|
93
|
+
get closed(): boolean
|
|
94
|
+
{
|
|
95
|
+
if (this.kind === 'Log')
|
|
96
|
+
return true;
|
|
97
|
+
else if (this.kind === 'Agg')
|
|
98
|
+
{
|
|
99
|
+
if (this.dateKey)
|
|
100
|
+
return this.dateClosed();
|
|
101
|
+
else if (this.monthKey)
|
|
102
|
+
return this.monthClosed();
|
|
103
|
+
else
|
|
104
|
+
return this.yearClosed();
|
|
105
|
+
}
|
|
106
|
+
else
|
|
107
|
+
return true;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
get yearID(): string { return `Agg_${this.mode}_${this.yearKey}.json` }
|
|
111
|
+
get monthID(): string { return `Agg_${this.mode}_${this.monthKey}.json` }
|
|
112
|
+
get dateID(): string { return `Agg_${this.mode}_${this.dateKey}.json` }
|
|
113
|
+
|
|
114
|
+
get isYear(): boolean { return this.monthKey === undefined }
|
|
115
|
+
get isMonth(): boolean { return this.monthKey !== undefined && this.dateKey === undefined }
|
|
116
|
+
get isDate(): boolean { return this.kind === 'Agg' && this.dateKey !== undefined }
|
|
117
|
+
get isLog(): boolean { return this.kind === 'Log' }
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
let nowKey: LogKey = new LogKey();
|
|
121
|
+
let nowDate = new Date();
|
|
122
|
+
nowKey.dateKey = dateToKey(nowDate);
|
|
123
|
+
nowKey.monthKey = dateToMonthKey(nowDate);
|
|
124
|
+
nowKey.yearKey = dateToYearKey(nowDate);
|
|
125
|
+
|