@alchemy.run/axiom 0.0.0 → 2.0.0-beta.84

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.
Files changed (83) hide show
  1. package/LICENSE +201 -0
  2. package/README.md +54 -4
  3. package/lib/Annotation.d.ts +51 -0
  4. package/lib/Annotation.d.ts.map +1 -0
  5. package/lib/Annotation.js +97 -0
  6. package/lib/Annotation.js.map +1 -0
  7. package/lib/ApiToken.d.ts +64 -0
  8. package/lib/ApiToken.d.ts.map +1 -0
  9. package/lib/ApiToken.js +123 -0
  10. package/lib/ApiToken.js.map +1 -0
  11. package/lib/AuthProvider.d.ts +40 -0
  12. package/lib/AuthProvider.d.ts.map +1 -0
  13. package/lib/AuthProvider.js +99 -0
  14. package/lib/AuthProvider.js.map +1 -0
  15. package/lib/Chart.d.ts +130 -0
  16. package/lib/Chart.d.ts.map +1 -0
  17. package/lib/Chart.js +14 -0
  18. package/lib/Chart.js.map +1 -0
  19. package/lib/Contributions.d.ts +7 -0
  20. package/lib/Contributions.d.ts.map +1 -0
  21. package/lib/Contributions.js +6 -0
  22. package/lib/Contributions.js.map +1 -0
  23. package/lib/Credentials.d.ts +10 -0
  24. package/lib/Credentials.d.ts.map +1 -0
  25. package/lib/Credentials.js +30 -0
  26. package/lib/Credentials.js.map +1 -0
  27. package/lib/Dashboard.d.ts +112 -0
  28. package/lib/Dashboard.d.ts.map +1 -0
  29. package/lib/Dashboard.js +157 -0
  30. package/lib/Dashboard.js.map +1 -0
  31. package/lib/Dataset.d.ts +120 -0
  32. package/lib/Dataset.d.ts.map +1 -0
  33. package/lib/Dataset.js +215 -0
  34. package/lib/Dataset.js.map +1 -0
  35. package/lib/Monitor.d.ts +76 -0
  36. package/lib/Monitor.d.ts.map +1 -0
  37. package/lib/Monitor.js +126 -0
  38. package/lib/Monitor.js.map +1 -0
  39. package/lib/Notifier.d.ts +65 -0
  40. package/lib/Notifier.d.ts.map +1 -0
  41. package/lib/Notifier.js +112 -0
  42. package/lib/Notifier.js.map +1 -0
  43. package/lib/OtelHeaders.d.ts +9 -0
  44. package/lib/OtelHeaders.d.ts.map +1 -0
  45. package/lib/OtelHeaders.js +9 -0
  46. package/lib/OtelHeaders.js.map +1 -0
  47. package/lib/Providers.d.ts +15 -0
  48. package/lib/Providers.d.ts.map +1 -0
  49. package/lib/Providers.js +34 -0
  50. package/lib/Providers.js.map +1 -0
  51. package/lib/Telemetry.d.ts +66 -0
  52. package/lib/Telemetry.d.ts.map +1 -0
  53. package/lib/Telemetry.js +68 -0
  54. package/lib/Telemetry.js.map +1 -0
  55. package/lib/View.d.ts +57 -0
  56. package/lib/View.d.ts.map +1 -0
  57. package/lib/View.js +100 -0
  58. package/lib/View.js.map +1 -0
  59. package/lib/VirtualField.d.ts +44 -0
  60. package/lib/VirtualField.d.ts.map +1 -0
  61. package/lib/VirtualField.js +97 -0
  62. package/lib/VirtualField.js.map +1 -0
  63. package/lib/index.d.ts +14 -0
  64. package/lib/index.d.ts.map +1 -0
  65. package/lib/index.js +14 -0
  66. package/lib/index.js.map +1 -0
  67. package/package.json +53 -3
  68. package/src/Annotation.ts +121 -0
  69. package/src/ApiToken.ts +148 -0
  70. package/src/AuthProvider.ts +135 -0
  71. package/src/Chart.ts +156 -0
  72. package/src/Contributions.ts +9 -0
  73. package/src/Credentials.ts +68 -0
  74. package/src/Dashboard.ts +192 -0
  75. package/src/Dataset.ts +326 -0
  76. package/src/Monitor.ts +148 -0
  77. package/src/Notifier.ts +136 -0
  78. package/src/OtelHeaders.ts +9 -0
  79. package/src/Providers.ts +60 -0
  80. package/src/Telemetry.ts +116 -0
  81. package/src/View.ts +130 -0
  82. package/src/VirtualField.ts +123 -0
  83. package/src/index.ts +13 -0
@@ -0,0 +1,112 @@
1
+ import * as Axiom from "@distilled.cloud/axiom";
2
+ import * as Provider from "alchemy/Provider";
3
+ import { Resource } from "alchemy/Resource";
4
+ import * as Effect from "effect/Effect";
5
+ /**
6
+ * An Axiom notifier — an alert destination (Slack, email, PagerDuty,
7
+ * Opsgenie, Discord, Microsoft Teams, generic webhook, or a fully custom
8
+ * webhook with templated body/headers) that {@link Monitor monitors} target
9
+ * via `notifierIds`. Exactly one channel under `properties` should be set.
10
+ * @see https://axiom.co/docs/monitor-data/notifiers
11
+ *
12
+ * ### Creating a Notifier
13
+ * **Example:** Slack incoming webhook
14
+ * ```typescript
15
+ * const slack = yield* Axiom.Notifier("ops-slack", {
16
+ * name: "ops-channel",
17
+ * properties: {
18
+ * slack: { slackUrl: process.env.SLACK_WEBHOOK_URL! },
19
+ * },
20
+ * });
21
+ * ```
22
+ *
23
+ * **Example:** Email distribution list
24
+ * ```typescript
25
+ * yield* Axiom.Notifier("ops-email", {
26
+ * name: "ops-team",
27
+ * properties: { email: { emails: ["sre@example.com", "oncall@example.com"] } },
28
+ * });
29
+ * ```
30
+ *
31
+ * **Example:** PagerDuty integration
32
+ * ```typescript
33
+ * yield* Axiom.Notifier("pagerduty", {
34
+ * name: "primary-oncall",
35
+ * properties: {
36
+ * pagerduty: { routingKey: process.env.PAGERDUTY_ROUTING_KEY!, token: "" },
37
+ * },
38
+ * });
39
+ * ```
40
+ *
41
+ * **Example:** Custom webhook with templated body
42
+ * ```typescript
43
+ * yield* Axiom.Notifier("incident-webhook", {
44
+ * name: "incident.io",
45
+ * properties: {
46
+ * customWebhook: {
47
+ * url: "https://api.incident.io/v2/alert_events",
48
+ * headers: { "Content-Type": "application/json" },
49
+ * secretHeaders: { Authorization: `Bearer ${process.env.INCIDENT_TOKEN}` },
50
+ * body: '{"title": "{{.Monitor.Name}}", "status": "firing"}',
51
+ * },
52
+ * },
53
+ * });
54
+ * ```
55
+ *
56
+ * @resource
57
+ * @product Monitor
58
+ */
59
+ export const Notifier = Resource("Axiom.Notifier");
60
+ export const NotifierProvider = () => Provider.effect(Notifier, Effect.gen(function* () {
61
+ const create = yield* Axiom.createNotifier;
62
+ const update = yield* Axiom.updateNotifier;
63
+ const get = yield* Axiom.getNotifier;
64
+ const listNotifiers = yield* Axiom.getNotifiers;
65
+ const del = yield* Axiom.deleteNotifier;
66
+ return {
67
+ stables: ["id"],
68
+ // Enumerate every notifier in the org. Axiom exposes a single
69
+ // account-wide `GET /v2/notifiers` collection op (no pagination), so we
70
+ // fetch it once and hydrate each row into the exact `read` Attributes
71
+ // shape (`CreateNotifierOutput & { id: string }`) — directly usable by
72
+ // `delete` with no follow-up get.
73
+ list: () => Effect.gen(function* () {
74
+ const notifiers = yield* listNotifiers({});
75
+ return notifiers.map((n) => ({ ...n, id: n.id ?? "" }));
76
+ }),
77
+ reconcile: Effect.fn(function* ({ news, output }) {
78
+ // Observe — Axiom assigns the notifier id server-side, so the
79
+ // only handle to a previously-created notifier is the cached
80
+ // `output.id`. Probe for live state with that id; treat NotFound
81
+ // (deleted out-of-band) as "no observed state" so we converge
82
+ // by re-creating.
83
+ const observed = output?.id
84
+ ? yield* get({ id: output.id }).pipe(Effect.catchTag("NotFound", () => Effect.succeed(undefined)))
85
+ : undefined;
86
+ // Ensure — POST mints a new notifier. The Axiom create response
87
+ // sometimes omits `id` on the body; default to "" to keep the
88
+ // attribute shape stable until the next read populates it.
89
+ if (observed === undefined) {
90
+ const result = yield* create(news);
91
+ return { ...result, id: result.id ?? "" };
92
+ }
93
+ // Sync — the notifier exists; PATCH against its id with the
94
+ // desired props. Preserve the cached id if the API response
95
+ // omits it.
96
+ const result = yield* update({ ...news, id: observed.id });
97
+ return { ...result, id: result.id ?? observed.id };
98
+ }),
99
+ delete: Effect.fn(function* ({ output }) {
100
+ yield* del({ id: output.id }).pipe(Effect.catchTag("NotFound", () => Effect.void));
101
+ }),
102
+ read: Effect.fn(function* ({ output }) {
103
+ if (!output?.id)
104
+ return undefined;
105
+ return yield* get({ id: output.id }).pipe(Effect.map((current) => ({
106
+ ...current,
107
+ id: current.id ?? output.id,
108
+ })), Effect.catchTag("NotFound", () => Effect.succeed(undefined)));
109
+ }),
110
+ };
111
+ }));
112
+ //# sourceMappingURL=Notifier.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Notifier.js","sourceRoot":"","sources":["../src/Notifier.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Axiom routes OTLP ingest by a dataset header. Traces and logs use
3
+ * `X-Axiom-Dataset`; the metrics endpoint requires `X-Axiom-Metrics-Dataset`
4
+ * instead (https://axiom.co/docs/send-data/opentelemetry).
5
+ *
6
+ * @internal
7
+ */
8
+ export declare const otelDatasetHeader: (metrics: boolean) => string;
9
+ //# sourceMappingURL=OtelHeaders.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"OtelHeaders.d.ts","sourceRoot":"","sources":["../src/OtelHeaders.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,eAAO,MAAM,iBAAiB,YAAa,OAAO,KAAG,MACI,CAAC"}
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Axiom routes OTLP ingest by a dataset header. Traces and logs use
3
+ * `X-Axiom-Dataset`; the metrics endpoint requires `X-Axiom-Metrics-Dataset`
4
+ * instead (https://axiom.co/docs/send-data/opentelemetry).
5
+ *
6
+ * @internal
7
+ */
8
+ export const otelDatasetHeader = (metrics) => metrics ? "X-Axiom-Metrics-Dataset" : "X-Axiom-Dataset";
9
+ //# sourceMappingURL=OtelHeaders.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"OtelHeaders.js","sourceRoot":"","sources":["../src/OtelHeaders.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,iBAAiB,GAAG,CAAC,OAAgB,EAAU,EAAE,CAC5D,OAAO,CAAC,CAAC,CAAC,yBAAyB,CAAC,CAAC,CAAC,iBAAiB,CAAC"}
@@ -0,0 +1,15 @@
1
+ import * as Provider from "alchemy/Provider";
2
+ import * as Layer from "effect/Layer";
3
+ import * as Credentials from "./Credentials.ts";
4
+ export { Credentials } from "@distilled.cloud/axiom/Credentials";
5
+ declare const Providers_base: Provider.ProviderCollection<Providers, "Axiom">;
6
+ export declare class Providers extends Providers_base {
7
+ }
8
+ export type ProviderRequirements = Layer.Services<ReturnType<typeof providers>>;
9
+ /**
10
+ * Axiom providers and credentials. Wires up Dataset, ApiToken, Notifier,
11
+ * Monitor, Dashboard, VirtualField, View and Annotation resources, and
12
+ * registers the Axiom AuthProvider so `alchemy profile edit` can configure it.
13
+ */
14
+ export declare const providers: () => Layer.Layer<Credentials.Credentials | import("alchemy/Auth/Credentials").CredentialsStore | import("effect/http/HttpClient").HttpClient | import("alchemy/Auth/Profile").ProfileStore | Providers, never, import("alchemy/Auth/AuthProvider").AuthProviders | import("effect/FileSystem").FileSystem | import("effect/Path").Path | import("alchemy/Stack").Stack | import("alchemy/Stage").Stage>;
15
+ //# sourceMappingURL=Providers.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Providers.d.ts","sourceRoot":"","sources":["../src/Providers.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,QAAQ,MAAM,kBAAkB,CAAC;AAE7C,OAAO,KAAK,KAAK,MAAM,cAAc,CAAC;AAItC,OAAO,KAAK,WAAW,MAAM,kBAAkB,CAAC;AAQhD,OAAO,EAAE,WAAW,EAAE,MAAM,oCAAoC,CAAC;;AAEjE,qBAAa,SAAU,SAAQ,cAAiD;CAAG;AAEnF,MAAM,MAAM,oBAAoB,GAAG,KAAK,CAAC,QAAQ,CAAC,UAAU,CAAC,OAAO,SAAS,CAAC,CAAC,CAAC;AAEhF;;;;GAIG;AACH,eAAO,MAAM,SAAS,0YAgCnB,CAAC"}
@@ -0,0 +1,34 @@
1
+ import { CredentialsStoreLive } from "alchemy/Auth/Credentials";
2
+ import { ProfileStoreLive } from "alchemy/Auth/Profile";
3
+ import * as Provider from "alchemy/Provider";
4
+ import * as FetchHttpClient from "effect/http/FetchHttpClient";
5
+ import * as Layer from "effect/Layer";
6
+ import { Annotation, AnnotationProvider } from "./Annotation.js";
7
+ import { ApiToken, ApiTokenProvider } from "./ApiToken.js";
8
+ import { AxiomAuth } from "./AuthProvider.js";
9
+ import * as Credentials from "./Credentials.js";
10
+ import { Dashboard, DashboardProvider } from "./Dashboard.js";
11
+ import { Dataset, DatasetProvider } from "./Dataset.js";
12
+ import { Monitor, MonitorProvider } from "./Monitor.js";
13
+ import { Notifier, NotifierProvider } from "./Notifier.js";
14
+ import { View, ViewProvider } from "./View.js";
15
+ import { VirtualField, VirtualFieldProvider } from "./VirtualField.js";
16
+ export { Credentials } from "@distilled.cloud/axiom/Credentials";
17
+ export class Providers extends Provider.ProviderCollection()("Axiom") {
18
+ }
19
+ /**
20
+ * Axiom providers and credentials. Wires up Dataset, ApiToken, Notifier,
21
+ * Monitor, Dashboard, VirtualField, View and Annotation resources, and
22
+ * registers the Axiom AuthProvider so `alchemy profile edit` can configure it.
23
+ */
24
+ export const providers = () => Layer.effect(Providers, Provider.collection([
25
+ Annotation,
26
+ ApiToken,
27
+ Dashboard,
28
+ Dataset,
29
+ Monitor,
30
+ Notifier,
31
+ View,
32
+ VirtualField,
33
+ ])).pipe(Layer.provide(Layer.mergeAll(AnnotationProvider(), ApiTokenProvider(), DashboardProvider(), DatasetProvider(), MonitorProvider(), NotifierProvider(), ViewProvider(), VirtualFieldProvider())), Layer.provideMerge(Credentials.fromAuthProvider()), Layer.provideMerge(FetchHttpClient.layer), Layer.provideMerge(AxiomAuth), Layer.provideMerge(ProfileStoreLive), Layer.provideMerge(CredentialsStoreLive), Layer.orDie);
34
+ //# sourceMappingURL=Providers.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Providers.js","sourceRoot":"","sources":["../src/Providers.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,oBAAoB,EAAE,MAAM,0BAA0B,CAAC;AAChE,OAAO,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AACxD,OAAO,KAAK,QAAQ,MAAM,kBAAkB,CAAC;AAC7C,OAAO,KAAK,eAAe,MAAM,6BAA6B,CAAC;AAC/D,OAAO,KAAK,KAAK,MAAM,cAAc,CAAC;AACtC,OAAO,EAAE,UAAU,EAAE,kBAAkB,EAAE,MAAM,iBAAiB,CAAC;AACjE,OAAO,EAAE,QAAQ,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AAC3D,OAAO,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAC;AAC9C,OAAO,KAAK,WAAW,MAAM,kBAAkB,CAAC;AAChD,OAAO,EAAE,SAAS,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AAC9D,OAAO,EAAE,OAAO,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AACxD,OAAO,EAAE,OAAO,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AACxD,OAAO,EAAE,QAAQ,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AAC3D,OAAO,EAAE,IAAI,EAAE,YAAY,EAAE,MAAM,WAAW,CAAC;AAC/C,OAAO,EAAE,YAAY,EAAE,oBAAoB,EAAE,MAAM,mBAAmB,CAAC;AAEvE,OAAO,EAAE,WAAW,EAAE,MAAM,oCAAoC,CAAC;AAEjE,MAAM,OAAO,SAAU,SAAQ,QAAQ,CAAC,kBAAkB,EAAa,CAAC,OAAO,CAAC;CAAG;AAInF;;;;GAIG;AACH,MAAM,CAAC,MAAM,SAAS,GAAG,GAAG,EAAE,CAC5B,KAAK,CAAC,MAAM,CACV,SAAS,EACT,QAAQ,CAAC,UAAU,CAAC;IAClB,UAAU;IACV,QAAQ;IACR,SAAS;IACT,OAAO;IACP,OAAO;IACP,QAAQ;IACR,IAAI;IACJ,YAAY;CACb,CAAC,CACH,CAAC,IAAI,CACJ,KAAK,CAAC,OAAO,CACX,KAAK,CAAC,QAAQ,CACZ,kBAAkB,EAAE,EACpB,gBAAgB,EAAE,EAClB,iBAAiB,EAAE,EACnB,eAAe,EAAE,EACjB,eAAe,EAAE,EACjB,gBAAgB,EAAE,EAClB,YAAY,EAAE,EACd,oBAAoB,EAAE,CACvB,CACF,EACD,KAAK,CAAC,YAAY,CAAC,WAAW,CAAC,gBAAgB,EAAE,CAAC,EAClD,KAAK,CAAC,YAAY,CAAC,eAAe,CAAC,KAAK,CAAC,EACzC,KAAK,CAAC,YAAY,CAAC,SAAS,CAAC,EAC7B,KAAK,CAAC,YAAY,CAAC,gBAAgB,CAAC,EACpC,KAAK,CAAC,YAAY,CAAC,oBAAoB,CAAC,EACxC,KAAK,CAAC,KAAK,CACZ,CAAC"}
@@ -0,0 +1,66 @@
1
+ import type { Input } from "alchemy/Input";
2
+ import * as Effect from "effect/Effect";
3
+ import * as Layer from "effect/Layer";
4
+ import type { ApiToken } from "./ApiToken.ts";
5
+ import type { Dataset } from "./Dataset.ts";
6
+ /**
7
+ * A resource passed to the layer: either the module-scope declaration (an
8
+ * Effect that resolves to the instance, same as what capability bindings
9
+ * accept) or an already-yielded instance.
10
+ */
11
+ export type ResourceInput<T> = T | Effect.Effect<T, never, any>;
12
+ /**
13
+ * Options for {@link Telemetry}: an ingest {@link ApiToken} plus one
14
+ * {@link Dataset} per OTel signal to export.
15
+ */
16
+ export interface AxiomTelemetryProps {
17
+ /**
18
+ * The ingest credential. Must have `ingest: ["create"]` capability on
19
+ * every dataset passed below.
20
+ */
21
+ token: ResourceInput<ApiToken>;
22
+ /** Dataset (kind `otel:traces:v1`) to export traces into. */
23
+ traces?: ResourceInput<Dataset> | undefined;
24
+ /** Dataset (kind `otel:logs:v1`) to export logs into. */
25
+ logs?: ResourceInput<Dataset> | undefined;
26
+ /** Dataset (kind `otel:metrics:v1`) to export metrics into. */
27
+ metrics?: ResourceInput<Dataset> | undefined;
28
+ /**
29
+ * The exported `service.name`.
30
+ * @default the deployed Function/Worker's physical name
31
+ */
32
+ serviceName?: Input<string> | undefined;
33
+ }
34
+ /**
35
+ * Export a Function/Worker's telemetry to Axiom.
36
+ *
37
+ * A binding layer over {@link layerOtlp | Alchemy.Telemetry.layerOtlp}:
38
+ * building it binds each dataset's OTLP endpoint and the ingest token's
39
+ * `Authorization` header (as a secret) onto the host, and at runtime the
40
+ * built-in exporter ships each signal to its dataset, flushed per event.
41
+ *
42
+ * Compose it into the Function/Worker's single `Effect.provide`:
43
+ *
44
+ * ```ts
45
+ * import * as Axiom from "@alchemy.run/axiom";
46
+ * import { Bucket } from "./bucket.ts";
47
+ * import { Ingest, Logs, Traces } from "./observability.ts";
48
+ *
49
+ * export default Cloudflare.Worker(
50
+ * "Worker",
51
+ * { main: import.meta.url },
52
+ * Effect.gen(function* () {
53
+ * // ...
54
+ * }).pipe(
55
+ * Effect.provide(
56
+ * Layer.mergeAll(
57
+ * Cloudflare.R2.ReadWriteBucketBinding,
58
+ * Axiom.Telemetry({ token: Ingest, traces: Traces, logs: Logs }),
59
+ * ),
60
+ * ),
61
+ * ),
62
+ * );
63
+ * ```
64
+ */
65
+ export declare const Telemetry: (props: AxiomTelemetryProps) => Layer.Layer<never>;
66
+ //# sourceMappingURL=Telemetry.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Telemetry.d.ts","sourceRoot":"","sources":["../src/Telemetry.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,eAAe,CAAC;AAG3C,OAAO,KAAK,MAAM,MAAM,eAAe,CAAC;AACxC,OAAO,KAAK,KAAK,MAAM,cAAc,CAAC;AAEtC,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAC9C,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAG5C;;;;GAIG;AACH,MAAM,MAAM,aAAa,CAAC,CAAC,IAAI,CAAC,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC,EAAE,KAAK,EAAE,GAAG,CAAC,CAAC;AAEhE;;;GAGG;AACH,MAAM,WAAW,mBAAmB;IAClC;;;OAGG;IACH,KAAK,EAAE,aAAa,CAAC,QAAQ,CAAC,CAAC;IAC/B,6DAA6D;IAC7D,MAAM,CAAC,EAAE,aAAa,CAAC,OAAO,CAAC,GAAG,SAAS,CAAC;IAC5C,yDAAyD;IACzD,IAAI,CAAC,EAAE,aAAa,CAAC,OAAO,CAAC,GAAG,SAAS,CAAC;IAC1C,+DAA+D;IAC/D,OAAO,CAAC,EAAE,aAAa,CAAC,OAAO,CAAC,GAAG,SAAS,CAAC;IAC7C;;;OAGG;IACH,WAAW,CAAC,EAAE,KAAK,CAAC,MAAM,CAAC,GAAG,SAAS,CAAC;CACzC;AA6BD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AACH,eAAO,MAAM,SAAS,UAAW,mBAAmB,KAAG,KAAK,CAAC,KAAK,CAAC,KAAK,CAiB/C,CAAC"}
@@ -0,0 +1,68 @@
1
+ import * as Output from "alchemy/Output";
2
+ import { layerOtlp } from "alchemy/Telemetry";
3
+ import * as Effect from "effect/Effect";
4
+ import * as Layer from "effect/Layer";
5
+ import * as Redacted from "effect/Redacted";
6
+ import { otelDatasetHeader } from "./OtelHeaders.js";
7
+ /**
8
+ * Resource declarations are Effects — yield them to get the instance with
9
+ * attribute Output accessors, same as `Binding.Service`'s callable does for
10
+ * capability bindings.
11
+ */
12
+ const instance = (resource) => Effect.isEffect(resource) ? resource : Effect.succeed(resource);
13
+ const signal = (token, dataset, urlAttr) => dataset === undefined
14
+ ? undefined
15
+ : {
16
+ url: dataset[urlAttr],
17
+ headers: {
18
+ Authorization: Output.map(token.token, (bearer) => Redacted.make(`Bearer ${Redacted.value(bearer)}`)),
19
+ [otelDatasetHeader(urlAttr === "otelMetricsEndpoint")]: dataset.name,
20
+ },
21
+ };
22
+ /**
23
+ * Export a Function/Worker's telemetry to Axiom.
24
+ *
25
+ * A binding layer over {@link layerOtlp | Alchemy.Telemetry.layerOtlp}:
26
+ * building it binds each dataset's OTLP endpoint and the ingest token's
27
+ * `Authorization` header (as a secret) onto the host, and at runtime the
28
+ * built-in exporter ships each signal to its dataset, flushed per event.
29
+ *
30
+ * Compose it into the Function/Worker's single `Effect.provide`:
31
+ *
32
+ * ```ts
33
+ * import * as Axiom from "@alchemy.run/axiom";
34
+ * import { Bucket } from "./bucket.ts";
35
+ * import { Ingest, Logs, Traces } from "./observability.ts";
36
+ *
37
+ * export default Cloudflare.Worker(
38
+ * "Worker",
39
+ * { main: import.meta.url },
40
+ * Effect.gen(function* () {
41
+ * // ...
42
+ * }).pipe(
43
+ * Effect.provide(
44
+ * Layer.mergeAll(
45
+ * Cloudflare.R2.ReadWriteBucketBinding,
46
+ * Axiom.Telemetry({ token: Ingest, traces: Traces, logs: Logs }),
47
+ * ),
48
+ * ),
49
+ * ),
50
+ * );
51
+ * ```
52
+ */
53
+ export const Telemetry = (props) => Layer.unwrap(Effect.gen(function* () {
54
+ // Declarations are yielded to instances (registering them on the
55
+ // Stack if the enclosing host is the first to reference them), so
56
+ // attribute accessors below produce real Outputs.
57
+ const token = yield* instance(props.token);
58
+ const traces = props.traces && (yield* instance(props.traces));
59
+ const logs = props.logs && (yield* instance(props.logs));
60
+ const metrics = props.metrics && (yield* instance(props.metrics));
61
+ return layerOtlp({
62
+ serviceName: props.serviceName,
63
+ traces: signal(token, traces, "otelTracesEndpoint"),
64
+ logs: signal(token, logs, "otelLogsEndpoint"),
65
+ metrics: signal(token, metrics, "otelMetricsEndpoint"),
66
+ });
67
+ }));
68
+ //# sourceMappingURL=Telemetry.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Telemetry.js","sourceRoot":"","sources":["../src/Telemetry.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,MAAM,MAAM,gBAAgB,CAAC;AACzC,OAAO,EAAE,SAAS,EAA0B,MAAM,mBAAmB,CAAC;AACtE,OAAO,KAAK,MAAM,MAAM,eAAe,CAAC;AACxC,OAAO,KAAK,KAAK,MAAM,cAAc,CAAC;AACtC,OAAO,KAAK,QAAQ,MAAM,iBAAiB,CAAC;AAG5C,OAAO,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AAgCrD;;;;GAIG;AACH,MAAM,QAAQ,GAAG,CAAI,QAA0B,EAAoB,EAAE,CACnE,MAAM,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAE,QAA6B,CAAC,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;AAExF,MAAM,MAAM,GAAG,CACb,KAAe,EACf,OAA4B,EAC5B,OAA0E,EAC3C,EAAE,CACjC,OAAO,KAAK,SAAS;IACnB,CAAC,CAAC,SAAS;IACX,CAAC,CAAC;QACE,GAAG,EAAE,OAAO,CAAC,OAAO,CAAC;QACrB,OAAO,EAAE;YACP,aAAa,EAAE,MAAM,CAAC,GAAG,CACvB,KAAK,CAAC,KAAK,EACX,CAAC,MAAM,EAAE,EAAE,CACT,QAAQ,CAAC,IAAI,CAAC,UAAU,QAAQ,CAAC,KAAK,CAAC,MAAM,CAAC,EAAE,CAA8B,CACjF;YACD,CAAC,iBAAiB,CAAC,OAAO,KAAK,qBAAqB,CAAC,CAAC,EAAE,OAAO,CAAC,IAAI;SACrE;KACF,CAAC;AAER;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AACH,MAAM,CAAC,MAAM,SAAS,GAAG,CAAC,KAA0B,EAAsB,EAAE,CAC1E,KAAK,CAAC,MAAM,CACV,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC;IAClB,iEAAiE;IACjE,kEAAkE;IAClE,kDAAkD;IAClD,MAAM,KAAK,GAAG,KAAK,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;IAC3C,MAAM,MAAM,GAAG,KAAK,CAAC,MAAM,IAAI,CAAC,KAAK,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC;IAC/D,MAAM,IAAI,GAAG,KAAK,CAAC,IAAI,IAAI,CAAC,KAAK,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC;IACzD,MAAM,OAAO,GAAG,KAAK,CAAC,OAAO,IAAI,CAAC,KAAK,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC;IAClE,OAAO,SAAS,CAAC;QACf,WAAW,EAAE,KAAK,CAAC,WAAW;QAC9B,MAAM,EAAE,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,oBAAoB,CAAC;QACnD,IAAI,EAAE,MAAM,CAAC,KAAK,EAAE,IAAI,EAAE,kBAAkB,CAAC;QAC7C,OAAO,EAAE,MAAM,CAAC,KAAK,EAAE,OAAO,EAAE,qBAAqB,CAAC;KACvD,CAAC,CAAC;AACL,CAAC,CAAC,CACmB,CAAC"}
package/lib/View.d.ts ADDED
@@ -0,0 +1,57 @@
1
+ import * as Axiom from "@distilled.cloud/axiom";
2
+ import * as Provider from "alchemy/Provider";
3
+ import { Resource } from "alchemy/Resource";
4
+ import type { Providers } from "./Providers.ts";
5
+ export type ViewProps = Axiom.CreateViewRequest;
6
+ export type View = Resource<"Axiom.View", ViewProps, Axiom.View & {
7
+ /**
8
+ * Path identifier used by `updateView` / `getView` / `deleteView`.
9
+ * Currently derived from `name` because Axiom's view list/get responses
10
+ * don't expose a separate id field.
11
+ */
12
+ id: string;
13
+ }, never, Providers>;
14
+ /**
15
+ * An Axiom saved view — a named, shareable APL query. Useful for building
16
+ * starter dashboards, providing canned "open in Axiom" links from your app,
17
+ * or pinning common investigations the team revisits.
18
+ *
19
+ * The path identifier is `name`. Renaming a view triggers a replacement
20
+ * (the old one is deleted, a new one is created).
21
+ * @see https://axiom.co/docs/query-data/datasets — APL query reference
22
+ *
23
+ * ### Creating a View
24
+ * **Example:** Recent errors across one dataset
25
+ * ```typescript
26
+ * yield* Axiom.View("recent-errors", {
27
+ * name: "recent-errors",
28
+ * description: "Last 100 5xx responses",
29
+ * datasets: ["my-app-traces"],
30
+ * aplQuery: `
31
+ * ['my-app-traces']
32
+ * | where status >= 500
33
+ * | order by _time desc
34
+ * | take 100
35
+ * `,
36
+ * });
37
+ * ```
38
+ *
39
+ * **Example:** Cross-dataset join (logs + traces by trace_id)
40
+ * ```typescript
41
+ * yield* Axiom.View("trace-with-logs", {
42
+ * name: "trace-with-logs",
43
+ * datasets: ["my-app-traces", "my-app-logs"],
44
+ * aplQuery: `
45
+ * ['my-app-traces']
46
+ * | where duration_ms > 1000
47
+ * | join kind=leftouter (['my-app-logs']) on trace_id
48
+ * `,
49
+ * });
50
+ * ```
51
+ *
52
+ * @resource
53
+ * @product Dashboard
54
+ */
55
+ export declare const View: import("alchemy/Resource").ResourceClass<View>;
56
+ export declare const ViewProvider: () => import("effect/Layer").Layer<Provider.Provider<View>, never, Axiom.AxiomOpContext>;
57
+ //# sourceMappingURL=View.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"View.d.ts","sourceRoot":"","sources":["../src/View.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,wBAAwB,CAAC;AAEhD,OAAO,KAAK,QAAQ,MAAM,kBAAkB,CAAC;AAC7C,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAE5C,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAEhD,MAAM,MAAM,SAAS,GAAG,KAAK,CAAC,iBAAiB,CAAC;AAEhD,MAAM,MAAM,IAAI,GAAG,QAAQ,CACzB,YAAY,EACZ,SAAS,EACT,KAAK,CAAC,IAAI,GAAG;IACX;;;;OAIG;IACH,EAAE,EAAE,MAAM,CAAC;CACZ,EACD,KAAK,EACL,SAAS,CACV,CAAC;AAEF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAwCG;AACH,eAAO,MAAM,IAAI,gDAA+B,CAAC;AAEjD,eAAO,MAAM,YAAY,0FA8DtB,CAAC"}
package/lib/View.js ADDED
@@ -0,0 +1,100 @@
1
+ import * as Axiom from "@distilled.cloud/axiom";
2
+ import { isResolved } from "alchemy/Diff";
3
+ import * as Provider from "alchemy/Provider";
4
+ import { Resource } from "alchemy/Resource";
5
+ import * as Effect from "effect/Effect";
6
+ /**
7
+ * An Axiom saved view — a named, shareable APL query. Useful for building
8
+ * starter dashboards, providing canned "open in Axiom" links from your app,
9
+ * or pinning common investigations the team revisits.
10
+ *
11
+ * The path identifier is `name`. Renaming a view triggers a replacement
12
+ * (the old one is deleted, a new one is created).
13
+ * @see https://axiom.co/docs/query-data/datasets — APL query reference
14
+ *
15
+ * ### Creating a View
16
+ * **Example:** Recent errors across one dataset
17
+ * ```typescript
18
+ * yield* Axiom.View("recent-errors", {
19
+ * name: "recent-errors",
20
+ * description: "Last 100 5xx responses",
21
+ * datasets: ["my-app-traces"],
22
+ * aplQuery: `
23
+ * ['my-app-traces']
24
+ * | where status >= 500
25
+ * | order by _time desc
26
+ * | take 100
27
+ * `,
28
+ * });
29
+ * ```
30
+ *
31
+ * **Example:** Cross-dataset join (logs + traces by trace_id)
32
+ * ```typescript
33
+ * yield* Axiom.View("trace-with-logs", {
34
+ * name: "trace-with-logs",
35
+ * datasets: ["my-app-traces", "my-app-logs"],
36
+ * aplQuery: `
37
+ * ['my-app-traces']
38
+ * | where duration_ms > 1000
39
+ * | join kind=leftouter (['my-app-logs']) on trace_id
40
+ * `,
41
+ * });
42
+ * ```
43
+ *
44
+ * @resource
45
+ * @product Dashboard
46
+ */
47
+ export const View = Resource("Axiom.View");
48
+ export const ViewProvider = () => Provider.effect(View, Effect.gen(function* () {
49
+ const create = yield* Axiom.createView;
50
+ const update = yield* Axiom.updateView;
51
+ const get = yield* Axiom.getView;
52
+ const listViews = yield* Axiom.getViews;
53
+ const del = yield* Axiom.deleteView;
54
+ return {
55
+ stables: ["id"],
56
+ // Enumerate every view in the org. Axiom exposes a single account-wide
57
+ // `GET /v2/views` collection op (no pagination) that already returns
58
+ // the full view objects, so we fetch it once and hydrate each row into
59
+ // the exact `read` Attributes shape (`id` is derived from `name`, the
60
+ // path identifier) — directly usable by `delete` with no follow-up get.
61
+ list: () => Effect.gen(function* () {
62
+ const views = yield* listViews({});
63
+ return views.map((view) => ({ ...view, id: view.name }));
64
+ }),
65
+ diff: Effect.fn(function* ({ news, output }) {
66
+ if (!isResolved(news))
67
+ return undefined;
68
+ if (output && news.name !== output.name) {
69
+ return { action: "replace" };
70
+ }
71
+ return undefined;
72
+ }),
73
+ reconcile: Effect.fn(function* ({ news, output }) {
74
+ // Observe — `name` is the path identifier for views. Renames are
75
+ // forced to a replacement by `diff` above, so the cached
76
+ // `output.id` (set to `news.name` on first create) and the
77
+ // current `news.name` always agree by the time we land here.
78
+ const viewId = output?.id ?? news.name;
79
+ const observed = yield* get({ id: viewId }).pipe(Effect.catchTag("NotFound", () => Effect.succeed(undefined)));
80
+ // Ensure — POST creates the view under `news.name`.
81
+ if (observed === undefined) {
82
+ const result = yield* create(news);
83
+ return { ...result, id: news.name };
84
+ }
85
+ // Sync — the view exists; PUT against its id with the desired
86
+ // props.
87
+ const result = yield* update({ ...news, id: viewId });
88
+ return { ...result, id: viewId };
89
+ }),
90
+ delete: Effect.fn(function* ({ output }) {
91
+ yield* del({ id: output.id }).pipe(Effect.catchTag("NotFound", () => Effect.void));
92
+ }),
93
+ read: Effect.fn(function* ({ output }) {
94
+ if (!output?.id)
95
+ return undefined;
96
+ return yield* get({ id: output.id }).pipe(Effect.map((current) => ({ ...current, id: output.id })), Effect.catchTag("NotFound", () => Effect.succeed(undefined)));
97
+ }),
98
+ };
99
+ }));
100
+ //# sourceMappingURL=View.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"View.js","sourceRoot":"","sources":["../src/View.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,44 @@
1
+ import * as Axiom from "@distilled.cloud/axiom";
2
+ import * as Provider from "alchemy/Provider";
3
+ import { Resource } from "alchemy/Resource";
4
+ import type { Providers } from "./Providers.ts";
5
+ export type VirtualFieldProps = Axiom.CreateVirtualFieldRequest;
6
+ export type VirtualField = Resource<"Axiom.VirtualField", VirtualFieldProps, Axiom.CreateVirtualFieldResponse, never, Providers>;
7
+ /**
8
+ * An Axiom virtual field — a saved APL expression that appears as a derived
9
+ * column on a dataset at query time. Use these to standardise common
10
+ * computations (status classes, latency buckets, parsed JSON paths) so
11
+ * dashboards and monitors don't have to redefine them.
12
+ *
13
+ * Bound to a single `dataset`; changing the dataset triggers a replacement.
14
+ * @see https://axiom.co/docs/query-data/virtual-fields
15
+ *
16
+ * ### Creating a Virtual Field
17
+ * **Example:** HTTP status class (e.g. 200 → "2xx")
18
+ * ```typescript
19
+ * yield* Axiom.VirtualField("status-class", {
20
+ * dataset: "my-app-traces",
21
+ * name: "status_class",
22
+ * description: "HTTP response class bucket",
23
+ * expression: 'strcat(tostring(toint(status / 100)), "xx")',
24
+ * type: "string",
25
+ * });
26
+ * ```
27
+ *
28
+ * **Example:** Latency bucket in seconds
29
+ * ```typescript
30
+ * yield* Axiom.VirtualField("latency-bucket", {
31
+ * dataset: "my-app-traces",
32
+ * name: "latency_bucket_s",
33
+ * expression: "bin(duration_ms / 1000.0, 0.5)",
34
+ * type: "number",
35
+ * unit: "s",
36
+ * });
37
+ * ```
38
+ *
39
+ * @resource
40
+ * @product Dataset
41
+ */
42
+ export declare const VirtualField: import("alchemy/Resource").ResourceClass<VirtualField>;
43
+ export declare const VirtualFieldProvider: () => import("effect/Layer").Layer<Provider.Provider<VirtualField>, never, Axiom.AxiomOpContext>;
44
+ //# sourceMappingURL=VirtualField.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"VirtualField.d.ts","sourceRoot":"","sources":["../src/VirtualField.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,wBAAwB,CAAC;AAEhD,OAAO,KAAK,QAAQ,MAAM,kBAAkB,CAAC;AAC7C,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAE5C,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAEhD,MAAM,MAAM,iBAAiB,GAAG,KAAK,CAAC,yBAAyB,CAAC;AAEhE,MAAM,MAAM,YAAY,GAAG,QAAQ,CACjC,oBAAoB,EACpB,iBAAiB,EACjB,KAAK,CAAC,0BAA0B,EAChC,KAAK,EACL,SAAS,CACV,CAAC;AAEF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkCG;AACH,eAAO,MAAM,YAAY,wDAA+C,CAAC;AAEzE,eAAO,MAAM,oBAAoB,kGAoE9B,CAAC"}