History

fix(relay): scope Axiom resources by stage

Julius Marminge committed 5 months ago

Commit fe2e5571 parent 4d31e084 files · +24 −4Browse files

Unified · Split

4 files
  1. docs/relay-observability.md +3 −1
  2. infra/relay/src/deploymentConfig.test.ts +10 −0
  3. infra/relay/src/deploymentConfig.ts +4 −0
  4. infra/relay/src/observability.ts +7 −3
docs/relay-observability.md+3−1
@@ -4,9 +4,11 @@ The relay Alchemy stack owns a focused Axiom trace setup: · 3 unmodified lines
4 4
5- `t3-code-relay-traces`, an OpenTelemetry trace dataset for Worker requests5- `t3-code-relay-traces`, an OpenTelemetry trace dataset for Worker requests
6- `t3-code-relay-otel-ingest`, a dataset-scoped ingest token bound to the Worker6- `t3-code-relay-otel-ingest`, a dataset-scoped ingest token bound to the Worker
7- `t3-code-relay-readonly-query`, a dataset-scoped token for scripted diagnostics
8- `t3-code-relay-recent-spans`, a view of recent request and endpoint spans7- `t3-code-relay-recent-spans`, a view of recent request and endpoint spans
9 8
9These are the production names. Non-production Alchemy stages append their sanitized stage name,
10for example `t3-code-relay-traces-dev-julius`.
11
10Deploy from `infra/relay` with the normal Alchemy workflow:12Deploy from `infra/relay` with the normal Alchemy workflow:
11 13
12```sh14```sh
infra/relay/src/deploymentConfig.test.ts+10−0
@@ -5,6 +5,7 @@ import { · 4 unmodified lines
5 managedEndpointHostname,5 managedEndpointHostname,
6 managedEndpointTunnelName,6 managedEndpointTunnelName,
7 relayPublicDomainForStage,7 relayPublicDomainForStage,
8 relayResourceNameForStage,
8 relayStageSlug,9 relayStageSlug,
9} from "./deploymentConfig.ts";10} from "./deploymentConfig.ts";
10 11
@@ -26,6 +27,15 @@ describe("relayPublicDomainForStage", () => { · 15 unmodified lines
26 });27 });
27});28});
28 29
30describe("relayResourceNameForStage", () => {
31 it("preserves production names and isolates personal stages", () => {
32 expect(relayResourceNameForStage("t3-code-relay-traces", "prod")).toBe("t3-code-relay-traces");
33 expect(relayResourceNameForStage("t3-code-relay-traces", "dev_julius")).toBe(
34 "t3-code-relay-traces-dev-julius",
35 );
36 });
37});
38
29describe("managed endpoint names", () => {39describe("managed endpoint names", () => {
30 it("uses the stage slug and a stable stage-scoped digest suffix", () => {40 it("uses the stage slug and a stable stage-scoped digest suffix", () => {
31 const hash = "ABCDEF0123456789ABCDEF0123456789";41 const hash = "ABCDEF0123456789ABCDEF0123456789";
infra/relay/src/deploymentConfig.ts+4−0
@@ -33,6 +33,10 @@ export function relayStageSlug(stage: string): string { · 32 unmodified lines
33 .replace(/^-+|-+$/g, "");33 .replace(/^-+|-+$/g, "");
34}34}
35 35
36export function relayResourceNameForStage(name: string, stage: string): string {
37 return stage === "prod" ? name : `${name}-${relayStageSlug(stage)}`;
38}
39
36export function relayPublicDomainForStage(stage: string, zoneName: string): string {40export function relayPublicDomainForStage(stage: string, zoneName: string): string {
37 const stageSlug = relayStageSlug(stage);41 const stageSlug = relayStageSlug(stage);
38 const relayLabel = stage === "prod" ? "relay" : `relay-${stageSlug}`;42 const relayLabel = stage === "prod" ? "relay" : `relay-${stageSlug}`;
infra/relay/src/observability.ts+7−3
@@ -1,3 +1,4 @@
1import * as Alchemy from "alchemy";
1import * as Axiom from "alchemy/Axiom";2import * as Axiom from "alchemy/Axiom";
2import * as Output from "alchemy/Output";3import * as Output from "alchemy/Output";
3import * as Layer from "effect/Layer";4import * as Layer from "effect/Layer";
@@ -5,6 +6,8 @@ import * as Effect from "effect/Effect"; · 1 unmodified line
5import * as Redacted from "effect/Redacted";6import * as Redacted from "effect/Redacted";
6import { OtlpSerialization, OtlpTracer } from "effect/unstable/observability";7import { OtlpSerialization, OtlpTracer } from "effect/unstable/observability";
7 8
9import { relayResourceNameForStage } from "./deploymentConfig.ts";
10
8const relayRecentSpansQuery = (dataset: string) =>11const relayRecentSpansQuery = (dataset: string) =>
9 [12 [
10 `['${dataset}']`,13 `['${dataset}']`,
@@ -17,8 +20,9 @@ const relayRecentSpansQuery = (dataset: string) => · 6 unmodified lines
17 ].join("\n");20 ].join("\n");
18 21
19export const RelayObservability = Effect.gen(function* () {22export const RelayObservability = Effect.gen(function* () {
23 const stage = yield* Alchemy.Stage;
20 const traces = yield* Axiom.Dataset("RelayTracesDataset", {24 const traces = yield* Axiom.Dataset("RelayTracesDataset", {
21 name: "t3-code-relay-traces",25 name: relayResourceNameForStage("t3-code-relay-traces", stage),
22 kind: "otel:traces:v1",26 kind: "otel:traces:v1",
23 description: "T3 Code relay Worker HTTP request spans.",27 description: "T3 Code relay Worker HTTP request spans.",
24 retentionDays: 30,28 retentionDays: 30,
@@ -26,7 +30,7 @@ export const RelayObservability = Effect.gen(function* () { · 1 unmodified line
26 });30 });
27 31
28 const ingestToken = yield* Axiom.ApiToken("RelayAxiomIngestToken", {32 const ingestToken = yield* Axiom.ApiToken("RelayAxiomIngestToken", {
29 name: "t3-code-relay-otel-ingest",33 name: relayResourceNameForStage("t3-code-relay-otel-ingest", stage),
30 description: "Owned by Alchemy. Scoped OTLP ingest token for relay HTTP spans.",34 description: "Owned by Alchemy. Scoped OTLP ingest token for relay HTTP spans.",
31 datasetCapabilities: Output.map(traces.name, (dataset) => ({35 datasetCapabilities: Output.map(traces.name, (dataset) => ({
32 [dataset]: { ingest: ["create" as const] },36 [dataset]: { ingest: ["create" as const] },
@@ -34,7 +38,7 @@ export const RelayObservability = Effect.gen(function* () { · 1 unmodified line
34 });38 });
35 39
36 yield* Axiom.View("RelayRecentSpansView", {40 yield* Axiom.View("RelayRecentSpansView", {
37 name: "t3-code-relay-recent-spans",41 name: relayResourceNameForStage("t3-code-relay-recent-spans", stage),
38 description: "Recent relay HTTP request spans.",42 description: "Recent relay HTTP request spans.",
39 datasets: [traces.name],43 datasets: [traces.name],
40 aplQuery: Output.map(traces.name, relayRecentSpansQuery),44 aplQuery: Output.map(traces.name, relayRecentSpansQuery),