@m1212e/rumble 0.23.9 → 0.23.10

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/out/index.cjs CHANGED
@@ -208,7 +208,7 @@ function mapNullFieldsToUndefined(obj) {
208
208
  }
209
209
  //#endregion
210
210
  //#region package.json
211
- var version = "0.23.9";
211
+ var version = "0.23.10";
212
212
  //#endregion
213
213
  //#region lib/helpers/mergeFilters.ts
214
214
  const EmptyFilter$1 = Symbol.for("drizzle:EmptyFilter");
@@ -1333,31 +1333,81 @@ const sofaOpenAPIWebhookDocs = {
1333
1333
  } }
1334
1334
  };
1335
1335
  //#endregion
1336
+ //#region lib/helpers/errorLogging.ts
1337
+ function hasMessage(error) {
1338
+ return typeof error === "object" && error !== null && "message" in error;
1339
+ }
1340
+ function toLoggedException(error) {
1341
+ if (hasMessage(error)) {
1342
+ const gqlError = error;
1343
+ return {
1344
+ "exception.type": gqlError.constructor?.name ?? gqlError.name ?? "Error",
1345
+ "exception.message": String(gqlError.message),
1346
+ ...gqlError.stack ? { "exception.stacktrace": gqlError.stack } : {},
1347
+ ...gqlError.path ? { path: gqlError.path } : {},
1348
+ ...gqlError.extensions && Object.keys(gqlError.extensions).length > 0 ? { extensions: gqlError.extensions } : {}
1349
+ };
1350
+ }
1351
+ return {
1352
+ "exception.type": "UnknownError",
1353
+ "exception.message": String(error)
1354
+ };
1355
+ }
1356
+ /**
1357
+ * Every erroneous rumble log carries the same `errors` array shape,
1358
+ * whether it originates from a thrown exception (single-element array)
1359
+ * or a GraphQL `ExecutionResult.errors` list (multi-element array).
1360
+ */
1361
+ function errorsLogField(errors) {
1362
+ return { errors: errors.map(toLoggedException) };
1363
+ }
1364
+ function errorLogField(error) {
1365
+ return errorsLogField([error]);
1366
+ }
1367
+ //#endregion
1336
1368
  //#region lib/helpers/tracing.ts
1369
+ const SUBSCRIBE_SPAN_NAME = "graphql.subscribe";
1370
+ function getOperationType(options) {
1371
+ return (0, graphql.getOperationAST)(options.document, options.operationName)?.operation;
1372
+ }
1373
+ function operationLogFields(operationName, operationType) {
1374
+ return {
1375
+ "graphql.operation.name": operationName,
1376
+ ...operationType ? { "graphql.operation.type": operationType } : {}
1377
+ };
1378
+ }
1379
+ function traceIdLogFields(span) {
1380
+ const { traceId, spanId, traceFlags } = span.spanContext();
1381
+ return {
1382
+ trace_id: traceId,
1383
+ span_id: spanId,
1384
+ trace_flags: traceFlags.toString(16).padStart(2, "0")
1385
+ };
1386
+ }
1337
1387
  function isAsyncIterable(value) {
1338
1388
  return typeof value === "object" && value !== null && Symbol.asyncIterator in value;
1339
1389
  }
1340
- async function* wrapSubscriptionIterator(iterator, log, operationName) {
1390
+ async function* wrapSubscriptionIterator(iterator, log, operationName, operationType) {
1341
1391
  let eventCount = 0;
1342
1392
  try {
1343
1393
  for await (const event of iterator) {
1344
1394
  eventCount++;
1345
1395
  if (event.errors?.length) log.error({
1346
- "graphql.operation.name": operationName,
1347
- eventCount,
1348
- errors: event.errors.map((e) => e.message)
1396
+ ...operationLogFields(operationName, operationType),
1397
+ event_count: eventCount,
1398
+ ...errorsLogField(event.errors)
1349
1399
  }, "graphql subscription event error");
1350
1400
  yield event;
1351
1401
  }
1352
1402
  log.info({
1353
- "graphql.operation.name": operationName,
1354
- eventCount
1403
+ ...operationLogFields(operationName, operationType),
1404
+ event_count: eventCount
1355
1405
  }, "graphql subscription completed");
1356
1406
  } catch (error) {
1357
1407
  log.error({
1358
- "graphql.operation.name": operationName,
1359
- eventCount,
1360
- err: error
1408
+ ...operationLogFields(operationName, operationType),
1409
+ event_count: eventCount,
1410
+ ...errorLogField(error)
1361
1411
  }, "graphql subscription threw");
1362
1412
  throw error;
1363
1413
  }
@@ -1366,32 +1416,28 @@ function buildTracedExecute(executeFn, rumbleInput) {
1366
1416
  return async (options) => {
1367
1417
  let log = rumbleInput.logger?.enabled ? rumbleInput.logger.logger : void 0;
1368
1418
  const operationName = options.operationName ?? "anonymous";
1419
+ const operationType = getOperationType(options);
1369
1420
  const start = Date.now();
1370
- log?.info({ "graphql.operation.name": operationName }, "graphql execute start");
1421
+ log?.info(operationLogFields(operationName, operationType), "graphql execute start");
1371
1422
  const run = async () => {
1372
1423
  const result = await executeFn(options);
1373
1424
  if (result && "errors" in result && result.errors?.length) log?.error({
1374
- "graphql.operation.name": operationName,
1375
- durationMs: Date.now() - start,
1376
- errors: result.errors.map((e) => e.message)
1425
+ ...operationLogFields(operationName, operationType),
1426
+ duration_ms: Date.now() - start,
1427
+ ...errorsLogField(result.errors)
1377
1428
  }, "graphql execute completed with errors");
1378
1429
  else log?.info({
1379
- "graphql.operation.name": operationName,
1380
- durationMs: Date.now() - start
1430
+ ...operationLogFields(operationName, operationType),
1431
+ duration_ms: Date.now() - start
1381
1432
  }, "graphql execute completed");
1382
1433
  return result;
1383
1434
  };
1384
1435
  if (rumbleInput.otel?.enabled) return rumbleInput.otel.tracer.startActiveSpan(_pothos_tracing_opentelemetry.SpanNames.EXECUTE, { attributes: {
1385
1436
  [_pothos_tracing_opentelemetry.AttributeNames.OPERATION_NAME]: operationName,
1386
- [_pothos_tracing_opentelemetry.AttributeNames.SOURCE]: options.document
1437
+ ...operationType ? { [_pothos_tracing_opentelemetry.AttributeNames.OPERATION_TYPE]: operationType } : {},
1438
+ "graphql.document": (0, graphql.print)(options.document)
1387
1439
  } }, async (span) => {
1388
- if (log && rumbleInput.logger?.injectTraceId !== false) {
1389
- const { traceId, spanId } = span.spanContext();
1390
- log = log.child({
1391
- traceId,
1392
- spanId
1393
- });
1394
- }
1440
+ if (log && rumbleInput.logger?.injectTraceId !== false) log = log.child(traceIdLogFields(span));
1395
1441
  try {
1396
1442
  const result = await run();
1397
1443
  if (result && "errors" in result && result.errors?.length) {
@@ -1402,9 +1448,9 @@ function buildTracedExecute(executeFn, rumbleInput) {
1402
1448
  } catch (error) {
1403
1449
  if (error instanceof Error) span.recordException(error);
1404
1450
  log?.error({
1405
- "graphql.operation.name": operationName,
1406
- durationMs: Date.now() - start,
1407
- err: error
1451
+ ...operationLogFields(operationName, operationType),
1452
+ duration_ms: Date.now() - start,
1453
+ ...errorLogField(error)
1408
1454
  }, "graphql execute threw");
1409
1455
  span.setStatus({ code: _opentelemetry_api.SpanStatusCode.ERROR });
1410
1456
  throw error;
@@ -1416,9 +1462,9 @@ function buildTracedExecute(executeFn, rumbleInput) {
1416
1462
  return await run();
1417
1463
  } catch (error) {
1418
1464
  log?.error({
1419
- "graphql.operation.name": operationName,
1420
- durationMs: Date.now() - start,
1421
- err: error
1465
+ ...operationLogFields(operationName, operationType),
1466
+ duration_ms: Date.now() - start,
1467
+ ...errorLogField(error)
1422
1468
  }, "graphql execute threw");
1423
1469
  throw error;
1424
1470
  }
@@ -1428,34 +1474,33 @@ function buildTracedSubscribe(subscribeFn, rumbleInput) {
1428
1474
  return async (options) => {
1429
1475
  let log = rumbleInput.logger?.enabled ? rumbleInput.logger.logger : void 0;
1430
1476
  const operationName = options.operationName ?? "anonymous";
1477
+ const operationType = getOperationType(options);
1431
1478
  const start = Date.now();
1432
1479
  const doSubscribe = async () => {
1433
- log?.info({ "graphql.operation.name": operationName }, "graphql subscribe start");
1480
+ log?.info(operationLogFields(operationName, operationType), "graphql subscribe start");
1434
1481
  const result = await subscribeFn(options);
1435
1482
  if (!isAsyncIterable(result)) {
1436
1483
  const execResult = result;
1437
1484
  if (execResult.errors?.length) log?.error({
1438
- "graphql.operation.name": operationName,
1439
- durationMs: Date.now() - start,
1440
- errors: execResult.errors.map((e) => e.message)
1485
+ ...operationLogFields(operationName, operationType),
1486
+ duration_ms: Date.now() - start,
1487
+ ...errorsLogField(execResult.errors)
1441
1488
  }, "graphql subscribe completed with errors");
1442
1489
  return execResult;
1443
1490
  }
1444
1491
  log?.info({
1445
- "graphql.operation.name": operationName,
1446
- durationMs: Date.now() - start
1492
+ ...operationLogFields(operationName, operationType),
1493
+ duration_ms: Date.now() - start
1447
1494
  }, "graphql subscription established");
1448
- if (log) return wrapSubscriptionIterator(result, log, operationName);
1495
+ if (log) return wrapSubscriptionIterator(result, log, operationName, operationType);
1449
1496
  return result;
1450
1497
  };
1451
- if (rumbleInput.otel?.enabled) return rumbleInput.otel.tracer.startActiveSpan("graphql.subscribe", async (span) => {
1452
- if (log && rumbleInput.logger?.injectTraceId !== false) {
1453
- const { traceId, spanId } = span.spanContext();
1454
- log = log.child({
1455
- traceId,
1456
- spanId
1457
- });
1458
- }
1498
+ if (rumbleInput.otel?.enabled) return rumbleInput.otel.tracer.startActiveSpan(SUBSCRIBE_SPAN_NAME, { attributes: {
1499
+ [_pothos_tracing_opentelemetry.AttributeNames.OPERATION_NAME]: operationName,
1500
+ ...operationType ? { [_pothos_tracing_opentelemetry.AttributeNames.OPERATION_TYPE]: operationType } : {},
1501
+ "graphql.document": (0, graphql.print)(options.document)
1502
+ } }, async (span) => {
1503
+ if (log && rumbleInput.logger?.injectTraceId !== false) log = log.child(traceIdLogFields(span));
1459
1504
  try {
1460
1505
  const result = await doSubscribe();
1461
1506
  if (!isAsyncIterable(result)) {
@@ -1469,9 +1514,9 @@ function buildTracedSubscribe(subscribeFn, rumbleInput) {
1469
1514
  } catch (error) {
1470
1515
  if (error instanceof Error) span.recordException(error);
1471
1516
  log?.error({
1472
- "graphql.operation.name": operationName,
1473
- durationMs: Date.now() - start,
1474
- err: error
1517
+ ...operationLogFields(operationName, operationType),
1518
+ duration_ms: Date.now() - start,
1519
+ ...errorLogField(error)
1475
1520
  }, "graphql subscribe threw");
1476
1521
  span.setStatus({ code: _opentelemetry_api.SpanStatusCode.ERROR });
1477
1522
  throw error;
@@ -1483,9 +1528,9 @@ function buildTracedSubscribe(subscribeFn, rumbleInput) {
1483
1528
  return await doSubscribe();
1484
1529
  } catch (error) {
1485
1530
  log?.error({
1486
- "graphql.operation.name": operationName,
1487
- durationMs: Date.now() - start,
1488
- err: error
1531
+ ...operationLogFields(operationName, operationType),
1532
+ duration_ms: Date.now() - start,
1533
+ ...errorLogField(error)
1489
1534
  }, "graphql subscribe threw");
1490
1535
  throw error;
1491
1536
  }
@@ -1578,7 +1623,7 @@ async function initSearchIfApplicable(input) {
1578
1623
  await input.db.execute(drizzle_orm.sql`CREATE EXTENSION IF NOT EXISTS pg_trgm;`);
1579
1624
  } catch (error) {
1580
1625
  const msg = "Failed to create pg_trgm extension. Search functionality may not work. Ensure the database user has CREATE privilege or the extension is pre-installed.";
1581
- log ? log.error({ err: error }, msg) : console.error(msg, error);
1626
+ log ? log.error(errorLogField(error), msg) : console.error(msg, error);
1582
1627
  return;
1583
1628
  }
1584
1629
  if (input.search?.threshold) {
@@ -2328,7 +2373,7 @@ var RuntimeFiltersPlugin = class extends _pothos_core.BasePlugin {
2328
2373
  } catch (error) {
2329
2374
  this.logger?.error({
2330
2375
  "graphql.field.name": fieldConfig.name,
2331
- err: error
2376
+ ...errorLogField(error)
2332
2377
  }, "runtime filter threw");
2333
2378
  throw error;
2334
2379
  } finally {
@@ -2340,7 +2385,7 @@ var RuntimeFiltersPlugin = class extends _pothos_core.BasePlugin {
2340
2385
  } catch (error) {
2341
2386
  this.logger?.error({
2342
2387
  "graphql.field.name": fieldConfig.name,
2343
- err: error
2388
+ ...errorLogField(error)
2344
2389
  }, "runtime filter threw");
2345
2390
  throw error;
2346
2391
  }
@@ -2393,13 +2438,13 @@ const createSchemaBuilder = ({ db, pubsub, pothosConfig, otel, logger }) => {
2393
2438
  if (error) log.error({
2394
2439
  "graphql.field.name": config.name,
2395
2440
  "graphql.parent.type": config.parentType,
2396
- durationMs: duration,
2397
- err: error
2441
+ duration_ms: duration,
2442
+ ...errorLogField(error)
2398
2443
  }, "resolver failed");
2399
2444
  else log.debug({
2400
2445
  "graphql.field.name": config.name,
2401
2446
  "graphql.parent.type": config.parentType,
2402
- durationMs: duration
2447
+ duration_ms: duration
2403
2448
  }, "resolver completed");
2404
2449
  });
2405
2450
  }