inspeffct 1.0.3 → 1.0.4
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/dist/bin.js +243 -181
- package/package.json +1 -1
package/dist/bin.js
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import * as NodeRuntime from '@effect/platform-node/NodeRuntime';
|
|
3
3
|
import * as NodeServices from '@effect/platform-node/NodeServices';
|
|
4
|
-
import * as
|
|
4
|
+
import * as Effect10 from 'effect/Effect';
|
|
5
5
|
import * as Command5 from 'effect/unstable/cli/Command';
|
|
6
6
|
import * as Argument2 from 'effect/unstable/cli/Argument';
|
|
7
|
-
import * as
|
|
7
|
+
import * as Context4 from 'effect/Context';
|
|
8
8
|
import * as Fiber from 'effect/Fiber';
|
|
9
9
|
import * as FileSystem from 'effect/FileSystem';
|
|
10
|
-
import * as
|
|
10
|
+
import * as Layer8 from 'effect/Layer';
|
|
11
11
|
import * as Schema from 'effect/Schema';
|
|
12
12
|
import * as Stream from 'effect/Stream';
|
|
13
13
|
import * as Formatter from 'effect/Formatter';
|
|
@@ -20,10 +20,11 @@ import * as Queue2 from 'effect/Queue';
|
|
|
20
20
|
import * as Socket from 'effect/unstable/socket/Socket';
|
|
21
21
|
import * as Chunk from 'effect/Chunk';
|
|
22
22
|
import * as Ref from 'effect/Ref';
|
|
23
|
+
import * as Random from 'effect/Random';
|
|
23
24
|
import * as SqliteClient from '@effect/sql-sqlite-node/SqliteClient';
|
|
24
25
|
import * as Struct5 from 'effect/Struct';
|
|
25
26
|
import * as Migrator from 'effect/unstable/sql/Migrator';
|
|
26
|
-
import * as
|
|
27
|
+
import * as SqlClient5 from 'effect/unstable/sql/SqlClient';
|
|
27
28
|
import * as SqlSchema from 'effect/unstable/sql/SqlSchema';
|
|
28
29
|
import * as SchemaGetter from 'effect/SchemaGetter';
|
|
29
30
|
import { flow } from 'effect/Function';
|
|
@@ -35,9 +36,9 @@ import * as crypto from 'crypto';
|
|
|
35
36
|
import * as fs from 'fs';
|
|
36
37
|
import * as os from 'os';
|
|
37
38
|
import * as path from 'path';
|
|
39
|
+
import * as Console2 from 'effect/Console';
|
|
38
40
|
import * as Option3 from 'effect/Option';
|
|
39
41
|
import * as ChildProcess from 'effect/unstable/process/ChildProcess';
|
|
40
|
-
import * as Console from 'effect/Console';
|
|
41
42
|
import * as Duration from 'effect/Duration';
|
|
42
43
|
import * as Graph from 'effect/Graph';
|
|
43
44
|
|
|
@@ -195,17 +196,17 @@ Schema.toCodecJson(
|
|
|
195
196
|
CaptureCurrentFibersRequest
|
|
196
197
|
]).annotate({ identifier: "InMessage" })
|
|
197
198
|
);
|
|
198
|
-
var BootloaderPath = class extends
|
|
199
|
+
var BootloaderPath = class extends Context4.Service()("inspeffct/BootloaderPath") {
|
|
199
200
|
};
|
|
200
|
-
var getPath =
|
|
201
|
-
var computeBootloaderPath =
|
|
201
|
+
var getPath = Effect10.map(BootloaderPath, (service) => service.path);
|
|
202
|
+
var computeBootloaderPath = Effect10.gen(function* () {
|
|
202
203
|
const path2 = yield* Path.Path;
|
|
203
204
|
const binDir = path2.dirname(import.meta.url.replace("file://", ""));
|
|
204
205
|
return path2.join(binDir, "bootloader.cjs");
|
|
205
206
|
});
|
|
206
|
-
var layer =
|
|
207
|
+
var layer = Layer8.effect(
|
|
207
208
|
BootloaderPath,
|
|
208
|
-
|
|
209
|
+
Effect10.map(computeBootloaderPath, (path2) => BootloaderPath.of({ path: path2 }))
|
|
209
210
|
);
|
|
210
211
|
var CdpRequest = Schema.Struct({
|
|
211
212
|
id: Schema.Number,
|
|
@@ -236,13 +237,13 @@ var CdpError = class extends Schema.TaggedErrorClass()("CdpError", {
|
|
|
236
237
|
code: Schema.optional(Schema.Number)
|
|
237
238
|
}) {
|
|
238
239
|
};
|
|
239
|
-
var CdpClient = class extends
|
|
240
|
+
var CdpClient = class extends Context4.Service()("inspeffct/CdpClient") {
|
|
240
241
|
};
|
|
241
242
|
var isCdpEvent = (msg) => typeof msg === "object" && msg !== null && "method" in msg && typeof msg.method === "string" && !("id" in msg);
|
|
242
243
|
var isCdpResponse = (msg) => typeof msg === "object" && msg !== null && "id" in msg && typeof msg.id === "number";
|
|
243
|
-
var makeConnection = (url) =>
|
|
244
|
+
var makeConnection = (url) => Effect10.gen(function* () {
|
|
244
245
|
const socket = yield* Socket.makeWebSocket(url).pipe(
|
|
245
|
-
|
|
246
|
+
Effect10.mapError((e) => new CdpError({ message: `Failed to connect to ${url}: ${e}` }))
|
|
246
247
|
);
|
|
247
248
|
const outgoing = yield* Queue2.unbounded();
|
|
248
249
|
const eventsPubSub = yield* PubSub2.unbounded();
|
|
@@ -256,14 +257,14 @@ var makeConnection = (url) => Effect8.gen(function* () {
|
|
|
256
257
|
})
|
|
257
258
|
),
|
|
258
259
|
Stream.runForEach(
|
|
259
|
-
(msg) =>
|
|
260
|
+
(msg) => Effect10.gen(function* () {
|
|
260
261
|
if (isCdpResponse(msg)) {
|
|
261
262
|
const resume = pendingRequests.get(msg.id);
|
|
262
263
|
if (resume) {
|
|
263
264
|
pendingRequests.delete(msg.id);
|
|
264
265
|
if (msg.error) {
|
|
265
266
|
resume(
|
|
266
|
-
|
|
267
|
+
Effect10.fail(
|
|
267
268
|
new CdpError({
|
|
268
269
|
message: msg.error.message,
|
|
269
270
|
code: msg.error.code
|
|
@@ -271,28 +272,28 @@ var makeConnection = (url) => Effect8.gen(function* () {
|
|
|
271
272
|
)
|
|
272
273
|
);
|
|
273
274
|
} else {
|
|
274
|
-
resume(
|
|
275
|
+
resume(Effect10.succeed(msg.result));
|
|
275
276
|
}
|
|
276
277
|
}
|
|
277
278
|
}
|
|
278
279
|
if (isCdpEvent(msg)) {
|
|
279
280
|
const decoded = yield* Schema.decodeUnknownEffect(CdpEvent)(msg).pipe(
|
|
280
|
-
|
|
281
|
+
Effect10.mapError((error) => new CdpError({ message: String(error) }))
|
|
281
282
|
);
|
|
282
283
|
yield* PubSub2.publish(eventsPubSub, decoded);
|
|
283
284
|
}
|
|
284
|
-
}).pipe(
|
|
285
|
+
}).pipe(Effect10.catchCause(Effect10.logDebug))
|
|
285
286
|
),
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
287
|
+
Effect10.ensuring(Queue2.shutdown(outgoing)),
|
|
288
|
+
Effect10.catchCause(Effect10.logDebug),
|
|
289
|
+
Effect10.forkScoped
|
|
289
290
|
);
|
|
290
291
|
const request = (method, params) => {
|
|
291
292
|
const id = nextId++;
|
|
292
|
-
return
|
|
293
|
+
return Effect10.callback((resume) => {
|
|
293
294
|
pendingRequests.set(id, resume);
|
|
294
295
|
Queue2.offerUnsafe(outgoing, { id, method, params });
|
|
295
|
-
return
|
|
296
|
+
return Effect10.sync(() => {
|
|
296
297
|
pendingRequests.delete(id);
|
|
297
298
|
});
|
|
298
299
|
});
|
|
@@ -304,19 +305,36 @@ var makeConnection = (url) => Effect8.gen(function* () {
|
|
|
304
305
|
events
|
|
305
306
|
};
|
|
306
307
|
});
|
|
307
|
-
var layer2 =
|
|
308
|
+
var layer2 = Layer8.effect(
|
|
308
309
|
CdpClient,
|
|
309
|
-
|
|
310
|
+
Effect10.gen(function* () {
|
|
310
311
|
const wsConstructor = yield* Socket.WebSocketConstructor;
|
|
311
312
|
return CdpClient.of({
|
|
312
313
|
connect: (url) => makeConnection(url).pipe(
|
|
313
|
-
|
|
314
|
+
Effect10.provideService(Socket.WebSocketConstructor, wsConstructor)
|
|
314
315
|
)
|
|
315
316
|
});
|
|
316
317
|
})
|
|
317
318
|
).pipe(
|
|
318
|
-
|
|
319
|
+
Layer8.provide(NodeSocket.layerWebSocketConstructor)
|
|
319
320
|
);
|
|
321
|
+
var randomByte = Random.nextIntBetween(0, 256, { halfOpen: true });
|
|
322
|
+
var randomUUID = Effect10.gen(function* () {
|
|
323
|
+
const bytes = yield* Effect10.all(Array.from({ length: 16 }, () => randomByte));
|
|
324
|
+
bytes[6] = bytes[6] & 15 | 64;
|
|
325
|
+
bytes[8] = bytes[8] & 63 | 128;
|
|
326
|
+
const hex = bytes.map((byte) => byte.toString(16).padStart(2, "0"));
|
|
327
|
+
return [
|
|
328
|
+
hex.slice(0, 4).join(""),
|
|
329
|
+
hex.slice(4, 6).join(""),
|
|
330
|
+
hex.slice(6, 8).join(""),
|
|
331
|
+
hex.slice(8, 10).join(""),
|
|
332
|
+
hex.slice(10, 16).join("")
|
|
333
|
+
].join("-");
|
|
334
|
+
});
|
|
335
|
+
var ExecutionId = class extends Context4.Service()("inspeffct/ExecutionId") {
|
|
336
|
+
};
|
|
337
|
+
var layer3 = Layer8.effect(ExecutionId, randomUUID);
|
|
320
338
|
var isSchema = (u) => typeof u === "object" && u !== null && "ast" in u;
|
|
321
339
|
var getMembers = (schema) => "members" in schema && Array.isArray(schema.members) ? schema.members : "cases" in schema ? Object.values(schema.cases) : [schema];
|
|
322
340
|
var evolveNested = (schema, evolve2) => {
|
|
@@ -435,8 +453,8 @@ var encodeStruct = (config) => (self) => {
|
|
|
435
453
|
})
|
|
436
454
|
);
|
|
437
455
|
};
|
|
438
|
-
var create_otel_tables_default =
|
|
439
|
-
const sql = yield*
|
|
456
|
+
var create_otel_tables_default = Effect10.gen(function* () {
|
|
457
|
+
const sql = yield* SqlClient5.SqlClient;
|
|
440
458
|
yield* sql`
|
|
441
459
|
CREATE TABLE spans (
|
|
442
460
|
span_id TEXT PRIMARY KEY,
|
|
@@ -457,15 +475,15 @@ var create_otel_tables_default = Effect8.gen(function* () {
|
|
|
457
475
|
dropped_links_count INTEGER NOT NULL DEFAULT 0,
|
|
458
476
|
is_external INTEGER NOT NULL DEFAULT 0
|
|
459
477
|
)
|
|
460
|
-
`.pipe(
|
|
461
|
-
yield* sql`CREATE INDEX idx_spans_trace_id ON spans(trace_id)`.pipe(
|
|
478
|
+
`.pipe(Effect10.withSpan("create_spans_table"));
|
|
479
|
+
yield* sql`CREATE INDEX idx_spans_trace_id ON spans(trace_id)`.pipe(Effect10.withSpan("create_idx_spans_trace_id"));
|
|
462
480
|
yield* sql`CREATE INDEX idx_spans_start_time ON spans(start_time)`.pipe(
|
|
463
|
-
|
|
481
|
+
Effect10.withSpan("create_idx_spans_start_time")
|
|
464
482
|
);
|
|
465
|
-
yield* sql`CREATE INDEX idx_spans_name ON spans(name)`.pipe(
|
|
466
|
-
yield* sql`CREATE INDEX idx_spans_parent ON spans(parent_span_id)`.pipe(
|
|
483
|
+
yield* sql`CREATE INDEX idx_spans_name ON spans(name)`.pipe(Effect10.withSpan("create_idx_spans_name"));
|
|
484
|
+
yield* sql`CREATE INDEX idx_spans_parent ON spans(parent_span_id)`.pipe(Effect10.withSpan("create_idx_spans_parent"));
|
|
467
485
|
yield* sql`CREATE INDEX idx_spans_running ON spans(span_id) WHERE end_time IS NULL`.pipe(
|
|
468
|
-
|
|
486
|
+
Effect10.withSpan("create_idx_spans_running")
|
|
469
487
|
);
|
|
470
488
|
yield* sql`
|
|
471
489
|
CREATE TABLE span_events (
|
|
@@ -477,9 +495,9 @@ var create_otel_tables_default = Effect8.gen(function* () {
|
|
|
477
495
|
attributes TEXT NOT NULL DEFAULT '{}',
|
|
478
496
|
dropped_attributes_count INTEGER NOT NULL DEFAULT 0
|
|
479
497
|
)
|
|
480
|
-
`.pipe(
|
|
498
|
+
`.pipe(Effect10.withSpan("create_span_events_table"));
|
|
481
499
|
yield* sql`CREATE INDEX idx_span_events_span ON span_events(span_id)`.pipe(
|
|
482
|
-
|
|
500
|
+
Effect10.withSpan("create_idx_span_events_span")
|
|
483
501
|
);
|
|
484
502
|
yield* sql`
|
|
485
503
|
CREATE TABLE span_links (
|
|
@@ -491,13 +509,22 @@ var create_otel_tables_default = Effect8.gen(function* () {
|
|
|
491
509
|
attributes TEXT NOT NULL DEFAULT '{}',
|
|
492
510
|
dropped_attributes_count INTEGER NOT NULL DEFAULT 0
|
|
493
511
|
)
|
|
494
|
-
`.pipe(
|
|
512
|
+
`.pipe(Effect10.withSpan("create_span_links_table"));
|
|
495
513
|
yield* sql`CREATE INDEX idx_span_links_span ON span_links(span_id)`.pipe(
|
|
496
|
-
|
|
514
|
+
Effect10.withSpan("create_idx_span_links_span")
|
|
515
|
+
);
|
|
516
|
+
});
|
|
517
|
+
var create_span_exits_table_default = Effect10.void;
|
|
518
|
+
var simplify_span_exits_default = Effect10.void;
|
|
519
|
+
var add_execution_id_default = Effect10.gen(function* () {
|
|
520
|
+
const sql = yield* SqlClient5.SqlClient;
|
|
521
|
+
yield* sql`ALTER TABLE spans ADD COLUMN execution_id TEXT NOT NULL DEFAULT ''`.pipe(
|
|
522
|
+
Effect10.withSpan("add_spans_execution_id")
|
|
523
|
+
);
|
|
524
|
+
yield* sql`CREATE INDEX idx_spans_execution_id ON spans(execution_id)`.pipe(
|
|
525
|
+
Effect10.withSpan("create_idx_spans_execution_id")
|
|
497
526
|
);
|
|
498
527
|
});
|
|
499
|
-
var create_span_exits_table_default = Effect8.void;
|
|
500
|
-
var simplify_span_exits_default = Effect8.void;
|
|
501
528
|
|
|
502
529
|
// src/services/Storage.ts
|
|
503
530
|
var SpanExitJson = Schema.toCodecJson(SpanExit);
|
|
@@ -567,6 +594,7 @@ var DbExternalSpan = ExternalSpan.pipe(
|
|
|
567
594
|
);
|
|
568
595
|
var DbAnySpan = Schema.Union([DbSpan, DbExternalSpan]);
|
|
569
596
|
var TraceSummary = Schema.Struct({
|
|
597
|
+
execution_id: Schema.String,
|
|
570
598
|
trace_id: Schema.String,
|
|
571
599
|
span_count: NumberFromBigInt,
|
|
572
600
|
root_span_name: Schema.NullOr(Schema.String),
|
|
@@ -586,40 +614,44 @@ var DbSpanLink = SpanLink.mapFields(
|
|
|
586
614
|
linkedTraceId: "linked_trace_id"
|
|
587
615
|
})
|
|
588
616
|
);
|
|
589
|
-
var Storage = class extends
|
|
617
|
+
var Storage = class extends Context4.Service()("inspeffct/Storage") {
|
|
590
618
|
};
|
|
591
619
|
var MigrationsLoader = Migrator.fromRecord({
|
|
592
620
|
"0001_create_otel_tables": create_otel_tables_default,
|
|
593
621
|
"0002_create_span_exits_table": create_span_exits_table_default,
|
|
594
|
-
"0003_simplify_span_exits": simplify_span_exits_default
|
|
622
|
+
"0003_simplify_span_exits": simplify_span_exits_default,
|
|
623
|
+
"0004_add_execution_id": add_execution_id_default
|
|
595
624
|
});
|
|
596
625
|
var runMigrations = Migrator.make({})({
|
|
597
626
|
loader: MigrationsLoader
|
|
598
627
|
});
|
|
599
|
-
var
|
|
600
|
-
|
|
628
|
+
var layer5 = (config) => Layer8.effectContext(
|
|
629
|
+
Effect10.gen(function* () {
|
|
601
630
|
const sql = yield* SqliteClient.SqliteClient;
|
|
602
631
|
yield* runMigrations;
|
|
603
632
|
const storage = Storage.of({
|
|
604
|
-
persistSpan: (span) =>
|
|
633
|
+
persistSpan: (span, executionId) => Effect10.gen(function* () {
|
|
605
634
|
const changed = yield* (
|
|
606
635
|
// @ts-ignore TS28 false positive from SqlSchema service inference
|
|
607
636
|
SqlSchema.findOne({
|
|
608
637
|
Request: DbAnySpan,
|
|
609
638
|
Result: Schema.Struct({ span_id: Schema.String }),
|
|
610
|
-
execute: (db) =>
|
|
611
|
-
|
|
639
|
+
execute: (db) => {
|
|
640
|
+
const row = { ...db, execution_id: executionId };
|
|
641
|
+
return sql`
|
|
642
|
+
INSERT INTO spans ${sql.insert(row)}
|
|
612
643
|
ON CONFLICT(span_id) DO UPDATE SET
|
|
613
|
-
${sql.update(
|
|
644
|
+
${sql.update(row, ["span_id"])}
|
|
614
645
|
WHERE
|
|
615
646
|
is_external = 1 OR
|
|
616
647
|
(end_time IS NULL AND excluded.is_external = 0)
|
|
617
648
|
RETURNING span_id
|
|
618
|
-
|
|
649
|
+
`;
|
|
650
|
+
}
|
|
619
651
|
})(span).pipe(
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
652
|
+
Effect10.as(true),
|
|
653
|
+
Effect10.catch(() => Effect10.succeed(false)),
|
|
654
|
+
Effect10.provideService(SqlClient5.SafeIntegers, true)
|
|
623
655
|
)
|
|
624
656
|
);
|
|
625
657
|
return changed;
|
|
@@ -644,7 +676,7 @@ var layer4 = (config) => Layer7.effectContext(
|
|
|
644
676
|
)
|
|
645
677
|
`
|
|
646
678
|
}),
|
|
647
|
-
|
|
679
|
+
Effect10.provideService(SqlClient5.SafeIntegers, true)
|
|
648
680
|
),
|
|
649
681
|
getSpansByTraceId: (traceId) => (
|
|
650
682
|
// @ts-ignore TS28 false positive from SqlSchema service inference
|
|
@@ -658,7 +690,7 @@ var layer4 = (config) => Layer7.effectContext(
|
|
|
658
690
|
ORDER BY s.start_time ASC
|
|
659
691
|
`
|
|
660
692
|
})(traceId).pipe(
|
|
661
|
-
|
|
693
|
+
Effect10.provideService(SqlClient5.SafeIntegers, true)
|
|
662
694
|
)
|
|
663
695
|
),
|
|
664
696
|
getRecentSpans: (limit = 100) => (
|
|
@@ -673,7 +705,7 @@ var layer4 = (config) => Layer7.effectContext(
|
|
|
673
705
|
LIMIT ${l}
|
|
674
706
|
`
|
|
675
707
|
})(limit).pipe(
|
|
676
|
-
|
|
708
|
+
Effect10.provideService(SqlClient5.SafeIntegers, true)
|
|
677
709
|
)
|
|
678
710
|
),
|
|
679
711
|
getSpanEvents: flow(
|
|
@@ -696,7 +728,7 @@ var layer4 = (config) => Layer7.effectContext(
|
|
|
696
728
|
ORDER BY time ASC
|
|
697
729
|
`
|
|
698
730
|
}),
|
|
699
|
-
|
|
731
|
+
Effect10.provideService(SqlClient5.SafeIntegers, true)
|
|
700
732
|
),
|
|
701
733
|
persistSpanLink: SqlSchema.void({
|
|
702
734
|
Request: DbSpanLink,
|
|
@@ -724,6 +756,7 @@ var layer4 = (config) => Layer7.effectContext(
|
|
|
724
756
|
}),
|
|
725
757
|
getTraces: (filters = {}) => SqlSchema.findAll({
|
|
726
758
|
Request: Schema.Struct({
|
|
759
|
+
executionId: Schema.optional(Schema.String),
|
|
727
760
|
limit: Schema.optional(Schema.Number),
|
|
728
761
|
since: Schema.optional(Schema.BigInt),
|
|
729
762
|
status: Schema.optional(Schema.Number)
|
|
@@ -731,9 +764,17 @@ var layer4 = (config) => Layer7.effectContext(
|
|
|
731
764
|
Result: TraceSummary,
|
|
732
765
|
execute: (req) => sql`
|
|
733
766
|
SELECT
|
|
767
|
+
s.execution_id,
|
|
734
768
|
s.trace_id,
|
|
735
769
|
COUNT(*) as span_count,
|
|
736
|
-
(
|
|
770
|
+
(
|
|
771
|
+
SELECT name
|
|
772
|
+
FROM spans
|
|
773
|
+
WHERE trace_id = s.trace_id
|
|
774
|
+
AND execution_id = s.execution_id
|
|
775
|
+
AND parent_span_id IS NULL
|
|
776
|
+
LIMIT 1
|
|
777
|
+
) as root_span_name,
|
|
737
778
|
MIN(s.start_time) as start_time,
|
|
738
779
|
MAX(s.end_time) as end_time,
|
|
739
780
|
MAX(
|
|
@@ -745,6 +786,7 @@ var layer4 = (config) => Layer7.effectContext(
|
|
|
745
786
|
) as status
|
|
746
787
|
FROM spans s
|
|
747
788
|
WHERE ${sql.and([
|
|
789
|
+
req.executionId !== void 0 ? sql`s.execution_id = ${req.executionId}` : sql`1=1`,
|
|
748
790
|
req.since !== void 0 ? sql`s.start_time >= ${req.since}` : sql`1=1`,
|
|
749
791
|
req.status !== void 0 ? sql`
|
|
750
792
|
CASE
|
|
@@ -754,17 +796,18 @@ var layer4 = (config) => Layer7.effectContext(
|
|
|
754
796
|
END = ${req.status}
|
|
755
797
|
` : sql`1=1`
|
|
756
798
|
])}
|
|
757
|
-
GROUP BY s.trace_id
|
|
799
|
+
GROUP BY s.execution_id, s.trace_id
|
|
758
800
|
ORDER BY start_time DESC
|
|
759
801
|
${req.limit !== void 0 ? sql`LIMIT ${req.limit}` : sql``}
|
|
760
802
|
`
|
|
761
803
|
})(filters).pipe(
|
|
762
|
-
|
|
804
|
+
Effect10.provideService(SqlClient5.SafeIntegers, true)
|
|
763
805
|
),
|
|
764
806
|
getSpans: (filters = {}) => (
|
|
765
807
|
// @ts-ignore TS28 false positive from SqlSchema service inference
|
|
766
808
|
SqlSchema.findAll({
|
|
767
809
|
Request: Schema.Struct({
|
|
810
|
+
executionId: Schema.optional(Schema.String),
|
|
768
811
|
limit: Schema.optional(Schema.Number),
|
|
769
812
|
minDuration: Schema.optional(Schema.BigInt),
|
|
770
813
|
name: Schema.optional(Schema.String),
|
|
@@ -776,6 +819,7 @@ var layer4 = (config) => Layer7.effectContext(
|
|
|
776
819
|
SELECT s.*
|
|
777
820
|
FROM spans s
|
|
778
821
|
WHERE ${sql.and([
|
|
822
|
+
req.executionId !== void 0 ? sql`s.execution_id = ${req.executionId}` : sql`1=1`,
|
|
779
823
|
req.traceId !== void 0 ? sql`s.trace_id = ${req.traceId}` : sql`1=1`,
|
|
780
824
|
req.name !== void 0 ? req.name.includes("%") ? sql`s.name LIKE ${req.name}` : sql`s.name = ${req.name}` : sql`1=1`,
|
|
781
825
|
req.minDuration !== void 0 ? sql`(s.end_time - s.start_time) >= ${req.minDuration}` : sql`1=1`,
|
|
@@ -791,36 +835,37 @@ var layer4 = (config) => Layer7.effectContext(
|
|
|
791
835
|
${req.limit !== void 0 ? sql`LIMIT ${req.limit}` : sql``}
|
|
792
836
|
`
|
|
793
837
|
})(filters).pipe(
|
|
794
|
-
|
|
838
|
+
Effect10.provideService(SqlClient5.SafeIntegers, true)
|
|
795
839
|
)
|
|
796
840
|
)
|
|
797
841
|
});
|
|
798
|
-
return
|
|
842
|
+
return Context4.make(Storage, storage);
|
|
799
843
|
})
|
|
800
|
-
).pipe(
|
|
844
|
+
).pipe(Layer8.provide(SqliteClient.layer(config)));
|
|
801
845
|
|
|
802
846
|
// src/services/EventCollector.ts
|
|
803
|
-
var EventCollector = class extends
|
|
847
|
+
var EventCollector = class extends Context4.Service()("inspeffct/EventCollector") {
|
|
804
848
|
};
|
|
805
|
-
var
|
|
849
|
+
var layer6 = Layer8.effect(
|
|
806
850
|
EventCollector,
|
|
807
|
-
|
|
851
|
+
Effect10.gen(function* () {
|
|
852
|
+
const executionId = yield* ExecutionId;
|
|
808
853
|
const storage = yield* Storage;
|
|
809
854
|
return EventCollector.of({
|
|
810
|
-
collect: (message) =>
|
|
855
|
+
collect: (message) => Effect10.gen(function* () {
|
|
811
856
|
switch (message._tag) {
|
|
812
857
|
case "InitNotification": {
|
|
813
|
-
yield*
|
|
858
|
+
yield* Effect10.logDebug(
|
|
814
859
|
`${message._tag} from ${message.instrumentationId} (inspectorURL: ${message.inspectorURL ?? "none"}, waitingForDebugger: ${message.waitingForDebugger})`
|
|
815
860
|
);
|
|
816
861
|
break;
|
|
817
862
|
}
|
|
818
863
|
case "TracerSpanNotification": {
|
|
819
864
|
const { instrumentationId, span } = message;
|
|
820
|
-
yield*
|
|
865
|
+
yield* Effect10.logDebug(`${message._tag} from ${instrumentationId}`);
|
|
821
866
|
if (span._tag === "Span" && span.status._tag === "Ended") {
|
|
822
|
-
yield* storage.persistSpan(span);
|
|
823
|
-
yield*
|
|
867
|
+
yield* storage.persistSpan(span, executionId);
|
|
868
|
+
yield* Effect10.logDebug(
|
|
824
869
|
`Persisted span ${span.name} (${span.spanId}) with exit ${span.status.exit._tag} to storage`
|
|
825
870
|
);
|
|
826
871
|
}
|
|
@@ -828,7 +873,7 @@ var layer5 = Layer7.effect(
|
|
|
828
873
|
}
|
|
829
874
|
case "TracerSpanEventNotification": {
|
|
830
875
|
const { event } = message;
|
|
831
|
-
yield*
|
|
876
|
+
yield* Effect10.logDebug(`${message._tag} from ${message.instrumentationId}`);
|
|
832
877
|
yield* storage.persistSpanEvent({
|
|
833
878
|
spanId: event.spanId,
|
|
834
879
|
traceId: event.traceId,
|
|
@@ -836,14 +881,14 @@ var layer5 = Layer7.effect(
|
|
|
836
881
|
time: event.time,
|
|
837
882
|
attributes: event.attributes
|
|
838
883
|
});
|
|
839
|
-
yield*
|
|
884
|
+
yield* Effect10.logDebug(
|
|
840
885
|
`Persisted span event ${event.name} for span ${event.spanId}`
|
|
841
886
|
);
|
|
842
887
|
break;
|
|
843
888
|
}
|
|
844
889
|
case "TracerSpanLinkNotification": {
|
|
845
890
|
const { link } = message;
|
|
846
|
-
yield*
|
|
891
|
+
yield* Effect10.logDebug(`${message._tag} from ${message.instrumentationId}`);
|
|
847
892
|
yield* storage.persistSpanLink({
|
|
848
893
|
spanId: link.spanId,
|
|
849
894
|
traceId: link.traceId,
|
|
@@ -851,7 +896,7 @@ var layer5 = Layer7.effect(
|
|
|
851
896
|
linkedTraceId: link.linkedTraceId,
|
|
852
897
|
attributes: link.attributes
|
|
853
898
|
});
|
|
854
|
-
yield*
|
|
899
|
+
yield* Effect10.logDebug(
|
|
855
900
|
`Persisted span link from ${link.spanId} to ${link.linkedSpanId}`
|
|
856
901
|
);
|
|
857
902
|
break;
|
|
@@ -860,48 +905,48 @@ var layer5 = Layer7.effect(
|
|
|
860
905
|
case "VariableReferenceInfo":
|
|
861
906
|
case "ResourcesForRequestReleased":
|
|
862
907
|
case "CurrentFibersInfo": {
|
|
863
|
-
yield*
|
|
908
|
+
yield* Effect10.logDebug(`${message._tag} from ${message.instrumentationId}`);
|
|
864
909
|
break;
|
|
865
910
|
}
|
|
866
911
|
}
|
|
867
|
-
}).pipe(
|
|
912
|
+
}).pipe(Effect10.catch((error) => Effect10.logWarning(`Failed to persist event: ${error}`)))
|
|
868
913
|
});
|
|
869
914
|
})
|
|
870
915
|
);
|
|
871
|
-
|
|
916
|
+
Layer8.succeed(
|
|
872
917
|
EventCollector,
|
|
873
918
|
EventCollector.of({
|
|
874
919
|
collect: (message) => {
|
|
875
920
|
if (message._tag === "InitNotification") {
|
|
876
|
-
return
|
|
921
|
+
return Effect10.logDebug(
|
|
877
922
|
`${message._tag} from ${message.instrumentationId} (inspectorURL: ${message.inspectorURL ?? "none"}, waitingForDebugger: ${message.waitingForDebugger})`
|
|
878
923
|
);
|
|
879
924
|
}
|
|
880
|
-
return
|
|
925
|
+
return Effect10.logDebug(`${message._tag} from ${message.instrumentationId}`);
|
|
881
926
|
}
|
|
882
927
|
})
|
|
883
928
|
);
|
|
884
|
-
|
|
929
|
+
Layer8.effect(
|
|
885
930
|
EventCollector,
|
|
886
|
-
|
|
931
|
+
Effect10.gen(function* () {
|
|
887
932
|
const messagesRef = yield* Ref.make(Chunk.empty());
|
|
888
933
|
return EventCollector.of({
|
|
889
934
|
collect: (message) => Ref.update(messagesRef, Chunk.append(message)),
|
|
890
|
-
getMessages: Ref.get(messagesRef).pipe(
|
|
935
|
+
getMessages: Ref.get(messagesRef).pipe(Effect10.map(Chunk.toReadonlyArray))
|
|
891
936
|
});
|
|
892
937
|
})
|
|
893
938
|
);
|
|
894
939
|
|
|
895
940
|
// src/services/CdpManager.ts
|
|
896
941
|
var BINDING_NAME = "__inspeffct_bridge__";
|
|
897
|
-
var CdpManager = class extends
|
|
942
|
+
var CdpManager = class extends Context4.Service()("inspeffct/CdpManager") {
|
|
898
943
|
};
|
|
899
|
-
var getBootloaderScript =
|
|
944
|
+
var getBootloaderScript = Effect10.gen(function* () {
|
|
900
945
|
const fs2 = yield* FileSystem.FileSystem;
|
|
901
946
|
const bootloaderPath = yield* getPath;
|
|
902
947
|
return yield* fs2.readFileString(bootloaderPath);
|
|
903
948
|
});
|
|
904
|
-
var connectAndListen = (url, bootloaderScript) =>
|
|
949
|
+
var connectAndListen = (url, bootloaderScript) => Effect10.gen(function* () {
|
|
905
950
|
const cdp = yield* CdpClient;
|
|
906
951
|
const collector = yield* EventCollector;
|
|
907
952
|
const connection = yield* cdp.connect(url);
|
|
@@ -909,21 +954,21 @@ var connectAndListen = (url, bootloaderScript) => Effect8.gen(function* () {
|
|
|
909
954
|
expression: bootloaderScript,
|
|
910
955
|
contextId,
|
|
911
956
|
silent: true
|
|
912
|
-
}).pipe(
|
|
957
|
+
}).pipe(Effect10.ensuring(connection.request("Runtime.runIfWaitingForDebugger").pipe(Effect10.ignore({ log: true }))));
|
|
913
958
|
const eventFiber = yield* connection.events.pipe(
|
|
914
959
|
Stream.takeUntil(
|
|
915
960
|
(event) => event.method === "Runtime.executionContextDestroyed" || event.method === "Runtime.executionContextsCleared" || event.method === "Inspector.detached"
|
|
916
961
|
),
|
|
917
962
|
Stream.runForEach(
|
|
918
|
-
(event) =>
|
|
963
|
+
(event) => Effect10.gen(function* () {
|
|
919
964
|
if (event.method === "Runtime.bindingCalled") {
|
|
920
965
|
const params = event.params;
|
|
921
966
|
if (params.name === BINDING_NAME) {
|
|
922
967
|
yield* Schema.decodeUnknownEffect(Schema.fromJsonString(OutMessage))(
|
|
923
968
|
params.payload
|
|
924
969
|
).pipe(
|
|
925
|
-
|
|
926
|
-
|
|
970
|
+
Effect10.flatMap((decoded) => collector.collect(decoded)),
|
|
971
|
+
Effect10.catch(() => Effect10.logError(`Failed to decode CDP message: ${params.payload}`))
|
|
927
972
|
);
|
|
928
973
|
}
|
|
929
974
|
}
|
|
@@ -933,44 +978,44 @@ var connectAndListen = (url, bootloaderScript) => Effect8.gen(function* () {
|
|
|
933
978
|
}
|
|
934
979
|
})
|
|
935
980
|
),
|
|
936
|
-
|
|
981
|
+
Effect10.forkScoped
|
|
937
982
|
);
|
|
938
|
-
yield*
|
|
983
|
+
yield* Effect10.yieldNow;
|
|
939
984
|
yield* connection.request("Runtime.addBinding", { name: BINDING_NAME });
|
|
940
985
|
yield* connection.request("Runtime.enable");
|
|
941
986
|
yield* connection.request("Runtime.runIfWaitingForDebugger");
|
|
942
|
-
yield*
|
|
987
|
+
yield* Effect10.logDebug(`CDP connected: ${url}`);
|
|
943
988
|
yield* Fiber.join(eventFiber);
|
|
944
989
|
});
|
|
945
|
-
var
|
|
990
|
+
var layer7 = Layer8.effect(
|
|
946
991
|
CdpManager,
|
|
947
|
-
|
|
992
|
+
Effect10.gen(function* () {
|
|
948
993
|
const bootloaderScript = yield* getBootloaderScript;
|
|
949
994
|
const cdpClient = yield* CdpClient;
|
|
950
995
|
const collector = yield* EventCollector;
|
|
951
|
-
const managerScope = yield*
|
|
996
|
+
const managerScope = yield* Effect10.scope;
|
|
952
997
|
const activeConnections = /* @__PURE__ */ new Map();
|
|
953
998
|
return CdpManager.of({
|
|
954
|
-
connect: (url) =>
|
|
999
|
+
connect: (url) => Effect10.gen(function* () {
|
|
955
1000
|
if (activeConnections.has(url)) {
|
|
956
1001
|
return;
|
|
957
1002
|
}
|
|
958
1003
|
activeConnections.set(url, true);
|
|
959
|
-
yield*
|
|
1004
|
+
yield* Effect10.logDebug(`Connecting to CDP: ${url}`);
|
|
960
1005
|
yield* connectAndListen(url, bootloaderScript).pipe(
|
|
961
|
-
|
|
962
|
-
|
|
963
|
-
|
|
964
|
-
|
|
1006
|
+
Effect10.provideService(CdpClient, cdpClient),
|
|
1007
|
+
Effect10.provideService(EventCollector, collector),
|
|
1008
|
+
Effect10.scoped,
|
|
1009
|
+
Effect10.catchCause((cause) => Effect10.logError(`CDP connection failed for ${url}: ${cause}`)),
|
|
965
1010
|
// Always remove from tracking when done (success, failure, or interruption)
|
|
966
|
-
|
|
967
|
-
|
|
1011
|
+
Effect10.ensuring(
|
|
1012
|
+
Effect10.sync(() => {
|
|
968
1013
|
activeConnections.delete(url);
|
|
969
1014
|
}).pipe(
|
|
970
|
-
|
|
1015
|
+
Effect10.tap(() => Effect10.logDebug(`CDP disconnected: ${url}`))
|
|
971
1016
|
)
|
|
972
1017
|
),
|
|
973
|
-
|
|
1018
|
+
Effect10.forkIn(managerScope)
|
|
974
1019
|
);
|
|
975
1020
|
})
|
|
976
1021
|
});
|
|
@@ -978,12 +1023,12 @@ var layer6 = Layer7.effect(
|
|
|
978
1023
|
);
|
|
979
1024
|
var namedSocketDirectory = os.platform() === "win32" ? "\\\\.\\pipe\\" : os.tmpdir();
|
|
980
1025
|
var pipeCounter = 0;
|
|
981
|
-
var generateIpcPath =
|
|
1026
|
+
var generateIpcPath = Effect10.sync(() => {
|
|
982
1027
|
const randomHex = crypto.randomBytes(4).toString("hex");
|
|
983
1028
|
const pipeName = `inspeffct.${process.pid}-${randomHex}-${pipeCounter++}.sock`;
|
|
984
1029
|
return path.join(namedSocketDirectory, pipeName);
|
|
985
1030
|
});
|
|
986
|
-
var cleanupSocketFile = (socketPath) =>
|
|
1031
|
+
var cleanupSocketFile = (socketPath) => Effect10.sync(() => {
|
|
987
1032
|
if (os.platform() !== "win32") {
|
|
988
1033
|
try {
|
|
989
1034
|
fs.unlinkSync(socketPath);
|
|
@@ -991,7 +1036,7 @@ var cleanupSocketFile = (socketPath) => Effect8.sync(() => {
|
|
|
991
1036
|
}
|
|
992
1037
|
}
|
|
993
1038
|
});
|
|
994
|
-
var IpcServer = class extends
|
|
1039
|
+
var IpcServer = class extends Context4.Service()("inspeffct/IpcServer") {
|
|
995
1040
|
};
|
|
996
1041
|
var tryParseMessage = (message) => {
|
|
997
1042
|
try {
|
|
@@ -1003,13 +1048,13 @@ var tryParseMessage = (message) => {
|
|
|
1003
1048
|
};
|
|
1004
1049
|
var ACK_SUCCESS = new Uint8Array([0]);
|
|
1005
1050
|
var parseMessages = (socket) => Stream.unwrap(
|
|
1006
|
-
|
|
1051
|
+
Effect10.gen(function* () {
|
|
1007
1052
|
const write = yield* socket.writer;
|
|
1008
1053
|
const decoder = new TextDecoder();
|
|
1009
1054
|
let buffer = "";
|
|
1010
1055
|
return Stream.callback(
|
|
1011
1056
|
(queue) => socket.run(
|
|
1012
|
-
(data) =>
|
|
1057
|
+
(data) => Effect10.gen(function* () {
|
|
1013
1058
|
buffer += decoder.decode(data);
|
|
1014
1059
|
let nullIndex;
|
|
1015
1060
|
while ((nullIndex = buffer.indexOf("\0")) !== -1) {
|
|
@@ -1024,13 +1069,13 @@ var parseMessages = (socket) => Stream.unwrap(
|
|
|
1024
1069
|
}
|
|
1025
1070
|
}
|
|
1026
1071
|
}),
|
|
1027
|
-
{ onOpen:
|
|
1072
|
+
{ onOpen: Effect10.void }
|
|
1028
1073
|
).pipe(
|
|
1029
|
-
|
|
1074
|
+
Effect10.andThen(() => {
|
|
1030
1075
|
if (buffer.length > 0) {
|
|
1031
1076
|
const decoded = tryParseMessage(buffer);
|
|
1032
1077
|
if (decoded) {
|
|
1033
|
-
return Queue2.offer(queue, decoded).pipe(
|
|
1078
|
+
return Queue2.offer(queue, decoded).pipe(Effect10.andThen(Queue2.end(queue)));
|
|
1034
1079
|
}
|
|
1035
1080
|
}
|
|
1036
1081
|
return Queue2.end(queue);
|
|
@@ -1039,18 +1084,18 @@ var parseMessages = (socket) => Stream.unwrap(
|
|
|
1039
1084
|
);
|
|
1040
1085
|
})
|
|
1041
1086
|
);
|
|
1042
|
-
var
|
|
1087
|
+
var layer8 = Layer8.effect(
|
|
1043
1088
|
IpcServer,
|
|
1044
|
-
|
|
1089
|
+
Effect10.gen(function* () {
|
|
1045
1090
|
const ipcPath = yield* generateIpcPath;
|
|
1046
|
-
yield*
|
|
1091
|
+
yield* Effect10.addFinalizer(() => cleanupSocketFile(ipcPath));
|
|
1047
1092
|
const server = yield* NodeSocketServer.make({ path: ipcPath });
|
|
1048
1093
|
const pubsub = yield* PubSub2.unbounded();
|
|
1049
1094
|
yield* server.run(
|
|
1050
1095
|
(socket) => parseMessages(socket).pipe(
|
|
1051
1096
|
Stream.runForEach((message) => PubSub2.publish(pubsub, message))
|
|
1052
1097
|
)
|
|
1053
|
-
).pipe(
|
|
1098
|
+
).pipe(Effect10.catchCause(Effect10.logDebug), Effect10.forkScoped);
|
|
1054
1099
|
const messages = Stream.fromPubSub(pubsub);
|
|
1055
1100
|
const subscribe3 = PubSub2.subscribe(pubsub);
|
|
1056
1101
|
return IpcServer.of({
|
|
@@ -1060,9 +1105,9 @@ var layer7 = Layer7.effect(
|
|
|
1060
1105
|
});
|
|
1061
1106
|
})
|
|
1062
1107
|
);
|
|
1063
|
-
|
|
1064
|
-
|
|
1065
|
-
|
|
1108
|
+
Effect10.map(IpcServer, (server) => server.path);
|
|
1109
|
+
Effect10.map(IpcServer, (server) => server.messages);
|
|
1110
|
+
Effect10.flatMap(IpcServer, (server) => server.subscribe);
|
|
1066
1111
|
|
|
1067
1112
|
// src/cli/options.ts
|
|
1068
1113
|
var dataOption = Flag3.string("data").pipe(
|
|
@@ -1094,23 +1139,28 @@ var buildEnv = (bootloaderPath, ipcPath) => {
|
|
|
1094
1139
|
};
|
|
1095
1140
|
};
|
|
1096
1141
|
var makeServicesLayer = (dataPath) => {
|
|
1097
|
-
const
|
|
1098
|
-
const
|
|
1099
|
-
const
|
|
1100
|
-
|
|
1101
|
-
|
|
1102
|
-
|
|
1142
|
+
const executionIdLayer = layer3;
|
|
1143
|
+
const storageLayer = layer5({ filename: dataPath });
|
|
1144
|
+
const eventCollectorLayer = layer6.pipe(
|
|
1145
|
+
Layer8.provide(executionIdLayer),
|
|
1146
|
+
Layer8.provide(storageLayer)
|
|
1147
|
+
);
|
|
1148
|
+
const bootloaderPathLayer = layer.pipe(Layer8.provide(NodePath.layer));
|
|
1149
|
+
return Layer8.mergeAll(
|
|
1150
|
+
executionIdLayer,
|
|
1151
|
+
layer8,
|
|
1103
1152
|
bootloaderPathLayer,
|
|
1104
|
-
|
|
1105
|
-
|
|
1106
|
-
|
|
1107
|
-
|
|
1108
|
-
|
|
1109
|
-
Layer7.provide(NodePath.layer)
|
|
1153
|
+
layer7.pipe(
|
|
1154
|
+
Layer8.provide(layer2),
|
|
1155
|
+
Layer8.provide(bootloaderPathLayer),
|
|
1156
|
+
Layer8.provide(NodeFileSystem.layer),
|
|
1157
|
+
Layer8.provide(NodePath.layer)
|
|
1110
1158
|
)
|
|
1159
|
+
).pipe(
|
|
1160
|
+
Layer8.provideMerge(eventCollectorLayer)
|
|
1111
1161
|
);
|
|
1112
1162
|
};
|
|
1113
|
-
var makeReadOnlyLayer = (dataPath) =>
|
|
1163
|
+
var makeReadOnlyLayer = (dataPath) => layer5({ filename: dataPath });
|
|
1114
1164
|
|
|
1115
1165
|
// src/cli/connect.ts
|
|
1116
1166
|
var command = Command5.make(
|
|
@@ -1121,16 +1171,16 @@ var command = Command5.make(
|
|
|
1121
1171
|
Argument2.withDescription("WebSocket URL of the inspector (ws://...)")
|
|
1122
1172
|
)
|
|
1123
1173
|
},
|
|
1124
|
-
({ data, url }) =>
|
|
1125
|
-
yield*
|
|
1126
|
-
yield*
|
|
1174
|
+
({ data, url }) => Effect10.gen(function* () {
|
|
1175
|
+
yield* Effect10.logDebug(`Connecting to URL: ${url}`);
|
|
1176
|
+
yield* Effect10.logDebug(`Data file: ${data}`);
|
|
1127
1177
|
const cdpManager = yield* CdpManager;
|
|
1128
1178
|
yield* cdpManager.connect(url);
|
|
1129
|
-
yield*
|
|
1130
|
-
return yield*
|
|
1179
|
+
yield* Effect10.logInfo(`Connected to ${url}`);
|
|
1180
|
+
return yield* Effect10.never;
|
|
1131
1181
|
}).pipe(
|
|
1132
|
-
|
|
1133
|
-
|
|
1182
|
+
Effect10.scoped,
|
|
1183
|
+
Effect10.provide(makeServicesLayer(data))
|
|
1134
1184
|
)
|
|
1135
1185
|
).pipe(Command5.withDescription("Connect to an existing inspector endpoint"));
|
|
1136
1186
|
var NODE_INSPECTOR_REGEX = /Debugger listening on (ws:\/\/[^\s]+)/;
|
|
@@ -1160,26 +1210,28 @@ var command2 = Command5.make(
|
|
|
1160
1210
|
Argument2.variadic({ min: 0 })
|
|
1161
1211
|
)
|
|
1162
1212
|
},
|
|
1163
|
-
({ args, data, encodedCommand }) =>
|
|
1213
|
+
({ args, data, encodedCommand }) => Effect10.gen(function* () {
|
|
1164
1214
|
const resolvedArgs = Option3.isSome(encodedCommand) ? JSON.parse(Buffer.from(encodedCommand.value, "base64url").toString("utf8")) : args;
|
|
1165
1215
|
const [rawExecutable, ...commandArgs] = resolvedArgs;
|
|
1166
1216
|
const executable = rawExecutable === "node" ? process.execPath : rawExecutable;
|
|
1167
|
-
|
|
1168
|
-
yield*
|
|
1217
|
+
const executionId = yield* ExecutionId;
|
|
1218
|
+
yield* Console2.log(`Execution ID: ${executionId}`);
|
|
1219
|
+
yield* Effect10.logDebug(`Running: ${executable} ${commandArgs.join(" ")}`);
|
|
1220
|
+
yield* Effect10.logDebug(`Data file: ${data}`);
|
|
1169
1221
|
const bootloaderPath = yield* getPath;
|
|
1170
|
-
yield*
|
|
1222
|
+
yield* Effect10.logDebug(`Bootloader: ${bootloaderPath}`);
|
|
1171
1223
|
const ipcServer = yield* IpcServer;
|
|
1172
|
-
yield*
|
|
1224
|
+
yield* Effect10.logDebug(`IPC socket: ${ipcServer.path}`);
|
|
1173
1225
|
const collector = yield* EventCollector;
|
|
1174
1226
|
const cdpManager = yield* CdpManager;
|
|
1175
1227
|
const env = buildEnv(bootloaderPath, ipcServer.path);
|
|
1176
|
-
yield*
|
|
1177
|
-
yield* Stream.runForEach(ipcServer.messages, (message) =>
|
|
1228
|
+
yield* Effect10.logDebug(`NODE_OPTIONS: ${env.NODE_OPTIONS}`);
|
|
1229
|
+
yield* Stream.runForEach(ipcServer.messages, (message) => Effect10.gen(function* () {
|
|
1178
1230
|
yield* collector.collect(message);
|
|
1179
1231
|
if (message._tag === "InitNotification" && message.inspectorURL) {
|
|
1180
1232
|
yield* cdpManager.connect(message.inspectorURL);
|
|
1181
1233
|
}
|
|
1182
|
-
})).pipe(
|
|
1234
|
+
})).pipe(Effect10.forkScoped);
|
|
1183
1235
|
const cmd = ChildProcess.make(executable, commandArgs, {
|
|
1184
1236
|
env,
|
|
1185
1237
|
extendEnv: true,
|
|
@@ -1188,33 +1240,33 @@ var command2 = Command5.make(
|
|
|
1188
1240
|
stdout: "inherit"
|
|
1189
1241
|
});
|
|
1190
1242
|
const childProcess = yield* cmd;
|
|
1191
|
-
yield*
|
|
1243
|
+
yield* Effect10.logDebug(`Started process with PID: ${childProcess.pid}`);
|
|
1192
1244
|
const textDecoder = new TextDecoder();
|
|
1193
1245
|
yield* Stream.runForEach(
|
|
1194
1246
|
childProcess.stderr,
|
|
1195
|
-
(chunk) =>
|
|
1196
|
-
yield*
|
|
1247
|
+
(chunk) => Effect10.gen(function* () {
|
|
1248
|
+
yield* Effect10.sync(() => process.stderr.write(chunk));
|
|
1197
1249
|
const inspectorUrl = parseInspectorUrl(chunk, textDecoder);
|
|
1198
1250
|
if (inspectorUrl) {
|
|
1199
|
-
yield*
|
|
1251
|
+
yield* Effect10.logDebug(`Detected inspector URL from stderr: ${inspectorUrl}`);
|
|
1200
1252
|
yield* cdpManager.connect(inspectorUrl);
|
|
1201
1253
|
}
|
|
1202
1254
|
})
|
|
1203
|
-
).pipe(
|
|
1204
|
-
const forwardSignal = (signal) =>
|
|
1255
|
+
).pipe(Effect10.forkScoped);
|
|
1256
|
+
const forwardSignal = (signal) => Effect10.sync(() => {
|
|
1205
1257
|
process.on(signal, () => {
|
|
1206
|
-
|
|
1258
|
+
Effect10.runPromise(childProcess.kill({ killSignal: signal }).pipe(Effect10.ignore));
|
|
1207
1259
|
});
|
|
1208
1260
|
});
|
|
1209
1261
|
yield* forwardSignal("SIGTERM");
|
|
1210
1262
|
yield* forwardSignal("SIGINT");
|
|
1211
1263
|
yield* forwardSignal("SIGHUP");
|
|
1212
1264
|
const exitCode = yield* childProcess.exitCode;
|
|
1213
|
-
yield*
|
|
1214
|
-
yield*
|
|
1265
|
+
yield* Effect10.logDebug(`Process exited with code: ${exitCode}`);
|
|
1266
|
+
yield* Effect10.sync(() => process.exitCode = exitCode);
|
|
1215
1267
|
}).pipe(
|
|
1216
|
-
|
|
1217
|
-
|
|
1268
|
+
Effect10.scoped,
|
|
1269
|
+
Effect10.provide(makeServicesLayer(data))
|
|
1218
1270
|
)
|
|
1219
1271
|
).pipe(Command5.withDescription("Run a command with Effect instrumentation"));
|
|
1220
1272
|
var getSpanId = (span) => span.spanId;
|
|
@@ -1346,6 +1398,10 @@ var command3 = Command5.make(
|
|
|
1346
1398
|
"spans",
|
|
1347
1399
|
{
|
|
1348
1400
|
data: dataOption,
|
|
1401
|
+
executionId: Flag3.string("execution-id").pipe(
|
|
1402
|
+
Flag3.withDescription("Filter by execution ID"),
|
|
1403
|
+
Flag3.optional
|
|
1404
|
+
),
|
|
1349
1405
|
json: jsonOption,
|
|
1350
1406
|
limit: limitOption,
|
|
1351
1407
|
minDuration: Flag3.string("min-duration").pipe(
|
|
@@ -1366,7 +1422,7 @@ var command3 = Command5.make(
|
|
|
1366
1422
|
Flag3.optional
|
|
1367
1423
|
)
|
|
1368
1424
|
},
|
|
1369
|
-
({ data, json, limit, minDuration, name, status, trace }) =>
|
|
1425
|
+
({ data, executionId, json, limit, minDuration, name, status, trace }) => Effect10.gen(function* () {
|
|
1370
1426
|
const storage = yield* Storage;
|
|
1371
1427
|
let statusCode;
|
|
1372
1428
|
if (Option3.isSome(status)) {
|
|
@@ -1381,10 +1437,11 @@ var command3 = Command5.make(
|
|
|
1381
1437
|
statusCode = 0;
|
|
1382
1438
|
break;
|
|
1383
1439
|
default:
|
|
1384
|
-
yield*
|
|
1440
|
+
yield* Effect10.logWarning(`Unknown status: ${status.value}, ignoring filter`);
|
|
1385
1441
|
}
|
|
1386
1442
|
}
|
|
1387
1443
|
const filters = {
|
|
1444
|
+
...Option3.isSome(executionId) ? { executionId: executionId.value } : {},
|
|
1388
1445
|
...Option3.isSome(trace) ? { traceId: trace.value } : {},
|
|
1389
1446
|
...Option3.isSome(name) ? { name: name.value } : {},
|
|
1390
1447
|
...statusCode !== void 0 ? { status: statusCode } : {},
|
|
@@ -1411,10 +1468,10 @@ var command3 = Command5.make(
|
|
|
1411
1468
|
isExternal: isExternalSpan(s)
|
|
1412
1469
|
};
|
|
1413
1470
|
});
|
|
1414
|
-
yield*
|
|
1471
|
+
yield* Console2.log(JSON.stringify(output, null, 2));
|
|
1415
1472
|
} else {
|
|
1416
1473
|
if (spans.length === 0) {
|
|
1417
|
-
yield*
|
|
1474
|
+
yield* Console2.log("No spans found.");
|
|
1418
1475
|
} else {
|
|
1419
1476
|
const spanItems = spans.map((s) => {
|
|
1420
1477
|
const endTime = getEndTime(s);
|
|
@@ -1444,12 +1501,12 @@ var command3 = Command5.make(
|
|
|
1444
1501
|
"",
|
|
1445
1502
|
...spanItems
|
|
1446
1503
|
].join("\n");
|
|
1447
|
-
yield*
|
|
1504
|
+
yield* Console2.log(renderDoc(doc));
|
|
1448
1505
|
}
|
|
1449
1506
|
}
|
|
1450
1507
|
}).pipe(
|
|
1451
|
-
|
|
1452
|
-
|
|
1508
|
+
Effect10.scoped,
|
|
1509
|
+
Effect10.provide(makeReadOnlyLayer(data))
|
|
1453
1510
|
)
|
|
1454
1511
|
).pipe(Command5.withDescription("List spans with optional filters"));
|
|
1455
1512
|
var command4 = Command5.make(
|
|
@@ -1461,11 +1518,11 @@ var command4 = Command5.make(
|
|
|
1461
1518
|
Argument2.withDescription("The trace ID to display")
|
|
1462
1519
|
)
|
|
1463
1520
|
},
|
|
1464
|
-
({ data, json, traceId }) =>
|
|
1521
|
+
({ data, json, traceId }) => Effect10.gen(function* () {
|
|
1465
1522
|
const storage = yield* Storage;
|
|
1466
1523
|
const spans = yield* storage.getSpans({ traceId });
|
|
1467
1524
|
if (spans.length === 0) {
|
|
1468
|
-
yield*
|
|
1525
|
+
yield* Console2.log(`No spans found for trace: ${traceId}`);
|
|
1469
1526
|
return;
|
|
1470
1527
|
}
|
|
1471
1528
|
const traces = yield* storage.getTraces({ limit: 1 });
|
|
@@ -1507,7 +1564,7 @@ var command4 = Command5.make(
|
|
|
1507
1564
|
spanCount: spans.length,
|
|
1508
1565
|
spans: roots.map((r) => buildJsonTree(graph, r.index))
|
|
1509
1566
|
};
|
|
1510
|
-
yield*
|
|
1567
|
+
yield* Console2.log(JSON.stringify(output, null, 2));
|
|
1511
1568
|
} else {
|
|
1512
1569
|
const header = [
|
|
1513
1570
|
field("Trace", traceId),
|
|
@@ -1515,11 +1572,11 @@ var command4 = Command5.make(
|
|
|
1515
1572
|
""
|
|
1516
1573
|
].join("\n");
|
|
1517
1574
|
const treeDoc = renderSpanGraph(graph);
|
|
1518
|
-
yield*
|
|
1575
|
+
yield* Console2.log(renderDoc([header, treeDoc].filter((line) => line.length > 0).join("\n")));
|
|
1519
1576
|
}
|
|
1520
1577
|
}).pipe(
|
|
1521
|
-
|
|
1522
|
-
|
|
1578
|
+
Effect10.scoped,
|
|
1579
|
+
Effect10.provide(makeReadOnlyLayer(data))
|
|
1523
1580
|
)
|
|
1524
1581
|
).pipe(Command5.withDescription("Show a trace as a tree view"));
|
|
1525
1582
|
var command5 = Command5.make(
|
|
@@ -1527,6 +1584,10 @@ var command5 = Command5.make(
|
|
|
1527
1584
|
{
|
|
1528
1585
|
data: dataOption,
|
|
1529
1586
|
json: jsonOption,
|
|
1587
|
+
executionId: Flag3.string("execution-id").pipe(
|
|
1588
|
+
Flag3.withDescription("Filter by execution ID"),
|
|
1589
|
+
Flag3.optional
|
|
1590
|
+
),
|
|
1530
1591
|
limit: limitOption,
|
|
1531
1592
|
since: Flag3.string("since").pipe(
|
|
1532
1593
|
Flag3.withDescription("Filter by time range (e.g., '1h', '30m')"),
|
|
@@ -1537,7 +1598,7 @@ var command5 = Command5.make(
|
|
|
1537
1598
|
Flag3.optional
|
|
1538
1599
|
)
|
|
1539
1600
|
},
|
|
1540
|
-
({ data, json, limit, since, status }) =>
|
|
1601
|
+
({ data, executionId, json, limit, since, status }) => Effect10.gen(function* () {
|
|
1541
1602
|
const storage = yield* Storage;
|
|
1542
1603
|
let statusCode;
|
|
1543
1604
|
if (Option3.isSome(status)) {
|
|
@@ -1552,7 +1613,7 @@ var command5 = Command5.make(
|
|
|
1552
1613
|
statusCode = 0;
|
|
1553
1614
|
break;
|
|
1554
1615
|
default:
|
|
1555
|
-
yield*
|
|
1616
|
+
yield* Effect10.logWarning(`Unknown status: ${status.value}, ignoring filter`);
|
|
1556
1617
|
}
|
|
1557
1618
|
}
|
|
1558
1619
|
let sinceNanos;
|
|
@@ -1562,6 +1623,7 @@ var command5 = Command5.make(
|
|
|
1562
1623
|
sinceNanos = nowNanos - durationNanos;
|
|
1563
1624
|
}
|
|
1564
1625
|
const filters = {
|
|
1626
|
+
...Option3.isSome(executionId) ? { executionId: executionId.value } : {},
|
|
1565
1627
|
...statusCode !== void 0 ? { status: statusCode } : {},
|
|
1566
1628
|
...sinceNanos !== void 0 ? { since: sinceNanos } : {},
|
|
1567
1629
|
...Option3.isSome(limit) ? { limit: limit.value } : {}
|
|
@@ -1577,10 +1639,10 @@ var command5 = Command5.make(
|
|
|
1577
1639
|
endTime: t.end_time ? formatTimestamp(t.end_time) : null,
|
|
1578
1640
|
durationMs: t.end_time ? Number((t.end_time - t.start_time) / 1000000n) : null
|
|
1579
1641
|
}));
|
|
1580
|
-
yield*
|
|
1642
|
+
yield* Console2.log(JSON.stringify(output, null, 2));
|
|
1581
1643
|
} else {
|
|
1582
1644
|
if (traces.length === 0) {
|
|
1583
|
-
yield*
|
|
1645
|
+
yield* Console2.log("No traces found.");
|
|
1584
1646
|
} else {
|
|
1585
1647
|
const traceItems = traces.map((t) => {
|
|
1586
1648
|
const duration = t.end_time ? formatDuration(t.end_time - t.start_time) : "running";
|
|
@@ -1598,12 +1660,12 @@ var command5 = Command5.make(
|
|
|
1598
1660
|
"",
|
|
1599
1661
|
...traceItems
|
|
1600
1662
|
].join("\n");
|
|
1601
|
-
yield*
|
|
1663
|
+
yield* Console2.log(renderDoc(doc));
|
|
1602
1664
|
}
|
|
1603
1665
|
}
|
|
1604
1666
|
}).pipe(
|
|
1605
|
-
|
|
1606
|
-
|
|
1667
|
+
Effect10.scoped,
|
|
1668
|
+
Effect10.provide(makeReadOnlyLayer(data))
|
|
1607
1669
|
)
|
|
1608
1670
|
).pipe(Command5.withDescription("List traces with optional filters"));
|
|
1609
1671
|
|
|
@@ -1629,6 +1691,6 @@ var run = (args) => cli(encodeRunSeparator(args));
|
|
|
1629
1691
|
|
|
1630
1692
|
// src/bin.ts
|
|
1631
1693
|
run(process.argv.slice(2)).pipe(
|
|
1632
|
-
|
|
1694
|
+
Effect10.provide(NodeServices.layer),
|
|
1633
1695
|
NodeRuntime.runMain
|
|
1634
1696
|
);
|