inspeffct 1.0.4 → 1.0.6

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.
Files changed (2) hide show
  1. package/dist/bin.js +277 -64
  2. package/package.json +1 -1
package/dist/bin.js CHANGED
@@ -2,8 +2,8 @@
2
2
  import * as NodeRuntime from '@effect/platform-node/NodeRuntime';
3
3
  import * as NodeServices from '@effect/platform-node/NodeServices';
4
4
  import * as Effect10 from 'effect/Effect';
5
- import * as Command5 from 'effect/unstable/cli/Command';
6
- import * as Argument2 from 'effect/unstable/cli/Argument';
5
+ import * as Command6 from 'effect/unstable/cli/Command';
6
+ import * as Argument3 from 'effect/unstable/cli/Argument';
7
7
  import * as Context4 from 'effect/Context';
8
8
  import * as Fiber from 'effect/Fiber';
9
9
  import * as FileSystem from 'effect/FileSystem';
@@ -332,9 +332,9 @@ var randomUUID = Effect10.gen(function* () {
332
332
  hex.slice(10, 16).join("")
333
333
  ].join("-");
334
334
  });
335
- var ExecutionId = class extends Context4.Service()("inspeffct/ExecutionId") {
335
+ var RunId = class extends Context4.Service()("inspeffct/RunId") {
336
336
  };
337
- var layer3 = Layer8.effect(ExecutionId, randomUUID);
337
+ var layer3 = Layer8.effect(RunId, randomUUID);
338
338
  var isSchema = (u) => typeof u === "object" && u !== null && "ast" in u;
339
339
  var getMembers = (schema) => "members" in schema && Array.isArray(schema.members) ? schema.members : "cases" in schema ? Object.values(schema.cases) : [schema];
340
340
  var evolveNested = (schema, evolve2) => {
@@ -516,13 +516,13 @@ var create_otel_tables_default = Effect10.gen(function* () {
516
516
  });
517
517
  var create_span_exits_table_default = Effect10.void;
518
518
  var simplify_span_exits_default = Effect10.void;
519
- var add_execution_id_default = Effect10.gen(function* () {
519
+ var add_run_id_default = Effect10.gen(function* () {
520
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")
521
+ yield* sql`ALTER TABLE spans ADD COLUMN run_id TEXT NOT NULL DEFAULT ''`.pipe(
522
+ Effect10.withSpan("add_spans_run_id")
523
523
  );
524
- yield* sql`CREATE INDEX idx_spans_execution_id ON spans(execution_id)`.pipe(
525
- Effect10.withSpan("create_idx_spans_execution_id")
524
+ yield* sql`CREATE INDEX idx_spans_run_id ON spans(run_id)`.pipe(
525
+ Effect10.withSpan("create_idx_spans_run_id")
526
526
  );
527
527
  });
528
528
 
@@ -594,7 +594,7 @@ var DbExternalSpan = ExternalSpan.pipe(
594
594
  );
595
595
  var DbAnySpan = Schema.Union([DbSpan, DbExternalSpan]);
596
596
  var TraceSummary = Schema.Struct({
597
- execution_id: Schema.String,
597
+ run_id: Schema.String,
598
598
  trace_id: Schema.String,
599
599
  span_count: NumberFromBigInt,
600
600
  root_span_name: Schema.NullOr(Schema.String),
@@ -620,7 +620,7 @@ var MigrationsLoader = Migrator.fromRecord({
620
620
  "0001_create_otel_tables": create_otel_tables_default,
621
621
  "0002_create_span_exits_table": create_span_exits_table_default,
622
622
  "0003_simplify_span_exits": simplify_span_exits_default,
623
- "0004_add_execution_id": add_execution_id_default
623
+ "0004_add_run_id": add_run_id_default
624
624
  });
625
625
  var runMigrations = Migrator.make({})({
626
626
  loader: MigrationsLoader
@@ -630,14 +630,14 @@ var layer5 = (config) => Layer8.effectContext(
630
630
  const sql = yield* SqliteClient.SqliteClient;
631
631
  yield* runMigrations;
632
632
  const storage = Storage.of({
633
- persistSpan: (span, executionId) => Effect10.gen(function* () {
633
+ persistSpan: (span, runId) => Effect10.gen(function* () {
634
634
  const changed = yield* (
635
635
  // @ts-ignore TS28 false positive from SqlSchema service inference
636
636
  SqlSchema.findOne({
637
637
  Request: DbAnySpan,
638
638
  Result: Schema.Struct({ span_id: Schema.String }),
639
639
  execute: (db) => {
640
- const row = { ...db, execution_id: executionId };
640
+ const row = { ...db, run_id: runId };
641
641
  return sql`
642
642
  INSERT INTO spans ${sql.insert(row)}
643
643
  ON CONFLICT(span_id) DO UPDATE SET
@@ -756,22 +756,22 @@ var layer5 = (config) => Layer8.effectContext(
756
756
  }),
757
757
  getTraces: (filters = {}) => SqlSchema.findAll({
758
758
  Request: Schema.Struct({
759
- executionId: Schema.optional(Schema.String),
760
759
  limit: Schema.optional(Schema.Number),
760
+ runId: Schema.optional(Schema.String),
761
761
  since: Schema.optional(Schema.BigInt),
762
762
  status: Schema.optional(Schema.Number)
763
763
  }),
764
764
  Result: TraceSummary,
765
765
  execute: (req) => sql`
766
766
  SELECT
767
- s.execution_id,
767
+ s.run_id,
768
768
  s.trace_id,
769
769
  COUNT(*) as span_count,
770
770
  (
771
771
  SELECT name
772
772
  FROM spans
773
773
  WHERE trace_id = s.trace_id
774
- AND execution_id = s.execution_id
774
+ AND run_id = s.run_id
775
775
  AND parent_span_id IS NULL
776
776
  LIMIT 1
777
777
  ) as root_span_name,
@@ -786,7 +786,7 @@ var layer5 = (config) => Layer8.effectContext(
786
786
  ) as status
787
787
  FROM spans s
788
788
  WHERE ${sql.and([
789
- req.executionId !== void 0 ? sql`s.execution_id = ${req.executionId}` : sql`1=1`,
789
+ req.runId !== void 0 ? sql`s.run_id = ${req.runId}` : sql`1=1`,
790
790
  req.since !== void 0 ? sql`s.start_time >= ${req.since}` : sql`1=1`,
791
791
  req.status !== void 0 ? sql`
792
792
  CASE
@@ -796,7 +796,7 @@ var layer5 = (config) => Layer8.effectContext(
796
796
  END = ${req.status}
797
797
  ` : sql`1=1`
798
798
  ])}
799
- GROUP BY s.execution_id, s.trace_id
799
+ GROUP BY s.run_id, s.trace_id
800
800
  ORDER BY start_time DESC
801
801
  ${req.limit !== void 0 ? sql`LIMIT ${req.limit}` : sql``}
802
802
  `
@@ -807,10 +807,11 @@ var layer5 = (config) => Layer8.effectContext(
807
807
  // @ts-ignore TS28 false positive from SqlSchema service inference
808
808
  SqlSchema.findAll({
809
809
  Request: Schema.Struct({
810
- executionId: Schema.optional(Schema.String),
811
810
  limit: Schema.optional(Schema.Number),
812
811
  minDuration: Schema.optional(Schema.BigInt),
813
812
  name: Schema.optional(Schema.String),
813
+ runId: Schema.optional(Schema.String),
814
+ spanId: Schema.optional(Schema.String),
814
815
  status: Schema.optional(Schema.Number),
815
816
  traceId: Schema.optional(Schema.String)
816
817
  }),
@@ -819,7 +820,8 @@ var layer5 = (config) => Layer8.effectContext(
819
820
  SELECT s.*
820
821
  FROM spans s
821
822
  WHERE ${sql.and([
822
- req.executionId !== void 0 ? sql`s.execution_id = ${req.executionId}` : sql`1=1`,
823
+ req.runId !== void 0 ? sql`s.run_id = ${req.runId}` : sql`1=1`,
824
+ req.spanId !== void 0 ? sql`s.span_id = ${req.spanId}` : sql`1=1`,
823
825
  req.traceId !== void 0 ? sql`s.trace_id = ${req.traceId}` : sql`1=1`,
824
826
  req.name !== void 0 ? req.name.includes("%") ? sql`s.name LIKE ${req.name}` : sql`s.name = ${req.name}` : sql`1=1`,
825
827
  req.minDuration !== void 0 ? sql`(s.end_time - s.start_time) >= ${req.minDuration}` : sql`1=1`,
@@ -849,7 +851,7 @@ var EventCollector = class extends Context4.Service()("inspeffct/EventCollector"
849
851
  var layer6 = Layer8.effect(
850
852
  EventCollector,
851
853
  Effect10.gen(function* () {
852
- const executionId = yield* ExecutionId;
854
+ const runId = yield* RunId;
853
855
  const storage = yield* Storage;
854
856
  return EventCollector.of({
855
857
  collect: (message) => Effect10.gen(function* () {
@@ -863,12 +865,10 @@ var layer6 = Layer8.effect(
863
865
  case "TracerSpanNotification": {
864
866
  const { instrumentationId, span } = message;
865
867
  yield* Effect10.logDebug(`${message._tag} from ${instrumentationId}`);
866
- if (span._tag === "Span" && span.status._tag === "Ended") {
867
- yield* storage.persistSpan(span, executionId);
868
- yield* Effect10.logDebug(
869
- `Persisted span ${span.name} (${span.spanId}) with exit ${span.status.exit._tag} to storage`
870
- );
871
- }
868
+ yield* storage.persistSpan(span, runId);
869
+ yield* Effect10.logDebug(
870
+ `Persisted span (${span.traceId}, ${span.spanId}) to storage`
871
+ );
872
872
  break;
873
873
  }
874
874
  case "TracerSpanEventNotification": {
@@ -1139,16 +1139,16 @@ var buildEnv = (bootloaderPath, ipcPath) => {
1139
1139
  };
1140
1140
  };
1141
1141
  var makeServicesLayer = (dataPath) => {
1142
- const executionIdLayer = layer3;
1142
+ const runIdLayer = layer3;
1143
1143
  const storageLayer = layer5({ filename: dataPath });
1144
1144
  const eventCollectorLayer = layer6.pipe(
1145
- Layer8.provide(executionIdLayer),
1145
+ Layer8.provide(runIdLayer),
1146
1146
  Layer8.provide(storageLayer)
1147
1147
  );
1148
1148
  const bootloaderPathLayer = layer.pipe(Layer8.provide(NodePath.layer));
1149
1149
  return Layer8.mergeAll(
1150
- executionIdLayer,
1151
1150
  layer8,
1151
+ runIdLayer,
1152
1152
  bootloaderPathLayer,
1153
1153
  layer7.pipe(
1154
1154
  Layer8.provide(layer2),
@@ -1163,12 +1163,12 @@ var makeServicesLayer = (dataPath) => {
1163
1163
  var makeReadOnlyLayer = (dataPath) => layer5({ filename: dataPath });
1164
1164
 
1165
1165
  // src/cli/connect.ts
1166
- var command = Command5.make(
1166
+ var command = Command6.make(
1167
1167
  "connect",
1168
1168
  {
1169
1169
  data: dataOption,
1170
- url: Argument2.string("url").pipe(
1171
- Argument2.withDescription("WebSocket URL of the inspector (ws://...)")
1170
+ url: Argument3.string("url").pipe(
1171
+ Argument3.withDescription("WebSocket URL of the inspector (ws://...)")
1172
1172
  )
1173
1173
  },
1174
1174
  ({ data, url }) => Effect10.gen(function* () {
@@ -1182,7 +1182,19 @@ var command = Command5.make(
1182
1182
  Effect10.scoped,
1183
1183
  Effect10.provide(makeServicesLayer(data))
1184
1184
  )
1185
- ).pipe(Command5.withDescription("Connect to an existing inspector endpoint"));
1185
+ ).pipe(
1186
+ Command6.withDescription("Connect to an existing CDP inspector endpoint"),
1187
+ Command6.withExamples([
1188
+ {
1189
+ command: "inspeffct connect ws://127.0.0.1:9229/<id>",
1190
+ description: "Connect to a running Node.js inspector endpoint"
1191
+ },
1192
+ {
1193
+ command: "inspeffct connect --data .inspeffct.db ws://127.0.0.1:9229/<id>",
1194
+ description: "Persist captured data to a specific SQLite database"
1195
+ }
1196
+ ])
1197
+ );
1186
1198
  var NODE_INSPECTOR_REGEX = /Debugger listening on (ws:\/\/[^\s]+)/;
1187
1199
  var BUN_INSPECTOR_REGEX = /https:\/\/debug\.bun\.sh\/#([^\s]+)/;
1188
1200
  var parseInspectorUrl = (chunk, decoder) => {
@@ -1197,7 +1209,7 @@ var parseInspectorUrl = (chunk, decoder) => {
1197
1209
  }
1198
1210
  return void 0;
1199
1211
  };
1200
- var command2 = Command5.make(
1212
+ var command2 = Command6.make(
1201
1213
  "run",
1202
1214
  {
1203
1215
  data: dataOption,
@@ -1205,17 +1217,17 @@ var command2 = Command5.make(
1205
1217
  Flag3.optional,
1206
1218
  Flag3.withHidden
1207
1219
  ),
1208
- args: Argument2.string("command").pipe(
1209
- Argument2.withDescription("The command to run"),
1210
- Argument2.variadic({ min: 0 })
1220
+ args: Argument3.string("command").pipe(
1221
+ Argument3.withDescription("The command to run"),
1222
+ Argument3.variadic({ min: 0 })
1211
1223
  )
1212
1224
  },
1213
1225
  ({ args, data, encodedCommand }) => Effect10.gen(function* () {
1214
1226
  const resolvedArgs = Option3.isSome(encodedCommand) ? JSON.parse(Buffer.from(encodedCommand.value, "base64url").toString("utf8")) : args;
1215
1227
  const [rawExecutable, ...commandArgs] = resolvedArgs;
1216
1228
  const executable = rawExecutable === "node" ? process.execPath : rawExecutable;
1217
- const executionId = yield* ExecutionId;
1218
- yield* Console2.log(`Execution ID: ${executionId}`);
1229
+ const runId = yield* RunId;
1230
+ yield* Console2.log(`Inspeffct Run ID: ${runId}`);
1219
1231
  yield* Effect10.logDebug(`Running: ${executable} ${commandArgs.join(" ")}`);
1220
1232
  yield* Effect10.logDebug(`Data file: ${data}`);
1221
1233
  const bootloaderPath = yield* getPath;
@@ -1268,7 +1280,19 @@ var command2 = Command5.make(
1268
1280
  Effect10.scoped,
1269
1281
  Effect10.provide(makeServicesLayer(data))
1270
1282
  )
1271
- ).pipe(Command5.withDescription("Run a command with Effect instrumentation"));
1283
+ ).pipe(
1284
+ Command6.withDescription("Run a command with Effect instrumentation"),
1285
+ Command6.withExamples([
1286
+ {
1287
+ command: "inspeffct run -- node app.js",
1288
+ description: "Run a Node.js application with instrumentation"
1289
+ },
1290
+ {
1291
+ command: "inspeffct run --data .inspeffct.db -- node --inspect app.js",
1292
+ description: "Capture data in a specific SQLite database"
1293
+ }
1294
+ ])
1295
+ );
1272
1296
  var getSpanId = (span) => span.spanId;
1273
1297
  var getTraceId = (span) => span.traceId;
1274
1298
  var getParentSpanId = (span) => span._tag === "Span" ? span.parentSpanId : null;
@@ -1321,6 +1345,7 @@ var formatStatusDoc = (status) => {
1321
1345
  }
1322
1346
  };
1323
1347
  var field = (label, value) => `${label}: ${value}`;
1348
+ var dim = (text) => `\x1B[2m${text}\x1B[22m`;
1324
1349
  var renderDoc = (doc) => doc;
1325
1350
  var statusSymbol = (status, hasEndTime) => {
1326
1351
  if (!hasEndTime) {
@@ -1360,6 +1385,17 @@ var formatSpanLine = (span) => {
1360
1385
  const duration = endTime !== null ? formatDuration(endTime - startTime) : "running";
1361
1386
  return `${symbol} ${getSpanName(span)} (${duration}) [${getSpanId(span)}]`;
1362
1387
  };
1388
+ var formatAttributeValue = (value) => {
1389
+ const json = JSON.stringify(value);
1390
+ return json === void 0 ? "undefined" : json;
1391
+ };
1392
+ var formatSpanAttributesLine = (span) => {
1393
+ const attributes = Object.entries(getAttributes(span));
1394
+ if (attributes.length === 0) {
1395
+ return null;
1396
+ }
1397
+ return attributes.map(([key, value]) => `${key}=${formatAttributeValue(value)}`).join(", ");
1398
+ };
1363
1399
  var renderGraphNode = (graph, nodeIndex, prefix, isLast, isRoot) => {
1364
1400
  const spanOpt = Graph.getNode(graph, nodeIndex);
1365
1401
  if (Option3.isNone(spanOpt)) return "";
@@ -1375,10 +1411,13 @@ var renderGraphNode = (graph, nodeIndex, prefix, isLast, isRoot) => {
1375
1411
  const connector = isRoot ? "" : isLast ? "\u2514\u2500 " : "\u251C\u2500 ";
1376
1412
  const line = `${prefix}${connector}${formatSpanLine(span)}`;
1377
1413
  const childPrefix = isRoot ? "" : prefix + (isLast ? " " : "\u2502 ");
1414
+ const attributePrefix = isRoot ? " " : `${childPrefix} `;
1415
+ const attributesLine = formatSpanAttributesLine(span);
1416
+ const attributeDoc = attributesLine === null ? [] : [`${attributePrefix}${dim(attributesLine)}`];
1378
1417
  const childDocs = children.map(
1379
1418
  (child, i) => renderGraphNode(graph, child.index, childPrefix, i === children.length - 1, false)
1380
1419
  );
1381
- return [line, ...childDocs.filter((doc) => doc.length > 0)].join("\n");
1420
+ return [line, ...attributeDoc, ...childDocs.filter((doc) => doc.length > 0)].join("\n");
1382
1421
  };
1383
1422
  var renderSpanGraph = (graph) => {
1384
1423
  const roots = [];
@@ -1393,13 +1432,133 @@ var renderSpanGraph = (graph) => {
1393
1432
  return rootDocs.filter((doc) => doc.length > 0).join("\n");
1394
1433
  };
1395
1434
 
1396
- // src/cli/spans.ts
1397
- var command3 = Command5.make(
1435
+ // src/cli/span.ts
1436
+ var attributesToObject = (attributes) => Object.fromEntries(attributes);
1437
+ var command3 = Command6.make(
1438
+ "span",
1439
+ {
1440
+ data: dataOption,
1441
+ json: jsonOption,
1442
+ traceId: Argument3.string("trace-id").pipe(
1443
+ Argument3.withDescription("The trace ID containing the span")
1444
+ ),
1445
+ spanId: Argument3.string("span-id").pipe(
1446
+ Argument3.withDescription("The span ID to display")
1447
+ )
1448
+ },
1449
+ ({ data, json, spanId, traceId }) => Effect10.gen(function* () {
1450
+ const storage = yield* Storage;
1451
+ const spans = yield* storage.getSpans({ spanId, traceId });
1452
+ const span = spans[0];
1453
+ if (span === void 0) {
1454
+ yield* Console2.log(`No span found for trace: ${traceId}, span: ${spanId}`);
1455
+ return;
1456
+ }
1457
+ const events = yield* storage.getSpanEvents({ traceId, spanId });
1458
+ const links = yield* storage.getSpanLinks({ traceId, spanId });
1459
+ const startTime = getStartTime(span);
1460
+ const endTime = getEndTime(span);
1461
+ const durationNanos = endTime !== null ? endTime - startTime : null;
1462
+ if (json) {
1463
+ const output = {
1464
+ span: {
1465
+ spanId: getSpanId(span),
1466
+ traceId: getTraceId(span),
1467
+ parentSpanId: getParentSpanId(span),
1468
+ name: getSpanName(span),
1469
+ kind: getSpanKind(span),
1470
+ statusCode: getStatusCode(span),
1471
+ statusMessage: getStatusMessage(span),
1472
+ startTime: formatTimestamp(startTime),
1473
+ endTime: endTime !== null ? formatTimestamp(endTime) : null,
1474
+ durationMs: durationNanos !== null ? Number(durationNanos / 1000000n) : null,
1475
+ attributes: getAttributes(span),
1476
+ isExternal: isExternalSpan(span)
1477
+ },
1478
+ events: events.map((event) => ({
1479
+ name: event.name,
1480
+ time: formatTimestamp(event.time),
1481
+ attributes: attributesToObject(event.attributes)
1482
+ })),
1483
+ links: links.map((link) => ({
1484
+ linkedSpanId: link.linkedSpanId,
1485
+ linkedTraceId: link.linkedTraceId,
1486
+ attributes: attributesToObject(link.attributes)
1487
+ }))
1488
+ };
1489
+ yield* Console2.log(JSON.stringify(output, null, 2));
1490
+ } else {
1491
+ const fields = [
1492
+ field("Span", getSpanId(span)),
1493
+ field("Name", getSpanName(span)),
1494
+ field("Trace", getTraceId(span)),
1495
+ field("Kind", String(getSpanKind(span))),
1496
+ field("Status", formatStatusDoc(getStatusCode(span))),
1497
+ field("Started", formatTimestamp(startTime)),
1498
+ field("Duration", durationNanos !== null ? formatDuration(durationNanos) : "running")
1499
+ ];
1500
+ const parentSpanId = getParentSpanId(span);
1501
+ if (parentSpanId !== null) {
1502
+ fields.push(field("Parent", parentSpanId));
1503
+ }
1504
+ if (endTime !== null) {
1505
+ fields.push(field("Ended", formatTimestamp(endTime)));
1506
+ }
1507
+ const statusMessage = getStatusMessage(span);
1508
+ if (statusMessage !== null) {
1509
+ fields.push(field("Status Message", statusMessage));
1510
+ }
1511
+ const attrs = getAttributes(span);
1512
+ if (Object.keys(attrs).length > 0) {
1513
+ fields.push(field("Attrs", JSON.stringify(attrs)));
1514
+ }
1515
+ const eventDocs = events.length === 0 ? ["Events: none"] : [
1516
+ `Events (${events.length}):`,
1517
+ ...events.map((event) => {
1518
+ const attrs2 = attributesToObject(event.attributes);
1519
+ const lines = [` ${event.name} @ ${formatTimestamp(event.time)}`];
1520
+ if (Object.keys(attrs2).length > 0) {
1521
+ lines.push(` ${field("Attrs", JSON.stringify(attrs2))}`);
1522
+ }
1523
+ return lines.join("\n");
1524
+ })
1525
+ ];
1526
+ const linkDocs = links.length === 0 ? ["Links: none"] : [
1527
+ `Links (${links.length}):`,
1528
+ ...links.map((link) => {
1529
+ const attrs2 = attributesToObject(link.attributes);
1530
+ const lines = [` ${link.linkedTraceId}/${link.linkedSpanId}`];
1531
+ if (Object.keys(attrs2).length > 0) {
1532
+ lines.push(` ${field("Attrs", JSON.stringify(attrs2))}`);
1533
+ }
1534
+ return lines.join("\n");
1535
+ })
1536
+ ];
1537
+ yield* Console2.log(renderDoc([...fields, "", ...eventDocs, "", ...linkDocs].join("\n")));
1538
+ }
1539
+ }).pipe(
1540
+ Effect10.scoped,
1541
+ Effect10.provide(makeReadOnlyLayer(data))
1542
+ )
1543
+ ).pipe(
1544
+ Command6.withDescription("Show detailed span information"),
1545
+ Command6.withExamples([
1546
+ {
1547
+ command: "inspeffct span <trace-id> <span-id>",
1548
+ description: "Show span details with events and links"
1549
+ },
1550
+ {
1551
+ command: "inspeffct span --json <trace-id> <span-id>",
1552
+ description: "Print span details as JSON"
1553
+ }
1554
+ ])
1555
+ );
1556
+ var command4 = Command6.make(
1398
1557
  "spans",
1399
1558
  {
1400
1559
  data: dataOption,
1401
- executionId: Flag3.string("execution-id").pipe(
1402
- Flag3.withDescription("Filter by execution ID"),
1560
+ runId: Flag3.string("run-id").pipe(
1561
+ Flag3.withDescription("Filter by run ID"),
1403
1562
  Flag3.optional
1404
1563
  ),
1405
1564
  json: jsonOption,
@@ -1412,17 +1571,21 @@ var command3 = Command5.make(
1412
1571
  Flag3.withDescription("Filter by span name (use % for wildcards)"),
1413
1572
  Flag3.optional
1414
1573
  ),
1574
+ spanId: Flag3.string("span-id").pipe(
1575
+ Flag3.withDescription("Filter by span ID"),
1576
+ Flag3.optional
1577
+ ),
1415
1578
  status: Flag3.string("status").pipe(
1416
1579
  Flag3.withDescription("Filter by status: ok, error, unset"),
1417
1580
  Flag3.optional
1418
1581
  ),
1419
- trace: Flag3.string("trace").pipe(
1582
+ trace: Flag3.string("trace-id").pipe(
1420
1583
  Flag3.withAlias("t"),
1421
1584
  Flag3.withDescription("Filter by trace ID"),
1422
1585
  Flag3.optional
1423
1586
  )
1424
1587
  },
1425
- ({ data, executionId, json, limit, minDuration, name, status, trace }) => Effect10.gen(function* () {
1588
+ ({ data, json, limit, minDuration, name, runId, spanId, status, trace }) => Effect10.gen(function* () {
1426
1589
  const storage = yield* Storage;
1427
1590
  let statusCode;
1428
1591
  if (Option3.isSome(status)) {
@@ -1441,7 +1604,8 @@ var command3 = Command5.make(
1441
1604
  }
1442
1605
  }
1443
1606
  const filters = {
1444
- ...Option3.isSome(executionId) ? { executionId: executionId.value } : {},
1607
+ ...Option3.isSome(runId) ? { runId: runId.value } : {},
1608
+ ...Option3.isSome(spanId) ? { spanId: spanId.value } : {},
1445
1609
  ...Option3.isSome(trace) ? { traceId: trace.value } : {},
1446
1610
  ...Option3.isSome(name) ? { name: name.value } : {},
1447
1611
  ...statusCode !== void 0 ? { status: statusCode } : {},
@@ -1508,14 +1672,30 @@ var command3 = Command5.make(
1508
1672
  Effect10.scoped,
1509
1673
  Effect10.provide(makeReadOnlyLayer(data))
1510
1674
  )
1511
- ).pipe(Command5.withDescription("List spans with optional filters"));
1512
- var command4 = Command5.make(
1675
+ ).pipe(
1676
+ Command6.withDescription("List spans with optional filters (from multiple traces)"),
1677
+ Command6.withExamples([
1678
+ {
1679
+ command: "inspeffct spans --trace-id <trace-id>",
1680
+ description: "List spans for a trace"
1681
+ },
1682
+ {
1683
+ command: "inspeffct spans --run-id <run-id>",
1684
+ description: "List spans captured during a specific run"
1685
+ },
1686
+ {
1687
+ command: "inspeffct spans --span-id <span-id>",
1688
+ description: "Find a span directly by ID"
1689
+ }
1690
+ ])
1691
+ );
1692
+ var command5 = Command6.make(
1513
1693
  "trace",
1514
1694
  {
1515
1695
  data: dataOption,
1516
1696
  json: jsonOption,
1517
- traceId: Argument2.string("trace-id").pipe(
1518
- Argument2.withDescription("The trace ID to display")
1697
+ traceId: Argument3.string("trace-id").pipe(
1698
+ Argument3.withDescription("The trace ID to display")
1519
1699
  )
1520
1700
  },
1521
1701
  ({ data, json, traceId }) => Effect10.gen(function* () {
@@ -1578,14 +1758,26 @@ var command4 = Command5.make(
1578
1758
  Effect10.scoped,
1579
1759
  Effect10.provide(makeReadOnlyLayer(data))
1580
1760
  )
1581
- ).pipe(Command5.withDescription("Show a trace as a tree view"));
1582
- var command5 = Command5.make(
1761
+ ).pipe(
1762
+ Command6.withDescription("Show a trace as a tree view with its spans as well"),
1763
+ Command6.withExamples([
1764
+ {
1765
+ command: "inspeffct trace <trace-id>",
1766
+ description: "Show a trace tree"
1767
+ },
1768
+ {
1769
+ command: "inspeffct trace --json <trace-id>",
1770
+ description: "Print the trace tree as JSON"
1771
+ }
1772
+ ])
1773
+ );
1774
+ var command6 = Command6.make(
1583
1775
  "traces",
1584
1776
  {
1585
1777
  data: dataOption,
1586
1778
  json: jsonOption,
1587
- executionId: Flag3.string("execution-id").pipe(
1588
- Flag3.withDescription("Filter by execution ID"),
1779
+ runId: Flag3.string("run-id").pipe(
1780
+ Flag3.withDescription("Filter by run ID"),
1589
1781
  Flag3.optional
1590
1782
  ),
1591
1783
  limit: limitOption,
@@ -1598,7 +1790,7 @@ var command5 = Command5.make(
1598
1790
  Flag3.optional
1599
1791
  )
1600
1792
  },
1601
- ({ data, executionId, json, limit, since, status }) => Effect10.gen(function* () {
1793
+ ({ data, json, limit, runId, since, status }) => Effect10.gen(function* () {
1602
1794
  const storage = yield* Storage;
1603
1795
  let statusCode;
1604
1796
  if (Option3.isSome(status)) {
@@ -1623,7 +1815,7 @@ var command5 = Command5.make(
1623
1815
  sinceNanos = nowNanos - durationNanos;
1624
1816
  }
1625
1817
  const filters = {
1626
- ...Option3.isSome(executionId) ? { executionId: executionId.value } : {},
1818
+ ...Option3.isSome(runId) ? { runId: runId.value } : {},
1627
1819
  ...statusCode !== void 0 ? { status: statusCode } : {},
1628
1820
  ...sinceNanos !== void 0 ? { since: sinceNanos } : {},
1629
1821
  ...Option3.isSome(limit) ? { limit: limit.value } : {}
@@ -1667,14 +1859,35 @@ var command5 = Command5.make(
1667
1859
  Effect10.scoped,
1668
1860
  Effect10.provide(makeReadOnlyLayer(data))
1669
1861
  )
1670
- ).pipe(Command5.withDescription("List traces with optional filters"));
1862
+ ).pipe(
1863
+ Command6.withDescription("List traces with optional filters"),
1864
+ Command6.withExamples([
1865
+ {
1866
+ command: "inspeffct traces",
1867
+ description: "List recent traces"
1868
+ },
1869
+ {
1870
+ command: "inspeffct traces --run-id <run-id>",
1871
+ description: "List traces captured during a specific run"
1872
+ },
1873
+ {
1874
+ command: "inspeffct traces --status error --since 1h",
1875
+ description: "List recent traces that contain errors"
1876
+ }
1877
+ ])
1878
+ );
1671
1879
 
1672
1880
  // src/cli.ts
1673
- var command6 = Command5.make("inspeffct").pipe(
1674
- Command5.withDescription("Inspect Effect applications without code changes"),
1675
- Command5.withSubcommands([command2, command, command5, command4, command3])
1881
+ var command7 = Command6.make("inspeffct").pipe(
1882
+ Command6.withDescription(
1883
+ "Run your Effect application with `npx inspeffct run ...` to start capturing data, and then inspect data with the CLI."
1884
+ ),
1885
+ Command6.withSubcommands([
1886
+ { group: "Capture", commands: [command2, command] },
1887
+ { group: "Inspect", commands: [command6, command5, command4, command3] }
1888
+ ])
1676
1889
  );
1677
- var cli = Command5.runWith(command6, {
1890
+ var cli = Command6.runWith(command7, {
1678
1891
  version: "0.0.1"
1679
1892
  });
1680
1893
  var encodeRunSeparator = (args) => {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "inspeffct",
3
- "version": "1.0.4",
3
+ "version": "1.0.6",
4
4
  "type": "module",
5
5
  "description": "A CLI to help agents and humans inspect Effect applications",
6
6
  "license": "MIT",