@pristine-ts/observability 2.0.16
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 +201 -0
- package/dist/lib/cjs/interfaces/interfaces.js +19 -0
- package/dist/lib/cjs/interfaces/interfaces.js.map +1 -0
- package/dist/lib/cjs/interfaces/serialized-span.interface.js +3 -0
- package/dist/lib/cjs/interfaces/serialized-span.interface.js.map +1 -0
- package/dist/lib/cjs/interfaces/serialized-trace.interface.js +3 -0
- package/dist/lib/cjs/interfaces/serialized-trace.interface.js.map +1 -0
- package/dist/lib/cjs/loggers/loggers.js +18 -0
- package/dist/lib/cjs/loggers/loggers.js.map +1 -0
- package/dist/lib/cjs/loggers/observability.logger.js +73 -0
- package/dist/lib/cjs/loggers/observability.logger.js.map +1 -0
- package/dist/lib/cjs/models/models.js +18 -0
- package/dist/lib/cjs/models/models.js.map +1 -0
- package/dist/lib/cjs/models/request-summary.model.js +19 -0
- package/dist/lib/cjs/models/request-summary.model.js.map +1 -0
- package/dist/lib/cjs/models/run-metadata.model.js +18 -0
- package/dist/lib/cjs/models/run-metadata.model.js.map +1 -0
- package/dist/lib/cjs/observability-configuration.js +49 -0
- package/dist/lib/cjs/observability-configuration.js.map +1 -0
- package/dist/lib/cjs/observability.configuration-keys.js +21 -0
- package/dist/lib/cjs/observability.configuration-keys.js.map +1 -0
- package/dist/lib/cjs/observability.module.js +98 -0
- package/dist/lib/cjs/observability.module.js.map +1 -0
- package/dist/lib/cjs/observability.module.keyname.js +5 -0
- package/dist/lib/cjs/observability.module.keyname.js.map +1 -0
- package/dist/lib/cjs/paths/observability-paths.js +78 -0
- package/dist/lib/cjs/paths/observability-paths.js.map +1 -0
- package/dist/lib/cjs/paths/paths.js +18 -0
- package/dist/lib/cjs/paths/paths.js.map +1 -0
- package/dist/lib/cjs/serializers/serialized-span.interface.js +3 -0
- package/dist/lib/cjs/serializers/serialized-span.interface.js.map +1 -0
- package/dist/lib/cjs/serializers/serialized-trace.interface.js +3 -0
- package/dist/lib/cjs/serializers/serialized-trace.interface.js.map +1 -0
- package/dist/lib/cjs/serializers/serializers.js +19 -0
- package/dist/lib/cjs/serializers/serializers.js.map +1 -0
- package/dist/lib/cjs/serializers/span-deserializer.js +26 -0
- package/dist/lib/cjs/serializers/span-deserializer.js.map +1 -0
- package/dist/lib/cjs/serializers/trace-deserializer.js +24 -0
- package/dist/lib/cjs/serializers/trace-deserializer.js.map +1 -0
- package/dist/lib/cjs/store/log-store.js +249 -0
- package/dist/lib/cjs/store/log-store.js.map +1 -0
- package/dist/lib/cjs/store/log-tailer.js +110 -0
- package/dist/lib/cjs/store/log-tailer.js.map +1 -0
- package/dist/lib/cjs/store/observability-paths.js +78 -0
- package/dist/lib/cjs/store/observability-paths.js.map +1 -0
- package/dist/lib/cjs/store/observability-run-manager.js +346 -0
- package/dist/lib/cjs/store/observability-run-manager.js.map +1 -0
- package/dist/lib/cjs/store/observability-store-reader.js +174 -0
- package/dist/lib/cjs/store/observability-store-reader.js.map +1 -0
- package/dist/lib/cjs/store/serializers/serialized-span.interface.js +3 -0
- package/dist/lib/cjs/store/serializers/serialized-span.interface.js.map +1 -0
- package/dist/lib/cjs/store/serializers/serialized-trace.interface.js +3 -0
- package/dist/lib/cjs/store/serializers/serialized-trace.interface.js.map +1 -0
- package/dist/lib/cjs/store/serializers/span-deserializer.js +26 -0
- package/dist/lib/cjs/store/serializers/span-deserializer.js.map +1 -0
- package/dist/lib/cjs/store/serializers/trace-deserializer.js +24 -0
- package/dist/lib/cjs/store/serializers/trace-deserializer.js.map +1 -0
- package/dist/lib/cjs/store/store.js +19 -0
- package/dist/lib/cjs/store/store.js.map +1 -0
- package/dist/lib/cjs/store/trace-deserializer.js +41 -0
- package/dist/lib/cjs/store/trace-deserializer.js.map +1 -0
- package/dist/lib/cjs/store/trace-store.js +281 -0
- package/dist/lib/cjs/store/trace-store.js.map +1 -0
- package/dist/lib/cjs/tailers/log-tailer.js +110 -0
- package/dist/lib/cjs/tailers/log-tailer.js.map +1 -0
- package/dist/lib/cjs/tailers/tailers.js +18 -0
- package/dist/lib/cjs/tailers/tailers.js.map +1 -0
- package/dist/lib/cjs/tracers/observability.tracer.js +65 -0
- package/dist/lib/cjs/tracers/observability.tracer.js.map +1 -0
- package/dist/lib/cjs/tracers/tracers.js +18 -0
- package/dist/lib/cjs/tracers/tracers.js.map +1 -0
- package/dist/lib/cjs/tsconfig.cjs.tsbuildinfo +1 -0
- package/dist/lib/esm/interfaces/interfaces.js +3 -0
- package/dist/lib/esm/interfaces/interfaces.js.map +1 -0
- package/dist/lib/esm/interfaces/serialized-span.interface.js +2 -0
- package/dist/lib/esm/interfaces/serialized-span.interface.js.map +1 -0
- package/dist/lib/esm/interfaces/serialized-trace.interface.js +2 -0
- package/dist/lib/esm/interfaces/serialized-trace.interface.js.map +1 -0
- package/dist/lib/esm/loggers/loggers.js +2 -0
- package/dist/lib/esm/loggers/loggers.js.map +1 -0
- package/dist/lib/esm/loggers/observability.logger.js +70 -0
- package/dist/lib/esm/loggers/observability.logger.js.map +1 -0
- package/dist/lib/esm/models/models.js +2 -0
- package/dist/lib/esm/models/models.js.map +1 -0
- package/dist/lib/esm/models/request-summary.model.js +15 -0
- package/dist/lib/esm/models/request-summary.model.js.map +1 -0
- package/dist/lib/esm/models/run-metadata.model.js +14 -0
- package/dist/lib/esm/models/run-metadata.model.js.map +1 -0
- package/dist/lib/esm/observability-configuration.js +46 -0
- package/dist/lib/esm/observability-configuration.js.map +1 -0
- package/dist/lib/esm/observability.configuration-keys.js +18 -0
- package/dist/lib/esm/observability.configuration-keys.js.map +1 -0
- package/dist/lib/esm/observability.module.js +81 -0
- package/dist/lib/esm/observability.module.js.map +1 -0
- package/dist/lib/esm/observability.module.keyname.js +2 -0
- package/dist/lib/esm/observability.module.keyname.js.map +1 -0
- package/dist/lib/esm/paths/observability-paths.js +41 -0
- package/dist/lib/esm/paths/observability-paths.js.map +1 -0
- package/dist/lib/esm/paths/paths.js +2 -0
- package/dist/lib/esm/paths/paths.js.map +1 -0
- package/dist/lib/esm/serializers/serialized-span.interface.js +2 -0
- package/dist/lib/esm/serializers/serialized-span.interface.js.map +1 -0
- package/dist/lib/esm/serializers/serialized-trace.interface.js +2 -0
- package/dist/lib/esm/serializers/serialized-trace.interface.js.map +1 -0
- package/dist/lib/esm/serializers/serializers.js +3 -0
- package/dist/lib/esm/serializers/serializers.js.map +1 -0
- package/dist/lib/esm/serializers/span-deserializer.js +22 -0
- package/dist/lib/esm/serializers/span-deserializer.js.map +1 -0
- package/dist/lib/esm/serializers/trace-deserializer.js +20 -0
- package/dist/lib/esm/serializers/trace-deserializer.js.map +1 -0
- package/dist/lib/esm/store/log-store.js +213 -0
- package/dist/lib/esm/store/log-store.js.map +1 -0
- package/dist/lib/esm/store/log-tailer.js +73 -0
- package/dist/lib/esm/store/log-tailer.js.map +1 -0
- package/dist/lib/esm/store/observability-paths.js +41 -0
- package/dist/lib/esm/store/observability-paths.js.map +1 -0
- package/dist/lib/esm/store/observability-run-manager.js +310 -0
- package/dist/lib/esm/store/observability-run-manager.js.map +1 -0
- package/dist/lib/esm/store/observability-store-reader.js +138 -0
- package/dist/lib/esm/store/observability-store-reader.js.map +1 -0
- package/dist/lib/esm/store/serializers/serialized-span.interface.js +2 -0
- package/dist/lib/esm/store/serializers/serialized-span.interface.js.map +1 -0
- package/dist/lib/esm/store/serializers/serialized-trace.interface.js +2 -0
- package/dist/lib/esm/store/serializers/serialized-trace.interface.js.map +1 -0
- package/dist/lib/esm/store/serializers/span-deserializer.js +22 -0
- package/dist/lib/esm/store/serializers/span-deserializer.js.map +1 -0
- package/dist/lib/esm/store/serializers/trace-deserializer.js +20 -0
- package/dist/lib/esm/store/serializers/trace-deserializer.js.map +1 -0
- package/dist/lib/esm/store/store.js +3 -0
- package/dist/lib/esm/store/store.js.map +1 -0
- package/dist/lib/esm/store/trace-deserializer.js +37 -0
- package/dist/lib/esm/store/trace-deserializer.js.map +1 -0
- package/dist/lib/esm/store/trace-store.js +245 -0
- package/dist/lib/esm/store/trace-store.js.map +1 -0
- package/dist/lib/esm/tailers/log-tailer.js +73 -0
- package/dist/lib/esm/tailers/log-tailer.js.map +1 -0
- package/dist/lib/esm/tailers/tailers.js +2 -0
- package/dist/lib/esm/tailers/tailers.js.map +1 -0
- package/dist/lib/esm/tracers/observability.tracer.js +62 -0
- package/dist/lib/esm/tracers/observability.tracer.js.map +1 -0
- package/dist/lib/esm/tracers/tracers.js +2 -0
- package/dist/lib/esm/tracers/tracers.js.map +1 -0
- package/dist/lib/esm/tsconfig.tsbuildinfo +1 -0
- package/dist/types/interfaces/interfaces.d.ts +2 -0
- package/dist/types/interfaces/serialized-span.interface.d.ts +14 -0
- package/dist/types/interfaces/serialized-trace.interface.d.ts +14 -0
- package/dist/types/loggers/loggers.d.ts +1 -0
- package/dist/types/loggers/observability.logger.d.ts +20 -0
- package/dist/types/models/models.d.ts +1 -0
- package/dist/types/models/request-summary.model.d.ts +52 -0
- package/dist/types/models/run-metadata.model.d.ts +28 -0
- package/dist/types/observability-configuration.d.ts +32 -0
- package/dist/types/observability.configuration-keys.d.ts +32 -0
- package/dist/types/observability.module.d.ts +28 -0
- package/dist/types/observability.module.keyname.d.ts +1 -0
- package/dist/types/paths/observability-paths.d.ts +30 -0
- package/dist/types/paths/paths.d.ts +1 -0
- package/dist/types/serializers/serialized-span.interface.d.ts +14 -0
- package/dist/types/serializers/serialized-trace.interface.d.ts +14 -0
- package/dist/types/serializers/serializers.d.ts +2 -0
- package/dist/types/serializers/span-deserializer.d.ts +11 -0
- package/dist/types/serializers/trace-deserializer.d.ts +9 -0
- package/dist/types/store/log-store.d.ts +79 -0
- package/dist/types/store/log-tailer.d.ts +27 -0
- package/dist/types/store/observability-paths.d.ts +30 -0
- package/dist/types/store/observability-run-manager.d.ts +96 -0
- package/dist/types/store/observability-store-reader.d.ts +55 -0
- package/dist/types/store/serializers/serialized-span.interface.d.ts +14 -0
- package/dist/types/store/serializers/serialized-trace.interface.d.ts +14 -0
- package/dist/types/store/serializers/span-deserializer.d.ts +11 -0
- package/dist/types/store/serializers/trace-deserializer.d.ts +9 -0
- package/dist/types/store/store.d.ts +2 -0
- package/dist/types/store/trace-deserializer.d.ts +41 -0
- package/dist/types/store/trace-store.d.ts +88 -0
- package/dist/types/tailers/log-tailer.d.ts +27 -0
- package/dist/types/tailers/tailers.d.ts +1 -0
- package/dist/types/tracers/observability.tracer.d.ts +16 -0
- package/dist/types/tracers/tracers.d.ts +1 -0
- package/package.json +60 -0
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import * as path from "path";
|
|
2
|
+
/**
|
|
3
|
+
* Resolves every path inside the observability store from the configured store directory.
|
|
4
|
+
* Pure and stateless past construction — instantiate once with the configured directory
|
|
5
|
+
* and reuse.
|
|
6
|
+
*
|
|
7
|
+
* Layout:
|
|
8
|
+
* ```
|
|
9
|
+
* <root>/
|
|
10
|
+
* <instanceId>/logs.jsonl
|
|
11
|
+
* <instanceId>/requests.jsonl
|
|
12
|
+
* <instanceId>/traces/<traceId>.json
|
|
13
|
+
* ```
|
|
14
|
+
*
|
|
15
|
+
* Each `<instanceId>` is one pristine process lifetime (= the kernel instantiation id).
|
|
16
|
+
* No metadata sidecars, no `latest.json` pointer — directory `mtime` answers "which is
|
|
17
|
+
* most recent."
|
|
18
|
+
*/
|
|
19
|
+
export class ObservabilityPaths {
|
|
20
|
+
constructor(configuredDirectory) {
|
|
21
|
+
this.root = path.isAbsolute(configuredDirectory)
|
|
22
|
+
? configuredDirectory
|
|
23
|
+
: path.resolve(process.cwd(), configuredDirectory);
|
|
24
|
+
}
|
|
25
|
+
instanceDirectory(instanceId) {
|
|
26
|
+
return path.join(this.root, instanceId);
|
|
27
|
+
}
|
|
28
|
+
logsFile(instanceId) {
|
|
29
|
+
return path.join(this.instanceDirectory(instanceId), "logs.jsonl");
|
|
30
|
+
}
|
|
31
|
+
requestsFile(instanceId) {
|
|
32
|
+
return path.join(this.instanceDirectory(instanceId), "requests.jsonl");
|
|
33
|
+
}
|
|
34
|
+
tracesDirectory(instanceId) {
|
|
35
|
+
return path.join(this.instanceDirectory(instanceId), "traces");
|
|
36
|
+
}
|
|
37
|
+
traceFile(instanceId, traceId) {
|
|
38
|
+
return path.join(this.tracesDirectory(instanceId), `${traceId}.json`);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
//# sourceMappingURL=observability-paths.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"observability-paths.js","sourceRoot":"","sources":["../../../../src/paths/observability-paths.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,IAAI,MAAM,MAAM,CAAC;AAE7B;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,OAAO,kBAAkB;IAO7B,YAAY,mBAA2B;QACrC,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC,UAAU,CAAC,mBAAmB,CAAC;YAC9C,CAAC,CAAC,mBAAmB;YACrB,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,mBAAmB,CAAC,CAAC;IACvD,CAAC;IAED,iBAAiB,CAAC,UAAkB;QAClC,OAAO,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,UAAU,CAAC,CAAC;IAC1C,CAAC;IAED,QAAQ,CAAC,UAAkB;QACzB,OAAO,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,iBAAiB,CAAC,UAAU,CAAC,EAAE,YAAY,CAAC,CAAC;IACrE,CAAC;IAED,YAAY,CAAC,UAAkB;QAC7B,OAAO,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,iBAAiB,CAAC,UAAU,CAAC,EAAE,gBAAgB,CAAC,CAAC;IACzE,CAAC;IAED,eAAe,CAAC,UAAkB;QAChC,OAAO,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,iBAAiB,CAAC,UAAU,CAAC,EAAE,QAAQ,CAAC,CAAC;IACjE,CAAC;IAED,SAAS,CAAC,UAAkB,EAAE,OAAe;QAC3C,OAAO,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,eAAe,CAAC,UAAU,CAAC,EAAE,GAAG,OAAO,OAAO,CAAC,CAAC;IACxE,CAAC;CACF"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"paths.js","sourceRoot":"","sources":["../../../../src/paths/paths.ts"],"names":[],"mappings":"AAAA,cAAc,uBAAuB,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"serialized-span.interface.js","sourceRoot":"","sources":["../../../../src/serializers/serialized-span.interface.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"serialized-trace.interface.js","sourceRoot":"","sources":["../../../../src/serializers/serialized-trace.interface.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"serializers.js","sourceRoot":"","sources":["../../../../src/serializers/serializers.ts"],"names":[],"mappings":"AAAA,cAAc,qBAAqB,CAAC;AACpC,cAAc,sBAAsB,CAAC"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { Span } from "@pristine-ts/common";
|
|
2
|
+
/**
|
|
3
|
+
* Rebuilds a `Span` (with its full child tree) from the stored plain object. Used by
|
|
4
|
+
* `TraceDeserializer` for the trace's root span and recursively for every descendant —
|
|
5
|
+
* so `traceRenderer.renderTree`/`renderFlat`, which call instance methods like
|
|
6
|
+
* `getDuration()`, work unchanged on stored traces.
|
|
7
|
+
*/
|
|
8
|
+
export class SpanDeserializer {
|
|
9
|
+
static deserialize(serialized, trace) {
|
|
10
|
+
var _a, _b;
|
|
11
|
+
const span = new Span(serialized.keyname, serialized.id, (_a = serialized.context) !== null && _a !== void 0 ? _a : {});
|
|
12
|
+
span.trace = trace;
|
|
13
|
+
span.startDate = serialized.startDate;
|
|
14
|
+
span.endDate = serialized.endDate;
|
|
15
|
+
span.inProgress = serialized.endDate === undefined;
|
|
16
|
+
for (const child of (_b = serialized.children) !== null && _b !== void 0 ? _b : []) {
|
|
17
|
+
span.addChild(SpanDeserializer.deserialize(child, trace));
|
|
18
|
+
}
|
|
19
|
+
return span;
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
//# sourceMappingURL=span-deserializer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"span-deserializer.js","sourceRoot":"","sources":["../../../../src/serializers/span-deserializer.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,IAAI,EAAQ,MAAM,qBAAqB,CAAC;AAGhD;;;;;GAKG;AACH,MAAM,OAAO,gBAAgB;IAC3B,MAAM,CAAC,WAAW,CAAC,UAA0B,EAAE,KAAY;;QACzD,MAAM,IAAI,GAAG,IAAI,IAAI,CAAC,UAAU,CAAC,OAAO,EAAE,UAAU,CAAC,EAAE,EAAE,MAAA,UAAU,CAAC,OAAO,mCAAI,EAAE,CAAC,CAAC;QACnF,IAAI,CAAC,KAAK,GAAG,KAAK,CAAC;QACnB,IAAI,CAAC,SAAS,GAAG,UAAU,CAAC,SAAS,CAAC;QACtC,IAAI,CAAC,OAAO,GAAG,UAAU,CAAC,OAAO,CAAC;QAClC,IAAI,CAAC,UAAU,GAAG,UAAU,CAAC,OAAO,KAAK,SAAS,CAAC;QAEnD,KAAK,MAAM,KAAK,IAAI,MAAA,UAAU,CAAC,QAAQ,mCAAI,EAAE,EAAE,CAAC;YAC9C,IAAI,CAAC,QAAQ,CAAC,gBAAgB,CAAC,WAAW,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC,CAAC;QAC5D,CAAC;QAED,OAAO,IAAI,CAAC;IACd,CAAC;CACF"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { Trace } from "@pristine-ts/common";
|
|
2
|
+
import { SpanDeserializer } from "./span-deserializer";
|
|
3
|
+
/**
|
|
4
|
+
* Rehydrates a stored trace JSON (the shape written by `ObservabilityTracer`) back into
|
|
5
|
+
* a `Trace` instance, with its full span tree rebuilt via `SpanDeserializer`.
|
|
6
|
+
*/
|
|
7
|
+
export class TraceDeserializer {
|
|
8
|
+
static deserialize(serialized) {
|
|
9
|
+
var _a;
|
|
10
|
+
const trace = new Trace(serialized.id, (_a = serialized.context) !== null && _a !== void 0 ? _a : {});
|
|
11
|
+
trace.startDate = serialized.startDate;
|
|
12
|
+
trace.endDate = serialized.endDate;
|
|
13
|
+
trace.hasEnded = serialized.endDate !== undefined;
|
|
14
|
+
if (serialized.rootSpan !== undefined) {
|
|
15
|
+
trace.rootSpan = SpanDeserializer.deserialize(serialized.rootSpan, trace);
|
|
16
|
+
}
|
|
17
|
+
return trace;
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
//# sourceMappingURL=trace-deserializer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"trace-deserializer.js","sourceRoot":"","sources":["../../../../src/serializers/trace-deserializer.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,KAAK,EAAC,MAAM,qBAAqB,CAAC;AAE1C,OAAO,EAAC,gBAAgB,EAAC,MAAM,qBAAqB,CAAC;AAErD;;;GAGG;AACH,MAAM,OAAO,iBAAiB;IAC5B,MAAM,CAAC,WAAW,CAAC,UAA2B;;QAC5C,MAAM,KAAK,GAAG,IAAI,KAAK,CAAC,UAAU,CAAC,EAAE,EAAE,MAAA,UAAU,CAAC,OAAO,mCAAI,EAAE,CAAC,CAAC;QACjE,KAAK,CAAC,SAAS,GAAG,UAAU,CAAC,SAAS,CAAC;QACvC,KAAK,CAAC,OAAO,GAAG,UAAU,CAAC,OAAO,CAAC;QACnC,KAAK,CAAC,QAAQ,GAAG,UAAU,CAAC,OAAO,KAAK,SAAS,CAAC;QAElD,IAAI,UAAU,CAAC,QAAQ,KAAK,SAAS,EAAE,CAAC;YACtC,KAAK,CAAC,QAAQ,GAAG,gBAAgB,CAAC,WAAW,CAAC,UAAU,CAAC,QAAQ,EAAE,KAAK,CAAC,CAAC;QAC5E,CAAC;QAED,OAAO,KAAK,CAAC;IACf,CAAC;CACF"}
|
|
@@ -0,0 +1,213 @@
|
|
|
1
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
2
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
3
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
4
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
5
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
6
|
+
};
|
|
7
|
+
var __metadata = (this && this.__metadata) || function (k, v) {
|
|
8
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
9
|
+
};
|
|
10
|
+
var __param = (this && this.__param) || function (paramIndex, decorator) {
|
|
11
|
+
return function (target, key) { decorator(target, key, paramIndex); }
|
|
12
|
+
};
|
|
13
|
+
var LogStore_1;
|
|
14
|
+
import * as fs from "fs";
|
|
15
|
+
import { inject, injectable, singleton } from "tsyringe";
|
|
16
|
+
import { injectConfig, InternalContainerParameterEnum, moduleScoped } from "@pristine-ts/common";
|
|
17
|
+
import { ObservabilityModuleKeyname } from "../observability.module.keyname";
|
|
18
|
+
import { ObservabilityConfigurationKeys } from "../observability.configuration-keys";
|
|
19
|
+
import { ObservabilityPaths } from "../paths/observability-paths";
|
|
20
|
+
import { LogTailer } from "../tailers/log-tailer";
|
|
21
|
+
/**
|
|
22
|
+
* The read/write layer for captured logs. The `ObservabilityLogger` (a `Logger`-tagged
|
|
23
|
+
* transport) calls `append` on every log it sees. The CLI's `logs` command calls `read`
|
|
24
|
+
* / `tail` — addressed by event/trace/request id, never by a partition selector.
|
|
25
|
+
*
|
|
26
|
+
* Internally, each pristine process writes to its own per-process directory (keyed by
|
|
27
|
+
* the kernel instantiation id) so concurrent processes never race on the same file.
|
|
28
|
+
* That partition is invisible to callers: `read` walks every directory newest-first and
|
|
29
|
+
* concatenates; `tail` follows the most-recently-written directory.
|
|
30
|
+
*
|
|
31
|
+
* Singleton so both the writer (logger) and any reader resolved during the same
|
|
32
|
+
* process see the same in-memory state.
|
|
33
|
+
*/
|
|
34
|
+
let LogStore = LogStore_1 = class LogStore {
|
|
35
|
+
constructor(enabled, directory, retainedInstances, partitionId) {
|
|
36
|
+
this.enabled = enabled;
|
|
37
|
+
this.retainedInstances = retainedInstances;
|
|
38
|
+
this.partitionId = partitionId;
|
|
39
|
+
this.directoryEnsured = false;
|
|
40
|
+
this.pruned = false;
|
|
41
|
+
this.paths = new ObservabilityPaths(directory);
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Whether capture is on. The `LoggerInterface` contract surfaces this through the
|
|
45
|
+
* adapter so `LogHandler` can skip dispatch entirely for disabled stores.
|
|
46
|
+
*/
|
|
47
|
+
isCaptureEnabled() {
|
|
48
|
+
return this.enabled;
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Appends one log entry to the current process's `logs.jsonl`. No-op when
|
|
52
|
+
* observability is disabled.
|
|
53
|
+
*
|
|
54
|
+
* The on-disk shape is the JSON-serialized `LogModel` itself — `severity` stays a
|
|
55
|
+
* numeric `SeverityEnum`, `date` becomes an ISO string — so the `logs` command can
|
|
56
|
+
* round-trip through `PrettyLogFormatter`. Stringification is cycle-safe because
|
|
57
|
+
* `log.extra` routinely holds `Span`/`Trace` objects whose `parentSpan` ↔ `children`
|
|
58
|
+
* back-references would otherwise blow up a naive serializer.
|
|
59
|
+
*/
|
|
60
|
+
append(log) {
|
|
61
|
+
if (this.enabled === false) {
|
|
62
|
+
return;
|
|
63
|
+
}
|
|
64
|
+
this.ensurePartitionDirectory();
|
|
65
|
+
const line = LogStore_1.safeStringify(log) + "\n";
|
|
66
|
+
fs.appendFileSync(this.paths.logsFile(this.partitionId), line);
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Every captured log entry across every partition, in write order within each
|
|
70
|
+
* partition and partitions concatenated newest-first. When `id` is provided, only
|
|
71
|
+
* entries whose `traceId` / `eventId` / `requestId` match are returned — useful for
|
|
72
|
+
* `pristine logs <id>`.
|
|
73
|
+
*/
|
|
74
|
+
read(id) {
|
|
75
|
+
const entries = [];
|
|
76
|
+
for (const partition of this.partitionsNewestFirst()) {
|
|
77
|
+
for (const entry of this.readJsonl(this.paths.logsFile(partition))) {
|
|
78
|
+
if (id === undefined || LogStore_1.entryMatchesId(entry, id)) {
|
|
79
|
+
entries.push(entry);
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
return entries;
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* Follows the most-recently-written partition's `logs.jsonl`, emitting each newly-
|
|
87
|
+
* appended line until the returned handle's `stop()` is called. When `id` is
|
|
88
|
+
* provided, only matching entries surface. Returns a no-op handle when the store
|
|
89
|
+
* has no partitions yet.
|
|
90
|
+
*/
|
|
91
|
+
tail(id, onLine) {
|
|
92
|
+
const partition = this.latestPartition();
|
|
93
|
+
if (partition === undefined) {
|
|
94
|
+
return { stop: () => undefined };
|
|
95
|
+
}
|
|
96
|
+
const tailer = new LogTailer(this.paths.logsFile(partition));
|
|
97
|
+
tailer.follow(line => {
|
|
98
|
+
if (id === undefined) {
|
|
99
|
+
onLine(line);
|
|
100
|
+
return;
|
|
101
|
+
}
|
|
102
|
+
try {
|
|
103
|
+
if (LogStore_1.entryMatchesId(JSON.parse(line), id)) {
|
|
104
|
+
onLine(line);
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
catch (_a) {
|
|
108
|
+
// Skip malformed lines rather than aborting the follow.
|
|
109
|
+
}
|
|
110
|
+
});
|
|
111
|
+
return { stop: () => tailer.stop() };
|
|
112
|
+
}
|
|
113
|
+
ensurePartitionDirectory() {
|
|
114
|
+
if (this.directoryEnsured) {
|
|
115
|
+
return;
|
|
116
|
+
}
|
|
117
|
+
fs.mkdirSync(this.paths.instanceDirectory(this.partitionId), { recursive: true });
|
|
118
|
+
this.directoryEnsured = true;
|
|
119
|
+
this.pruneOldPartitions();
|
|
120
|
+
}
|
|
121
|
+
/**
|
|
122
|
+
* Drops partition directories beyond the retained limit, ordered by `mtime`. Once
|
|
123
|
+
* per process — additional appends are zero-cost. Best-effort: a failure to prune
|
|
124
|
+
* never blocks a write.
|
|
125
|
+
*/
|
|
126
|
+
pruneOldPartitions() {
|
|
127
|
+
if (this.pruned) {
|
|
128
|
+
return;
|
|
129
|
+
}
|
|
130
|
+
this.pruned = true;
|
|
131
|
+
try {
|
|
132
|
+
const ordered = this.partitionsNewestFirst();
|
|
133
|
+
for (const stale of ordered.slice(Math.max(this.retainedInstances, 1))) {
|
|
134
|
+
fs.rmSync(this.paths.instanceDirectory(stale), { recursive: true, force: true });
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
catch (_a) {
|
|
138
|
+
// Best-effort.
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
partitionsNewestFirst() {
|
|
142
|
+
try {
|
|
143
|
+
return fs.readdirSync(this.paths.root, { withFileTypes: true })
|
|
144
|
+
.filter(entry => entry.isDirectory())
|
|
145
|
+
.map(entry => ({ name: entry.name, mtime: this.directoryMtime(entry.name) }))
|
|
146
|
+
.sort((a, b) => b.mtime - a.mtime)
|
|
147
|
+
.map(entry => entry.name);
|
|
148
|
+
}
|
|
149
|
+
catch (_a) {
|
|
150
|
+
return [];
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
latestPartition() {
|
|
154
|
+
return this.partitionsNewestFirst()[0];
|
|
155
|
+
}
|
|
156
|
+
directoryMtime(name) {
|
|
157
|
+
try {
|
|
158
|
+
return fs.statSync(this.paths.instanceDirectory(name)).mtimeMs;
|
|
159
|
+
}
|
|
160
|
+
catch (_a) {
|
|
161
|
+
return 0;
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
readJsonl(filePath) {
|
|
165
|
+
try {
|
|
166
|
+
return fs.readFileSync(filePath, "utf8")
|
|
167
|
+
.split("\n")
|
|
168
|
+
.filter(line => line.trim().length > 0)
|
|
169
|
+
.map(line => JSON.parse(line));
|
|
170
|
+
}
|
|
171
|
+
catch (_a) {
|
|
172
|
+
return [];
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
/**
|
|
176
|
+
* True when any of the entry's correlation fields match the requested id.
|
|
177
|
+
* `requestId` is checked too even though `LogModel` doesn't define it as a field
|
|
178
|
+
* today — JSON deserialization is permissive, so a custom mapper that does set it
|
|
179
|
+
* will round-trip and match.
|
|
180
|
+
*/
|
|
181
|
+
static entryMatchesId(entry, id) {
|
|
182
|
+
return entry.traceId === id || entry.eventId === id || entry.requestId === id;
|
|
183
|
+
}
|
|
184
|
+
/**
|
|
185
|
+
* `JSON.stringify` with a cycle guard — an object seen earlier in the walk is rendered
|
|
186
|
+
* as `"[Circular]"` rather than recursed into. Faithful at any depth, and immune to the
|
|
187
|
+
* `Span.parentSpan` ↔ `Span.children` cycles common in `log.extra`.
|
|
188
|
+
*/
|
|
189
|
+
static safeStringify(value) {
|
|
190
|
+
const seen = new WeakSet();
|
|
191
|
+
return JSON.stringify(value, (_key, val) => {
|
|
192
|
+
if (typeof val === "object" && val !== null) {
|
|
193
|
+
if (seen.has(val)) {
|
|
194
|
+
return "[Circular]";
|
|
195
|
+
}
|
|
196
|
+
seen.add(val);
|
|
197
|
+
}
|
|
198
|
+
return val;
|
|
199
|
+
});
|
|
200
|
+
}
|
|
201
|
+
};
|
|
202
|
+
LogStore = LogStore_1 = __decorate([
|
|
203
|
+
moduleScoped(ObservabilityModuleKeyname),
|
|
204
|
+
singleton(),
|
|
205
|
+
injectable(),
|
|
206
|
+
__param(0, injectConfig(ObservabilityConfigurationKeys.Enabled)),
|
|
207
|
+
__param(1, injectConfig(ObservabilityConfigurationKeys.Directory)),
|
|
208
|
+
__param(2, injectConfig(ObservabilityConfigurationKeys.RetainedInstances)),
|
|
209
|
+
__param(3, inject(InternalContainerParameterEnum.KernelInstantiationId)),
|
|
210
|
+
__metadata("design:paramtypes", [Boolean, String, Number, String])
|
|
211
|
+
], LogStore);
|
|
212
|
+
export { LogStore };
|
|
213
|
+
//# sourceMappingURL=log-store.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"log-store.js","sourceRoot":"","sources":["../../../../src/store/log-store.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import * as fs from "fs";
|
|
2
|
+
import * as path from "path";
|
|
3
|
+
/**
|
|
4
|
+
* Follows a growing `.jsonl` file and emits each newly-appended complete line. The
|
|
5
|
+
* `logs --follow` command and the REPL use this for a `tail -f`-style live view.
|
|
6
|
+
*
|
|
7
|
+
* Watches the file's parent directory (watching a not-yet-created file directly is
|
|
8
|
+
* unreliable across platforms) and reads the byte delta on each change. Partial trailing
|
|
9
|
+
* lines are buffered until their terminating newline arrives.
|
|
10
|
+
*
|
|
11
|
+
* Not a DI service — a plain utility. Instantiate, `follow()`, and `stop()` when done.
|
|
12
|
+
*/
|
|
13
|
+
export class LogTailer {
|
|
14
|
+
constructor(filePath) {
|
|
15
|
+
this.filePath = filePath;
|
|
16
|
+
this.offset = 0;
|
|
17
|
+
this.buffer = "";
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Starts following. Existing content is skipped — only lines appended after this call
|
|
21
|
+
* are emitted. Call `stop()` to release the watch.
|
|
22
|
+
*/
|
|
23
|
+
follow(onLine) {
|
|
24
|
+
this.offset = fs.existsSync(this.filePath) ? fs.statSync(this.filePath).size : 0;
|
|
25
|
+
const directory = path.dirname(this.filePath);
|
|
26
|
+
const filename = path.basename(this.filePath);
|
|
27
|
+
this.watcher = fs.watch(directory, (_eventType, changed) => {
|
|
28
|
+
if (changed !== null && changed !== filename) {
|
|
29
|
+
return;
|
|
30
|
+
}
|
|
31
|
+
this.drain(onLine);
|
|
32
|
+
});
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Stops following and releases the filesystem watch.
|
|
36
|
+
*/
|
|
37
|
+
stop() {
|
|
38
|
+
var _a;
|
|
39
|
+
(_a = this.watcher) === null || _a === void 0 ? void 0 : _a.close();
|
|
40
|
+
this.watcher = undefined;
|
|
41
|
+
}
|
|
42
|
+
drain(onLine) {
|
|
43
|
+
var _a;
|
|
44
|
+
if (fs.existsSync(this.filePath) === false) {
|
|
45
|
+
return;
|
|
46
|
+
}
|
|
47
|
+
const size = fs.statSync(this.filePath).size;
|
|
48
|
+
if (size <= this.offset) {
|
|
49
|
+
// Truncated or unchanged — reset to the new end so we don't replay stale bytes.
|
|
50
|
+
this.offset = size;
|
|
51
|
+
return;
|
|
52
|
+
}
|
|
53
|
+
const fd = fs.openSync(this.filePath, "r");
|
|
54
|
+
try {
|
|
55
|
+
const length = size - this.offset;
|
|
56
|
+
const chunk = Buffer.alloc(length);
|
|
57
|
+
fs.readSync(fd, chunk, 0, length, this.offset);
|
|
58
|
+
this.offset = size;
|
|
59
|
+
this.buffer += chunk.toString("utf8");
|
|
60
|
+
}
|
|
61
|
+
finally {
|
|
62
|
+
fs.closeSync(fd);
|
|
63
|
+
}
|
|
64
|
+
const lines = this.buffer.split("\n");
|
|
65
|
+
this.buffer = (_a = lines.pop()) !== null && _a !== void 0 ? _a : "";
|
|
66
|
+
for (const line of lines) {
|
|
67
|
+
if (line.length > 0) {
|
|
68
|
+
onLine(line);
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
//# sourceMappingURL=log-tailer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"log-tailer.js","sourceRoot":"","sources":["../../../../src/store/log-tailer.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,IAAI,CAAC;AACzB,OAAO,KAAK,IAAI,MAAM,MAAM,CAAC;AAE7B;;;;;;;;;GASG;AACH,MAAM,OAAO,SAAS;IAKpB,YAA6B,QAAgB;QAAhB,aAAQ,GAAR,QAAQ,CAAQ;QAHrC,WAAM,GAAG,CAAC,CAAC;QACX,WAAM,GAAG,EAAE,CAAC;IAGpB,CAAC;IAED;;;OAGG;IACH,MAAM,CAAC,MAA8B;QACnC,IAAI,CAAC,MAAM,GAAG,EAAE,CAAC,UAAU,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,QAAQ,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;QAEjF,MAAM,SAAS,GAAG,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QAC9C,MAAM,QAAQ,GAAG,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QAE9C,IAAI,CAAC,OAAO,GAAG,EAAE,CAAC,KAAK,CAAC,SAAS,EAAE,CAAC,UAAU,EAAE,OAAO,EAAE,EAAE;YACzD,IAAI,OAAO,KAAK,IAAI,IAAI,OAAO,KAAK,QAAQ,EAAE,CAAC;gBAC7C,OAAO;YACT,CAAC;YACD,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;QACrB,CAAC,CAAC,CAAC;IACL,CAAC;IAED;;OAEG;IACH,IAAI;;QACF,MAAA,IAAI,CAAC,OAAO,0CAAE,KAAK,EAAE,CAAC;QACtB,IAAI,CAAC,OAAO,GAAG,SAAS,CAAC;IAC3B,CAAC;IAEO,KAAK,CAAC,MAA8B;;QAC1C,IAAI,EAAE,CAAC,UAAU,CAAC,IAAI,CAAC,QAAQ,CAAC,KAAK,KAAK,EAAE,CAAC;YAC3C,OAAO;QACT,CAAC;QAED,MAAM,IAAI,GAAG,EAAE,CAAC,QAAQ,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC;QAC7C,IAAI,IAAI,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC;YACxB,gFAAgF;YAChF,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC;YACnB,OAAO;QACT,CAAC;QAED,MAAM,EAAE,GAAG,EAAE,CAAC,QAAQ,CAAC,IAAI,CAAC,QAAQ,EAAE,GAAG,CAAC,CAAC;QAC3C,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,IAAI,GAAG,IAAI,CAAC,MAAM,CAAC;YAClC,MAAM,KAAK,GAAG,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;YACnC,EAAE,CAAC,QAAQ,CAAC,EAAE,EAAE,KAAK,EAAE,CAAC,EAAE,MAAM,EAAE,IAAI,CAAC,MAAM,CAAC,CAAC;YAC/C,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC;YACnB,IAAI,CAAC,MAAM,IAAI,KAAK,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;QACxC,CAAC;gBAAS,CAAC;YACT,EAAE,CAAC,SAAS,CAAC,EAAE,CAAC,CAAC;QACnB,CAAC;QAED,MAAM,KAAK,GAAG,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QACtC,IAAI,CAAC,MAAM,GAAG,MAAA,KAAK,CAAC,GAAG,EAAE,mCAAI,EAAE,CAAC;QAChC,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;YACzB,IAAI,IAAI,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBACpB,MAAM,CAAC,IAAI,CAAC,CAAC;YACf,CAAC;QACH,CAAC;IACH,CAAC;CACF"}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import * as path from "path";
|
|
2
|
+
/**
|
|
3
|
+
* Resolves every path inside the observability store from the configured store directory.
|
|
4
|
+
* Pure and stateless past construction — instantiate once with the configured directory
|
|
5
|
+
* and reuse.
|
|
6
|
+
*
|
|
7
|
+
* Layout:
|
|
8
|
+
* ```
|
|
9
|
+
* <root>/
|
|
10
|
+
* <instanceId>/logs.jsonl
|
|
11
|
+
* <instanceId>/requests.jsonl
|
|
12
|
+
* <instanceId>/traces/<traceId>.json
|
|
13
|
+
* ```
|
|
14
|
+
*
|
|
15
|
+
* Each `<instanceId>` is one pristine process lifetime (= the kernel instantiation id).
|
|
16
|
+
* No metadata sidecars, no `latest.json` pointer — directory `mtime` answers "which is
|
|
17
|
+
* most recent."
|
|
18
|
+
*/
|
|
19
|
+
export class ObservabilityPaths {
|
|
20
|
+
constructor(configuredDirectory) {
|
|
21
|
+
this.root = path.isAbsolute(configuredDirectory)
|
|
22
|
+
? configuredDirectory
|
|
23
|
+
: path.resolve(process.cwd(), configuredDirectory);
|
|
24
|
+
}
|
|
25
|
+
instanceDirectory(instanceId) {
|
|
26
|
+
return path.join(this.root, instanceId);
|
|
27
|
+
}
|
|
28
|
+
logsFile(instanceId) {
|
|
29
|
+
return path.join(this.instanceDirectory(instanceId), "logs.jsonl");
|
|
30
|
+
}
|
|
31
|
+
requestsFile(instanceId) {
|
|
32
|
+
return path.join(this.instanceDirectory(instanceId), "requests.jsonl");
|
|
33
|
+
}
|
|
34
|
+
tracesDirectory(instanceId) {
|
|
35
|
+
return path.join(this.instanceDirectory(instanceId), "traces");
|
|
36
|
+
}
|
|
37
|
+
traceFile(instanceId, traceId) {
|
|
38
|
+
return path.join(this.tracesDirectory(instanceId), `${traceId}.json`);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
//# sourceMappingURL=observability-paths.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"observability-paths.js","sourceRoot":"","sources":["../../../../src/store/observability-paths.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,IAAI,MAAM,MAAM,CAAC;AAE7B;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,OAAO,kBAAkB;IAO7B,YAAY,mBAA2B;QACrC,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC,UAAU,CAAC,mBAAmB,CAAC;YAC9C,CAAC,CAAC,mBAAmB;YACrB,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,mBAAmB,CAAC,CAAC;IACvD,CAAC;IAED,iBAAiB,CAAC,UAAkB;QAClC,OAAO,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,UAAU,CAAC,CAAC;IAC1C,CAAC;IAED,QAAQ,CAAC,UAAkB;QACzB,OAAO,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,iBAAiB,CAAC,UAAU,CAAC,EAAE,YAAY,CAAC,CAAC;IACrE,CAAC;IAED,YAAY,CAAC,UAAkB;QAC7B,OAAO,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,iBAAiB,CAAC,UAAU,CAAC,EAAE,gBAAgB,CAAC,CAAC;IACzE,CAAC;IAED,eAAe,CAAC,UAAkB;QAChC,OAAO,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,iBAAiB,CAAC,UAAU,CAAC,EAAE,QAAQ,CAAC,CAAC;IACjE,CAAC;IAED,SAAS,CAAC,UAAkB,EAAE,OAAe;QAC3C,OAAO,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,eAAe,CAAC,UAAU,CAAC,EAAE,GAAG,OAAO,OAAO,CAAC,CAAC;IACxE,CAAC;CACF"}
|