whet 0.1.0 → 0.2.0

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.
@@ -1,7 +1,9 @@
1
1
  import {MemoryCache} from "./MemoryCache.js"
2
2
  import {FileCache} from "./FileCache.js"
3
3
  import {CacheStrategy, CacheDurability, DurabilityCheck} from "./Cache.js"
4
+ import {BaseCache} from "./BaseCache.js"
4
5
  import {RootDir} from "../SourceId.js"
6
+ import {SourceHash} from "../SourceHash.js"
5
7
  import {Log} from "../Log.js"
6
8
  import * as Path from "path"
7
9
  import {Register} from "../../genes/Register.js"
@@ -26,8 +28,36 @@ class CacheManager extends Register.inherits() {
26
28
  switch (_g._hx_index) {
27
29
  case 0:
28
30
  return stone.acquire(function () {
29
- return stone.finalMaybeHash().then(function (hash) {
30
- return stone.generateSource(hash);
31
+ return ((stone.project.profiler != null) ? stone.project.profiler.withSpan(stone, "Hash", function () {
32
+ return stone.finalMaybeHash().then(function (hash) {
33
+ let span = (stone.project.profiler != null) ? stone.project.profiler.getCurrentSpan() : null;
34
+ let meta = (hash != null) ? SourceHash.toHex(hash) : null;
35
+ if (span != null) {
36
+ span.metadata = {"hashHex": meta};
37
+ };
38
+ return hash;
39
+ });
40
+ }, null) : stone.finalMaybeHash().then(function (hash) {
41
+ let span = (stone.project.profiler != null) ? stone.project.profiler.getCurrentSpan() : null;
42
+ let meta = (hash != null) ? SourceHash.toHex(hash) : null;
43
+ if (span != null) {
44
+ span.metadata = {"hashHex": meta};
45
+ };
46
+ return hash;
47
+ })).then(function (hash) {
48
+ if (stone.project.profiler != null) {
49
+ return stone.project.profiler.withSpan(stone, "Generate", function () {
50
+ return stone.generateSource(hash).then(function (src) {
51
+ BaseCache.setGenerateMeta((stone.project.profiler != null) ? stone.project.profiler.getCurrentSpan() : null, src);
52
+ return src;
53
+ });
54
+ }, null);
55
+ } else {
56
+ return stone.generateSource(hash).then(function (src) {
57
+ BaseCache.setGenerateMeta((stone.project.profiler != null) ? stone.project.profiler.getCurrentSpan() : null, src);
58
+ return src;
59
+ });
60
+ };
31
61
  });
32
62
  });
33
63
  break
@@ -51,10 +81,34 @@ class CacheManager extends Register.inherits() {
51
81
  switch (_g._hx_index) {
52
82
  case 0:
53
83
  return stone.acquire(function () {
54
- return stone.finalMaybeHash().then(function (hash) {
55
- return stone.generatePartialSource(sourceId, hash).then(function (r) {
56
- return r.source.filterTo(sourceId);
84
+ return ((stone.project.profiler != null) ? stone.project.profiler.withSpan(stone, "Hash", function () {
85
+ return stone.finalMaybeHash().then(function (hash) {
86
+ let span = (stone.project.profiler != null) ? stone.project.profiler.getCurrentSpan() : null;
87
+ let meta = (hash != null) ? SourceHash.toHex(hash) : null;
88
+ if (span != null) {
89
+ span.metadata = {"hashHex": meta};
90
+ };
91
+ return hash;
57
92
  });
93
+ }, null) : stone.finalMaybeHash().then(function (hash) {
94
+ let span = (stone.project.profiler != null) ? stone.project.profiler.getCurrentSpan() : null;
95
+ let meta = (hash != null) ? SourceHash.toHex(hash) : null;
96
+ if (span != null) {
97
+ span.metadata = {"hashHex": meta};
98
+ };
99
+ return hash;
100
+ })).then(function (hash) {
101
+ if (stone.project.profiler != null) {
102
+ return stone.project.profiler.withSpan(stone, "GeneratePartial", function () {
103
+ return stone.generatePartialSource(sourceId, hash).then(function (r) {
104
+ return r.source.filterTo(sourceId);
105
+ });
106
+ }, {"sourceId": sourceId});
107
+ } else {
108
+ return stone.generatePartialSource(sourceId, hash).then(function (r) {
109
+ return r.source.filterTo(sourceId);
110
+ });
111
+ };
58
112
  });
59
113
  });
60
114
  break
@@ -82,8 +136,36 @@ class CacheManager extends Register.inherits() {
82
136
  switch (stone.cacheStrategy._hx_index) {
83
137
  case 0:
84
138
  return stone.acquire(function () {
85
- return stone.finalMaybeHash().then(function (hash) {
86
- return stone.generateSource(hash);
139
+ return ((stone.project.profiler != null) ? stone.project.profiler.withSpan(stone, "Hash", function () {
140
+ return stone.finalMaybeHash().then(function (hash) {
141
+ let span = (stone.project.profiler != null) ? stone.project.profiler.getCurrentSpan() : null;
142
+ let meta = (hash != null) ? SourceHash.toHex(hash) : null;
143
+ if (span != null) {
144
+ span.metadata = {"hashHex": meta};
145
+ };
146
+ return hash;
147
+ });
148
+ }, null) : stone.finalMaybeHash().then(function (hash) {
149
+ let span = (stone.project.profiler != null) ? stone.project.profiler.getCurrentSpan() : null;
150
+ let meta = (hash != null) ? SourceHash.toHex(hash) : null;
151
+ if (span != null) {
152
+ span.metadata = {"hashHex": meta};
153
+ };
154
+ return hash;
155
+ })).then(function (hash) {
156
+ if (stone.project.profiler != null) {
157
+ return stone.project.profiler.withSpan(stone, "Generate", function () {
158
+ return stone.generateSource(hash).then(function (src) {
159
+ BaseCache.setGenerateMeta((stone.project.profiler != null) ? stone.project.profiler.getCurrentSpan() : null, src);
160
+ return src;
161
+ });
162
+ }, null);
163
+ } else {
164
+ return stone.generateSource(hash).then(function (src) {
165
+ BaseCache.setGenerateMeta((stone.project.profiler != null) ? stone.project.profiler.getCurrentSpan() : null, src);
166
+ return src;
167
+ });
168
+ };
87
169
  });
88
170
  });
89
171
  break
@@ -0,0 +1,65 @@
1
+ import {SpanStats} from "./SpanStats"
2
+ import {SpanRecorder} from "./SpanRecorder"
3
+ import {SpanEvent, AnySpan, SpanEventType} from "./Span"
4
+ import {AnyStone} from "../Stone"
5
+ import {AsyncLocalStorage} from "node:async_hooks"
6
+
7
+ export declare class Profiler {
8
+ constructor(config?: null | ProfilerConfig)
9
+ recorder: SpanRecorder
10
+ stats: SpanStats
11
+ protected listeners: ((arg0: SpanEvent) => void)[]
12
+ protected context: AsyncLocalStorage<AnySpan>
13
+ protected baseEpochUs: number
14
+ protected basePerfUs: number
15
+ protected nextSpanId: number
16
+
17
+ /**
18
+ Primary API: wraps an async operation with timing and ALS context.
19
+ */
20
+ withSpan<T, R>(stone: AnyStone, op: string, fn: (() => Promise<R>), meta?: null | T): Promise<R>
21
+
22
+ /**
23
+ Secondary API: manual start for spans where no function can be wrapped (e.g. LockWait).
24
+ */
25
+ startSpan<T>(stone: AnyStone, op: string, meta?: null | T): AnySpan
26
+
27
+ /**
28
+ Complete a manually started span.
29
+ */
30
+ endSpan(span: AnySpan): void
31
+
32
+ /**
33
+ Returns the current span from AsyncLocalStorage context, or null if none.
34
+ */
35
+ getCurrentSpan(): null | AnySpan
36
+
37
+ /**
38
+ Subscribe to span events. Returns unsubscribe function.
39
+ */
40
+ subscribe(listener: ((arg0: SpanEvent) => void)): (() => void)
41
+
42
+ /**
43
+ Export spans in the given format ("json" or "trace"). Defaults to "json".
44
+ */
45
+ export(format: string): any
46
+
47
+ /**
48
+ Return spans recorded since the given span ID (exclusive).
49
+ */
50
+ getSpansSince(sinceId: number): AnySpan[]
51
+
52
+ /**
53
+ Return aggregated profiling summary.
54
+ */
55
+ getSummary(): any
56
+ protected exportJson(): any
57
+ protected exportChromeTrace(): any
58
+ protected serializeSpan(span: AnySpan): any
59
+ protected emit(type: SpanEventType, span: AnySpan): void
60
+ protected static ensureStoneEntry(byStone: {[key: string]: any}, stone: string): void
61
+ }
62
+
63
+ export type ProfilerConfig = {
64
+ maxSpans?: null | number
65
+ }
@@ -0,0 +1,351 @@
1
+ import {SpanStats} from "./SpanStats.js"
2
+ import {SpanRecorder} from "./SpanRecorder.js"
3
+ import {Span, SpanEventType, SpanStatus} from "./Span.js"
4
+ import {AsyncLocalStorage} from "node:async_hooks"
5
+ import {IntMap} from "../../haxe/ds/IntMap.js"
6
+ import {EsMap} from "../../genes/util/EsMap.js"
7
+ import {Register} from "../../genes/Register.js"
8
+ import {Std} from "../../Std.js"
9
+ import {Reflect as Reflect__1} from "../../Reflect.js"
10
+ import {HxOverrides} from "../../HxOverrides.js"
11
+
12
+ const $global = Register.$global
13
+
14
+ export const Profiler = Register.global("$hxClasses")["whet.profiler.Profiler"] =
15
+ class Profiler extends Register.inherits() {
16
+ [Register.new](config) {
17
+ this.nextSpanId = 0;
18
+ this.listeners = [];
19
+ this.recorder = new SpanRecorder((config != null && config.maxSpans != null) ? config.maxSpans : 10000);
20
+ this.stats = new SpanStats();
21
+ this.context = new AsyncLocalStorage();
22
+ this.baseEpochUs = Date.now() * 1000;
23
+ this.basePerfUs = performance.now() * 1000;
24
+ }
25
+
26
+ /**
27
+ Primary API: wraps an async operation with timing and ALS context.
28
+ */
29
+ withSpan(stone, op, fn, meta) {
30
+ let parent = this.context.getStore();
31
+ let span = new Span(this.nextSpanId++, (parent != null) ? parent.id : null, stone.id, op, performance.now(), meta);
32
+ span.estimatedDuration = this.stats.getEstimate(stone.id, op);
33
+ this.emit(SpanEventType.Start, span);
34
+ let _gthis = this;
35
+ return this.context.run(span, function () {
36
+ return fn().then(function (result) {
37
+ span.endTime = performance.now();
38
+ span.duration = span.endTime - span.startTime;
39
+ span.status = SpanStatus.Ok;
40
+ _gthis.recorder.record(span);
41
+ _gthis.stats.update(stone.id, op, span.duration);
42
+ _gthis.emit(SpanEventType.End, span);
43
+ return result;
44
+ })["catch"](function (err) {
45
+ span.endTime = performance.now();
46
+ span.duration = span.endTime - span.startTime;
47
+ span.status = SpanStatus.Error(Std.string(err));
48
+ _gthis.recorder.record(span);
49
+ _gthis.emit(SpanEventType.End, span);
50
+ return Promise.reject(err);
51
+ });
52
+ });
53
+ }
54
+
55
+ /**
56
+ Secondary API: manual start for spans where no function can be wrapped (e.g. LockWait).
57
+ */
58
+ startSpan(stone, op, meta) {
59
+ let parent = this.context.getStore();
60
+ let span = new Span(this.nextSpanId++, (parent != null) ? parent.id : null, stone.id, op, performance.now(), meta);
61
+ span.estimatedDuration = this.stats.getEstimate(stone.id, op);
62
+ this.emit(SpanEventType.Start, span);
63
+ return span;
64
+ }
65
+
66
+ /**
67
+ Complete a manually started span.
68
+ */
69
+ endSpan(span) {
70
+ span.endTime = performance.now();
71
+ span.duration = span.endTime - span.startTime;
72
+ span.status = SpanStatus.Ok;
73
+ this.recorder.record(span);
74
+ this.stats.update(span.stone, span.operation, span.duration);
75
+ this.emit(SpanEventType.End, span);
76
+ }
77
+
78
+ /**
79
+ Returns the current span from AsyncLocalStorage context, or null if none.
80
+ */
81
+ getCurrentSpan() {
82
+ return this.context.getStore();
83
+ }
84
+
85
+ /**
86
+ Subscribe to span events. Returns unsubscribe function.
87
+ */
88
+ subscribe(listener) {
89
+ this.listeners.push(listener);
90
+ let _gthis = this;
91
+ return function () {
92
+ HxOverrides.remove(_gthis.listeners, listener);
93
+ };
94
+ }
95
+
96
+ /**
97
+ Export spans in the given format ("json" or "trace"). Defaults to "json".
98
+ */
99
+ export(format) {
100
+ if (format == "trace") {
101
+ return this.exportChromeTrace();
102
+ } else {
103
+ return this.exportJson();
104
+ };
105
+ }
106
+
107
+ /**
108
+ Return spans recorded since the given span ID (exclusive).
109
+ */
110
+ getSpansSince(sinceId) {
111
+ return this.recorder.getSpansSince(sinceId);
112
+ }
113
+
114
+ /**
115
+ Return aggregated profiling summary.
116
+ */
117
+ getSummary() {
118
+ let spans = this.recorder.getSpans();
119
+ let byStone = {};
120
+ let byOperation = {};
121
+ let cacheHits = 0;
122
+ let cacheLookups = 0;
123
+ let _g = 0;
124
+ while (_g < spans.length) {
125
+ let span = spans[_g];
126
+ ++_g;
127
+ let opKey = span.operation;
128
+ let opEntry = byOperation[opKey];
129
+ if (opEntry == null) {
130
+ opEntry = {"count": 0, "totalMs": 0.0};
131
+ byOperation[opKey] = opEntry;
132
+ };
133
+ opEntry.count++;
134
+ opEntry.totalMs += span.duration;
135
+ if (opKey == "Generate") {
136
+ Profiler.ensureStoneEntry(byStone, span.stone);
137
+ let entry = byStone[span.stone];
138
+ entry.generates++;
139
+ entry.totalDuration += span.duration;
140
+ entry.avgDuration = entry.totalDuration / entry.generates;
141
+ entry.lastDuration = span.duration;
142
+ };
143
+ if (span.metadata != null) {
144
+ let meta = span.metadata;
145
+ if (meta.cacheResult != null) {
146
+ ++cacheLookups;
147
+ if (meta.cacheResult == "hit") {
148
+ ++cacheHits;
149
+ Profiler.ensureStoneEntry(byStone, span.stone);
150
+ byStone[span.stone].cacheHits++;
151
+ };
152
+ };
153
+ };
154
+ };
155
+ return {"byStone": byStone, "byOperation": byOperation, "cacheHitRate": (cacheLookups > 0) ? cacheHits / cacheLookups : 0.0};
156
+ }
157
+ exportJson() {
158
+ let spans = this.recorder.getSpans();
159
+ let _g = [];
160
+ let _g1 = 0;
161
+ while (_g1 < spans.length) _g.push(this.serializeSpan(spans[_g1++]));
162
+ let stoneSet_inst = new Map();
163
+ let generateCount = 0;
164
+ let cacheHits = 0;
165
+ let cacheLookups = 0;
166
+ let _g2 = 0;
167
+ while (_g2 < spans.length) {
168
+ let span = spans[_g2];
169
+ ++_g2;
170
+ stoneSet_inst.set(span.stone, true);
171
+ if (span.operation == "Generate") {
172
+ ++generateCount;
173
+ };
174
+ if (span.metadata != null) {
175
+ let meta = span.metadata;
176
+ if (meta.cacheResult != null) {
177
+ ++cacheLookups;
178
+ if (meta.cacheResult == "hit") {
179
+ ++cacheHits;
180
+ };
181
+ };
182
+ };
183
+ };
184
+ let stoneCount = 0;
185
+ let _ = EsMap.adaptIterator(stoneSet_inst.values());
186
+ while (_.hasNext()) {
187
+ _.next();
188
+ ++stoneCount;
189
+ };
190
+ return {"spans": _g, "meta": {"spanCount": spans.length, "stoneCount": stoneCount, "totalGenerations": generateCount, "cacheHitRate": (cacheLookups > 0) ? cacheHits / cacheLookups : 0.0}};
191
+ }
192
+ exportChromeTrace() {
193
+ let spans = this.recorder.getSpans();
194
+ let spanById_inst = new Map();
195
+ let _g = 0;
196
+ while (_g < spans.length) {
197
+ let span = spans[_g];
198
+ ++_g;
199
+ spanById_inst.set(span.id, span);
200
+ };
201
+ let childrenOf_inst = new Map();
202
+ let roots = [];
203
+ let _g1 = 0;
204
+ while (_g1 < spans.length) {
205
+ let span = spans[_g1];
206
+ ++_g1;
207
+ let pid = span.parentId;
208
+ if (pid == null || !spanById_inst.has(pid)) {
209
+ roots.push(span);
210
+ } else {
211
+ if (!childrenOf_inst.has(pid)) {
212
+ childrenOf_inst.set(pid, []);
213
+ };
214
+ childrenOf_inst.get(pid).push(span);
215
+ };
216
+ };
217
+ let spanTid_inst = new Map();
218
+ let nextTid = 1;
219
+ let assignTids = null;
220
+ assignTids = function (span, tid) {
221
+ spanTid_inst.set(span.id, tid);
222
+ let children = childrenOf_inst.get(span.id);
223
+ if (children == null || children.length == 0) {
224
+ return;
225
+ };
226
+ children.sort(function (a, b) {
227
+ return Reflect__1.compare(a.startTime, b.startTime);
228
+ });
229
+ let laneEndTimes = [];
230
+ let laneTids = [];
231
+ let _g = 0;
232
+ while (_g < children.length) {
233
+ let child = children[_g];
234
+ ++_g;
235
+ let lane = -1;
236
+ let _g1 = 0;
237
+ let _g2 = laneEndTimes.length;
238
+ while (_g1 < _g2) {
239
+ let i = _g1++;
240
+ if (laneEndTimes[i] <= child.startTime) {
241
+ lane = i;
242
+ break;
243
+ };
244
+ };
245
+ if (lane == -1) {
246
+ lane = laneEndTimes.length;
247
+ let assignTids;
248
+ if (lane == 0) {
249
+ assignTids = tid;
250
+ } else {
251
+ nextTid += 1;
252
+ assignTids = nextTid - 1;
253
+ };
254
+ laneTids.push(assignTids);
255
+ laneEndTimes.push(child.endTime);
256
+ } else {
257
+ laneEndTimes[lane] = child.endTime;
258
+ };
259
+ assignTids(child, laneTids[lane]);
260
+ };
261
+ };
262
+ roots.sort(function (a, b) {
263
+ return Reflect__1.compare(a.startTime, b.startTime);
264
+ });
265
+ let _g2 = 0;
266
+ while (_g2 < roots.length) {
267
+ nextTid += 1;
268
+ assignTids(roots[_g2++], nextTid - 1);
269
+ };
270
+ let events = [];
271
+ let tidNames = new IntMap();
272
+ let _g3 = 0;
273
+ while (_g3 < spans.length) {
274
+ let span = spans[_g3];
275
+ ++_g3;
276
+ let tid = spanTid_inst.get(span.id);
277
+ if (tid != null && !tidNames.inst.has(tid)) {
278
+ tidNames.inst.set(tid, span.stone);
279
+ };
280
+ };
281
+ let map = tidNames;
282
+ let _g_keys = map.keys();
283
+ while (_g_keys.hasNext()) {
284
+ let key = _g_keys.next();
285
+ events.push({"ph": "M", "pid": 1, "tid": key, "name": "thread_name", "args": {"name": map.get(key)}});
286
+ };
287
+ let flowId = 0;
288
+ let _g4 = 0;
289
+ while (_g4 < spans.length) {
290
+ let span = spans[_g4];
291
+ ++_g4;
292
+ let tid = spanTid_inst.get(span.id);
293
+ if (tid == null) {
294
+ continue;
295
+ };
296
+ let ts = this.baseEpochUs + (span.startTime * 1000 - this.basePerfUs);
297
+ events.push({"ph": "X", "name": span.operation + " " + span.stone, "cat": "whet", "ts": ts, "dur": span.duration * 1000, "pid": 1, "tid": tid, "args": (span.metadata != null) ? span.metadata : {}});
298
+ if (span.parentId != null) {
299
+ let parent = spanById_inst.get(span.parentId);
300
+ if (parent != null) {
301
+ let parentTid = spanTid_inst.get(parent.id);
302
+ if (parentTid != null && parentTid != tid) {
303
+ events.push({"ph": "s", "id": flowId, "pid": 1, "tid": parentTid, "ts": this.baseEpochUs + (parent.startTime * 1000 - this.basePerfUs), "name": "trigger", "cat": "flow"});
304
+ events.push({"ph": "f", "bp": "e", "id": flowId, "pid": 1, "tid": tid, "ts": ts, "name": "trigger", "cat": "flow"});
305
+ ++flowId;
306
+ };
307
+ };
308
+ };
309
+ };
310
+ return {"traceEvents": events};
311
+ }
312
+ serializeSpan(span) {
313
+ let _g = span.status;
314
+ let tmp;
315
+ switch (_g._hx_index) {
316
+ case 0:
317
+ tmp = "ok";
318
+ break
319
+ case 1:
320
+ tmp = "error: " + _g.msg;
321
+ break
322
+
323
+ };
324
+ return {"id": span.id, "parentId": span.parentId, "stone": span.stone, "operation": span.operation, "startTime": span.startTime, "endTime": span.endTime, "duration": span.duration, "estimatedDuration": span.estimatedDuration, "metadata": span.metadata, "status": tmp};
325
+ }
326
+ emit(type, span) {
327
+ let event = {"type": type, "span": span};
328
+ let _g = 0;
329
+ let _g1 = this.listeners;
330
+ while (_g < _g1.length) _g1[_g++](event);
331
+ }
332
+ static ensureStoneEntry(byStone, stone) {
333
+ if (!Object.prototype.hasOwnProperty.call(byStone, stone)) {
334
+ byStone[stone] = {"generates": 0, "totalDuration": 0.0, "avgDuration": 0.0, "lastDuration": 0.0, "cacheHits": 0};
335
+ };
336
+ }
337
+ static get __name__() {
338
+ return "whet.profiler.Profiler"
339
+ }
340
+ get __class__() {
341
+ return Profiler
342
+ }
343
+ }
344
+ Profiler.prototype.recorder = null;
345
+ Profiler.prototype.stats = null;
346
+ Profiler.prototype.listeners = null;
347
+ Profiler.prototype.context = null;
348
+ Profiler.prototype.baseEpochUs = null;
349
+ Profiler.prototype.basePerfUs = null;
350
+ Profiler.prototype.nextSpanId = null;
351
+
@@ -0,0 +1,90 @@
1
+
2
+ export declare class Span<T> {
3
+ constructor(id: number, parentId: null | number, stone: string, op: string, startTime: number, metadata?: null | T)
4
+ id: number
5
+ parentId: null | number
6
+ stone: string
7
+ operation: string
8
+ startTime: number
9
+ endTime: number
10
+ duration: number
11
+ estimatedDuration: number
12
+ metadata: T
13
+ status: SpanStatus
14
+ }
15
+
16
+ export type AnySpan = Span<any>
17
+
18
+ export declare namespace SpanStatus {
19
+ export type Ok = {_hx_index: 0, __enum__: "whet.profiler.SpanStatus"}
20
+ export const Ok: Ok
21
+ export type Error = {_hx_index: 1, msg: string, __enum__: "whet.profiler.SpanStatus"}
22
+ export const Error: (msg: string) => SpanStatus
23
+ }
24
+
25
+ export declare type SpanStatus =
26
+ | SpanStatus.Ok
27
+ | SpanStatus.Error
28
+
29
+ export declare namespace SpanEventType {
30
+ export type Start = {_hx_index: 0, __enum__: "whet.profiler.SpanEventType"}
31
+ export const Start: Start
32
+ export type End = {_hx_index: 1, __enum__: "whet.profiler.SpanEventType"}
33
+ export const End: End
34
+ }
35
+
36
+ export declare type SpanEventType =
37
+ | SpanEventType.Start
38
+ | SpanEventType.End
39
+
40
+ export type SpanEvent = {
41
+ span: AnySpan,
42
+ type: SpanEventType
43
+ }
44
+
45
+ /**
46
+ Metadata types per span operation.
47
+ */
48
+ export type LockWaitMeta = {
49
+ queueLength?: null | number,
50
+ queuePosition?: null | number
51
+ }
52
+
53
+ export type LockHeldMeta = {
54
+ cacheResult?: null | string
55
+ }
56
+
57
+ export type HashMeta = {
58
+ dependencyCount?: null | number,
59
+ hashHex?: null | string
60
+ }
61
+
62
+ export type GenerateMeta = {
63
+ outputCount?: null | number,
64
+ totalBytes?: null | number
65
+ }
66
+
67
+ export type GeneratePartialMeta = {
68
+ outputBytes?: null | number,
69
+ sourceId?: null | string
70
+ }
71
+
72
+ export type DepResolveMeta = {
73
+ dependencyIds?: null | string[]
74
+ }
75
+
76
+ export type CacheWriteMeta = {
77
+ entryCount?: null | number,
78
+ strategy?: null | string
79
+ }
80
+
81
+ export type ListMeta = {
82
+ resultCount?: null | number
83
+ }
84
+
85
+ export type ServeMeta = {
86
+ method?: null | string,
87
+ path?: null | string,
88
+ responseBytes?: null | number,
89
+ statusCode?: null | number
90
+ }
@@ -0,0 +1,56 @@
1
+ import {Register} from "../../genes/Register.js"
2
+
3
+ const $global = Register.$global
4
+
5
+ export const Span = Register.global("$hxClasses")["whet.profiler.Span"] =
6
+ class Span extends Register.inherits() {
7
+ [Register.new](id, parentId, stone, op, startTime, metadata) {
8
+ this.id = id;
9
+ this.parentId = parentId;
10
+ this.stone = stone;
11
+ this.operation = op;
12
+ this.startTime = startTime;
13
+ this.metadata = metadata;
14
+ this.estimatedDuration = 0;
15
+ this.status = SpanStatus.Ok;
16
+ }
17
+ static get __name__() {
18
+ return "whet.profiler.Span"
19
+ }
20
+ get __class__() {
21
+ return Span
22
+ }
23
+ }
24
+ Span.prototype.id = null;
25
+ Span.prototype.parentId = null;
26
+ Span.prototype.stone = null;
27
+ Span.prototype.operation = null;
28
+ Span.prototype.startTime = null;
29
+ Span.prototype.endTime = null;
30
+ Span.prototype.duration = null;
31
+ Span.prototype.estimatedDuration = null;
32
+ Span.prototype.metadata = null;
33
+ Span.prototype.status = null;
34
+
35
+
36
+ export const SpanStatus =
37
+ Register.global("$hxEnums")["whet.profiler.SpanStatus"] =
38
+ {
39
+ __ename__: "whet.profiler.SpanStatus",
40
+
41
+ Ok: {_hx_name: "Ok", _hx_index: 0, __enum__: "whet.profiler.SpanStatus"},
42
+ Error: Object.assign((msg) => ({_hx_index: 1, __enum__: "whet.profiler.SpanStatus", "msg": msg}), {_hx_name: "Error", __params__: ["msg"]})
43
+ }
44
+ SpanStatus.__constructs__ = [SpanStatus.Ok, SpanStatus.Error]
45
+ SpanStatus.__empty_constructs__ = [SpanStatus.Ok]
46
+
47
+ export const SpanEventType =
48
+ Register.global("$hxEnums")["whet.profiler.SpanEventType"] =
49
+ {
50
+ __ename__: "whet.profiler.SpanEventType",
51
+
52
+ Start: {_hx_name: "Start", _hx_index: 0, __enum__: "whet.profiler.SpanEventType"},
53
+ End: {_hx_name: "End", _hx_index: 1, __enum__: "whet.profiler.SpanEventType"}
54
+ }
55
+ SpanEventType.__constructs__ = [SpanEventType.Start, SpanEventType.End]
56
+ SpanEventType.__empty_constructs__ = [SpanEventType.Start, SpanEventType.End]
@@ -0,0 +1,20 @@
1
+ import {AnySpan} from "./Span"
2
+
3
+ export declare class SpanRecorder {
4
+ constructor(maxSize: number)
5
+ maxSize: number
6
+ totalCount: number
7
+ protected buffer: AnySpan[]
8
+ protected writeIndex: number
9
+ record(span: AnySpan): void
10
+
11
+ /**
12
+ Returns all recorded spans in chronological order.
13
+ */
14
+ getSpans(): AnySpan[]
15
+
16
+ /**
17
+ Returns spans recorded since the given span ID (exclusive).
18
+ */
19
+ getSpansSince(sinceId: number): AnySpan[]
20
+ }