@wizeworks/lens-cloud 0.0.0-stage → 0.3.0-alpha.2
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/LICENSE +21 -0
- package/README.md +115 -2
- package/dist/alerts/evaluate.d.ts +10 -0
- package/dist/alerts/evaluate.d.ts.map +1 -0
- package/dist/alerts/evaluate.js +81 -0
- package/dist/alerts/evaluate.js.map +1 -0
- package/dist/alerts/notify.d.ts +28 -0
- package/dist/alerts/notify.d.ts.map +1 -0
- package/dist/alerts/notify.js +52 -0
- package/dist/alerts/notify.js.map +1 -0
- package/dist/app.d.ts +26 -0
- package/dist/app.d.ts.map +1 -0
- package/dist/app.js +2 -0
- package/dist/app.js.map +1 -0
- package/dist/auth/auth.d.ts +51 -0
- package/dist/auth/auth.d.ts.map +1 -0
- package/dist/auth/auth.js +63 -0
- package/dist/auth/auth.js.map +1 -0
- package/dist/auth/bridge.d.ts +7 -0
- package/dist/auth/bridge.d.ts.map +1 -0
- package/dist/auth/bridge.js +39 -0
- package/dist/auth/bridge.js.map +1 -0
- package/dist/auth/crypto.d.ts +14 -0
- package/dist/auth/crypto.d.ts.map +1 -0
- package/dist/auth/crypto.js +16 -0
- package/dist/auth/crypto.js.map +1 -0
- package/dist/auth/delete-user.d.ts +16 -0
- package/dist/auth/delete-user.d.ts.map +1 -0
- package/dist/auth/delete-user.js +21 -0
- package/dist/auth/delete-user.js.map +1 -0
- package/dist/auth/deps.d.ts +27 -0
- package/dist/auth/deps.d.ts.map +1 -0
- package/dist/auth/deps.js +3 -0
- package/dist/auth/deps.js.map +1 -0
- package/dist/auth/email-token.d.ts +8 -0
- package/dist/auth/email-token.d.ts.map +1 -0
- package/dist/auth/email-token.js +15 -0
- package/dist/auth/email-token.js.map +1 -0
- package/dist/auth/hooks.d.ts +4 -0
- package/dist/auth/hooks.d.ts.map +1 -0
- package/dist/auth/hooks.js +143 -0
- package/dist/auth/hooks.js.map +1 -0
- package/dist/auth/options.d.ts +17 -0
- package/dist/auth/options.d.ts.map +1 -0
- package/dist/auth/options.js +98 -0
- package/dist/auth/options.js.map +1 -0
- package/dist/auth/password.d.ts +10 -0
- package/dist/auth/password.d.ts.map +1 -0
- package/dist/auth/password.js +22 -0
- package/dist/auth/password.js.map +1 -0
- package/dist/auth/plugins.d.ts +4 -0
- package/dist/auth/plugins.d.ts.map +1 -0
- package/dist/auth/plugins.js +45 -0
- package/dist/auth/plugins.js.map +1 -0
- package/dist/auth/principal.d.ts +38 -0
- package/dist/auth/principal.d.ts.map +1 -0
- package/dist/auth/principal.js +69 -0
- package/dist/auth/principal.js.map +1 -0
- package/dist/auth/roles.d.ts +50 -0
- package/dist/auth/roles.d.ts.map +1 -0
- package/dist/auth/roles.js +18 -0
- package/dist/auth/roles.js.map +1 -0
- package/dist/auth/schema-names.d.ts +130 -0
- package/dist/auth/schema-names.d.ts.map +1 -0
- package/dist/auth/schema-names.js +53 -0
- package/dist/auth/schema-names.js.map +1 -0
- package/dist/auth/secret.d.ts +12 -0
- package/dist/auth/secret.d.ts.map +1 -0
- package/dist/auth/secret.js +32 -0
- package/dist/auth/secret.js.map +1 -0
- package/dist/auth/security-notices.d.ts +34 -0
- package/dist/auth/security-notices.d.ts.map +1 -0
- package/dist/auth/security-notices.js +81 -0
- package/dist/auth/security-notices.js.map +1 -0
- package/dist/auth/signup.d.ts +23 -0
- package/dist/auth/signup.d.ts.map +1 -0
- package/dist/auth/signup.js +61 -0
- package/dist/auth/signup.js.map +1 -0
- package/dist/auth/sso.d.ts +21 -0
- package/dist/auth/sso.d.ts.map +1 -0
- package/dist/auth/sso.js +35 -0
- package/dist/auth/sso.js.map +1 -0
- package/dist/auth/wire.d.ts +16 -0
- package/dist/auth/wire.d.ts.map +1 -0
- package/dist/auth/wire.js +47 -0
- package/dist/auth/wire.js.map +1 -0
- package/dist/cli-args.d.ts +5 -0
- package/dist/cli-args.d.ts.map +1 -0
- package/dist/cli-args.js +86 -0
- package/dist/cli-args.js.map +1 -0
- package/dist/cli.d.ts +3 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +44 -0
- package/dist/cli.js.map +1 -0
- package/dist/config.d.ts +55 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +55 -0
- package/dist/config.js.map +1 -0
- package/dist/db/db.d.ts +22 -0
- package/dist/db/db.d.ts.map +1 -0
- package/dist/db/db.js +64 -0
- package/dist/db/db.js.map +1 -0
- package/dist/db/migrate.d.ts +6 -0
- package/dist/db/migrate.d.ts.map +1 -0
- package/dist/db/migrate.js +35 -0
- package/dist/db/migrate.js.map +1 -0
- package/dist/db/schema-auth.d.ts +2 -0
- package/dist/db/schema-auth.d.ts.map +1 -0
- package/dist/db/schema-auth.js +93 -0
- package/dist/db/schema-auth.js.map +1 -0
- package/dist/db/schema-mail.d.ts +2 -0
- package/dist/db/schema-mail.d.ts.map +1 -0
- package/dist/db/schema-mail.js +8 -0
- package/dist/db/schema-mail.js.map +1 -0
- package/dist/db/schema-notify.d.ts +2 -0
- package/dist/db/schema-notify.d.ts.map +1 -0
- package/dist/db/schema-notify.js +26 -0
- package/dist/db/schema-notify.js.map +1 -0
- package/dist/db/schema-sso.d.ts +2 -0
- package/dist/db/schema-sso.d.ts.map +1 -0
- package/dist/db/schema-sso.js +17 -0
- package/dist/db/schema-sso.js.map +1 -0
- package/dist/db/schema.d.ts +3 -0
- package/dist/db/schema.d.ts.map +1 -0
- package/dist/db/schema.js +208 -0
- package/dist/db/schema.js.map +1 -0
- package/dist/http/http.d.ts +19 -0
- package/dist/http/http.d.ts.map +1 -0
- package/dist/http/http.js +66 -0
- package/dist/http/http.js.map +1 -0
- package/dist/http/limiter.d.ts +11 -0
- package/dist/http/limiter.d.ts.map +1 -0
- package/dist/http/limiter.js +31 -0
- package/dist/http/limiter.js.map +1 -0
- package/dist/http/router.d.ts +21 -0
- package/dist/http/router.d.ts.map +1 -0
- package/dist/http/router.js +28 -0
- package/dist/http/router.js.map +1 -0
- package/dist/index.d.ts +7 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +4 -0
- package/dist/index.js.map +1 -0
- package/dist/jobs.d.ts +4 -0
- package/dist/jobs.d.ts.map +1 -0
- package/dist/jobs.js +53 -0
- package/dist/jobs.js.map +1 -0
- package/dist/mail/blocks.d.ts +14 -0
- package/dist/mail/blocks.d.ts.map +1 -0
- package/dist/mail/blocks.js +35 -0
- package/dist/mail/blocks.js.map +1 -0
- package/dist/mail/content.d.ts +68 -0
- package/dist/mail/content.d.ts.map +1 -0
- package/dist/mail/content.js +6 -0
- package/dist/mail/content.js.map +1 -0
- package/dist/mail/emails-digest.d.ts +10 -0
- package/dist/mail/emails-digest.d.ts.map +1 -0
- package/dist/mail/emails-digest.js +55 -0
- package/dist/mail/emails-digest.js.map +1 -0
- package/dist/mail/emails-health.d.ts +6 -0
- package/dist/mail/emails-health.d.ts.map +1 -0
- package/dist/mail/emails-health.js +36 -0
- package/dist/mail/emails-health.js.map +1 -0
- package/dist/mail/emails-security.d.ts +14 -0
- package/dist/mail/emails-security.d.ts.map +1 -0
- package/dist/mail/emails-security.js +27 -0
- package/dist/mail/emails-security.js.map +1 -0
- package/dist/mail/emails-team.d.ts +11 -0
- package/dist/mail/emails-team.d.ts.map +1 -0
- package/dist/mail/emails-team.js +45 -0
- package/dist/mail/emails-team.js.map +1 -0
- package/dist/mail/emails.d.ts +9 -0
- package/dist/mail/emails.d.ts.map +1 -0
- package/dist/mail/emails.js +49 -0
- package/dist/mail/emails.js.map +1 -0
- package/dist/mail/layout.d.ts +6 -0
- package/dist/mail/layout.d.ts.map +1 -0
- package/dist/mail/layout.js +10 -0
- package/dist/mail/layout.js.map +1 -0
- package/dist/mail/mailer.d.ts +25 -0
- package/dist/mail/mailer.d.ts.map +1 -0
- package/dist/mail/mailer.js +49 -0
- package/dist/mail/mailer.js.map +1 -0
- package/dist/mail/preview.d.ts +6 -0
- package/dist/mail/preview.d.ts.map +1 -0
- package/dist/mail/preview.js +26 -0
- package/dist/mail/preview.js.map +1 -0
- package/dist/mail/resend.d.ts +11 -0
- package/dist/mail/resend.d.ts.map +1 -0
- package/dist/mail/resend.js +34 -0
- package/dist/mail/resend.js.map +1 -0
- package/dist/mail/samples.d.ts +3 -0
- package/dist/mail/samples.d.ts.map +1 -0
- package/dist/mail/samples.js +63 -0
- package/dist/mail/samples.js.map +1 -0
- package/dist/mail/stop-route.d.ts +4 -0
- package/dist/mail/stop-route.d.ts.map +1 -0
- package/dist/mail/stop-route.js +41 -0
- package/dist/mail/stop-route.js.map +1 -0
- package/dist/mail/svix.d.ts +8 -0
- package/dist/mail/svix.d.ts.map +1 -0
- package/dist/mail/svix.js +17 -0
- package/dist/mail/svix.js.map +1 -0
- package/dist/mail/templates.d.ts +12 -0
- package/dist/mail/templates.d.ts.map +1 -0
- package/dist/mail/templates.js +18 -0
- package/dist/mail/templates.js.map +1 -0
- package/dist/mail/text.d.ts +4 -0
- package/dist/mail/text.d.ts.map +1 -0
- package/dist/mail/text.js +17 -0
- package/dist/mail/text.js.map +1 -0
- package/dist/mail/theme.d.ts +26 -0
- package/dist/mail/theme.d.ts.map +1 -0
- package/dist/mail/theme.js +21 -0
- package/dist/mail/theme.js.map +1 -0
- package/dist/mail/unsubscribe.d.ts +14 -0
- package/dist/mail/unsubscribe.d.ts.map +1 -0
- package/dist/mail/unsubscribe.js +39 -0
- package/dist/mail/unsubscribe.js.map +1 -0
- package/dist/mail/webhook.d.ts +5 -0
- package/dist/mail/webhook.d.ts.map +1 -0
- package/dist/mail/webhook.js +41 -0
- package/dist/mail/webhook.js.map +1 -0
- package/dist/notify/digest-data.d.ts +31 -0
- package/dist/notify/digest-data.d.ts.map +1 -0
- package/dist/notify/digest-data.js +37 -0
- package/dist/notify/digest-data.js.map +1 -0
- package/dist/notify/digest.d.ts +17 -0
- package/dist/notify/digest.d.ts.map +1 -0
- package/dist/notify/digest.js +76 -0
- package/dist/notify/digest.js.map +1 -0
- package/dist/notify/health.d.ts +6 -0
- package/dist/notify/health.d.ts.map +1 -0
- package/dist/notify/health.js +43 -0
- package/dist/notify/health.js.map +1 -0
- package/dist/notify/team-describe.d.ts +22 -0
- package/dist/notify/team-describe.d.ts.map +1 -0
- package/dist/notify/team-describe.js +67 -0
- package/dist/notify/team-describe.js.map +1 -0
- package/dist/notify/team.d.ts +6 -0
- package/dist/notify/team.d.ts.map +1 -0
- package/dist/notify/team.js +56 -0
- package/dist/notify/team.js.map +1 -0
- package/dist/repo/alerts.d.ts +52 -0
- package/dist/repo/alerts.d.ts.map +1 -0
- package/dist/repo/alerts.js +38 -0
- package/dist/repo/alerts.js.map +1 -0
- package/dist/repo/audit.d.ts +11 -0
- package/dist/repo/audit.d.ts.map +1 -0
- package/dist/repo/audit.js +17 -0
- package/dist/repo/audit.js.map +1 -0
- package/dist/repo/auth-prune.d.ts +4 -0
- package/dist/repo/auth-prune.d.ts.map +1 -0
- package/dist/repo/auth-prune.js +8 -0
- package/dist/repo/auth-prune.js.map +1 -0
- package/dist/repo/mail-prefs.d.ts +35 -0
- package/dist/repo/mail-prefs.d.ts.map +1 -0
- package/dist/repo/mail-prefs.js +34 -0
- package/dist/repo/mail-prefs.js.map +1 -0
- package/dist/repo/metric-read.d.ts +12 -0
- package/dist/repo/metric-read.d.ts.map +1 -0
- package/dist/repo/metric-read.js +11 -0
- package/dist/repo/metric-read.js.map +1 -0
- package/dist/repo/metric-write.d.ts +9 -0
- package/dist/repo/metric-write.d.ts.map +1 -0
- package/dist/repo/metric-write.js +53 -0
- package/dist/repo/metric-write.js.map +1 -0
- package/dist/repo/orgs.d.ts +37 -0
- package/dist/repo/orgs.d.ts.map +1 -0
- package/dist/repo/orgs.js +33 -0
- package/dist/repo/orgs.js.map +1 -0
- package/dist/repo/projects.d.ts +37 -0
- package/dist/repo/projects.d.ts.map +1 -0
- package/dist/repo/projects.js +57 -0
- package/dist/repo/projects.js.map +1 -0
- package/dist/repo/suppressions.d.ts +8 -0
- package/dist/repo/suppressions.d.ts.map +1 -0
- package/dist/repo/suppressions.js +16 -0
- package/dist/repo/suppressions.js.map +1 -0
- package/dist/repo/trace-read.d.ts +28 -0
- package/dist/repo/trace-read.d.ts.map +1 -0
- package/dist/repo/trace-read.js +76 -0
- package/dist/repo/trace-read.js.map +1 -0
- package/dist/repo/trace-write.d.ts +9 -0
- package/dist/repo/trace-write.d.ts.map +1 -0
- package/dist/repo/trace-write.js +82 -0
- package/dist/repo/trace-write.js.map +1 -0
- package/dist/repo/users.d.ts +13 -0
- package/dist/repo/users.d.ts.map +1 -0
- package/dist/repo/users.js +7 -0
- package/dist/repo/users.js.map +1 -0
- package/dist/routes/alerts.d.ts +4 -0
- package/dist/routes/alerts.d.ts.map +1 -0
- package/dist/routes/alerts.js +116 -0
- package/dist/routes/alerts.js.map +1 -0
- package/dist/routes/data.d.ts +7 -0
- package/dist/routes/data.d.ts.map +1 -0
- package/dist/routes/data.js +74 -0
- package/dist/routes/data.js.map +1 -0
- package/dist/routes/index.d.ts +5 -0
- package/dist/routes/index.d.ts.map +1 -0
- package/dist/routes/index.js +25 -0
- package/dist/routes/index.js.map +1 -0
- package/dist/routes/ingest.d.ts +8 -0
- package/dist/routes/ingest.d.ts.map +1 -0
- package/dist/routes/ingest.js +38 -0
- package/dist/routes/ingest.js.map +1 -0
- package/dist/routes/mcp.d.ts +4 -0
- package/dist/routes/mcp.d.ts.map +1 -0
- package/dist/routes/mcp.js +52 -0
- package/dist/routes/mcp.js.map +1 -0
- package/dist/routes/me.d.ts +4 -0
- package/dist/routes/me.d.ts.map +1 -0
- package/dist/routes/me.js +37 -0
- package/dist/routes/me.js.map +1 -0
- package/dist/routes/metrics.d.ts +13 -0
- package/dist/routes/metrics.d.ts.map +1 -0
- package/dist/routes/metrics.js +29 -0
- package/dist/routes/metrics.js.map +1 -0
- package/dist/routes/models.d.ts +4 -0
- package/dist/routes/models.d.ts.map +1 -0
- package/dist/routes/models.js +71 -0
- package/dist/routes/models.js.map +1 -0
- package/dist/routes/notify.d.ts +4 -0
- package/dist/routes/notify.d.ts.map +1 -0
- package/dist/routes/notify.js +55 -0
- package/dist/routes/notify.js.map +1 -0
- package/dist/routes/orgs.d.ts +4 -0
- package/dist/routes/orgs.d.ts.map +1 -0
- package/dist/routes/orgs.js +73 -0
- package/dist/routes/orgs.js.map +1 -0
- package/dist/routes/projects.d.ts +4 -0
- package/dist/routes/projects.d.ts.map +1 -0
- package/dist/routes/projects.js +55 -0
- package/dist/routes/projects.js.map +1 -0
- package/dist/routes/shares.d.ts +11 -0
- package/dist/routes/shares.d.ts.map +1 -0
- package/dist/routes/shares.js +61 -0
- package/dist/routes/shares.js.map +1 -0
- package/dist/scale-exec.d.ts +11 -0
- package/dist/scale-exec.d.ts.map +1 -0
- package/dist/scale-exec.js +26 -0
- package/dist/scale-exec.js.map +1 -0
- package/dist/server.d.ts +15 -0
- package/dist/server.d.ts.map +1 -0
- package/dist/server.js +126 -0
- package/dist/server.js.map +1 -0
- package/dist/settle.d.ts +26 -0
- package/dist/settle.d.ts.map +1 -0
- package/dist/settle.js +85 -0
- package/dist/settle.js.map +1 -0
- package/package.json +76 -3
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"suppressions.js","sourceRoot":"","sources":["../../src/repo/suppressions.ts"],"names":[],"mappings":"AAIA,MAAM,IAAI,GAAG,CAAC,KAAa,EAAE,EAAE,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;AAE3D,0GAA0G;AAC1G,MAAM,CAAC,KAAK,UAAU,QAAQ,CAAC,CAAY,EAAE,KAAa,EAAE,MAAsB,EAAE,MAAc,EAAE,GAAW;IAC7G,MAAM,CAAC,CAAC,KAAK,CACX;;kEAE8D,EAC9D,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,MAAM,EAAE,MAAM,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,GAAG,CAAC,CACjD,CAAC;AACJ,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,aAAa,CAAC,CAAY,EAAE,KAAa;IAC7D,MAAM,IAAI,GAAG,MAAM,CAAC,CAAC,KAAK,CAA6B,uDAAuD,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;IAC/H,OAAO,IAAI,CAAC,CAAC,CAAC,EAAE,MAAM,IAAI,IAAI,CAAC;AACjC,CAAC;AAED,uGAAuG;AACvG,MAAM,CAAC,KAAK,UAAU,UAAU,CAAC,CAAY,EAAE,KAAa;IAC1D,MAAM,CAAC,CAAC,KAAK,CAAC,gDAAgD,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;AACjF,CAAC"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { type HubService, type Trace } from "@wizeworks/lens-core";
|
|
2
|
+
import type { Queryable } from "../db/db.js";
|
|
3
|
+
export interface TraceQuery {
|
|
4
|
+
projectId: string;
|
|
5
|
+
/** Changed at or after (server clock). */
|
|
6
|
+
since?: number;
|
|
7
|
+
/** Started before. For paging back. */
|
|
8
|
+
before?: number;
|
|
9
|
+
/** Started at or after. For time windows. */
|
|
10
|
+
from?: number;
|
|
11
|
+
env?: string;
|
|
12
|
+
session?: string;
|
|
13
|
+
limit: number;
|
|
14
|
+
}
|
|
15
|
+
export declare function findTraceIds(q: Queryable, t: TraceQuery): Promise<string[]>;
|
|
16
|
+
/** Full traces, in the order of `ids`. */
|
|
17
|
+
export declare function loadTraces(q: Queryable, projectId: string, ids: readonly string[]): Promise<Trace[]>;
|
|
18
|
+
export declare const queryTraces: (q: Queryable, t: TraceQuery) => Promise<Trace[]>;
|
|
19
|
+
export declare function getTrace(q: Queryable, projectId: string, traceId: string): Promise<Trace | undefined>;
|
|
20
|
+
/** How many traces started in [from, to). */
|
|
21
|
+
export declare function countTraces(q: Queryable, projectId: string, from: number, to: number, env?: string): Promise<number>;
|
|
22
|
+
export declare function listServices(q: Queryable, projectId: string, now: number): Promise<HubService[]>;
|
|
23
|
+
export declare function environmentsOf(q: Queryable, projectId: string): Promise<string[]>;
|
|
24
|
+
export declare function countRows(q: Queryable, projectId: string): Promise<{
|
|
25
|
+
traces: number;
|
|
26
|
+
spans: number;
|
|
27
|
+
}>;
|
|
28
|
+
//# sourceMappingURL=trace-read.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"trace-read.d.ts","sourceRoot":"","sources":["../../src/repo/trace-read.ts"],"names":[],"mappings":"AAAA,OAAO,EAA6C,KAAK,UAAU,EAA6B,KAAK,KAAK,EAAE,MAAM,sBAAsB,CAAC;AACzI,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAE7C,MAAM,WAAW,UAAU;IACzB,SAAS,EAAE,MAAM,CAAC;IAClB,0CAA0C;IAC1C,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,uCAAuC;IACvC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,6CAA6C;IAC7C,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;CACf;AAID,wBAAsB,YAAY,CAAC,CAAC,EAAE,SAAS,EAAE,CAAC,EAAE,UAAU,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAejF;AAmBD,0CAA0C;AAC1C,wBAAsB,UAAU,CAAC,CAAC,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,EAAE,GAAG,EAAE,SAAS,MAAM,EAAE,GAAG,OAAO,CAAC,KAAK,EAAE,CAAC,CAS1G;AAED,eAAO,MAAM,WAAW,MAAa,SAAS,KAAK,UAAU,KAAG,OAAO,CAAC,KAAK,EAAE,CAAyD,CAAC;AAEzI,wBAAsB,QAAQ,CAAC,CAAC,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,KAAK,GAAG,SAAS,CAAC,CAG3G;AAED,6CAA6C;AAC7C,wBAAsB,WAAW,CAAC,CAAC,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,EAAE,GAAG,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAM1H;AASD,wBAAsB,YAAY,CAAC,CAAC,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,EAAE,CAAC,CAGtG;AAED,wBAAsB,cAAc,CAAC,CAAC,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAGvF;AAED,wBAAsB,SAAS,CAAC,CAAC,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC,CAG3G"}
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import { buildTrace, HUB_ONLINE_MS } from "@wizeworks/lens-core";
|
|
2
|
+
const CHUNK = 500;
|
|
3
|
+
export async function findTraceIds(q, t) {
|
|
4
|
+
const where = ["project_id = $1"];
|
|
5
|
+
const args = [t.projectId];
|
|
6
|
+
const add = (sql, v) => {
|
|
7
|
+
args.push(v);
|
|
8
|
+
where.push(sql.replace("?", `$${args.length}`));
|
|
9
|
+
};
|
|
10
|
+
if (t.since !== undefined)
|
|
11
|
+
add("updated_ms >= ?", t.since);
|
|
12
|
+
if (t.before !== undefined)
|
|
13
|
+
add("start_ms < ?", t.before);
|
|
14
|
+
if (t.from !== undefined)
|
|
15
|
+
add("start_ms >= ?", t.from);
|
|
16
|
+
if (t.env)
|
|
17
|
+
add("env = ?", t.env);
|
|
18
|
+
if (t.session)
|
|
19
|
+
add("trace_id IN (SELECT trace_id FROM spans WHERE project_id = $1 AND session = ?)", t.session);
|
|
20
|
+
args.push(t.limit);
|
|
21
|
+
const rows = await q.query(`SELECT trace_id FROM traces WHERE ${where.join(" AND ")} ORDER BY start_ms DESC LIMIT $${args.length}`, args);
|
|
22
|
+
return rows.map((r) => r.trace_id);
|
|
23
|
+
}
|
|
24
|
+
async function jsonByTrace(q, table, projectId, ids) {
|
|
25
|
+
const out = new Map();
|
|
26
|
+
for (let i = 0; i < ids.length; i += CHUNK) {
|
|
27
|
+
const part = ids.slice(i, i + CHUNK);
|
|
28
|
+
const rows = await q.query(`SELECT trace_id, json FROM ${table} WHERE project_id = $1 AND trace_id = ANY($2)`, [
|
|
29
|
+
projectId,
|
|
30
|
+
part,
|
|
31
|
+
]);
|
|
32
|
+
for (const r of rows) {
|
|
33
|
+
const list = out.get(r.trace_id);
|
|
34
|
+
if (list)
|
|
35
|
+
list.push(r.json);
|
|
36
|
+
else
|
|
37
|
+
out.set(r.trace_id, [r.json]);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
return out;
|
|
41
|
+
}
|
|
42
|
+
/** Full traces, in the order of `ids`. */
|
|
43
|
+
export async function loadTraces(q, projectId, ids) {
|
|
44
|
+
if (ids.length === 0)
|
|
45
|
+
return [];
|
|
46
|
+
const spans = await jsonByTrace(q, "spans", projectId, ids);
|
|
47
|
+
const logs = await jsonByTrace(q, "logs", projectId, ids);
|
|
48
|
+
return ids.map((id) => {
|
|
49
|
+
const s = (spans.get(id) ?? []).map((j) => JSON.parse(j));
|
|
50
|
+
const l = (logs.get(id) ?? []).map((j) => JSON.parse(j)).sort((a, b) => a.timeMs - b.timeMs);
|
|
51
|
+
return buildTrace(id, s, l, []);
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
export const queryTraces = async (q, t) => loadTraces(q, t.projectId, await findTraceIds(q, t));
|
|
55
|
+
export async function getTrace(q, projectId, traceId) {
|
|
56
|
+
const [trace] = await loadTraces(q, projectId, [traceId]);
|
|
57
|
+
return trace && trace.spanCount + trace.logs.length > 0 ? trace : undefined;
|
|
58
|
+
}
|
|
59
|
+
/** How many traces started in [from, to). */
|
|
60
|
+
export async function countTraces(q, projectId, from, to, env) {
|
|
61
|
+
const [row] = await q.query(`SELECT count(*)::int AS n FROM traces WHERE project_id = $1 AND start_ms >= $2 AND start_ms < $3 AND ($4::text = '' OR env = $4::text)`, [projectId, from, to, env ?? ""]);
|
|
62
|
+
return row?.n ?? 0;
|
|
63
|
+
}
|
|
64
|
+
export async function listServices(q, projectId, now) {
|
|
65
|
+
const rows = await q.query("SELECT via, info, first_seen, last_seen FROM services WHERE project_id = $1 ORDER BY last_seen DESC", [projectId]);
|
|
66
|
+
return rows.map((r) => ({ ...JSON.parse(r.info), via: r.via, firstSeenMs: r.first_seen, lastSeenMs: r.last_seen, online: now - r.last_seen <= HUB_ONLINE_MS }));
|
|
67
|
+
}
|
|
68
|
+
export async function environmentsOf(q, projectId) {
|
|
69
|
+
const rows = await q.query("SELECT environment AS e FROM services WHERE project_id = $1 UNION SELECT DISTINCT env FROM traces WHERE project_id = $1", [projectId]);
|
|
70
|
+
return rows.map((r) => r.e).filter(Boolean).sort();
|
|
71
|
+
}
|
|
72
|
+
export async function countRows(q, projectId) {
|
|
73
|
+
const n = async (table) => (await q.query(`SELECT count(*)::int AS n FROM ${table} WHERE project_id = $1`, [projectId]))[0]?.n ?? 0;
|
|
74
|
+
return { traces: await n("traces"), spans: await n("spans") };
|
|
75
|
+
}
|
|
76
|
+
//# sourceMappingURL=trace-read.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"trace-read.js","sourceRoot":"","sources":["../../src/repo/trace-read.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { HubWrite } from "@wizeworks/lens-hub/kit";
|
|
2
|
+
import type { Queryable } from "../db/db.js";
|
|
3
|
+
/** Save one batch for one project, in the caller's transaction. */
|
|
4
|
+
export declare function writeBatch(q: Queryable, projectId: string, w: HubWrite, now: number): Promise<void>;
|
|
5
|
+
/** Drop metric points older than each organization's retention. */
|
|
6
|
+
export declare function pruneMetricsByRetention(q: Queryable, now: number): Promise<void>;
|
|
7
|
+
/** Drop traces older than each organization's retention. Returns how many traces were dropped. */
|
|
8
|
+
export declare function pruneByRetention(q: Queryable, now: number): Promise<number>;
|
|
9
|
+
//# sourceMappingURL=trace-write.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"trace-write.d.ts","sourceRoot":"","sources":["../../src/repo/trace-write.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,yBAAyB,CAAC;AACxD,OAAO,KAAK,EAAM,SAAS,EAAE,MAAM,aAAa,CAAC;AAoCjD,mEAAmE;AACnE,wBAAsB,UAAU,CAAC,CAAC,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,EAAE,CAAC,EAAE,QAAQ,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAwBzG;AASD,mEAAmE;AACnE,wBAAsB,uBAAuB,CAAC,CAAC,EAAE,SAAS,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAOtF;AAED,kGAAkG;AAClG,wBAAsB,gBAAgB,CAAC,CAAC,EAAE,SAAS,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAejF"}
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import { createHash } from "node:crypto";
|
|
2
|
+
import { ATTR_BROWSER_SESSION, logKey, PG_DIALECT, pruneStatements, seriesKeyOf } from "@wizeworks/lens-core";
|
|
3
|
+
import { runStatements, stateOf } from "../settle.js";
|
|
4
|
+
import { pruneMetricRollups, writeMetricRollups } from "./metric-write.js";
|
|
5
|
+
const CHUNK = 200;
|
|
6
|
+
/** `INSERT ... VALUES ($1, $2), ($3, $4) ... <tail>` for many rows at once. */
|
|
7
|
+
async function insertMany(q, head, rows, tail) {
|
|
8
|
+
for (let i = 0; i < rows.length; i += CHUNK) {
|
|
9
|
+
const part = rows.slice(i, i + CHUNK);
|
|
10
|
+
const width = part[0].length;
|
|
11
|
+
const values = part.map((_, r) => `(${Array.from({ length: width }, (_, c) => `$${r * width + c + 1}`).join(", ")})`);
|
|
12
|
+
await q.query(`${head} VALUES ${values.join(", ")} ${tail}`, part.flat());
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
const sha1 = (text) => createHash("sha1").update(text).digest("hex");
|
|
16
|
+
const sessionOf = (s) => {
|
|
17
|
+
const v = s.attributes[ATTR_BROWSER_SESSION];
|
|
18
|
+
return typeof v === "string" && v ? v : null;
|
|
19
|
+
};
|
|
20
|
+
/** Trace rows: one per trace id, with the earliest start and latest end in this batch. */
|
|
21
|
+
function traceRows(w, projectId, now) {
|
|
22
|
+
const bounds = new Map();
|
|
23
|
+
const touch = (id, start, end) => {
|
|
24
|
+
const b = bounds.get(id);
|
|
25
|
+
bounds.set(id, b ? [Math.min(b[0], start), Math.max(b[1], end)] : [start, end]);
|
|
26
|
+
};
|
|
27
|
+
for (const s of w.spans)
|
|
28
|
+
touch(s.traceId, s.startMs, s.startMs + s.durationMs);
|
|
29
|
+
for (const { traceId, log } of w.logs)
|
|
30
|
+
touch(traceId, log.timeMs, log.timeMs);
|
|
31
|
+
const env = w.sender.environment ?? "";
|
|
32
|
+
return [...bounds].map(([id, [start, end]]) => [projectId, id, start, end, now, env]);
|
|
33
|
+
}
|
|
34
|
+
/** Save one batch for one project, in the caller's transaction. */
|
|
35
|
+
export async function writeBatch(q, projectId, w, now) {
|
|
36
|
+
const s = w.sender;
|
|
37
|
+
await q.query(`INSERT INTO services (project_id, service, environment, host, via, info, first_seen, last_seen) VALUES ($1, $2, $3, $4, $5, $6, $7, $7)
|
|
38
|
+
ON CONFLICT (project_id, service, environment, host) DO UPDATE SET via = EXCLUDED.via, info = EXCLUDED.info, last_seen = EXCLUDED.last_seen`, [projectId, s.service, s.environment ?? "", s.host ?? "", w.via, JSON.stringify(s), now]);
|
|
39
|
+
await insertMany(q, "INSERT INTO traces (project_id, trace_id, start_ms, end_ms, updated_ms, env)", traceRows(w, projectId, now), `
|
|
40
|
+
ON CONFLICT (project_id, trace_id) DO UPDATE SET start_ms = LEAST(traces.start_ms, EXCLUDED.start_ms),
|
|
41
|
+
end_ms = GREATEST(traces.end_ms, EXCLUDED.end_ms), updated_ms = EXCLUDED.updated_ms,
|
|
42
|
+
env = CASE WHEN traces.env = '' THEN EXCLUDED.env ELSE traces.env END`);
|
|
43
|
+
const spans = dedupe(w.spans, (x) => x.traceId + x.spanId).map((x) => [projectId, x.traceId, x.spanId, x.service, x.startMs, x.durationMs, sessionOf(x), JSON.stringify(x)]);
|
|
44
|
+
await insertMany(q, "INSERT INTO spans (project_id, trace_id, span_id, service, start_ms, duration_ms, session, json)", spans, `
|
|
45
|
+
ON CONFLICT (project_id, trace_id, span_id) DO UPDATE SET json = EXCLUDED.json, duration_ms = EXCLUDED.duration_ms`);
|
|
46
|
+
const logs = dedupe(w.logs.map(({ traceId, log }) => ({ traceId, log, key: createHash("sha1").update(logKey(log)).digest("hex") })), (l) => l.traceId + l.key).map((l) => [projectId, l.traceId, l.key, l.log.timeMs, JSON.stringify(l.log)]);
|
|
47
|
+
await insertMany(q, "INSERT INTO logs (project_id, trace_id, key, time_ms, json)", logs, "ON CONFLICT DO NOTHING");
|
|
48
|
+
const env = s.environment ?? "";
|
|
49
|
+
// The series key holds NUL separators, which Postgres text cannot store, so keep its hash.
|
|
50
|
+
const metrics = (w.metrics ?? []).map((p) => [projectId, p.timeMs, env, p.service, p.name, sha1(seriesKeyOf(p)), JSON.stringify(p)]);
|
|
51
|
+
await insertMany(q, "INSERT INTO metric_points (project_id, time_ms, env, service, name, series_key, json)", metrics, "");
|
|
52
|
+
await writeMetricRollups(q, projectId, env, w.metrics ?? [], now);
|
|
53
|
+
}
|
|
54
|
+
/** Postgres rejects one statement that updates the same row twice, so keep the last of each key. */
|
|
55
|
+
function dedupe(items, key) {
|
|
56
|
+
const map = new Map();
|
|
57
|
+
for (const t of items)
|
|
58
|
+
map.set(key(t), t);
|
|
59
|
+
return [...map.values()];
|
|
60
|
+
}
|
|
61
|
+
/** Drop metric points older than each organization's retention. */
|
|
62
|
+
export async function pruneMetricsByRetention(q, now) {
|
|
63
|
+
await q.query(`DELETE FROM metric_points m USING projects p, orgs o WHERE p.id = m.project_id AND o.id = p.org_id
|
|
64
|
+
AND m.time_ms < $1 - o.retention_days * 86400000.0`, [now]);
|
|
65
|
+
await pruneMetricRollups(q, now);
|
|
66
|
+
}
|
|
67
|
+
/** Drop traces older than each organization's retention. Returns how many traces were dropped. */
|
|
68
|
+
export async function pruneByRetention(q, now) {
|
|
69
|
+
const prune = async (x) => {
|
|
70
|
+
const doomed = await x.query(`SELECT t.project_id, t.trace_id, t.env, t.contrib, o.retention_days FROM traces t JOIN projects p ON p.id = t.project_id JOIN orgs o ON o.id = p.org_id
|
|
71
|
+
WHERE t.start_ms < $1 - o.retention_days * 86400000.0 LIMIT 5000`, [now]);
|
|
72
|
+
// Take their contributions out of the rollups and drop their facts first.
|
|
73
|
+
await runStatements(x, pruneStatements(PG_DIALECT, doomed.map((d) => stateOf(d, d.retention_days ?? 30)), now, true));
|
|
74
|
+
for (const table of ["spans", "logs", "traces"]) {
|
|
75
|
+
for (const d of doomed)
|
|
76
|
+
await x.query(`DELETE FROM ${table} WHERE project_id = $1 AND trace_id = $2`, [d.project_id, d.trace_id]);
|
|
77
|
+
}
|
|
78
|
+
return doomed.length;
|
|
79
|
+
};
|
|
80
|
+
return "tx" in q ? q.tx(prune) : prune(q);
|
|
81
|
+
}
|
|
82
|
+
//# sourceMappingURL=trace-write.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"trace-write.js","sourceRoot":"","sources":["../../src/repo/trace-write.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { Queryable } from "../db/db.js";
|
|
2
|
+
/** A signed-in person, as our routes see them. Accounts themselves are Better Auth's (auth/auth.ts). */
|
|
3
|
+
export interface User {
|
|
4
|
+
id: string;
|
|
5
|
+
email: string;
|
|
6
|
+
name: string;
|
|
7
|
+
emailVerified: boolean;
|
|
8
|
+
twoFactorEnabled: boolean;
|
|
9
|
+
}
|
|
10
|
+
export declare function userCount(q: Queryable): Promise<number>;
|
|
11
|
+
/** Emails of an organization's members, for alert emails. When mail really goes out, only confirmed ones. */
|
|
12
|
+
export declare const memberEmails: (q: Queryable, orgId: string, confirmedOnly: boolean) => Promise<string[]>;
|
|
13
|
+
//# sourceMappingURL=users.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"users.d.ts","sourceRoot":"","sources":["../../src/repo/users.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAE7C,wGAAwG;AACxG,MAAM,WAAW,IAAI;IACnB,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,aAAa,EAAE,OAAO,CAAC;IACvB,gBAAgB,EAAE,OAAO,CAAC;CAC3B;AAED,wBAAsB,SAAS,CAAC,CAAC,EAAE,SAAS,GAAG,OAAO,CAAC,MAAM,CAAC,CAG7D;AAED,6GAA6G;AAC7G,eAAO,MAAM,YAAY,MAAa,SAAS,SAAS,MAAM,iBAAiB,OAAO,KAAG,OAAO,CAAC,MAAM,EAAE,CAGtG,CAAC"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export async function userCount(q) {
|
|
2
|
+
const [row] = await q.query("SELECT count(*)::int AS n FROM users");
|
|
3
|
+
return row?.n ?? 0;
|
|
4
|
+
}
|
|
5
|
+
/** Emails of an organization's members, for alert emails. When mail really goes out, only confirmed ones. */
|
|
6
|
+
export const memberEmails = async (q, orgId, confirmedOnly) => (await q.query("SELECT u.email FROM members m JOIN users u ON u.id = m.user_id WHERE m.org_id = $1 AND (u.email_verified OR NOT $2)", [orgId, confirmedOnly])).map((r) => r.email);
|
|
7
|
+
//# sourceMappingURL=users.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"users.js","sourceRoot":"","sources":["../../src/repo/users.ts"],"names":[],"mappings":"AAWA,MAAM,CAAC,KAAK,UAAU,SAAS,CAAC,CAAY;IAC1C,MAAM,CAAC,GAAG,CAAC,GAAG,MAAM,CAAC,CAAC,KAAK,CAAgB,sCAAsC,CAAC,CAAC;IACnF,OAAO,GAAG,EAAE,CAAC,IAAI,CAAC,CAAC;AACrB,CAAC;AAED,6GAA6G;AAC7G,MAAM,CAAC,MAAM,YAAY,GAAG,KAAK,EAAE,CAAY,EAAE,KAAa,EAAE,aAAsB,EAAqB,EAAE,CAC3G,CAAC,MAAM,CAAC,CAAC,KAAK,CAAoB,qHAAqH,EAAE,CAAC,KAAK,EAAE,aAAa,CAAC,CAAC,CAAC,CAAC,GAAG,CACnL,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,CACf,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"alerts.d.ts","sourceRoot":"","sources":["../../src/routes/alerts.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,WAAW,CAAC;AAGrC,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAC;AAsGhD,wBAAgB,WAAW,CAAC,CAAC,EAAE,MAAM,CAAC,GAAG,CAAC,GAAG,IAAI,CAMhD"}
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
import { isAlertMetric, isMetricAlertStat, MAX_METRIC_NAME } from "@wizeworks/lens-core";
|
|
2
|
+
import { notify } from "../alerts/evaluate.js";
|
|
3
|
+
import { checkTarget } from "../alerts/notify.js";
|
|
4
|
+
import { requireProject } from "../auth/principal.js";
|
|
5
|
+
import { fail, readJsonBody, sendJson, str } from "../http/http.js";
|
|
6
|
+
import { memberEmails } from "../repo/users.js";
|
|
7
|
+
import { createRule, deleteRule, listEvents, listRules, ruleById, updateRule } from "../repo/alerts.js";
|
|
8
|
+
const WINDOWS = [5, 15, 60, 360, 1440].map((m) => m * 60_000);
|
|
9
|
+
const MAX_CHANNELS = 5;
|
|
10
|
+
const MAX_EMAILS = 20;
|
|
11
|
+
/** Email goes only to members of the organization with a confirmed address, so a rule cannot send mail to strangers. */
|
|
12
|
+
async function emailChannel(ctx, orgId, to) {
|
|
13
|
+
const allowed = new Set(await memberEmails(ctx.app.db, orgId, ctx.app.mailer.live));
|
|
14
|
+
const list = Array.isArray(to) ? [...new Set(to.filter((x) => typeof x === "string").map((x) => x.trim().toLowerCase()))] : [];
|
|
15
|
+
if (list.length === 0 || list.length > MAX_EMAILS)
|
|
16
|
+
fail(400, `Send to 1 to ${MAX_EMAILS} email addresses.`);
|
|
17
|
+
const stranger = list.find((e) => !allowed.has(e));
|
|
18
|
+
if (stranger)
|
|
19
|
+
fail(400, `${stranger} is not a member of this organization with a confirmed email.`);
|
|
20
|
+
return { kind: "email", to: list };
|
|
21
|
+
}
|
|
22
|
+
async function channelsOf(ctx, orgId, raw) {
|
|
23
|
+
const list = Array.isArray(raw) ? raw.slice(0, MAX_CHANNELS) : [];
|
|
24
|
+
const out = [];
|
|
25
|
+
for (const c of list) {
|
|
26
|
+
if (c.kind === "email") {
|
|
27
|
+
out.push(await emailChannel(ctx, orgId, c.to));
|
|
28
|
+
continue;
|
|
29
|
+
}
|
|
30
|
+
if ((c.kind !== "webhook" && c.kind !== "slack") || typeof c.url !== "string")
|
|
31
|
+
return fail(400, "Each channel needs kind (webhook, slack, or email) and url (or to).");
|
|
32
|
+
const problem = await checkTarget(c.url, ctx.app.config.allowPrivateWebhooks);
|
|
33
|
+
if (problem)
|
|
34
|
+
fail(400, `${c.url}: ${problem}`);
|
|
35
|
+
out.push({ kind: c.kind, url: c.url });
|
|
36
|
+
}
|
|
37
|
+
return out;
|
|
38
|
+
}
|
|
39
|
+
/** The metric part of a rule: for "metric" rules, the OpenTelemetry metric to read. */
|
|
40
|
+
function metricPart(b) {
|
|
41
|
+
if (b.metric !== "metric") {
|
|
42
|
+
if (!isAlertMetric(b.metric))
|
|
43
|
+
fail(400, "Pick a metric: error_rate, p95_ms, avg_ms, requests, new_errors, slow_queries, or metric.");
|
|
44
|
+
return { metric: b.metric, metricName: "", metricStat: "", metricService: "" };
|
|
45
|
+
}
|
|
46
|
+
const name = typeof b.metricName === "string" ? b.metricName.trim() : "";
|
|
47
|
+
if (!name || name.length > MAX_METRIC_NAME)
|
|
48
|
+
fail(400, "Set metricName to the metric to watch, for example process.cpu.utilization.");
|
|
49
|
+
const stat = b.metricStat ?? "avg";
|
|
50
|
+
if (!isMetricAlertStat(stat))
|
|
51
|
+
fail(400, "Pick a metricStat: last, avg, max, p95, p99, or rate.");
|
|
52
|
+
const service = typeof b.metricService === "string" ? b.metricService.trim().slice(0, 100) : "";
|
|
53
|
+
return { metric: "metric", metricName: name, metricStat: stat, metricService: service };
|
|
54
|
+
}
|
|
55
|
+
/** Check a rule from the request body. A change sends only what it changes: the rest comes from `current`. */
|
|
56
|
+
async function ruleInput(ctx, orgId, current) {
|
|
57
|
+
const b = { ...current, ...(await readJsonBody(ctx.req)) };
|
|
58
|
+
const metric = metricPart(b);
|
|
59
|
+
if (b.op !== ">" && b.op !== "<")
|
|
60
|
+
fail(400, 'Set op to ">" or "<".');
|
|
61
|
+
const threshold = Number(b.threshold);
|
|
62
|
+
if (!Number.isFinite(threshold))
|
|
63
|
+
fail(400, "Set a number for threshold.");
|
|
64
|
+
const windowMs = Number(b.windowMs ?? 5 * 60_000);
|
|
65
|
+
if (!WINDOWS.includes(windowMs))
|
|
66
|
+
fail(400, "Pick a window of 5, 15, 60, 360, or 1440 minutes.");
|
|
67
|
+
return {
|
|
68
|
+
name: str(b, "name").slice(0, 100),
|
|
69
|
+
...metric,
|
|
70
|
+
op: b.op,
|
|
71
|
+
threshold,
|
|
72
|
+
windowMs,
|
|
73
|
+
env: typeof b.env === "string" ? b.env.slice(0, 50) : "",
|
|
74
|
+
channels: await channelsOf(ctx, orgId, b.channels),
|
|
75
|
+
enabled: b.enabled !== false,
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
async function list(ctx) {
|
|
79
|
+
const { project } = await requireProject(ctx, ctx.params.project);
|
|
80
|
+
sendJson(ctx.res, 200, { rules: await listRules(ctx.app.db, project.id), events: await listEvents(ctx.app.db, project.id, 100) });
|
|
81
|
+
}
|
|
82
|
+
async function create(ctx) {
|
|
83
|
+
const { project, actor } = await requireProject(ctx, ctx.params.project, "write");
|
|
84
|
+
const id = await createRule(ctx.app.db, project.id, await ruleInput(ctx, project.orgId), actor, ctx.app.config.now());
|
|
85
|
+
sendJson(ctx.res, 201, await ruleById(ctx.app.db, project.id, id));
|
|
86
|
+
}
|
|
87
|
+
async function change(ctx) {
|
|
88
|
+
const { project } = await requireProject(ctx, ctx.params.project, "write");
|
|
89
|
+
const current = await ruleById(ctx.app.db, project.id, ctx.params.id);
|
|
90
|
+
if (!current)
|
|
91
|
+
fail(404, "Alert rule not found.");
|
|
92
|
+
await updateRule(ctx.app.db, project.id, ctx.params.id, await ruleInput(ctx, project.orgId, current));
|
|
93
|
+
sendJson(ctx.res, 200, await ruleById(ctx.app.db, project.id, ctx.params.id));
|
|
94
|
+
}
|
|
95
|
+
async function remove(ctx) {
|
|
96
|
+
const { project } = await requireProject(ctx, ctx.params.project, "write");
|
|
97
|
+
if (!(await deleteRule(ctx.app.db, project.id, ctx.params.id)))
|
|
98
|
+
fail(404, "Alert rule not found.");
|
|
99
|
+
sendJson(ctx.res, 200, { ok: true });
|
|
100
|
+
}
|
|
101
|
+
/** Send a test notice through the rule's channels now. */
|
|
102
|
+
async function test(ctx) {
|
|
103
|
+
const { project } = await requireProject(ctx, ctx.params.project, "write");
|
|
104
|
+
const rule = await ruleById(ctx.app.db, project.id, ctx.params.id);
|
|
105
|
+
if (!rule)
|
|
106
|
+
return fail(404, "Alert rule not found.");
|
|
107
|
+
sendJson(ctx.res, 200, { delivery: await notify(ctx.app, rule, "test", rule.lastValue, ctx.app.config.now()) });
|
|
108
|
+
}
|
|
109
|
+
export function alertRoutes(r) {
|
|
110
|
+
r.on("GET", "api/projects/:project/alerts", list)
|
|
111
|
+
.on("POST", "api/projects/:project/alerts", create)
|
|
112
|
+
.on("PATCH", "api/projects/:project/alerts/:id", change)
|
|
113
|
+
.on("DELETE", "api/projects/:project/alerts/:id", remove)
|
|
114
|
+
.on("POST", "api/projects/:project/alerts/:id/test", test);
|
|
115
|
+
}
|
|
116
|
+
//# sourceMappingURL=alerts.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"alerts.js","sourceRoot":"","sources":["../../src/routes/alerts.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { Ctx } from "../app.js";
|
|
2
|
+
import { type ProjectAccess } from "../auth/principal.js";
|
|
3
|
+
import type { Router } from "../http/router.js";
|
|
4
|
+
/** The project named by `?project=`, with access checked. */
|
|
5
|
+
export declare function projectOf(ctx: Ctx): Promise<ProjectAccess>;
|
|
6
|
+
export declare function dataRoutes(r: Router<Ctx>): void;
|
|
7
|
+
//# sourceMappingURL=data.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"data.d.ts","sourceRoot":"","sources":["../../src/routes/data.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,WAAW,CAAC;AACrC,OAAO,EAAe,KAAK,aAAa,EAAkB,MAAM,sBAAsB,CAAC;AAEvF,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAC;AAOhD,6DAA6D;AAC7D,wBAAsB,SAAS,CAAC,GAAG,EAAE,GAAG,GAAG,OAAO,CAAC,aAAa,CAAC,CAIhE;AA0DD,wBAAgB,UAAU,CAAC,CAAC,EAAE,MAAM,CAAC,GAAG,CAAC,GAAG,IAAI,CAK/C"}
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import { principalOf, requireProject } from "../auth/principal.js";
|
|
2
|
+
import { fail, sendJson } from "../http/http.js";
|
|
3
|
+
import { countRows, environmentsOf, getTrace, listServices, queryTraces } from "../repo/trace-read.js";
|
|
4
|
+
const DAY_MS = 86_400_000;
|
|
5
|
+
const clamp = (v, min, max) => Math.min(max, Math.max(min, v));
|
|
6
|
+
const num = (p, k) => (p.has(k) && Number.isFinite(Number(p.get(k))) ? Number(p.get(k)) : undefined);
|
|
7
|
+
/** The project named by `?project=`, with access checked. */
|
|
8
|
+
export async function projectOf(ctx) {
|
|
9
|
+
const id = ctx.url.searchParams.get("project");
|
|
10
|
+
if (!id)
|
|
11
|
+
return fail(400, "Add ?project=<project id>.");
|
|
12
|
+
return requireProject(ctx, id);
|
|
13
|
+
}
|
|
14
|
+
async function retentionMs(ctx) {
|
|
15
|
+
const id = ctx.url.searchParams.get("project");
|
|
16
|
+
const p = id ? await principalOf(ctx) : undefined;
|
|
17
|
+
if (!id || !p)
|
|
18
|
+
return ctx.app.config.retentionDays * DAY_MS;
|
|
19
|
+
const access = await requireProject(ctx, id).catch(() => undefined);
|
|
20
|
+
if (!access)
|
|
21
|
+
return ctx.app.config.retentionDays * DAY_MS;
|
|
22
|
+
const [row] = await ctx.app.db.query("SELECT retention_days AS d FROM orgs WHERE id = $1", [access.project.orgId]);
|
|
23
|
+
return (row?.d ?? ctx.app.config.retentionDays) * DAY_MS;
|
|
24
|
+
}
|
|
25
|
+
async function info(ctx) {
|
|
26
|
+
const value = {
|
|
27
|
+
mode: "cloud",
|
|
28
|
+
capabilities: ["environments", "registry", "accounts", "alerts", "sharing", "serverStats", "metrics", "serverMetrics"],
|
|
29
|
+
service: "WizeLens Cloud",
|
|
30
|
+
version: ctx.app.version,
|
|
31
|
+
runtime: `node ${process.version}`,
|
|
32
|
+
mcp: true,
|
|
33
|
+
startedMs: ctx.app.startedMs,
|
|
34
|
+
storage: { kind: ctx.app.db.kind === "postgres" ? "postgres" : "sqlite", maxAgeMs: await retentionMs(ctx) },
|
|
35
|
+
redactKeys: [...ctx.app.config.redactKeys],
|
|
36
|
+
};
|
|
37
|
+
sendJson(ctx.res, 200, value);
|
|
38
|
+
}
|
|
39
|
+
async function traces(ctx) {
|
|
40
|
+
const { project } = await projectOf(ctx);
|
|
41
|
+
const p = ctx.url.searchParams;
|
|
42
|
+
const full = p.get("full") === "true";
|
|
43
|
+
const q = { projectId: project.id, limit: clamp(num(p, "limit") ?? (full ? 1000 : 50), 1, full ? 5000 : 1000) };
|
|
44
|
+
q.since = num(p, "since");
|
|
45
|
+
q.before = num(p, "before");
|
|
46
|
+
q.env = p.get("env") || undefined;
|
|
47
|
+
q.session = p.get("session") || undefined;
|
|
48
|
+
const list = await queryTraces(ctx.app.db, q);
|
|
49
|
+
sendJson(ctx.res, 200, full ? list : list.map(({ spans: _s, logs: _l, remotes: _r, ...summary }) => summary));
|
|
50
|
+
}
|
|
51
|
+
async function trace(ctx) {
|
|
52
|
+
const { project } = await projectOf(ctx);
|
|
53
|
+
const t = await getTrace(ctx.app.db, project.id, ctx.params.id);
|
|
54
|
+
if (!t)
|
|
55
|
+
fail(404, "Trace not found.");
|
|
56
|
+
sendJson(ctx.res, 200, t);
|
|
57
|
+
}
|
|
58
|
+
async function services(ctx) {
|
|
59
|
+
const { project } = await projectOf(ctx);
|
|
60
|
+
const db = ctx.app.db;
|
|
61
|
+
sendJson(ctx.res, 200, {
|
|
62
|
+
services: await listServices(db, project.id, ctx.app.config.now()),
|
|
63
|
+
environments: await environmentsOf(db, project.id),
|
|
64
|
+
projects: [],
|
|
65
|
+
...(await countRows(db, project.id)),
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
export function dataRoutes(r) {
|
|
69
|
+
r.on("GET", "api/info", info)
|
|
70
|
+
.on("GET", "api/traces", traces)
|
|
71
|
+
.on("GET", "api/traces/:id", trace)
|
|
72
|
+
.on("GET", "api/services", services);
|
|
73
|
+
}
|
|
74
|
+
//# sourceMappingURL=data.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"data.js","sourceRoot":"","sources":["../../src/routes/data.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,WAAW,EAAsB,cAAc,EAAE,MAAM,sBAAsB,CAAC;AACvF,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,iBAAiB,CAAC;AAEjD,OAAO,EAAE,SAAS,EAAE,cAAc,EAAE,QAAQ,EAAE,YAAY,EAAE,WAAW,EAAmB,MAAM,uBAAuB,CAAC;AAExH,MAAM,MAAM,GAAG,UAAU,CAAC;AAC1B,MAAM,KAAK,GAAG,CAAC,CAAS,EAAE,GAAW,EAAE,GAAW,EAAE,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,CAAC;AACvF,MAAM,GAAG,GAAG,CAAC,CAAkB,EAAE,CAAS,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC;AAE9H,6DAA6D;AAC7D,MAAM,CAAC,KAAK,UAAU,SAAS,CAAC,GAAQ;IACtC,MAAM,EAAE,GAAG,GAAG,CAAC,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;IAC/C,IAAI,CAAC,EAAE;QAAE,OAAO,IAAI,CAAC,GAAG,EAAE,4BAA4B,CAAC,CAAC;IACxD,OAAO,cAAc,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC;AACjC,CAAC;AAED,KAAK,UAAU,WAAW,CAAC,GAAQ;IACjC,MAAM,EAAE,GAAG,GAAG,CAAC,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;IAC/C,MAAM,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,MAAM,WAAW,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;IAClD,IAAI,CAAC,EAAE,IAAI,CAAC,CAAC;QAAE,OAAO,GAAG,CAAC,GAAG,CAAC,MAAM,CAAC,aAAa,GAAG,MAAM,CAAC;IAC5D,MAAM,MAAM,GAAG,MAAM,cAAc,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,SAAS,CAAC,CAAC;IACpE,IAAI,CAAC,MAAM;QAAE,OAAO,GAAG,CAAC,GAAG,CAAC,MAAM,CAAC,aAAa,GAAG,MAAM,CAAC;IAC1D,MAAM,CAAC,GAAG,CAAC,GAAG,MAAM,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC,KAAK,CAAgB,oDAAoD,EAAE,CAAC,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC;IAClI,OAAO,CAAC,GAAG,EAAE,CAAC,IAAI,GAAG,CAAC,GAAG,CAAC,MAAM,CAAC,aAAa,CAAC,GAAG,MAAM,CAAC;AAC3D,CAAC;AAED,KAAK,UAAU,IAAI,CAAC,GAAQ;IAC1B,MAAM,KAAK,GAAgB;QACzB,IAAI,EAAE,OAAO;QACb,YAAY,EAAE,CAAC,cAAc,EAAE,UAAU,EAAE,UAAU,EAAE,QAAQ,EAAE,SAAS,EAAE,aAAa,EAAE,SAAS,EAAE,eAAe,CAAC;QACtH,OAAO,EAAE,gBAAgB;QACzB,OAAO,EAAE,GAAG,CAAC,GAAG,CAAC,OAAO;QACxB,OAAO,EAAE,QAAQ,OAAO,CAAC,OAAO,EAAE;QAClC,GAAG,EAAE,IAAI;QACT,SAAS,EAAE,GAAG,CAAC,GAAG,CAAC,SAAS;QAC5B,OAAO,EAAE,EAAE,IAAI,EAAE,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC,IAAI,KAAK,UAAU,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,QAAQ,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC,GAAG,CAAC,EAAE;QAC3G,UAAU,EAAE,CAAC,GAAG,GAAG,CAAC,GAAG,CAAC,MAAM,CAAC,UAAU,CAAC;KAC3C,CAAC;IACF,QAAQ,CAAC,GAAG,CAAC,GAAG,EAAE,GAAG,EAAE,KAAK,CAAC,CAAC;AAChC,CAAC;AAED,KAAK,UAAU,MAAM,CAAC,GAAQ;IAC5B,MAAM,EAAE,OAAO,EAAE,GAAG,MAAM,SAAS,CAAC,GAAG,CAAC,CAAC;IACzC,MAAM,CAAC,GAAG,GAAG,CAAC,GAAG,CAAC,YAAY,CAAC;IAC/B,MAAM,IAAI,GAAG,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,KAAK,MAAM,CAAC;IACtC,MAAM,CAAC,GAAe,EAAE,SAAS,EAAE,OAAO,CAAC,EAAE,EAAE,KAAK,EAAE,KAAK,CAAC,GAAG,CAAC,CAAC,EAAE,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC;IAC5H,CAAC,CAAC,KAAK,GAAG,GAAG,CAAC,CAAC,EAAE,OAAO,CAAC,CAAC;IAC1B,CAAC,CAAC,MAAM,GAAG,GAAG,CAAC,CAAC,EAAE,QAAQ,CAAC,CAAC;IAC5B,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,SAAS,CAAC;IAClC,CAAC,CAAC,OAAO,GAAG,CAAC,CAAC,GAAG,CAAC,SAAS,CAAC,IAAI,SAAS,CAAC;IAC1C,MAAM,IAAI,GAAG,MAAM,WAAW,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC;IAC9C,QAAQ,CAAC,GAAG,CAAC,GAAG,EAAE,GAAG,EAAE,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,KAAK,EAAE,EAAE,EAAE,IAAI,EAAE,EAAE,EAAE,OAAO,EAAE,EAAE,EAAE,GAAG,OAAO,EAAE,EAAE,EAAE,CAAC,OAAO,CAAC,CAAC,CAAC;AAChH,CAAC;AAED,KAAK,UAAU,KAAK,CAAC,GAAQ;IAC3B,MAAM,EAAE,OAAO,EAAE,GAAG,MAAM,SAAS,CAAC,GAAG,CAAC,CAAC;IACzC,MAAM,CAAC,GAAG,MAAM,QAAQ,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,EAAE,OAAO,CAAC,EAAE,EAAE,GAAG,CAAC,MAAM,CAAC,EAAG,CAAC,CAAC;IACjE,IAAI,CAAC,CAAC;QAAE,IAAI,CAAC,GAAG,EAAE,kBAAkB,CAAC,CAAC;IACtC,QAAQ,CAAC,GAAG,CAAC,GAAG,EAAE,GAAG,EAAE,CAAC,CAAC,CAAC;AAC5B,CAAC;AAED,KAAK,UAAU,QAAQ,CAAC,GAAQ;IAC9B,MAAM,EAAE,OAAO,EAAE,GAAG,MAAM,SAAS,CAAC,GAAG,CAAC,CAAC;IACzC,MAAM,EAAE,GAAG,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC;IACtB,QAAQ,CAAC,GAAG,CAAC,GAAG,EAAE,GAAG,EAAE;QACrB,QAAQ,EAAE,MAAM,YAAY,CAAC,EAAE,EAAE,OAAO,CAAC,EAAE,EAAE,GAAG,CAAC,GAAG,CAAC,MAAM,CAAC,GAAG,EAAE,CAAC;QAClE,YAAY,EAAE,MAAM,cAAc,CAAC,EAAE,EAAE,OAAO,CAAC,EAAE,CAAC;QAClD,QAAQ,EAAE,EAAE;QACZ,GAAG,CAAC,MAAM,SAAS,CAAC,EAAE,EAAE,OAAO,CAAC,EAAE,CAAC,CAAC;KACrC,CAAC,CAAC;AACL,CAAC;AAED,MAAM,UAAU,UAAU,CAAC,CAAc;IACvC,CAAC,CAAC,EAAE,CAAC,KAAK,EAAE,UAAU,EAAE,IAAI,CAAC;SAC1B,EAAE,CAAC,KAAK,EAAE,YAAY,EAAE,MAAM,CAAC;SAC/B,EAAE,CAAC,KAAK,EAAE,gBAAgB,EAAE,KAAK,CAAC;SAClC,EAAE,CAAC,KAAK,EAAE,cAAc,EAAE,QAAQ,CAAC,CAAC;AACzC,CAAC"}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import type { Ctx } from "../app.js";
|
|
2
|
+
import { Router } from "../http/router.js";
|
|
3
|
+
/** Every route below `/_wizelens/`, except ingest and OTLP (they use ingest keys and are matched first). */
|
|
4
|
+
export declare function allRoutes(): Router<Ctx>;
|
|
5
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/routes/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,WAAW,CAAC;AACrC,OAAO,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAC;AAW3C,4GAA4G;AAC5G,wBAAgB,SAAS,IAAI,MAAM,CAAC,GAAG,CAAC,CAYvC"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { Router } from "../http/router.js";
|
|
2
|
+
import { alertRoutes } from "./alerts.js";
|
|
3
|
+
import { meRoutes } from "./me.js";
|
|
4
|
+
import { mcpRoutes } from "./mcp.js";
|
|
5
|
+
import { shareRoutes } from "./shares.js";
|
|
6
|
+
import { dataRoutes } from "./data.js";
|
|
7
|
+
import { modelRoutes } from "./models.js";
|
|
8
|
+
import { notifyRoutes } from "./notify.js";
|
|
9
|
+
import { orgRoutes } from "./orgs.js";
|
|
10
|
+
import { projectRoutes } from "./projects.js";
|
|
11
|
+
/** Every route below `/_wizelens/`, except ingest and OTLP (they use ingest keys and are matched first). */
|
|
12
|
+
export function allRoutes() {
|
|
13
|
+
const r = new Router();
|
|
14
|
+
meRoutes(r);
|
|
15
|
+
notifyRoutes(r);
|
|
16
|
+
orgRoutes(r);
|
|
17
|
+
projectRoutes(r);
|
|
18
|
+
dataRoutes(r);
|
|
19
|
+
modelRoutes(r);
|
|
20
|
+
alertRoutes(r);
|
|
21
|
+
shareRoutes(r);
|
|
22
|
+
mcpRoutes(r);
|
|
23
|
+
return r;
|
|
24
|
+
}
|
|
25
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/routes/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAC;AAC3C,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAC1C,OAAO,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AACnC,OAAO,EAAE,SAAS,EAAE,MAAM,UAAU,CAAC;AACrC,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAC1C,OAAO,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;AACvC,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAC1C,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAC3C,OAAO,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AACtC,OAAO,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAE9C,4GAA4G;AAC5G,MAAM,UAAU,SAAS;IACvB,MAAM,CAAC,GAAG,IAAI,MAAM,EAAO,CAAC;IAC5B,QAAQ,CAAC,CAAC,CAAC,CAAC;IACZ,YAAY,CAAC,CAAC,CAAC,CAAC;IAChB,SAAS,CAAC,CAAC,CAAC,CAAC;IACb,aAAa,CAAC,CAAC,CAAC,CAAC;IACjB,UAAU,CAAC,CAAC,CAAC,CAAC;IACd,WAAW,CAAC,CAAC,CAAC,CAAC;IACf,WAAW,CAAC,CAAC,CAAC,CAAC;IACf,WAAW,CAAC,CAAC,CAAC,CAAC;IACf,SAAS,CAAC,CAAC,CAAC,CAAC;IACb,OAAO,CAAC,CAAC;AACX,CAAC"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { Ctx } from "../app.js";
|
|
2
|
+
import type { RateLimiter } from "../http/limiter.js";
|
|
3
|
+
import { type OtlpSignal } from "@wizeworks/lens-hub/kit";
|
|
4
|
+
/** `POST api/ingest`: a WizeLens add-on batch. */
|
|
5
|
+
export declare function ingestBatch(ctx: Ctx, limiter: RateLimiter): Promise<void>;
|
|
6
|
+
/** `POST /v1/traces` and `/v1/logs`: OpenTelemetry apps. */
|
|
7
|
+
export declare function ingestOtlp(ctx: Ctx, signal: OtlpSignal, limiter: RateLimiter): Promise<void>;
|
|
8
|
+
//# sourceMappingURL=ingest.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ingest.d.ts","sourceRoot":"","sources":["../../src/routes/ingest.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,WAAW,CAAC;AAErC,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAGtD,OAAO,EAA6B,KAAK,UAAU,EAAoC,MAAM,yBAAyB,CAAC;AAevH,kDAAkD;AAClD,wBAAsB,WAAW,CAAC,GAAG,EAAE,GAAG,EAAE,OAAO,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC,CAW/E;AAED,4DAA4D;AAC5D,wBAAsB,UAAU,CAAC,GAAG,EAAE,GAAG,EAAE,MAAM,EAAE,UAAU,EAAE,OAAO,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC,CAGlG"}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { bearerOf, fail } from "../http/http.js";
|
|
2
|
+
import { keyByToken } from "../repo/projects.js";
|
|
3
|
+
import { writeBatch } from "../repo/trace-write.js";
|
|
4
|
+
import { handleOtlp, parseIngest, parseJson, readBody } from "@wizeworks/lens-hub/kit";
|
|
5
|
+
/** The project an ingest key writes to. Add-ons send it as WIZELENS_HUB_TOKEN; OTLP apps as a bearer header. */
|
|
6
|
+
async function ingestProject(ctx, limiter) {
|
|
7
|
+
const token = bearerOf(ctx.req);
|
|
8
|
+
if (!token?.startsWith("wl_ik_"))
|
|
9
|
+
return fail(401, "Send an ingest key: Authorization: Bearer wl_ik_...");
|
|
10
|
+
const key = await keyByToken(ctx.app.db, token, ctx.app.config.now());
|
|
11
|
+
if (!key || key.kind !== "ingest")
|
|
12
|
+
return fail(401, "This ingest key is not valid.");
|
|
13
|
+
if (!limiter.take(key.id))
|
|
14
|
+
fail(429, "Too many calls for this key. Slow down and retry.");
|
|
15
|
+
return key.projectIds[0];
|
|
16
|
+
}
|
|
17
|
+
const save = (ctx, projectId) => (w) => ctx.app.db.tx((q) => writeBatch(q, projectId, w, ctx.app.config.now()));
|
|
18
|
+
/** `POST api/ingest`: a WizeLens add-on batch. */
|
|
19
|
+
export async function ingestBatch(ctx, limiter) {
|
|
20
|
+
const projectId = await ingestProject(ctx, limiter);
|
|
21
|
+
let w;
|
|
22
|
+
try {
|
|
23
|
+
w = parseIngest(parseJson(await readBody(ctx.req)), ctx.app.config.redactKeys);
|
|
24
|
+
}
|
|
25
|
+
catch {
|
|
26
|
+
return fail(400, "The body is not valid JSON.");
|
|
27
|
+
}
|
|
28
|
+
if (!w)
|
|
29
|
+
fail(400, "sender.service is required.");
|
|
30
|
+
await save(ctx, projectId)(w);
|
|
31
|
+
ctx.res.writeHead(204).end();
|
|
32
|
+
}
|
|
33
|
+
/** `POST /v1/traces` and `/v1/logs`: OpenTelemetry apps. */
|
|
34
|
+
export async function ingestOtlp(ctx, signal, limiter) {
|
|
35
|
+
const projectId = await ingestProject(ctx, limiter);
|
|
36
|
+
await handleOtlp(signal, ctx.req, ctx.res, save(ctx, projectId), ctx.app.config.redactKeys);
|
|
37
|
+
}
|
|
38
|
+
//# sourceMappingURL=ingest.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ingest.js","sourceRoot":"","sources":["../../src/routes/ingest.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,QAAQ,EAAE,IAAI,EAAE,MAAM,iBAAiB,CAAC;AAEjD,OAAO,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AACjD,OAAO,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAC;AACpD,OAAO,EAAE,UAAU,EAAkC,WAAW,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,yBAAyB,CAAC;AAEvH,gHAAgH;AAChH,KAAK,UAAU,aAAa,CAAC,GAAQ,EAAE,OAAoB;IACzD,MAAM,KAAK,GAAG,QAAQ,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IAChC,IAAI,CAAC,KAAK,EAAE,UAAU,CAAC,QAAQ,CAAC;QAAE,OAAO,IAAI,CAAC,GAAG,EAAE,qDAAqD,CAAC,CAAC;IAC1G,MAAM,GAAG,GAAG,MAAM,UAAU,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,EAAE,KAAK,EAAE,GAAG,CAAC,GAAG,CAAC,MAAM,CAAC,GAAG,EAAE,CAAC,CAAC;IACtE,IAAI,CAAC,GAAG,IAAI,GAAG,CAAC,IAAI,KAAK,QAAQ;QAAE,OAAO,IAAI,CAAC,GAAG,EAAE,+BAA+B,CAAC,CAAC;IACrF,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC;QAAE,IAAI,CAAC,GAAG,EAAE,mDAAmD,CAAC,CAAC;IAC1F,OAAO,GAAG,CAAC,UAAU,CAAC,CAAC,CAAE,CAAC;AAC5B,CAAC;AAED,MAAM,IAAI,GAAG,CAAC,GAAQ,EAAE,SAAiB,EAAE,EAAE,CAAC,CAAC,CAAW,EAAE,EAAE,CAC5D,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,UAAU,CAAC,CAAC,EAAE,SAAS,EAAE,CAAC,EAAE,GAAG,CAAC,GAAG,CAAC,MAAM,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC;AAE1E,kDAAkD;AAClD,MAAM,CAAC,KAAK,UAAU,WAAW,CAAC,GAAQ,EAAE,OAAoB;IAC9D,MAAM,SAAS,GAAG,MAAM,aAAa,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC;IACpD,IAAI,CAAkB,CAAC;IACvB,IAAI,CAAC;QACH,CAAC,GAAG,WAAW,CAAC,SAAS,CAAC,MAAM,QAAQ,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,EAAE,GAAG,CAAC,GAAG,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC;IACjF,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC,GAAG,EAAE,6BAA6B,CAAC,CAAC;IAClD,CAAC;IACD,IAAI,CAAC,CAAC;QAAE,IAAI,CAAC,GAAG,EAAE,6BAA6B,CAAC,CAAC;IACjD,MAAM,IAAI,CAAC,GAAG,EAAE,SAAS,CAAC,CAAC,CAAE,CAAC,CAAC;IAC/B,GAAG,CAAC,GAAG,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,CAAC;AAC/B,CAAC;AAED,4DAA4D;AAC5D,MAAM,CAAC,KAAK,UAAU,UAAU,CAAC,GAAQ,EAAE,MAAkB,EAAE,OAAoB;IACjF,MAAM,SAAS,GAAG,MAAM,aAAa,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC;IACpD,MAAM,UAAU,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,EAAE,GAAG,CAAC,GAAG,EAAE,IAAI,CAAC,GAAG,EAAE,SAAS,CAAC,EAAE,GAAG,CAAC,GAAG,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC;AAC9F,CAAC"}
|