@lunora/observability 1.0.0-alpha.52 → 1.0.0-alpha.54
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.mts +31 -10
- package/dist/index.d.ts +31 -10
- package/dist/index.mjs +1 -1
- package/dist/packem_shared/LogBuffer-BmD4CfV0.mjs +1 -0
- package/dist/packem_shared/MIN_ADMIN_TOKEN_LENGTH-DSOQ6rno.mjs +1 -0
- package/dist/packem_shared/{REQUEST_LOG_TABLE-DMQIHLi_.mjs → REQUEST_LOG_TABLE-C50rAMgd.mjs} +1 -1
- package/dist/packem_shared/SpanBuffer-DnYOc8uk.mjs +1 -0
- package/dist/packem_shared/{createDatabaseTally-DCMuBKoP.mjs → createDatabaseTally-CUsegqK0.mjs} +1 -1
- package/dist/packem_shared/createMetrics-44chFv_T.mjs +1 -0
- package/dist/packem_shared/findDanglingReferences-BNgg0jD_.mjs +1 -0
- package/dist/packem_shared/{readQueryInsights-D37H7MII.mjs → readQueryInsights-B98JliCi.mjs} +5 -5
- package/dist/packem_shared/request-log-l0ZqMbzd.mjs +22 -0
- package/package.json +3 -3
- package/dist/packem_shared/LogBuffer-86QaCGLN.mjs +0 -1
- package/dist/packem_shared/MIN_ADMIN_TOKEN_LENGTH-CidkqOQ1.mjs +0 -1
- package/dist/packem_shared/SpanBuffer-CEdTCCbZ.mjs +0 -1
- package/dist/packem_shared/createMetrics-B366_-Qf.mjs +0 -1
- package/dist/packem_shared/findDanglingReferences-Dxl42LBT.mjs +0 -1
- package/dist/packem_shared/request-log-COB2xhns.mjs +0 -22
package/dist/index.d.mts
CHANGED
|
@@ -1363,7 +1363,14 @@ interface MetricHistoryResult {
|
|
|
1363
1363
|
* omitted field keeps the historical behaviour.
|
|
1364
1364
|
*/
|
|
1365
1365
|
interface MetricHistoryOptions {
|
|
1366
|
-
/**
|
|
1366
|
+
/**
|
|
1367
|
+
* Distinct series tracked before a brand-new one is REFUSED admission
|
|
1368
|
+
* (default {@link METRIC_HISTORY_MAX_SERIES}). Nothing is evicted: an
|
|
1369
|
+
* already-tracked series keeps accumulating past the cap, and a flood of
|
|
1370
|
+
* one-off series cannot displace the app's real ones — see
|
|
1371
|
+
* {@link admitNewSeries}. `readMetricHistory`'s `capped` flag is the
|
|
1372
|
+
* read-side signal that admission is being refused.
|
|
1373
|
+
*/
|
|
1367
1374
|
maxSeries?: number;
|
|
1368
1375
|
/** Minute-buckets kept per series before older rows are trimmed (default {@link METRIC_HISTORY_BUCKET_RETENTION}). */
|
|
1369
1376
|
retentionBuckets?: number;
|
|
@@ -1560,14 +1567,19 @@ interface ReadRequestLogOptions {
|
|
|
1560
1567
|
outcome?: RequestOutcome;
|
|
1561
1568
|
/** Exact shard-key match. */
|
|
1562
1569
|
shardKey?: string;
|
|
1563
|
-
/**
|
|
1570
|
+
/**
|
|
1571
|
+
* Only entries strictly after this cursor. Setting it switches the read to
|
|
1572
|
+
* ASCENDING order — see {@link readRequestLog} — because that is the only
|
|
1573
|
+
* ordering under which advancing the cursor to the last returned `seq`
|
|
1574
|
+
* actually pages forward without a hole.
|
|
1575
|
+
*/
|
|
1564
1576
|
sinceSeq?: number;
|
|
1565
1577
|
/** Keep only entries whose read OR written table set contains this table. */
|
|
1566
1578
|
tableTouched?: string;
|
|
1567
1579
|
/** Exact acting-userId match. */
|
|
1568
1580
|
userId?: string;
|
|
1569
1581
|
}
|
|
1570
|
-
/** Payload of a `__lunora_admin__:getRequestLog` call: the recorded entries, newest first. */
|
|
1582
|
+
/** Payload of a `__lunora_admin__:getRequestLog` call: the recorded entries, newest first — or oldest first when the request paged forward with `sinceSeq` (see {@link readRequestLog}). */
|
|
1571
1583
|
interface RequestLogResult {
|
|
1572
1584
|
entries: RequestLogEntry[];
|
|
1573
1585
|
}
|
|
@@ -1776,12 +1788,21 @@ declare const parseLogArgs: (args: unknown[], boundFields?: LogFields) => {
|
|
|
1776
1788
|
*/
|
|
1777
1789
|
declare const emitLogEvent: (input: LogEventInput, options?: RequestLogWriteOptions) => void;
|
|
1778
1790
|
/**
|
|
1779
|
-
* Read request-log entries
|
|
1780
|
-
*
|
|
1781
|
-
*
|
|
1782
|
-
*
|
|
1783
|
-
*
|
|
1784
|
-
*
|
|
1791
|
+
* Read request-log entries, AND-combining the supplied filters (function-path
|
|
1792
|
+
* prefix, exact userId/shardKey/outcome, and a table-touched match against the
|
|
1793
|
+
* read OR written table sets), up to `limit` (clamped to [1, 10000]). Each value
|
|
1794
|
+
* is a bound parameter, so no filter can inject SQL. Creates the table first so
|
|
1795
|
+
* reads on a never-logged shard return `[]` instead of throwing. Mirrors
|
|
1796
|
+
* `readAuditLog`/`readCdcChanges`.
|
|
1797
|
+
*
|
|
1798
|
+
* **Ordering follows `sinceSeq`.** Without a cursor this is a "show me the tail"
|
|
1799
|
+
* read and returns NEWEST FIRST, which is what the studio's Logs tab renders.
|
|
1800
|
+
* With `sinceSeq` it is forward paging and returns OLDEST FIRST, starting at the
|
|
1801
|
+
* cursor: descending there silently loses rows, because `ORDER BY seq DESC LIMIT
|
|
1802
|
+
* n` answers "the newest n after the cursor", so a consumer that advances to the
|
|
1803
|
+
* largest returned `seq` skips everything between `sinceSeq` and that page
|
|
1804
|
+
* whenever more than `limit` rows accumulated between polls — the more traffic
|
|
1805
|
+
* the shard takes, the more it drops.
|
|
1785
1806
|
*/
|
|
1786
1807
|
declare const readRequestLog: (sql: SqlExec, options?: ReadRequestLogOptions) => RequestLogEntry[];
|
|
1787
1808
|
declare const readErrorIssues: (sql: SqlExec, options?: ReadIssuesOptions) => ErrorIssue[];
|
|
@@ -1799,7 +1820,7 @@ type SecurityFindingLevel = "error" | "info" | "warning";
|
|
|
1799
1820
|
*
|
|
1800
1821
|
* `admin-token-weak`: `LUNORA_ADMIN_TOKEN` is set but short enough to be brute-forceable. (An *unset* token disables admin introspection entirely, so this audit — itself admin-gated — only ever runs with a token present.)
|
|
1801
1822
|
*
|
|
1802
|
-
* `ws-gate-open`:
|
|
1823
|
+
* `ws-gate-open`: `LUNORA_WS_BEARER` is unset, so the WebSocket upgrade gate defaults open and anyone who can reach the worker can open a socket and run ordinary USER subscriptions (whatever `ctx.auth` / RLS then allows them to read). Admin subscriptions are NOT part of this: they require the socket's `admin` stamp, which the upgrade sets only from `LUNORA_ADMIN_TOKEN` or a minted admin sub-token, so an unset `LUNORA_WS_BEARER` never exposes Logs/Metrics/introspection. Which is why this is a posture finding about the app's own live-query surface, not an admin hole — set the var when subscribers are expected to present a shared credential.
|
|
1803
1824
|
*
|
|
1804
1825
|
* `dev-args-unredacted`: the worker reports a development environment, so the durable request log captures raw, un-redacted args and identity (PII). A production deploy mislabeled as dev would persist sensitive payloads.
|
|
1805
1826
|
*
|
package/dist/index.d.ts
CHANGED
|
@@ -1363,7 +1363,14 @@ interface MetricHistoryResult {
|
|
|
1363
1363
|
* omitted field keeps the historical behaviour.
|
|
1364
1364
|
*/
|
|
1365
1365
|
interface MetricHistoryOptions {
|
|
1366
|
-
/**
|
|
1366
|
+
/**
|
|
1367
|
+
* Distinct series tracked before a brand-new one is REFUSED admission
|
|
1368
|
+
* (default {@link METRIC_HISTORY_MAX_SERIES}). Nothing is evicted: an
|
|
1369
|
+
* already-tracked series keeps accumulating past the cap, and a flood of
|
|
1370
|
+
* one-off series cannot displace the app's real ones — see
|
|
1371
|
+
* {@link admitNewSeries}. `readMetricHistory`'s `capped` flag is the
|
|
1372
|
+
* read-side signal that admission is being refused.
|
|
1373
|
+
*/
|
|
1367
1374
|
maxSeries?: number;
|
|
1368
1375
|
/** Minute-buckets kept per series before older rows are trimmed (default {@link METRIC_HISTORY_BUCKET_RETENTION}). */
|
|
1369
1376
|
retentionBuckets?: number;
|
|
@@ -1560,14 +1567,19 @@ interface ReadRequestLogOptions {
|
|
|
1560
1567
|
outcome?: RequestOutcome;
|
|
1561
1568
|
/** Exact shard-key match. */
|
|
1562
1569
|
shardKey?: string;
|
|
1563
|
-
/**
|
|
1570
|
+
/**
|
|
1571
|
+
* Only entries strictly after this cursor. Setting it switches the read to
|
|
1572
|
+
* ASCENDING order — see {@link readRequestLog} — because that is the only
|
|
1573
|
+
* ordering under which advancing the cursor to the last returned `seq`
|
|
1574
|
+
* actually pages forward without a hole.
|
|
1575
|
+
*/
|
|
1564
1576
|
sinceSeq?: number;
|
|
1565
1577
|
/** Keep only entries whose read OR written table set contains this table. */
|
|
1566
1578
|
tableTouched?: string;
|
|
1567
1579
|
/** Exact acting-userId match. */
|
|
1568
1580
|
userId?: string;
|
|
1569
1581
|
}
|
|
1570
|
-
/** Payload of a `__lunora_admin__:getRequestLog` call: the recorded entries, newest first. */
|
|
1582
|
+
/** Payload of a `__lunora_admin__:getRequestLog` call: the recorded entries, newest first — or oldest first when the request paged forward with `sinceSeq` (see {@link readRequestLog}). */
|
|
1571
1583
|
interface RequestLogResult {
|
|
1572
1584
|
entries: RequestLogEntry[];
|
|
1573
1585
|
}
|
|
@@ -1776,12 +1788,21 @@ declare const parseLogArgs: (args: unknown[], boundFields?: LogFields) => {
|
|
|
1776
1788
|
*/
|
|
1777
1789
|
declare const emitLogEvent: (input: LogEventInput, options?: RequestLogWriteOptions) => void;
|
|
1778
1790
|
/**
|
|
1779
|
-
* Read request-log entries
|
|
1780
|
-
*
|
|
1781
|
-
*
|
|
1782
|
-
*
|
|
1783
|
-
*
|
|
1784
|
-
*
|
|
1791
|
+
* Read request-log entries, AND-combining the supplied filters (function-path
|
|
1792
|
+
* prefix, exact userId/shardKey/outcome, and a table-touched match against the
|
|
1793
|
+
* read OR written table sets), up to `limit` (clamped to [1, 10000]). Each value
|
|
1794
|
+
* is a bound parameter, so no filter can inject SQL. Creates the table first so
|
|
1795
|
+
* reads on a never-logged shard return `[]` instead of throwing. Mirrors
|
|
1796
|
+
* `readAuditLog`/`readCdcChanges`.
|
|
1797
|
+
*
|
|
1798
|
+
* **Ordering follows `sinceSeq`.** Without a cursor this is a "show me the tail"
|
|
1799
|
+
* read and returns NEWEST FIRST, which is what the studio's Logs tab renders.
|
|
1800
|
+
* With `sinceSeq` it is forward paging and returns OLDEST FIRST, starting at the
|
|
1801
|
+
* cursor: descending there silently loses rows, because `ORDER BY seq DESC LIMIT
|
|
1802
|
+
* n` answers "the newest n after the cursor", so a consumer that advances to the
|
|
1803
|
+
* largest returned `seq` skips everything between `sinceSeq` and that page
|
|
1804
|
+
* whenever more than `limit` rows accumulated between polls — the more traffic
|
|
1805
|
+
* the shard takes, the more it drops.
|
|
1785
1806
|
*/
|
|
1786
1807
|
declare const readRequestLog: (sql: SqlExec, options?: ReadRequestLogOptions) => RequestLogEntry[];
|
|
1787
1808
|
declare const readErrorIssues: (sql: SqlExec, options?: ReadIssuesOptions) => ErrorIssue[];
|
|
@@ -1799,7 +1820,7 @@ type SecurityFindingLevel = "error" | "info" | "warning";
|
|
|
1799
1820
|
*
|
|
1800
1821
|
* `admin-token-weak`: `LUNORA_ADMIN_TOKEN` is set but short enough to be brute-forceable. (An *unset* token disables admin introspection entirely, so this audit — itself admin-gated — only ever runs with a token present.)
|
|
1801
1822
|
*
|
|
1802
|
-
* `ws-gate-open`:
|
|
1823
|
+
* `ws-gate-open`: `LUNORA_WS_BEARER` is unset, so the WebSocket upgrade gate defaults open and anyone who can reach the worker can open a socket and run ordinary USER subscriptions (whatever `ctx.auth` / RLS then allows them to read). Admin subscriptions are NOT part of this: they require the socket's `admin` stamp, which the upgrade sets only from `LUNORA_ADMIN_TOKEN` or a minted admin sub-token, so an unset `LUNORA_WS_BEARER` never exposes Logs/Metrics/introspection. Which is why this is a posture finding about the app's own live-query surface, not an admin hole — set the var when subscribers are expected to present a shared credential.
|
|
1803
1824
|
*
|
|
1804
1825
|
* `dev-args-unredacted`: the worker reports a development environment, so the durable request log captures raw, un-redacted args and identity (PII). A production deploy mislabeled as dev would persist sensitive payloads.
|
|
1805
1826
|
*
|
package/dist/index.mjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{AUTH_METRICS_BUCKETS_TABLE as t,AUTH_METRICS_BUCKET_MS as T,AUTH_METRICS_BUCKET_RETENTION as o,AUTH_METRICS_TABLE as a,ensureAuthMetricsTables as s,readAuthMetrics as E,recordAuthEvent as _}from"./packem_shared/AUTH_METRICS_BUCKETS_TABLE-CeplWoRm.mjs";import{createMetrics as S,createSpanCollector as I,createTracedFetch as i,createTracer as n,dispatchRootSpan as M}from"./packem_shared/createMetrics-
|
|
1
|
+
import{AUTH_METRICS_BUCKETS_TABLE as t,AUTH_METRICS_BUCKET_MS as T,AUTH_METRICS_BUCKET_RETENTION as o,AUTH_METRICS_TABLE as a,ensureAuthMetricsTables as s,readAuthMetrics as E,recordAuthEvent as _}from"./packem_shared/AUTH_METRICS_BUCKETS_TABLE-CeplWoRm.mjs";import{createMetrics as S,createSpanCollector as I,createTracedFetch as i,createTracer as n,dispatchRootSpan as M}from"./packem_shared/createMetrics-44chFv_T.mjs";import{createDatabaseTally as A,formatTally as C,instrumentDatabase as N}from"./packem_shared/createDatabaseTally-CUsegqK0.mjs";import{FUNCTION_METRICS_BUCKETS_TABLE as f,FUNCTION_METRICS_BUCKET_MS as U,FUNCTION_METRICS_BUCKET_RETENTION as d,FUNCTION_METRICS_INDEX_TABLE as R,FUNCTION_METRICS_MAX_PATHS as L,FUNCTION_METRICS_READ_LIMIT as m,FUNCTION_METRICS_SCANS_TABLE as x,FUNCTION_METRICS_TABLE as B,ensureFunctionMetricsTables as F,mergeScanAttribution as l,readFunctionMetricBuckets as g,readFunctionMetricIndexHits as O,readFunctionMetricScans as H,readFunctionMetrics as y,readFunctionMetricsTotals as b,recordFunctionMetric as D}from"./packem_shared/FUNCTION_METRICS_BUCKETS_TABLE-ChlIe0vF.mjs";import{DEFAULT_EXPLAIN_ISSUE_MODEL as K,explainIssue as q,parseExplainIssueArgs as v}from"./packem_shared/DEFAULT_EXPLAIN_ISSUE_MODEL-BGGX6k5D.mjs";import{ISSUE_SEVERITIES as G,ISSUE_STATE_TABLE as X,ISSUE_STATUSES as P,upsertIssueState as k}from"./packem_shared/ISSUE_SEVERITIES-gLC4VEPQ.mjs";import{LogBuffer as j}from"./packem_shared/LogBuffer-BmD4CfV0.mjs";import{M as z}from"./packem_shared/metric-buffer-Bx0XbypU.mjs";import{readMetricHistory as W,recordMetricHistory as Y}from"./packem_shared/readMetricHistory-TKfnwFNv.mjs";import{readQueryInsights as $,readQueryMetrics as ee,recordQueryMetric as re}from"./packem_shared/readQueryInsights-B98JliCi.mjs";import{R as Te,a as oe,e as ae,b as se,c as Ee,p as _e,r as ce,d as Se,f as Ie}from"./packem_shared/request-log-l0ZqMbzd.mjs";import{MIN_ADMIN_TOKEN_LENGTH as ne,MIN_AUTH_SECRET_LENGTH as Me,buildSecurityAudit as ue}from"./packem_shared/MIN_ADMIN_TOKEN_LENGTH-DSOQ6rno.mjs";import{SpanBuffer as Ce,foldTraces as Ne}from"./packem_shared/SpanBuffer-DnYOc8uk.mjs";import{findDanglingReferences as fe}from"./packem_shared/findDanglingReferences-BNgg0jD_.mjs";import{r as de}from"./packem_shared/trace-context-DfJZi_g2.mjs";export{t as AUTH_METRICS_BUCKETS_TABLE,T as AUTH_METRICS_BUCKET_MS,o as AUTH_METRICS_BUCKET_RETENTION,a as AUTH_METRICS_TABLE,K as DEFAULT_EXPLAIN_ISSUE_MODEL,f as FUNCTION_METRICS_BUCKETS_TABLE,U as FUNCTION_METRICS_BUCKET_MS,d as FUNCTION_METRICS_BUCKET_RETENTION,R as FUNCTION_METRICS_INDEX_TABLE,L as FUNCTION_METRICS_MAX_PATHS,m as FUNCTION_METRICS_READ_LIMIT,x as FUNCTION_METRICS_SCANS_TABLE,B as FUNCTION_METRICS_TABLE,G as ISSUE_SEVERITIES,X as ISSUE_STATE_TABLE,P as ISSUE_STATUSES,j as LogBuffer,ne as MIN_ADMIN_TOKEN_LENGTH,Me as MIN_AUTH_SECRET_LENGTH,z as MetricBuffer,Te as REQUEST_LOG_TABLE,Ce as SpanBuffer,oe as appendRequestLogEntry,ue as buildSecurityAudit,A as createDatabaseTally,S as createMetrics,I as createSpanCollector,i as createTracedFetch,n as createTracer,M as dispatchRootSpan,ae as emitLogEvent,se as emitRequestLogEvent,s as ensureAuthMetricsTables,F as ensureFunctionMetricsTables,Ee as ensureRequestLogTable,q as explainIssue,fe as findDanglingReferences,Ne as foldTraces,C as formatTally,N as instrumentDatabase,l as mergeScanAttribution,v as parseExplainIssueArgs,_e as parseLogArgs,E as readAuthMetrics,ce as readErrorIssues,g as readFunctionMetricBuckets,O as readFunctionMetricIndexHits,H as readFunctionMetricScans,y as readFunctionMetrics,b as readFunctionMetricsTotals,W as readMetricHistory,$ as readQueryInsights,ee as readQueryMetrics,Se as readRequestLog,_ as recordAuthEvent,D as recordFunctionMetric,Y as recordMetricHistory,re as recordQueryMetric,Ie as redactArgs,de as resolveTraceAnchor,k as upsertIssueState};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
const s=500,r=t=>Number.isFinite(t)&&t>=1?Math.trunc(t):500;class i{buffer=[];capacity;droppedCount=0;constructor(e=500){this.capacity=r(e)}get dropped(){return this.droppedCount}get size(){return this.buffer.length}clear(){this.buffer.length=0,this.droppedCount=0}entries(){return this.buffer.toReversed()}push(e){this.buffer.push(e),this.buffer.length>this.capacity&&(this.buffer.shift(),this.droppedCount+=1)}}export{s as DEFAULT_CAPACITY,i as LogBuffer,r as normalizeCapacity};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
const u=new Set(["0","disabled","false","no","off"]),f=new Set(["1","enabled","on","true","yes"]),a=e=>typeof e=="string"&&u.has(e.trim().toLowerCase()),L=e=>typeof e=="string"&&f.has(e.trim().toLowerCase()),d=24,l=32,c={error:0,info:2,warning:1},E=e=>typeof e=="string"?e.trim().toLowerCase():void 0,h=e=>{const t=e.AUTH_SECRET??e.BETTER_AUTH_SECRET,n=typeof t=="string"?t.trim().length:0;return n>0&&n<l?[{detail:{length:n,min:l},kind:"auth-secret-weak",level:"warning"}]:[]},A=e=>{const t=E(e.LUNORA_ALLOWED_ORIGINS),n=L(e.LUNORA_CORS_ALLOW_CREDENTIALS);return(t?.split(",").some(s=>s.trim()==="*")??!1)&&n?[{kind:"cors-wildcard-credentials",level:"error"}]:[]},R=(e,t)=>{if(t)return[];const n=[];return a(e.LUNORA_SECURITY_HEADERS)&&n.push({kind:"security-headers-disabled",level:"warning"}),a(e.LUNORA_SECURITY_CSRF)&&n.push({kind:"csrf-disabled",level:"warning"}),E(e.BETTER_AUTH_URL)?.startsWith("http://")===!0&&n.push({kind:"cookies-insecure",level:"warning"}),n},S=(e,t)=>{const n=e??{},i=[],s=n.LUNORA_ADMIN_TOKEN;typeof s=="string"&&s.length>0&&s.length<d&&i.push({detail:{length:s.length,min:d},kind:"admin-token-weak",level:"warning"});const o=n.LUNORA_WS_BEARER,{dev:r}=t;return(typeof o!="string"||o==="")&&i.push({kind:"ws-gate-open",level:r?"info":"warning"}),r&&i.push({kind:"dev-args-unredacted",level:"warning"}),i.push(...h(n),...A(n),...R(n,r)),{findings:i.toSorted((_,g)=>c[_.level]-c[g.level])}};export{d as MIN_ADMIN_TOKEN_LENGTH,l as MIN_AUTH_SECRET_LENGTH,S as buildSecurityAudit};
|
package/dist/packem_shared/{REQUEST_LOG_TABLE-DMQIHLi_.mjs → REQUEST_LOG_TABLE-C50rAMgd.mjs}
RENAMED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{g as t,R as o,a as g,e as E,b as L,c as R,p,r as d,d as n,f as u,h as T}from"./request-log-
|
|
1
|
+
import{g as t,R as o,a as g,e as E,b as L,c as R,p,r as d,d as n,f as u,h as T}from"./request-log-l0ZqMbzd.mjs";import"./ISSUE_SEVERITIES-gLC4VEPQ.mjs";import"./run-sql-0aPgJkIw.mjs";export{t as REQUEST_LOG_RETENTION,o as REQUEST_LOG_TABLE,g as appendRequestLogEntry,E as emitLogEvent,L as emitRequestLogEvent,R as ensureRequestLogTable,p as parseLogArgs,d as readErrorIssues,n as readRequestLog,u as redactArgs,T as renderLogMessage};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{DEFAULT_CAPACITY as l,normalizeCapacity as I}from"./LogBuffer-BmD4CfV0.mjs";class k{buffer=[];capacity;droppedCount=0;constructor(n=l){this.capacity=I(n)}get dropped(){return this.droppedCount}get size(){return this.buffer.length}clear(){this.buffer.length=0,this.droppedCount=0}entries(){return[...this.buffer]}hasTrace(n){return this.buffer.some(o=>o.traceId===n)}push(n){this.buffer.push(n),this.buffer.length>this.capacity&&(this.buffer.shift(),this.droppedCount+=1)}}const b=50,T=c=>{const n=new Map;for(const o of c){const d=n.get(o.traceId);d===void 0?n.set(o.traceId,[o]):d.push(o)}return n},v=(c,n)=>{const o=c.find(a=>a.dispatch===!0);if(o!==void 0)return o;const d=c.toSorted((a,t)=>a.startTs-t.startTs);return d.find(a=>!n.has(a.parentSpanId))??d[0]},m=(c,n)=>{const o=new Map([[c.spanId,0]]);return d=>{const a=[],t=new Set;let e=d,r=0;for(;;){const i=o.get(e.spanId);if(i!==void 0){r=i;break}if(t.has(e.spanId))break;t.add(e.spanId),a.push(e);const f=n.get(e.parentSpanId);if(f===void 0)break;e=f}for(const[i,f]of a.toReversed().entries())o.set(f.spanId,r+i+1);return o.get(d.spanId)??r}},g=(c,n)=>{const o=new Map(c.map(t=>[t.spanId,t.depth])),d=new Map,a=[];for(const t of c){if(t.spanId===n){a.push(t);continue}const e=o.get(t.parentSpanId)===t.depth-1?t.parentSpanId:n,r=d.get(e);r===void 0?d.set(e,[t]):r.push(t)}for(const t of d.values())t.sort((e,r)=>e.offsetMs-r.offsetMs);return{childrenOf:d,roots:a}},y=(c,n)=>{const{childrenOf:o,roots:d}=g(c,n),a=[],t=new Set,e=d.toReversed();for(;e.length>0;){const r=e.pop();if(t.has(r))continue;t.add(r),a.push(r);const i=o.get(r.spanId);if(i!==void 0)for(const f of i.toReversed())e.push(f)}if(a.length!==c.length)for(const r of c)t.has(r)||a.push(r);return a},S=(c,n=b)=>{const o=T(c),d=[...o.entries()].map(([t,e])=>({group:e,startTs:Math.min(...e.map(r=>r.startTs)),traceId:t})).toSorted((t,e)=>e.startTs-t.startTs).slice(0,n),a=[];for(const{group:t,traceId:e}of d){const r=new Map(t.map(s=>[s.spanId,s])),i=v(t,r);if(i===void 0)continue;const f=m(i,r),{startTs:p}=i,h=Math.max(...t.map(s=>s.startTs+s.durationMs)),u=t.map(s=>({...s.attributes===void 0?{}:{attributes:s.attributes},depth:f(s),durationMs:s.durationMs,...s.error===void 0?{}:{error:s.error},...s.events===void 0?{}:{events:s.events},...s.kind===void 0?{}:{kind:s.kind},name:s.name,offsetMs:Math.max(0,s.startTs-p),ok:s.ok,parentSpanId:s.parentSpanId,spanId:s.spanId}));a.push({durationMs:h-p,functionPath:i.functionPath,ok:t.every(s=>s.ok),rootName:i.name,...i.shardKey===void 0?{}:{shardKey:i.shardKey},spans:y(u,i.spanId),startTs:p,traceId:e})}return{total:o.size,traces:a.toSorted((t,e)=>e.startTs-t.startTs)}};export{b as DEFAULT_TRACE_LIMIT,k as SpanBuffer,S as foldTraces};
|
package/dist/packem_shared/{createDatabaseTally-DCMuBKoP.mjs → createDatabaseTally-CUsegqK0.mjs}
RENAMED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{o as m,t as b}from"./trace-context-DfJZi_g2.mjs";import{f as M}from"./request-log-
|
|
1
|
+
import{o as m,t as b}from"./trace-context-DfJZi_g2.mjs";import{f as M}from"./request-log-l0ZqMbzd.mjs";const y=100,T=new Set(["aggregate","count","delete","deleteMany","deleteWhere","findFirst","findFirstOrThrow","findMany","get","groupBy","insert","insertMany","insertManyUnsafe","lookupById","patch","patchMany","patchWhere","rank","rankBefore","rankPage","rankPageRows","replace","restore"]),w=new Set(["aggregate","count","deleteWhere","findFirst","findFirstOrThrow","findMany","groupBy","insert","insertMany","insertManyUnsafe","patchWhere","rank","rankBefore","rankPage","rankPageRows"]),S=(e,t)=>{if(!w.has(e))return;const n=t[0];return typeof n=="string"&&n.length>0?n:void 0},k=e=>e instanceof Error?e.message:typeof e=="string"?e:JSON.stringify(e)??String(e),E=e=>{const{deps:t,durationMs:n,failure:a,operation:s,startTs:r,table:o}=e;return{attributes:{"db.operation.name":s,...o===void 0?{}:{"db.collection.name":o},"db.system.name":"sqlite"},durationMs:n,...a===void 0?{}:{error:{message:M(k(a),t.captureRaw),type:b(a)}},functionPath:t.functionPath,kind:"client",name:o===void 0?`db.${s}`:`db.${s} ${o}`,ok:a===void 0,parentSpanId:t.anchor.rootSpanId,shardKey:t.shardKey,spanId:m(8),startTs:r,traceId:t.anchor.traceId,userId:t.userId()}},v=(e,t)=>{if(t.mode==="off")return e;const{tally:n}=t,a=new Map;return new Proxy(e,{get(s,r,o){const c=Reflect.get(s,r,o);if(typeof r!="string"||typeof c!="function"||!T.has(r))return c;const f=a.get(r);if(f!==void 0)return f;const g=c,u=async(...p)=>{const l=Date.now(),h=S(r,p);let d;try{return await g.apply(s,p)}catch(i){throw d=i,i}finally{const i=Date.now()-l;n.calls+=1,n.durationMs+=i,n.perOperation[r]=(n.perOperation[r]??0)+1,d!==void 0&&(n.errors+=1);try{t.mode==="spans"&&(n.spansEmitted>=y?n.spansTruncated=!0:(n.spansEmitted+=1,t.record(E({deps:t,durationMs:i,failure:d,operation:r,startTs:l,table:h}))))}catch{}}};return a.set(r,u),u}})},D=()=>({calls:0,durationMs:0,errors:0,perOperation:{},spansEmitted:0,spansTruncated:!1}),P=e=>{const t={"db.calls":e.calls,"db.duration_ms":e.durationMs};e.errors>0&&(t["db.errors"]=e.errors),e.spansTruncated&&(t["db.spans_truncated"]=!0);for(const[n,a]of Object.entries(e.perOperation))t[`db.op.${n}`]=a;return t};export{D as createDatabaseTally,P as formatTally,v as instrumentDatabase};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{f as M,n as m}from"./request-log-l0ZqMbzd.mjs";import{L as g,o as $,b as x,t as P}from"./trace-context-DfJZi_g2.mjs";const z=/[\w.-]/u,K=t=>{let e="";for(const r of t)e+=z.test(r)?r:"_";return e},L=t=>{if(typeof t.name!="string"||t.name.length===0)throw new TypeError("recordEvaluation requires a non-empty `name`");if(typeof t.score!="number"||!Number.isFinite(t.score))throw new TypeError("recordEvaluation `score` must be a finite number");const e=K(t.name),r={[`gen_ai.evaluation.${e}.score`]:t.score};return t.label!==void 0&&(r[`gen_ai.evaluation.${e}.label`]=t.label),r},U=t=>{const e=Object.keys(t);return e.length>0&&e.every(r=>r==="attributes"||r==="kind"||r==="links")},D=128,F=128,H=128,w=(t,e)=>{if(e===void 0)return;let r=Object.keys(t).length;for(const[o,s]of Object.entries(e)){const n=!Object.hasOwn(t,o);n&&r>=H||(n&&(r+=1),t[o]=s)}},N=t=>{const e=m(t);if(e===void 0||Object.keys(e).length<=H)return e;const r={};return w(r,e),r},q=t=>{try{const e=new URL(t);return`${e.protocol}//${e.host}${e.pathname}`}catch{return t}},C=t=>{try{return new URL(t).host}catch{return t}},X=(t,e)=>{try{return t(new URL(e))}catch{return!1}},B=t=>t===void 0?{}:U(t)?t:{attributes:t},V=(t,e)=>{if(t.isTraced){t.setAttribute(g.functionPath,e.functionPath),t.setAttribute(g.ok,e.ok),t.setAttribute(g.durationMs,e.durationMs),e.shardKey!==void 0&&t.setAttribute(g.shardKey,e.shardKey),e.userId!==void 0&&t.setAttribute(g.userId,e.userId),e.error!==void 0&&(t.setAttribute(g.errorType,e.error.type),t.setAttribute(g.errorMessage,e.error.message));for(const[r,o]of Object.entries(e.attributes))(typeof o=="boolean"||typeof o=="number"||typeof o=="string")&&t.setAttribute(`lunora.attr.${r}`,o)}},G=(t,e=!1)=>{const r={attributes:{},events:[],links:[]},o={spanContext:()=>t,addEvent:(s,n)=>{if(r.events.length>=D)return;const a=N(n);r.events.push({...a===void 0?{}:{attributes:a},name:s,ts:Date.now()})},addLink:s=>{if(r.links.length>=F)return;const n=N(s.attributes);r.links.push({...n===void 0?{}:{attributes:n},spanId:s.spanId,traceId:s.traceId})},recordEvaluation:s=>{w(r.attributes,m(L(s)))},recordException:s=>{const n=s instanceof Error?s.message:String(s);o.addEvent("exception",{"exception.message":M(n,e),...e&&s instanceof Error&&typeof s.stack=="string"?{"exception.stacktrace":s.stack}:{},"exception.type":P(s)})},setAttribute:(s,n)=>{w(r.attributes,m({[s]:n}))},setAttributes:s=>{w(r.attributes,m(s))}};return{collected:r,handle:o}},W=t=>{const{anchor:e,captureRaw:r=!1,fuseHostSpans:o,functionPath:s,record:n,resolveHostTracing:a,shardKey:c,userId:b}=t,u=y=>async(k,T,d)=>{const E=$(8),h=Date.now(),l=B(d),i=m(l.attributes),{collected:v,handle:j}=G({spanId:E,traceId:e.traceId},r),R=async A=>{let f=!0,I;try{return await T(u(E),j)}catch(p){f=!1;const _=p instanceof Error?p.message:String(p);throw I={message:M(_,r),type:P(p)},p}finally{const p=Date.now()-h,_=b(),S={};w(S,i),w(S,v.attributes);const O=[...l.links??[],...v.links];try{n({...Object.keys(S).length===0?{}:{attributes:S},durationMs:p,...v.events.length===0?{}:{events:v.events},...I===void 0?{}:{error:I},functionPath:s,...l.kind===void 0||l.kind==="internal"?{}:{kind:l.kind},...O.length===0?{}:{links:O},name:k,ok:f,parentSpanId:y,shardKey:c,spanId:E,startTs:h,traceId:e.traceId,userId:_})}catch{}if(A!==void 0)try{V(A,{attributes:S,durationMs:p,error:I,functionPath:s,ok:f,shardKey:c,userId:_})}catch{}}};if(o===!0&&a!==void 0){let A=!1;try{const f=await a();if(f!==void 0&&typeof f.enterSpan=="function")return await f.enterSpan(k,I=>(A=!0,R(I)))}catch(f){if(A)throw f}}return await R()};return u(e.rootSpanId)},Y=(t,e)=>{const{anchor:r,captureRaw:o=!1,functionPath:s,propagate:n=!0,record:a,shardKey:c,userId:b}=t;return async(u,y)=>{const k=$(8),T=Date.now(),d=new Request(u,y);(typeof n=="function"?X(n,d.url):n)&&d.headers.set("traceparent",x(r.traceId,k,r.sampled??!0));let h,l;try{const i=await e(d);return l=i.status,i.ok||(h={message:`HTTP ${String(i.status)}`,type:`HTTP_${String(i.status)}`}),i}catch(i){const v=i instanceof Error?i.message:String(i);throw h={message:M(v,o),type:P(i)},i}finally{try{a({attributes:{"http.request.method":d.method,...l===void 0?{}:{"http.response.status_code":l},"url.full":q(d.url)},durationMs:Date.now()-T,...h===void 0?{}:{error:h},functionPath:s,kind:"client",name:`${d.method} ${C(d.url)}`,ok:h===void 0,parentSpanId:r.rootSpanId,shardKey:c,spanId:k,startTs:T,traceId:r.traceId,userId:b()})}catch{}}}},Z=t=>{const{functionPath:e,record:r,shardKey:o}=t,s=(n,a,c,b)=>{if(!Number.isFinite(c))return;const u=m(b);try{r({...u===void 0?{}:{attributes:u},functionPath:e,kind:n,name:a,shardKey:o,ts:Date.now(),value:c})}catch{}};return{count:(n,a=1,c)=>{s("counter",n,a,c)},gauge:(n,a,c)=>{s("gauge",n,a,c)},record:(n,a,c)=>{s("histogram",n,a,c)}}},tt=t=>{const{anchor:e,captureRaw:r=!1,collected:o,durationMs:s,failure:n,functionPath:a,shardKey:c,startTs:b,userId:u}=t,y=o?.attributes??{};return{...Object.keys(y).length===0?{}:{attributes:y},dispatch:!0,durationMs:s,...o===void 0||o.events.length===0?{}:{events:o.events},...n===void 0?{}:{error:{message:M(n.thrown instanceof Error?n.thrown.message:String(n.thrown),r),type:P(n.thrown)}},functionPath:a,...o===void 0||o.links.length===0?{}:{links:o.links},name:a,ok:n===void 0,parentSpanId:"",shardKey:c,spanId:e.rootSpanId,startTs:b,traceId:e.traceId,userId:u}};export{V as applyHostSpanAttributes,Z as createMetrics,G as createSpanCollector,Y as createTracedFetch,W as createTracer,tt as dispatchRootSpan};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
const l=/^[A-Za-z_$][\w$]*$/u,N=e=>l.test(e)?e:`"${e.replaceAll("\\",String.raw`\\`).replaceAll('"',String.raw`\"`)}"`,A=e=>`"${e.replaceAll('"','""')}"`,S=5e3,C=500,f="__doc__",p=e=>e.startsWith("sqlite_")||e.startsWith("_cf_")||e.startsWith("__miniflare")||e.startsWith("__lunora")||e.includes("__fts_"),u=(e,n)=>p(n)?!1:e.exec("SELECT name FROM sqlite_master WHERE type = 'table' AND name = ? LIMIT 1",n).toArray().length>0,d=(e,n)=>{const s=n.includes(e),c=n.includes(f);if(!(!s&&!c))return s?{expression:A(e),params:[]}:{expression:`json_extract(${A(f)}, ?)`,params:[`$.${N(e)}`]}},L=(e,n,s,c,a,i,r)=>{const t=d(c,a);if(t===void 0)return;const _=e.exec(`SELECT id, ${t.expression} AS ref FROM ${n} WHERE ${t.expression} IS NOT NULL AND ${t.expression} <> '' LIMIT ?`,...t.params,...t.params,...t.params,5001).toArray();_.length>5e3&&(r.truncated=!0);for(const o of _.slice(0,5e3))if(r.scanned+=1,!i.has(o.ref)){if(r.references.length>=500){r.truncated=!0;continue}r.references.push({column:c,id:o.id,key:o.ref,table:s})}},E=(e,n,s)=>{const c=s instanceof Set?s:new Set(s),a={references:[],scanned:0,truncated:!1};for(const[i,r]of Object.entries(n)){if(!u(e,i))continue;const t=A(i),_=e.exec(`PRAGMA table_info(${t})`).toArray().map(o=>o.name);for(const o of r)L(e,t,i,o,_,c,a)}return a};export{C as DANGLING_RESULT_CAP,S as DANGLING_SCAN_CAP,E as findDanglingReferences};
|
package/dist/packem_shared/{readQueryInsights-D37H7MII.mjs → readQueryInsights-B98JliCi.mjs}
RENAMED
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import{r as a}from"./run-sql-0aPgJkIw.mjs";const g=2166136261,
|
|
1
|
+
import{r as a}from"./run-sql-0aPgJkIw.mjs";const g=2166136261,C=16777619,b=(t,e=g)=>{let r=e;for(let o=0;o<t.length;o+=1)r^=t.charCodeAt(o),r=Math.imul(r,C);return(r>>>0).toString(16).padStart(8,"0")},i="__lunora_metrics_queries",m="__lunora_metrics_queries_buckets",L=6e4,y=90,d=[1,2,5,10,25,50,100,250,500,1e3,5e3],U=512,I=500,$=t=>{let e=t.replaceAll(/'(?:[^']|'')*'/g,"?").replaceAll(/\b0x[\da-f]+\b/gi,"?").replaceAll(/(?<=[=,([\s])\d+(?:\.\d+)?/g,"?").replaceAll(/\s+/g," ").trim();return e.length>U&&(e=`${e.slice(0,U-1)}…`),e},M=new WeakSet,R=t=>{M.has(t)||(a(t,`CREATE TABLE IF NOT EXISTS "${i}" (
|
|
2
2
|
normalized_sql TEXT PRIMARY KEY,
|
|
3
3
|
exec_count INTEGER NOT NULL DEFAULT 0,
|
|
4
4
|
total_duration_ms REAL NOT NULL DEFAULT 0,
|
|
5
5
|
rows_read INTEGER NOT NULL DEFAULT 0,
|
|
6
6
|
rows_written INTEGER NOT NULL DEFAULT 0
|
|
7
|
-
)`),M.add(t))},h=new WeakMap,N=t=>Math.floor(t/L)*L,D=t=>
|
|
7
|
+
)`),M.add(t))},h=new WeakMap,N=t=>Math.floor(t/L)*L,D=t=>b(t),p=t=>{const e=d.findIndex(r=>t<=r);return e===-1?d.length:e},T=t=>`lat_${String(t)}`,O=new WeakSet,f=t=>{if(O.has(t))return;const e=Array.from({length:d.length+1},(r,o)=>`${T(o)} INTEGER NOT NULL DEFAULT 0`).join(", ");a(t,`CREATE TABLE IF NOT EXISTS "${m}" (
|
|
8
8
|
sql_hash TEXT NOT NULL,
|
|
9
9
|
bucket_ms INTEGER NOT NULL,
|
|
10
10
|
exec_count INTEGER NOT NULL DEFAULT 0,
|
|
@@ -20,13 +20,13 @@ import{r as a}from"./run-sql-0aPgJkIw.mjs";const g=2166136261,b=16777619,C=(t,e=
|
|
|
20
20
|
total_duration_ms = total_duration_ms + excluded.total_duration_ms,
|
|
21
21
|
rows_read = rows_read + excluded.rows_read,
|
|
22
22
|
rows_written = rows_written + excluded.rows_written,
|
|
23
|
-
${E} = ${E} + excluded.${E}`;a(t,S,D(e),N(c),s,r,o,_,s);const n=N(c);h.get(t)!==n&&(h.set(t,n),B(t,c))}catch{}},x=(t,e)=>{const r=t.reduce((c,s)=>c+s,0);if(r===0)return 0;const o=r*e;let _=0;for(const[c,s]of t.entries())if(_+=s,_>=o)return d[c]??d.at(-1)??0;return d.at(-1)??0},
|
|
23
|
+
${E} = ${E} + excluded.${E}`;a(t,S,D(e),N(c),s,r,o,_,s);const n=N(c);h.get(t)!==n&&(h.set(t,n),B(t,c))}catch{}},x=(t,e)=>{const r=t.reduce((c,s)=>c+s,0);if(r===0)return 0;const o=r*e;let _=0;for(const[c,s]of t.entries())if(_+=s,_>=o)return d[c]??d.at(-1)??0;return d.at(-1)??0},H=(t,e,r=Date.now())=>{try{R(t),f(t)}catch{return{buckets:[],capped:!1,entries:[],trackedStatements:0}}const o=N(r-e),_=Array.from({length:d.length+1},(n,l)=>`SUM(${T(l)}) AS ${T(l)}`).join(", "),c=a(t,`SELECT sql_hash, SUM(exec_count) AS exec_count, SUM(total_duration_ms) AS total_duration_ms,
|
|
24
24
|
SUM(rows_read) AS rows_read, SUM(rows_written) AS rows_written, ${_}
|
|
25
25
|
FROM "${m}" WHERE bucket_ms >= ? GROUP BY sql_hash`,o).toArray(),s=new Map;for(const n of a(t,`SELECT normalized_sql FROM "${i}"`))s.set(D(n.normalized_sql),n.normalized_sql);const u=c.map(n=>{const l=Array.from({length:d.length+1},(G,F)=>Number(n[T(F)]??0)),A=Number(n.exec_count??0),w=Number(n.total_duration_ms??0);return{avgDurationMs:A>0?w/A:0,execCount:A,normalizedSql:s.get(String(n.sql_hash))??String(n.sql_hash),p50DurationMs:x(l,.5),p95DurationMs:x(l,.95),rowsRead:Number(n.rows_read??0),rowsWritten:Number(n.rows_written??0),totalDurationMs:w}});u.sort((n,l)=>l.totalDurationMs-n.totalDurationMs);const E=a(t,`SELECT bucket_ms, SUM(exec_count) AS exec_count, SUM(total_duration_ms) AS total_duration_ms
|
|
26
|
-
FROM "${m}" WHERE bucket_ms >= ? GROUP BY bucket_ms ORDER BY bucket_ms ASC`,o).toArray().map(n=>({avgDurationMs:n.exec_count>0?n.total_duration_ms/n.exec_count:0,bucketMs:n.bucket_ms,execCount:n.exec_count})),S=a(t,`SELECT COUNT(*) AS n FROM "${i}"`).one().n;return{buckets:E,capped:S>=I,entries:u,trackedStatements:S}},k=new WeakMap,Q=t=>{let e=k.get(t);return e===void 0&&(e=new Set,k.set(t,e)),e},z=(t,e)=>{const r=Q(t);return r.has(e)?!0:a(t,`SELECT 1 AS c FROM "${i}" WHERE normalized_sql = ? LIMIT 1`,e).toArray().length>0?(r.add(e),!0):a(t,`SELECT COUNT(*) AS n FROM "${i}"`).one().n>=I?!1:(r.add(e),!0)},
|
|
26
|
+
FROM "${m}" WHERE bucket_ms >= ? GROUP BY bucket_ms ORDER BY bucket_ms ASC`,o).toArray().map(n=>({avgDurationMs:n.exec_count>0?n.total_duration_ms/n.exec_count:0,bucketMs:n.bucket_ms,execCount:n.exec_count})),S=a(t,`SELECT COUNT(*) AS n FROM "${i}"`).one().n;return{buckets:E,capped:S>=I,entries:u,trackedStatements:S}},k=new WeakMap,Q=t=>{let e=k.get(t);return e===void 0&&(e=new Set,k.set(t,e)),e},z=(t,e)=>{const r=Q(t);return r.has(e)?!0:a(t,`SELECT 1 AS c FROM "${i}" WHERE normalized_sql = ? LIMIT 1`,e).toArray().length>0?(r.add(e),!0):a(t,`SELECT COUNT(*) AS n FROM "${i}"`).one().n>=I?!1:(r.add(e),!0)},P=(t,e,r,o,_,c=Date.now(),s=1)=>{const u=$(e);if(u.length===0||(R(t),!z(t,u)))return;const E=`INSERT INTO "${i}" (normalized_sql, exec_count, total_duration_ms, rows_read, rows_written)
|
|
27
27
|
VALUES (?, ?, ?, ?, ?)
|
|
28
28
|
ON CONFLICT(normalized_sql) DO UPDATE SET
|
|
29
29
|
exec_count = exec_count + excluded.exec_count,
|
|
30
30
|
total_duration_ms = total_duration_ms + excluded.total_duration_ms,
|
|
31
31
|
rows_read = rows_read + excluded.rows_read,
|
|
32
|
-
rows_written = rows_written + excluded.rows_written`;a(t,E,u,s,r,o,_),Y(t,u,r,o,_,c,s)},K=t=>(R(t),a(t,`SELECT normalized_sql, exec_count, total_duration_ms, rows_read, rows_written FROM "${i}" ORDER BY total_duration_ms DESC`).toArray().map(r=>({execCount:r.exec_count,normalizedSql:r.normalized_sql,rowsRead:r.rows_read,rowsWritten:r.rows_written,totalDurationMs:r.total_duration_ms})));export{d as LATENCY_BUCKET_EDGES,m as QUERY_BUCKETS_TABLE,L as QUERY_BUCKET_MS,y as QUERY_BUCKET_RETENTION,U as QUERY_METRICS_MAX_SQL_LEN,I as QUERY_METRICS_MAX_STATEMENTS,i as QUERY_METRICS_TABLE,f as ensureQueryBucketsTable,R as ensureQueryMetricsTable,D as hashStatement,p as latencyBucketIndex,$ as normalizeSql,x as percentileFrom,B as pruneQueryBuckets,
|
|
32
|
+
rows_written = rows_written + excluded.rows_written`;a(t,E,u,s,r,o,_),Y(t,u,r,o,_,c,s)},K=t=>(R(t),a(t,`SELECT normalized_sql, exec_count, total_duration_ms, rows_read, rows_written FROM "${i}" ORDER BY total_duration_ms DESC`).toArray().map(r=>({execCount:r.exec_count,normalizedSql:r.normalized_sql,rowsRead:r.rows_read,rowsWritten:r.rows_written,totalDurationMs:r.total_duration_ms})));export{d as LATENCY_BUCKET_EDGES,m as QUERY_BUCKETS_TABLE,L as QUERY_BUCKET_MS,y as QUERY_BUCKET_RETENTION,U as QUERY_METRICS_MAX_SQL_LEN,I as QUERY_METRICS_MAX_STATEMENTS,i as QUERY_METRICS_TABLE,f as ensureQueryBucketsTable,R as ensureQueryMetricsTable,D as hashStatement,p as latencyBucketIndex,$ as normalizeSql,x as percentileFrom,B as pruneQueryBuckets,H as readQueryInsights,K as readQueryMetrics,Y as recordQueryBucket,P as recordQueryMetric};
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import{fingerprintError as b}from"@lunora/fingerprint";import{redact as M,standardRules as U}from"@visulima/redact";import{readIssueStates as P}from"./ISSUE_SEVERITIES-gLC4VEPQ.mjs";import{r as h}from"./run-sql-0aPgJkIw.mjs";const D=e=>{if(typeof e=="string")return e;try{return JSON.stringify(e)??String(e)}catch{return String(e)}},S=e=>typeof e=="boolean"||typeof e=="number"||typeof e=="string"?e:D(e),R=(e,t)=>{if(e===void 0&&t===void 0)return;const s={};if(t!==void 0)for(const[o,r]of Object.entries(t))s[o]=S(r);if(e!==void 0)for(const[o,r]of Object.entries(e))s[o]=S(r);return Object.keys(s).length===0?void 0:s},d="__lunora_reqlog__",T=1e3,v="lunora",X=["error_fingerprint TEXT","trace_id TEXT"],u=(e,t=!1)=>t||e===null||e===void 0?e:M(e,U),N=new WeakSet,m=e=>{if(!N.has(e)){h(e,`CREATE TABLE IF NOT EXISTS "${d}" (
|
|
2
|
+
seq INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
3
|
+
ts REAL NOT NULL,
|
|
4
|
+
function_path TEXT NOT NULL,
|
|
5
|
+
shard_key TEXT,
|
|
6
|
+
user_id TEXT,
|
|
7
|
+
identity TEXT,
|
|
8
|
+
args TEXT,
|
|
9
|
+
outcome TEXT NOT NULL,
|
|
10
|
+
error_message TEXT,
|
|
11
|
+
error_fingerprint TEXT,
|
|
12
|
+
trace_id TEXT,
|
|
13
|
+
duration_ms REAL NOT NULL,
|
|
14
|
+
tables_read TEXT NOT NULL DEFAULT '[]',
|
|
15
|
+
tables_written TEXT NOT NULL DEFAULT '[]',
|
|
16
|
+
cache_hit INTEGER,
|
|
17
|
+
subscriptions_rerun INTEGER NOT NULL DEFAULT 0
|
|
18
|
+
)`);for(const t of X)try{h(e,`ALTER TABLE "${d}" ADD COLUMN ${t}`)}catch{}N.add(e)}},L=e=>JSON.stringify([...new Set(e)].toSorted((t,s)=>t.localeCompare(s))),F=e=>e===void 0?null:e?1:0,w=(e,t,s={})=>{m(e);const o=s.captureRaw??!1,r=s.retention??T,g=t.outcome==="error"&&t.errorMessage!==void 0?b({functionPath:t.functionPath,message:t.errorMessage}).hash:void 0;h(e,`INSERT INTO "${d}"
|
|
19
|
+
(ts, function_path, shard_key, user_id, identity, args, outcome, error_message, error_fingerprint, trace_id, duration_ms, tables_read, tables_written, cache_hit, subscriptions_rerun)
|
|
20
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,t.ts,t.functionPath,t.shardKey??null,t.userId??null,t.identity===void 0?null:JSON.stringify(u(t.identity,o)),t.redactedArgs===void 0?null:JSON.stringify(u(t.redactedArgs,o)),t.outcome,t.errorMessage===void 0?null:u(t.errorMessage,o),g??null,t.traceId??null,t.durationMs,L(t.tablesRead),L(t.tablesWritten),F(t.cacheHit),t.subscriptionsReRun??0),h(e,`DELETE FROM "${d}" WHERE seq <= (SELECT MAX(seq) - ? FROM "${d}")`,r)},V=(e,t={})=>{const s=t.captureRaw??!1,o={args:e.redactedArgs===void 0?void 0:u(e.redactedArgs,s),cacheHit:e.cacheHit,durationMs:e.durationMs,error:e.errorMessage===void 0?void 0:u(e.errorMessage,s),function:e.functionPath,identity:e.identity===void 0?void 0:u(e.identity,s),outcome:e.outcome,shard:e.shardKey,source:v,tablesRead:e.tablesRead??[],tablesWritten:e.tablesWritten??[],traceId:e.traceId,ts:e.ts,type:"request",userId:e.userId},r=JSON.stringify(o);e.outcome==="error"?console.error(r):console.log(r)},$="log",j=e=>e.map(t=>{if(typeof t=="string")return t;try{return JSON.stringify(t)??String(t)}catch{return String(t)}}).join(" "),k=e=>{if(typeof e!="object"||e===null||Array.isArray(e))return!1;const t=Object.getPrototypeOf(e);return t===Object.prototype||t===null},Y=(e,t)=>e.length===2&&typeof e[0]=="string"&&k(e[1])?{fields:R(e[1],t),message:e[0]}:{fields:R(void 0,t),message:j(e)},B=(e,t={})=>{const s=t.captureRaw??!1,o={fields:e.fields===void 0?void 0:u(e.fields,s),function:e.functionPath,level:e.level,message:e.message,shard:e.shardKey,source:v,spanId:e.spanId,traceId:e.traceId,ts:e.ts,type:$,userId:e.userId};let r;try{r=JSON.stringify(o)}catch{r=JSON.stringify({...o,fields:void 0})}e.level==="error"||e.level==="fatal"?console.error(r):e.level==="warn"?console.warn(r):console.log(r)},J=(e,t)=>`lower(substr(${e}, 1, ${String([...t].length)})) = lower(?)`,I=(e,t,s)=>{s.functionPathPrefix!==void 0&&s.functionPathPrefix!==""&&(e.push(J("function_path",s.functionPathPrefix)),t.push(s.functionPathPrefix)),s.userId!==void 0&&s.userId!==""&&(e.push("user_id = ?"),t.push(s.userId)),s.shardKey!==void 0&&s.shardKey!==""&&(e.push("shard_key = ?"),t.push(s.shardKey))},O=e=>{try{const t=JSON.parse(e);return Array.isArray(t)?t.filter(s=>typeof s=="string"):[]}catch{return[]}},C=e=>{try{const t=JSON.parse(e);return t!==null&&typeof t=="object"?t:void 0}catch{return}},q=e=>{try{return JSON.parse(e)}catch{return}},Q=(e,t={})=>{m(e);const s=Math.max(1,Math.min(t.limit??T,1e4)),o=["seq > ?"],r=[t.sinceSeq??0];if(I(o,r,t),t.outcome!==void 0&&(o.push("outcome = ?"),r.push(t.outcome)),t.tableTouched!==void 0&&t.tableTouched!==""){const i=JSON.stringify(t.tableTouched);o.push("(instr(lower(tables_read), lower(?)) > 0 OR instr(lower(tables_written), lower(?)) > 0)"),r.push(i,i)}r.push(s);const g=t.sinceSeq===void 0?"DESC":"ASC";return h(e,`SELECT seq, ts, function_path, shard_key, user_id, identity, args, outcome, error_message, trace_id, duration_ms, tables_read, tables_written, cache_hit, subscriptions_rerun
|
|
21
|
+
FROM "${d}" WHERE ${o.join(" AND ")} ORDER BY seq ${g} LIMIT ?`,...r).toArray().map(i=>{const a={durationMs:i.duration_ms,functionPath:i.function_path,outcome:i.outcome==="error"?"error":"ok",seq:i.seq,subscriptionsReRun:i.subscriptions_rerun,tablesRead:O(i.tables_read),tablesWritten:O(i.tables_written),ts:i.ts};if(i.shard_key!==null&&(a.shardKey=i.shard_key),i.user_id!==null&&(a.userId=i.user_id),i.identity!==null){const l=C(i.identity);l!==void 0&&(a.identity=l)}if(i.args!==null){const l=q(i.args);l!==void 0&&(a.redactedArgs=l)}return i.error_message!==null&&(a.errorMessage=i.error_message),i.cache_hit!==null&&(a.cacheHit=i.cache_hit===1),i.trace_id!==null&&(a.traceId=i.trace_id),a})},x=(e,t)=>{const s=P(e,[...t.keys()]);for(const o of t.values()){const r=s.get(o.hash);r!==void 0&&(o.stateUpdatedAt=r.updatedAt,r.assignee!==void 0&&(o.assignee=r.assignee),r.severity!==void 0&&(o.severity=r.severity),o.status=r.status==="resolved"&&o.lastSeen>r.updatedAt?"open":r.status)}},z=(e,t={})=>{m(e);const s=Math.max(1,Math.min(t.limit??T,1e4)),o=["outcome = 'error'"],r=[];I(o,r,t),r.push(s);const g=h(e,`SELECT function_path, error_message, error_fingerprint, ts
|
|
22
|
+
FROM "${d}" WHERE ${o.join(" AND ")} ORDER BY seq DESC LIMIT ?`,...r).toArray(),E=new Map,i=new Map;for(const n of g){const _=n.error_message??"",{culprit:A,hash:y,title:p}=b({functionPath:n.function_path,message:_}),f=n.error_fingerprint??y,c=E.get(f);if(c===void 0){E.set(f,{count:1,culprit:A,firstSeen:n.ts,hash:f,lastSeen:n.ts,sampleMessage:_,status:"open",title:p}),i.set(f,n.ts);continue}c.count+=1,c.firstSeen=Math.min(c.firstSeen,n.ts),c.lastSeen=Math.max(c.lastSeen,n.ts),n.ts>(i.get(f)??Number.NEGATIVE_INFINITY)&&(i.set(f,n.ts),c.sampleMessage=_,c.title=p)}x(e,E);const a=[...E.values()];return(t.status===void 0?a:a.filter(n=>n.status===t.status)).toSorted((n,_)=>_.lastSeen-n.lastSeen)};export{d as R,w as a,V as b,m as c,Q as d,B as e,u as f,T as g,j as h,R as n,Y as p,z as r};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lunora/observability",
|
|
3
|
-
"version": "1.0.0-alpha.
|
|
3
|
+
"version": "1.0.0-alpha.54",
|
|
4
4
|
"description": "Host-neutral telemetry storage and read models for Lunora, backing the Studio's Logs, Traces, Metrics and Issues views",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"lunora",
|
|
@@ -43,9 +43,9 @@
|
|
|
43
43
|
"access": "public"
|
|
44
44
|
},
|
|
45
45
|
"dependencies": {
|
|
46
|
-
"@lunora/errors": "1.0.0-alpha.
|
|
46
|
+
"@lunora/errors": "1.0.0-alpha.30",
|
|
47
47
|
"@lunora/fingerprint": "1.0.0-alpha.9",
|
|
48
|
-
"@lunora/shard-engine": "1.0.0-alpha.
|
|
48
|
+
"@lunora/shard-engine": "1.0.0-alpha.53",
|
|
49
49
|
"@visulima/redact": "4.0.0"
|
|
50
50
|
},
|
|
51
51
|
"engines": {
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
const r=t=>Number.isFinite(t)&&t>=1?Math.trunc(t):500;class s{buffer=[];capacity;droppedCount=0;constructor(e=500){this.capacity=r(e)}get dropped(){return this.droppedCount}get size(){return this.buffer.length}clear(){this.buffer.length=0,this.droppedCount=0}entries(){return this.buffer.toReversed()}push(e){this.buffer.push(e),this.buffer.length>this.capacity&&(this.buffer.shift(),this.droppedCount+=1)}}export{s as LogBuffer};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
const A=24,L=32,d={error:0,info:2,warning:1},l=new Set(["0","disabled","false","no","off"]),c=new Set(["1","enabled","on","true","yes"]),r=n=>typeof n=="string"?n.trim().toLowerCase():void 0,N=n=>{const t=n.AUTH_SECRET??n.BETTER_AUTH_SECRET,e=typeof t=="string"?t.trim().length:0;return e>0&&e<32?[{detail:{length:e,min:32},kind:"auth-secret-weak",level:"warning"}]:[]},T=n=>{const t=r(n.LUNORA_ALLOWED_ORIGINS),e=c.has(r(n.LUNORA_CORS_ALLOW_CREDENTIALS)??"");return(t?.split(",").some(s=>s.trim()==="*")??!1)&&e?[{kind:"cors-wildcard-credentials",level:"error"}]:[]},u=(n,t)=>{if(t)return[];const e=[];return l.has(r(n.LUNORA_SECURITY_HEADERS)??"")&&e.push({kind:"security-headers-disabled",level:"warning"}),l.has(r(n.LUNORA_SECURITY_CSRF)??"")&&e.push({kind:"csrf-disabled",level:"warning"}),r(n.BETTER_AUTH_URL)?.startsWith("http://")===!0&&e.push({kind:"cookies-insecure",level:"warning"}),e},R=(n,t)=>{const e=n??{},i=[],s=e.LUNORA_ADMIN_TOKEN;typeof s=="string"&&s.length>0&&s.length<24&&i.push({detail:{length:s.length,min:24},kind:"admin-token-weak",level:"warning"});const a=e.LUNORA_WS_BEARER,{dev:o}=t;return(typeof a!="string"||a==="")&&i.push({kind:"ws-gate-open",level:o?"info":"error"}),o&&i.push({kind:"dev-args-unredacted",level:"warning"}),i.push(...N(e),...T(e),...u(e,o)),{findings:i.toSorted((E,_)=>d[E.level]-d[_.level])}};export{A as MIN_ADMIN_TOKEN_LENGTH,L as MIN_AUTH_SECRET_LENGTH,R as buildSecurityAudit};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
const I=n=>Number.isFinite(n)&&n>=1?Math.trunc(n):500;class M{buffer=[];capacity;droppedCount=0;constructor(o=500){this.capacity=I(o)}get dropped(){return this.droppedCount}get size(){return this.buffer.length}clear(){this.buffer.length=0,this.droppedCount=0}entries(){return[...this.buffer]}hasTrace(o){return this.buffer.some(a=>a.traceId===o)}push(o){this.buffer.push(o),this.buffer.length>this.capacity&&(this.buffer.shift(),this.droppedCount+=1)}}const l=50,T=n=>{const o=new Map;for(const a of n){const c=o.get(a.traceId);c===void 0?o.set(a.traceId,[a]):c.push(a)}return o},b=(n,o)=>{const a=n.find(d=>d.dispatch===!0);if(a!==void 0)return a;const c=n.toSorted((d,t)=>d.startTs-t.startTs);return c.find(d=>!o.has(d.parentSpanId))??c[0]},v=(n,o)=>{const a=new Map([[n.spanId,0]]);return c=>{const d=[],t=new Set;let e=c,r=0;for(;;){const i=a.get(e.spanId);if(i!==void 0){r=i;break}if(t.has(e.spanId))break;t.add(e.spanId),d.push(e);const f=o.get(e.parentSpanId);if(f===void 0)break;e=f}for(const[i,f]of d.toReversed().entries())a.set(f.spanId,r+i+1);return a.get(c.spanId)??r}},m=(n,o)=>{const a=new Map(n.map(t=>[t.spanId,t.depth])),c=new Map,d=[];for(const t of n){if(t.spanId===o){d.push(t);continue}const e=a.get(t.parentSpanId)===t.depth-1?t.parentSpanId:o,r=c.get(e);r===void 0?c.set(e,[t]):r.push(t)}for(const t of c.values())t.sort((e,r)=>e.offsetMs-r.offsetMs);return{childrenOf:c,roots:d}},g=(n,o)=>{const{childrenOf:a,roots:c}=m(n,o),d=[],t=new Set,e=c.toReversed();for(;e.length>0;){const r=e.pop();if(t.has(r))continue;t.add(r),d.push(r);const i=a.get(r.spanId);if(i!==void 0)for(const f of i.toReversed())e.push(f)}if(d.length!==n.length)for(const r of n)t.has(r)||d.push(r);return d},y=(n,o=l)=>{const a=T(n),c=[...a.entries()].map(([t,e])=>({group:e,startTs:Math.min(...e.map(r=>r.startTs)),traceId:t})).toSorted((t,e)=>e.startTs-t.startTs).slice(0,o),d=[];for(const{group:t,traceId:e}of c){const r=new Map(t.map(s=>[s.spanId,s])),i=b(t,r);if(i===void 0)continue;const f=v(i,r),{startTs:h}=i,p=Math.max(...t.map(s=>s.startTs+s.durationMs)),u=t.map(s=>({...s.attributes===void 0?{}:{attributes:s.attributes},depth:f(s),durationMs:s.durationMs,...s.error===void 0?{}:{error:s.error},...s.events===void 0?{}:{events:s.events},...s.kind===void 0?{}:{kind:s.kind},name:s.name,offsetMs:Math.max(0,s.startTs-h),ok:s.ok,parentSpanId:s.parentSpanId,spanId:s.spanId}));d.push({durationMs:p-h,functionPath:i.functionPath,ok:t.every(s=>s.ok),rootName:i.name,...i.shardKey===void 0?{}:{shardKey:i.shardKey},spans:g(u,i.spanId),startTs:h,traceId:e})}return{total:a.size,traces:d.toSorted((t,e)=>e.startTs-t.startTs)}};export{l as DEFAULT_TRACE_LIMIT,M as SpanBuffer,y as foldTraces};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{f as E,n as y}from"./request-log-COB2xhns.mjs";import{L as b,o as O,b as H,t as _}from"./trace-context-DfJZi_g2.mjs";const x=/[\w.-]/u,K=t=>{let e="";for(const r of t)e+=x.test(r)?r:"_";return e},L=t=>{if(typeof t.name!="string"||t.name.length===0)throw new TypeError("recordEvaluation requires a non-empty `name`");if(typeof t.score!="number"||!Number.isFinite(t.score))throw new TypeError("recordEvaluation `score` must be a finite number");const e=K(t.name),r={[`gen_ai.evaluation.${e}.score`]:t.score};return t.label!==void 0&&(r[`gen_ai.evaluation.${e}.label`]=t.label),r},j=t=>{const e=Object.keys(t);return e.length>0&&e.every(r=>r==="attributes"||r==="kind"||r==="links")},z=128,U=128,D=128,P=(t,e)=>{if(e===void 0)return;let r=Object.keys(t).length;for(const[o,s]of Object.entries(e)){const n=!Object.hasOwn(t,o);n&&r>=D||(n&&(r+=1),t[o]=s)}},F=t=>{try{const e=new URL(t);return`${e.protocol}//${e.host}${e.pathname}`}catch{return t}},q=t=>{try{return new URL(t).host}catch{return t}},C=(t,e)=>{try{return t(new URL(e))}catch{return!1}},X=t=>t===void 0?{}:j(t)?t:{attributes:t},B=(t,e)=>{if(t.isTraced){t.setAttribute(b.functionPath,e.functionPath),t.setAttribute(b.ok,e.ok),t.setAttribute(b.durationMs,e.durationMs),e.shardKey!==void 0&&t.setAttribute(b.shardKey,e.shardKey),e.userId!==void 0&&t.setAttribute(b.userId,e.userId),e.error!==void 0&&(t.setAttribute(b.errorType,e.error.type),t.setAttribute(b.errorMessage,e.error.message));for(const[r,o]of Object.entries(e.attributes))(typeof o=="boolean"||typeof o=="number"||typeof o=="string")&&t.setAttribute(`lunora.attr.${r}`,o)}},V=(t,e=!1)=>{const r={attributes:{},events:[],links:[]},o={spanContext:()=>t,addEvent:(s,n)=>{if(r.events.length>=z)return;const a=y(n);r.events.push({...a===void 0?{}:{attributes:a},name:s,ts:Date.now()})},addLink:s=>{if(r.links.length>=U)return;const n=y(s.attributes);r.links.push({...n===void 0?{}:{attributes:n},spanId:s.spanId,traceId:s.traceId})},recordEvaluation:s=>{P(r.attributes,y(L(s)))},recordException:s=>{const n=s instanceof Error?s.message:String(s);o.addEvent("exception",{"exception.message":E(n,e),...e&&s instanceof Error&&typeof s.stack=="string"?{"exception.stacktrace":s.stack}:{},"exception.type":_(s)})},setAttribute:(s,n)=>{P(r.attributes,y({[s]:n}))},setAttributes:s=>{P(r.attributes,y(s))}};return{collected:r,handle:o}},Q=t=>{const{anchor:e,captureRaw:r=!1,fuseHostSpans:o,functionPath:s,record:n,resolveHostTracing:a,shardKey:c,userId:g}=t,u=v=>async(m,A,d)=>{const S=O(8),h=Date.now(),l=X(d),i=y(l.attributes),{collected:I,handle:$}=V({spanId:S,traceId:e.traceId},r),R=async k=>{let f=!0,w;try{return await A(u(S),$)}catch(p){f=!1;const T=p instanceof Error?p.message:String(p);throw w={message:E(T,r),type:_(p)},p}finally{const p=Date.now()-h,T=g(),M={...i,...I.attributes},N=[...l.links??[],...I.links];try{n({...Object.keys(M).length===0?{}:{attributes:M},durationMs:p,...I.events.length===0?{}:{events:I.events},...w===void 0?{}:{error:w},functionPath:s,...l.kind===void 0||l.kind==="internal"?{}:{kind:l.kind},...N.length===0?{}:{links:N},name:m,ok:f,parentSpanId:v,shardKey:c,spanId:S,startTs:h,traceId:e.traceId,userId:T})}catch{}if(k!==void 0)try{B(k,{attributes:M,durationMs:p,error:w,functionPath:s,ok:f,shardKey:c,userId:T})}catch{}}};if(o===!0&&a!==void 0){let k=!1;try{const f=await a();if(f!==void 0&&typeof f.enterSpan=="function")return await f.enterSpan(m,w=>(k=!0,R(w)))}catch(f){if(k)throw f}}return await R()};return u(e.rootSpanId)},W=(t,e)=>{const{anchor:r,captureRaw:o=!1,functionPath:s,propagate:n=!0,record:a,shardKey:c,userId:g}=t;return async(u,v)=>{const m=O(8),A=Date.now(),d=new Request(u,v);(typeof n=="function"?C(n,d.url):n)&&d.headers.set("traceparent",H(r.traceId,m,r.sampled??!0));let h,l;try{const i=await e(d);return l=i.status,i.ok||(h={message:`HTTP ${String(i.status)}`,type:`HTTP_${String(i.status)}`}),i}catch(i){const I=i instanceof Error?i.message:String(i);throw h={message:E(I,o),type:_(i)},i}finally{try{a({attributes:{"http.request.method":d.method,...l===void 0?{}:{"http.response.status_code":l},"url.full":F(d.url)},durationMs:Date.now()-A,...h===void 0?{}:{error:h},functionPath:s,kind:"client",name:`${d.method} ${q(d.url)}`,ok:h===void 0,parentSpanId:r.rootSpanId,shardKey:c,spanId:m,startTs:A,traceId:r.traceId,userId:g()})}catch{}}}},Y=t=>{const{functionPath:e,record:r,shardKey:o}=t,s=(n,a,c,g)=>{if(!Number.isFinite(c))return;const u=y(g);try{r({...u===void 0?{}:{attributes:u},functionPath:e,kind:n,name:a,shardKey:o,ts:Date.now(),value:c})}catch{}};return{count:(n,a=1,c)=>{s("counter",n,a,c)},gauge:(n,a,c)=>{s("gauge",n,a,c)},record:(n,a,c)=>{s("histogram",n,a,c)}}},Z=t=>{const{anchor:e,captureRaw:r=!1,collected:o,durationMs:s,failure:n,functionPath:a,shardKey:c,startTs:g,userId:u}=t,v=o?.attributes??{};return{...Object.keys(v).length===0?{}:{attributes:v},dispatch:!0,durationMs:s,...o===void 0||o.events.length===0?{}:{events:o.events},...n===void 0?{}:{error:{message:E(n.thrown instanceof Error?n.thrown.message:String(n.thrown),r),type:_(n.thrown)}},functionPath:a,...o===void 0||o.links.length===0?{}:{links:o.links},name:a,ok:n===void 0,parentSpanId:"",shardKey:c,spanId:e.rootSpanId,startTs:g,traceId:e.traceId,userId:u}};export{B as applyHostSpanAttributes,Y as createMetrics,V as createSpanCollector,W as createTracedFetch,Q as createTracer,Z as dispatchRootSpan};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
const u=5e3,C=500,A="__doc__",l=e=>e.startsWith("sqlite_")||e.startsWith("_cf_")||e.startsWith("__miniflare")||e.startsWith("__lunora")||e.includes("__fts_"),f=e=>`"${e.replaceAll('"','""')}"`,N=(e,n)=>l(n)?!1:e.exec("SELECT name FROM sqlite_master WHERE type = 'table' AND name = ? LIMIT 1",n).toArray().length>0,d=(e,n)=>{const s=n.includes(e),i=n.includes(A);if(!(!s&&!i))return s?{expression:f(e),params:[]}:{expression:`json_extract(${f(A)}, ?)`,params:[`$."${e.replaceAll('"','""')}"`]}},p=(e,n,s,i,a,c,r)=>{const t=d(i,a);if(t===void 0)return;const _=e.exec(`SELECT id, ${t.expression} AS ref FROM ${n} WHERE ${t.expression} IS NOT NULL AND ${t.expression} <> '' LIMIT ?`,...t.params,...t.params,...t.params,5001).toArray();_.length>5e3&&(r.truncated=!0);for(const o of _.slice(0,5e3))if(r.scanned+=1,!c.has(o.ref)){if(r.references.length>=500){r.truncated=!0;continue}r.references.push({column:i,id:o.id,key:o.ref,table:s})}},L=(e,n,s)=>{const i=s instanceof Set?s:new Set(s),a={references:[],scanned:0,truncated:!1};for(const[c,r]of Object.entries(n)){if(!N(e,c))continue;const t=f(c),_=e.exec(`PRAGMA table_info(${t})`).toArray().map(o=>o.name);for(const o of r)p(e,t,c,o,_,i,a)}return a};export{C as DANGLING_RESULT_CAP,u as DANGLING_SCAN_CAP,L as findDanglingReferences};
|
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
import{fingerprintError as L}from"@lunora/fingerprint";import{redact as A,standardRules as y}from"@visulima/redact";import{readIssueStates as M}from"./ISSUE_SEVERITIES-gLC4VEPQ.mjs";import{r as h}from"./run-sql-0aPgJkIw.mjs";const U=e=>{if(typeof e=="string")return e;try{return JSON.stringify(e)??String(e)}catch{return String(e)}},p=e=>typeof e=="boolean"||typeof e=="number"||typeof e=="string"?e:U(e),R=(e,t)=>{if(e===void 0&&t===void 0)return;const s={};if(t!==void 0)for(const[i,r]of Object.entries(t))s[i]=p(r);if(e!==void 0)for(const[i,r]of Object.entries(e))s[i]=p(r);return Object.keys(s).length===0?void 0:s},u="__lunora_reqlog__",_=1e3,O="lunora",P=["error_fingerprint TEXT","trace_id TEXT"],l=(e,t=!1)=>t||e===null||e===void 0?e:A(e,y),T=e=>{h(e,`CREATE TABLE IF NOT EXISTS "${u}" (
|
|
2
|
-
seq INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
3
|
-
ts REAL NOT NULL,
|
|
4
|
-
function_path TEXT NOT NULL,
|
|
5
|
-
shard_key TEXT,
|
|
6
|
-
user_id TEXT,
|
|
7
|
-
identity TEXT,
|
|
8
|
-
args TEXT,
|
|
9
|
-
outcome TEXT NOT NULL,
|
|
10
|
-
error_message TEXT,
|
|
11
|
-
error_fingerprint TEXT,
|
|
12
|
-
trace_id TEXT,
|
|
13
|
-
duration_ms REAL NOT NULL,
|
|
14
|
-
tables_read TEXT NOT NULL DEFAULT '[]',
|
|
15
|
-
tables_written TEXT NOT NULL DEFAULT '[]',
|
|
16
|
-
cache_hit INTEGER,
|
|
17
|
-
subscriptions_rerun INTEGER NOT NULL DEFAULT 0
|
|
18
|
-
)`);for(const t of P)try{h(e,`ALTER TABLE "${u}" ADD COLUMN ${t}`)}catch{}},S=e=>JSON.stringify([...new Set(e)].toSorted((t,s)=>t.localeCompare(s))),D=e=>e===void 0?null:e?1:0,W=(e,t,s={})=>{T(e);const i=s.captureRaw??!1,r=s.retention??_,E=t.outcome==="error"&&t.errorMessage!==void 0?L({functionPath:t.functionPath,message:t.errorMessage}).hash:void 0;h(e,`INSERT INTO "${u}"
|
|
19
|
-
(ts, function_path, shard_key, user_id, identity, args, outcome, error_message, error_fingerprint, trace_id, duration_ms, tables_read, tables_written, cache_hit, subscriptions_rerun)
|
|
20
|
-
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,t.ts,t.functionPath,t.shardKey??null,t.userId??null,t.identity===void 0?null:JSON.stringify(l(t.identity,i)),t.redactedArgs===void 0?null:JSON.stringify(l(t.redactedArgs,i)),t.outcome,t.errorMessage===void 0?null:l(t.errorMessage,i),E??null,t.traceId??null,t.durationMs,S(t.tablesRead),S(t.tablesWritten),D(t.cacheHit),t.subscriptionsReRun??0),h(e,`DELETE FROM "${u}" WHERE seq <= (SELECT MAX(seq) - ? FROM "${u}")`,r)},V=(e,t={})=>{const s=t.captureRaw??!1,i={args:e.redactedArgs===void 0?void 0:l(e.redactedArgs,s),cacheHit:e.cacheHit,durationMs:e.durationMs,error:e.errorMessage===void 0?void 0:l(e.errorMessage,s),function:e.functionPath,identity:e.identity===void 0?void 0:l(e.identity,s),outcome:e.outcome,shard:e.shardKey,source:O,tablesRead:e.tablesRead??[],tablesWritten:e.tablesWritten??[],traceId:e.traceId,ts:e.ts,type:"request",userId:e.userId},r=JSON.stringify(i);e.outcome==="error"?console.error(r):console.log(r)},X="log",F=e=>e.map(t=>{if(typeof t=="string")return t;try{return JSON.stringify(t)??String(t)}catch{return String(t)}}).join(" "),j=e=>{if(typeof e!="object"||e===null||Array.isArray(e))return!1;const t=Object.getPrototypeOf(e);return t===Object.prototype||t===null},Y=(e,t)=>e.length===2&&typeof e[0]=="string"&&j(e[1])?{fields:R(e[1],t),message:e[0]}:{fields:R(void 0,t),message:F(e)},w=(e,t={})=>{const s=t.captureRaw??!1,i={fields:e.fields===void 0?void 0:l(e.fields,s),function:e.functionPath,level:e.level,message:e.message,shard:e.shardKey,source:O,spanId:e.spanId,traceId:e.traceId,ts:e.ts,type:X,userId:e.userId};let r;try{r=JSON.stringify(i)}catch{r=JSON.stringify({...i,fields:void 0})}e.level==="error"||e.level==="fatal"?console.error(r):e.level==="warn"?console.warn(r):console.log(r)},J=(e,t)=>`lower(substr(${e}, 1, ${String([...t].length)})) = lower(?)`,b=(e,t,s)=>{s.functionPathPrefix!==void 0&&s.functionPathPrefix!==""&&(e.push(J("function_path",s.functionPathPrefix)),t.push(s.functionPathPrefix)),s.userId!==void 0&&s.userId!==""&&(e.push("user_id = ?"),t.push(s.userId)),s.shardKey!==void 0&&s.shardKey!==""&&(e.push("shard_key = ?"),t.push(s.shardKey))},N=e=>{try{const t=JSON.parse(e);return Array.isArray(t)?t.filter(s=>typeof s=="string"):[]}catch{return[]}},$=e=>{try{const t=JSON.parse(e);return t!==null&&typeof t=="object"?t:void 0}catch{return}},k=e=>{try{return JSON.parse(e)}catch{return}},B=(e,t={})=>{T(e);const s=Math.max(1,Math.min(t.limit??_,1e4)),i=["seq > ?"],r=[t.sinceSeq??0];if(b(i,r,t),t.outcome!==void 0&&(i.push("outcome = ?"),r.push(t.outcome)),t.tableTouched!==void 0&&t.tableTouched!==""){const o=JSON.stringify(t.tableTouched);i.push("(instr(lower(tables_read), lower(?)) > 0 OR instr(lower(tables_written), lower(?)) > 0)"),r.push(o,o)}return r.push(s),h(e,`SELECT seq, ts, function_path, shard_key, user_id, identity, args, outcome, error_message, trace_id, duration_ms, tables_read, tables_written, cache_hit, subscriptions_rerun
|
|
21
|
-
FROM "${u}" WHERE ${i.join(" AND ")} ORDER BY seq DESC LIMIT ?`,...r).toArray().map(o=>{const n={durationMs:o.duration_ms,functionPath:o.function_path,outcome:o.outcome==="error"?"error":"ok",seq:o.seq,subscriptionsReRun:o.subscriptions_rerun,tablesRead:N(o.tables_read),tablesWritten:N(o.tables_written),ts:o.ts};if(o.shard_key!==null&&(n.shardKey=o.shard_key),o.user_id!==null&&(n.userId=o.user_id),o.identity!==null){const c=$(o.identity);c!==void 0&&(n.identity=c)}if(o.args!==null){const c=k(o.args);c!==void 0&&(n.redactedArgs=c)}return o.error_message!==null&&(n.errorMessage=o.error_message),o.cache_hit!==null&&(n.cacheHit=o.cache_hit===1),o.trace_id!==null&&(n.traceId=o.trace_id),n})},q=(e,t)=>{const s=M(e,[...t.keys()]);for(const i of t.values()){const r=s.get(i.hash);r!==void 0&&(i.stateUpdatedAt=r.updatedAt,r.assignee!==void 0&&(i.assignee=r.assignee),r.severity!==void 0&&(i.severity=r.severity),i.status=r.status==="resolved"&&i.lastSeen>r.updatedAt?"open":r.status)}},Q=(e,t={})=>{T(e);const s=Math.max(1,Math.min(t.limit??_,1e4)),i=["outcome = 'error'"],r=[];b(i,r,t),r.push(s);const E=h(e,`SELECT function_path, error_message, error_fingerprint, ts
|
|
22
|
-
FROM "${u}" WHERE ${i.join(" AND ")} ORDER BY seq DESC LIMIT ?`,...r).toArray(),o=new Map,n=new Map;for(const a of E){const g=a.error_message??"",{culprit:I,hash:v,title:m}=L({functionPath:a.function_path,message:g}),f=a.error_fingerprint??v,d=o.get(f);if(d===void 0){o.set(f,{count:1,culprit:I,firstSeen:a.ts,hash:f,lastSeen:a.ts,sampleMessage:g,status:"open",title:m}),n.set(f,a.ts);continue}d.count+=1,d.firstSeen=Math.min(d.firstSeen,a.ts),d.lastSeen=Math.max(d.lastSeen,a.ts),a.ts>(n.get(f)??Number.NEGATIVE_INFINITY)&&(n.set(f,a.ts),d.sampleMessage=g,d.title=m)}q(e,o);const c=[...o.values()];return(t.status===void 0?c:c.filter(a=>a.status===t.status)).toSorted((a,g)=>g.lastSeen-a.lastSeen)};export{u as R,W as a,V as b,T as c,B as d,w as e,l as f,_ as g,F as h,R as n,Y as p,Q as r};
|