@neat.is/core 0.4.4 → 0.4.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.
package/dist/index.d.cts CHANGED
@@ -130,6 +130,7 @@ declare function buildApi(opts: BuildApiOptions): Promise<FastifyInstance>;
130
130
 
131
131
  interface ParsedSpan {
132
132
  service: string;
133
+ resourceServiceNamePresent?: boolean;
133
134
  traceId: string;
134
135
  spanId: string;
135
136
  parentSpanId?: string;
package/dist/index.d.ts CHANGED
@@ -130,6 +130,7 @@ declare function buildApi(opts: BuildApiOptions): Promise<FastifyInstance>;
130
130
 
131
131
  interface ParsedSpan {
132
132
  service: string;
133
+ resourceServiceNamePresent?: boolean;
133
134
  traceId: string;
134
135
  spanId: string;
135
136
  parentSpanId?: string;
package/dist/index.js CHANGED
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  routeSpanToProject,
3
3
  startDaemon
4
- } from "./chunk-J4YBTD24.js";
4
+ } from "./chunk-NON5AXOR.js";
5
5
  import {
6
6
  ProjectNameCollisionError,
7
7
  addProject,
@@ -37,15 +37,15 @@ import {
37
37
  thresholdForEdgeType,
38
38
  touchLastSeen,
39
39
  writeAtomically
40
- } from "./chunk-G3YGPWJL.js";
40
+ } from "./chunk-RBWL4HRB.js";
41
41
  import {
42
42
  startOtelGrpcReceiver
43
- } from "./chunk-YJOA7BBF.js";
43
+ } from "./chunk-3QCRUEQD.js";
44
44
  import {
45
45
  buildOtelReceiver,
46
46
  logSpanHandler,
47
47
  parseOtlpRequest
48
- } from "./chunk-ZVNP3ZDH.js";
48
+ } from "./chunk-HVF4S7J3.js";
49
49
  export {
50
50
  ProjectNameCollisionError,
51
51
  addProject,
package/dist/neatd.cjs CHANGED
@@ -337,12 +337,15 @@ function parseOtlpRequest(body) {
337
337
  const out = [];
338
338
  for (const rs of body.resourceSpans ?? []) {
339
339
  const resourceAttrs = attrsToRecord(rs.resource?.attributes);
340
- const service = typeof resourceAttrs["service.name"] === "string" ? resourceAttrs["service.name"] : "unknown";
340
+ const rawServiceName = resourceAttrs["service.name"];
341
+ const resourceServiceNamePresent = typeof rawServiceName === "string" && rawServiceName.length > 0;
342
+ const service = resourceServiceNamePresent ? rawServiceName : "unidentified";
341
343
  for (const ss of rs.scopeSpans ?? []) {
342
344
  for (const span of ss.spans ?? []) {
343
345
  const attrs = attrsToRecord(span.attributes);
344
346
  const parsed = {
345
347
  service,
348
+ resourceServiceNamePresent,
346
349
  traceId: span.traceId ?? "",
347
350
  spanId: span.spanId ?? "",
348
351
  parentSpanId: span.parentSpanId || void 0,
@@ -1578,6 +1581,14 @@ var DEFAULT_STALE_THRESHOLDS = {
1578
1581
  function nowIso(ctx) {
1579
1582
  return new Date(ctx.now ? ctx.now() : Date.now()).toISOString();
1580
1583
  }
1584
+ var unidentifiedWarnedProjects = /* @__PURE__ */ new Set();
1585
+ function warnUnidentifiedSpan(project) {
1586
+ if (unidentifiedWarnedProjects.has(project)) return;
1587
+ unidentifiedWarnedProjects.add(project);
1588
+ console.warn(
1589
+ `[neatd] span lacked service.name; routed to 'unidentified' in project ${project}; check your OTel SDK config.`
1590
+ );
1591
+ }
1581
1592
  function pickAttr(span, ...keys) {
1582
1593
  for (const k of keys) {
1583
1594
  const v = span.attributes[k];
@@ -1832,6 +1843,9 @@ async function handleSpan(ctx, span) {
1832
1843
  const ts = span.startTimeIso ?? nowIso(ctx);
1833
1844
  const nowMs = ctx.now ? ctx.now() : Date.now();
1834
1845
  const env = span.env ?? "unknown";
1846
+ if (span.resourceServiceNamePresent === false) {
1847
+ warnUnidentifiedSpan(ctx.project ?? DEFAULT_PROJECT);
1848
+ }
1835
1849
  const sourceId = ensureServiceNode(ctx.graph, span.service, env);
1836
1850
  const isError = span.statusCode === 2;
1837
1851
  cacheSpanService(span, nowMs);
@@ -5872,11 +5886,45 @@ async function startDaemon(opts = {}) {
5872
5886
  });
5873
5887
  };
5874
5888
  process.on("SIGHUP", sighupHandler);
5889
+ const REGISTRY_RELOAD_DEBOUNCE_MS = 500;
5890
+ let registryWatcher = null;
5891
+ let reloadTimer = null;
5892
+ try {
5893
+ const regDir = import_node_path37.default.dirname(regPath);
5894
+ const regBase = import_node_path37.default.basename(regPath);
5895
+ registryWatcher = (0, import_node_fs22.watch)(regDir, (_eventType, filename) => {
5896
+ if (filename !== null && filename !== regBase) return;
5897
+ if (reloadTimer) clearTimeout(reloadTimer);
5898
+ reloadTimer = setTimeout(() => {
5899
+ reloadTimer = null;
5900
+ void reload().catch((err) => {
5901
+ console.warn(
5902
+ `neatd: registry-watch reload failed \u2014 ${err.message}`
5903
+ );
5904
+ });
5905
+ }, REGISTRY_RELOAD_DEBOUNCE_MS);
5906
+ });
5907
+ } catch (err) {
5908
+ console.warn(
5909
+ `neatd: failed to watch registry at ${regPath} \u2014 ${err.message}. Run \`neatd reload\` (or send SIGHUP) after registering new projects.`
5910
+ );
5911
+ }
5875
5912
  let stopped = false;
5876
5913
  const stop = async () => {
5877
5914
  if (stopped) return;
5878
5915
  stopped = true;
5879
5916
  process.off("SIGHUP", sighupHandler);
5917
+ if (reloadTimer) {
5918
+ clearTimeout(reloadTimer);
5919
+ reloadTimer = null;
5920
+ }
5921
+ if (registryWatcher) {
5922
+ try {
5923
+ registryWatcher.close();
5924
+ } catch {
5925
+ }
5926
+ registryWatcher = null;
5927
+ }
5880
5928
  if (otlpApp) await otlpApp.close().catch(() => {
5881
5929
  });
5882
5930
  if (restApp) await restApp.close().catch(() => {