@oconde/radar 0.3.0 → 0.4.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,7 +1,7 @@
1
1
  import { ArgumentsHost, NestInterceptor, ExecutionContext, CallHandler, NestModule, OnApplicationShutdown, DynamicModule, ModuleMetadata, FactoryProvider, MiddlewareConsumer } from '@nestjs/common';
2
2
  import { BaseExceptionFilter } from '@nestjs/core';
3
3
  import { Observable } from 'rxjs';
4
- import { c as RadarOptions, A as Attributes, L as LogRequestOptions } from '../client-BB-to8cr.cjs';
4
+ import { c as RadarOptions, A as Attributes, L as LogRequestOptions } from '../client-DRZ7htMJ.cjs';
5
5
  import { UserInfo } from '../protocol/index.cjs';
6
6
 
7
7
  declare const RADAR_OPTIONS: unique symbol;
@@ -1,7 +1,7 @@
1
1
  import { ArgumentsHost, NestInterceptor, ExecutionContext, CallHandler, NestModule, OnApplicationShutdown, DynamicModule, ModuleMetadata, FactoryProvider, MiddlewareConsumer } from '@nestjs/common';
2
2
  import { BaseExceptionFilter } from '@nestjs/core';
3
3
  import { Observable } from 'rxjs';
4
- import { c as RadarOptions, A as Attributes, L as LogRequestOptions } from '../client-BS798K3S.js';
4
+ import { c as RadarOptions, A as Attributes, L as LogRequestOptions } from '../client-FkXWx8sJ.js';
5
5
  import { UserInfo } from '../protocol/index.js';
6
6
 
7
7
  declare const RADAR_OPTIONS: unique symbol;
@@ -279,6 +279,12 @@ function requestPath(req) {
279
279
  const end = url.indexOf("?");
280
280
  return end >= 0 ? url.slice(0, end) : url;
281
281
  }
282
+ function matchesRequest(pattern, path, route) {
283
+ const candidates = route === void 0 ? [path] : [path, route];
284
+ if (pattern instanceof RegExp) return candidates.some((value) => value.search(pattern) !== -1);
285
+ const prefix = pattern.endsWith("/") ? pattern : `${pattern}/`;
286
+ return candidates.some((value) => value === pattern || value.startsWith(prefix));
287
+ }
282
288
  function requestRoute(req, route) {
283
289
  if (route) return route;
284
290
  if (typeof req.route?.path !== "string") return void 0;
@@ -418,11 +424,24 @@ function createMiddleware(logger) {
418
424
  // src/options.ts
419
425
  var DEFAULT_ENDPOINT = "https://radar-ingest.oconde.dev";
420
426
  var LEVELS = ["debug", "info", "warn", "error"];
427
+ function patterns(value) {
428
+ if (!Array.isArray(value)) return [];
429
+ return value.flatMap((item) => {
430
+ if (item instanceof RegExp) return [item];
431
+ if (typeof item === "string" && item.trim() !== "") return [item.trim()];
432
+ return [];
433
+ });
434
+ }
421
435
  function resolveTraceFetch(value) {
422
- if (!value) return { enabled: false, propagateTo: [] };
423
- if (value === true) return { enabled: true, propagateTo: [] };
424
- const targets2 = Array.isArray(value.propagateTo) ? value.propagateTo : [];
425
- return { enabled: true, propagateTo: targets2.filter((target) => typeof target === "string" ? target.trim() !== "" : target instanceof RegExp) };
436
+ if (!value) return { enabled: false, propagateTo: [], ignore: [] };
437
+ if (value === true) return { enabled: true, propagateTo: [], ignore: [] };
438
+ return { enabled: true, propagateTo: patterns(value.propagateTo), ignore: patterns(value.ignore) };
439
+ }
440
+ function resolveLogRequests(value) {
441
+ if (value === false) return { enabled: false, include: [], exclude: [], sample: 1 };
442
+ if (value === void 0 || value === true || typeof value !== "object" || value === null) return { enabled: true, include: [], exclude: [], sample: 1 };
443
+ const sample = typeof value.sample === "number" && Number.isFinite(value.sample) && value.sample >= 0 && value.sample <= 1 ? value.sample : 1;
444
+ return { enabled: true, include: patterns(value.include), exclude: patterns(value.exclude), sample };
426
445
  }
427
446
  function resolveOptions(options = {}, env = process.env) {
428
447
  const key = options.key?.trim() || void 0;
@@ -436,7 +455,7 @@ function resolveOptions(options = {}, env = process.env) {
436
455
  minLevel: options.minLevel && LEVELS.includes(options.minLevel) ? options.minLevel : "info",
437
456
  redact: options.redact === "none" ? "none" : "mask",
438
457
  requestDetail: options.requestDetail === "route" ? "route" : "full",
439
- logRequests: options.logRequests ?? true,
458
+ logRequests: resolveLogRequests(options.logRequests),
440
459
  ignorePaths: options.ignorePaths ?? ["/healthz", "/health"],
441
460
  captureUnhandled: options.captureUnhandled ?? true,
442
461
  traceFetch: resolveTraceFetch(options.traceFetch),
@@ -590,8 +609,8 @@ function headerOf(code, index, prefix) {
590
609
  return header;
591
610
  }
592
611
  function nameIn(header) {
593
- const patterns = ANONYMOUS_FUNCTION.test(header) ? NAME_PATTERNS : [...NAME_PATTERNS, METHOD_PATTERN];
594
- for (const pattern of patterns) {
612
+ const patterns2 = ANONYMOUS_FUNCTION.test(header) ? NAME_PATTERNS : [...NAME_PATTERNS, METHOD_PATTERN];
613
+ for (const pattern of patterns2) {
595
614
  const name = pattern.exec(header)?.[1];
596
615
  if (name && !KEYWORDS.has(name)) return name.slice(0, MAX_NAME_LENGTH);
597
616
  }
@@ -911,12 +930,19 @@ function originOf(value) {
911
930
  return null;
912
931
  }
913
932
  }
914
- function targets(url, target) {
915
- if (target instanceof RegExp) return target.test(url.host);
916
- const wanted = target.trim().toLowerCase();
933
+ function hostMatches(url, host) {
934
+ const wanted = host.trim().toLowerCase();
917
935
  if (wanted.startsWith(".")) return url.hostname.toLowerCase().endsWith(wanted);
918
936
  return url.host.toLowerCase() === wanted || url.hostname.toLowerCase() === wanted;
919
937
  }
938
+ function targets(url, target) {
939
+ if (target instanceof RegExp) return url.host.search(target) !== -1;
940
+ return hostMatches(url, target);
941
+ }
942
+ function ignored(url, target) {
943
+ if (target instanceof RegExp) return `${url.host}${url.pathname}`.search(target) !== -1;
944
+ return hostMatches(url, target);
945
+ }
920
946
  function isPlainObject(value) {
921
947
  if (value === null || typeof value !== "object") return false;
922
948
  const prototype = Object.getPrototypeOf(value);
@@ -940,6 +966,7 @@ function traceFetch(config) {
940
966
  const method = (init?.method ?? (input instanceof Request ? input.method : "GET")).toUpperCase();
941
967
  const context = currentContext();
942
968
  const [nextInput, nextInit] = context && config.propagateTo.some((target) => targets(url, target)) ? withRequestId(input, init, context.requestId) : [input, init];
969
+ if (config.ignore?.some((target) => ignored(url, target))) return original(nextInput, nextInit);
943
970
  const attrs = { method, host: url.host, path: outboundPath(url.pathname, config.redact) };
944
971
  const started = performance.now();
945
972
  try {
@@ -1188,7 +1215,7 @@ function withTimeout(promise, ms) {
1188
1215
 
1189
1216
  // src/version.ts
1190
1217
  var SDK_NAME = "@oconde/radar";
1191
- var SDK_VERSION = true ? "0.3.0" : "0.0.0-dev";
1218
+ var SDK_VERSION = true ? "0.4.1" : "0.0.0-dev";
1192
1219
 
1193
1220
  // src/client.ts
1194
1221
  var MAX_CHECK_IN_DURATION_MS = 7 * 864e5;
@@ -1232,6 +1259,7 @@ var RadarClient = class {
1232
1259
  this.restoreFetch = traceFetch({
1233
1260
  endpoint: this.options.endpoint,
1234
1261
  propagateTo: this.options.traceFetch.propagateTo,
1262
+ ignore: this.options.traceFetch.ignore,
1235
1263
  redact: this.options.redact,
1236
1264
  record: (level, attrs) => this.safely(() => this.emitLog(level, "http.client", attrs))
1237
1265
  });
@@ -1342,22 +1370,28 @@ var RadarClient = class {
1342
1370
  return createMiddleware(this);
1343
1371
  }
1344
1372
  shouldLogRequest(req) {
1345
- return this.options.logRequests && !this.options.ignorePaths.includes(requestPath(req));
1373
+ return this.options.logRequests.enabled && !this.options.ignorePaths.includes(requestPath(req));
1346
1374
  }
1347
1375
  logHttpRequest(context, status) {
1348
1376
  this.safely(() => {
1349
1377
  const req = context.req;
1350
1378
  if (!req) return;
1351
- const level = status >= 500 ? "error" : status >= 400 ? "warn" : "info";
1352
1379
  const route = requestRoute(req, context.route);
1380
+ const path = requestPath(req);
1381
+ const { include, exclude, sample } = this.options.logRequests;
1382
+ if (include.length > 0 && !include.some((pattern) => matchesRequest(pattern, path, route))) return;
1383
+ if (exclude.some((pattern) => matchesRequest(pattern, path, route))) return;
1384
+ if (sample < 1 && Math.random() >= sample) return;
1385
+ const level = status >= 500 ? "error" : status >= 400 ? "warn" : "info";
1353
1386
  runWithContext(
1354
1387
  context,
1355
1388
  () => this.emitLog(level, "http.request", {
1356
1389
  method: (req.method ?? "GET").toUpperCase(),
1357
1390
  ...route ? { route } : {},
1358
- ...this.options.requestDetail === "full" ? { path: redactPath(requestPath(req), pathParams(req, requestPath(req)), this.options.redact) } : {},
1391
+ ...this.options.requestDetail === "full" ? { path: redactPath(path, pathParams(req, path), this.options.redact) } : {},
1359
1392
  status,
1360
- durationMs: elapsedSince(context.startedAt)
1393
+ durationMs: elapsedSince(context.startedAt),
1394
+ ...sample < 1 ? { sampleRate: sample } : {}
1361
1395
  })
1362
1396
  );
1363
1397
  });