chore: import upstream snapshot with attribution
This commit is contained in:
@@ -0,0 +1,2 @@
|
||||
BASELIME_API_KEY=
|
||||
BASELIME_SERVICE="webapp"
|
||||
@@ -0,0 +1,129 @@
|
||||
ARG NODE_IMAGE=node:22.23.1-bookworm-slim@sha256:813a7480f28fdadac1f7f5c824bcdad435b5bc1322a5968bbbdef8d058f9dff4
|
||||
|
||||
FROM golang:1.26-alpine AS goose_builder
|
||||
RUN go install github.com/pressly/goose/v3/cmd/goose@v3.27.1
|
||||
|
||||
FROM ${NODE_IMAGE} AS pruner
|
||||
|
||||
WORKDIR /triggerdotdev
|
||||
|
||||
COPY --chown=node:node . .
|
||||
RUN npx -q turbo@2.10.0 prune --scope=webapp --docker
|
||||
RUN find . -name "node_modules" -type d -prune -exec rm -rf '{}' +
|
||||
|
||||
# Base strategy to have layer caching
|
||||
FROM ${NODE_IMAGE} AS base
|
||||
RUN apt-get update && apt-get upgrade -y && apt-get install -y --no-install-recommends openssl dumb-init && rm -rf /var/lib/apt/lists/*
|
||||
WORKDIR /triggerdotdev
|
||||
COPY --chown=node:node .gitignore .gitignore
|
||||
COPY --from=pruner --chown=node:node /triggerdotdev/out/json/ .
|
||||
COPY --from=pruner --chown=node:node /triggerdotdev/out/pnpm-lock.yaml ./pnpm-lock.yaml
|
||||
COPY --from=pruner --chown=node:node /triggerdotdev/out/pnpm-workspace.yaml ./pnpm-workspace.yaml
|
||||
COPY --chown=node:node patches ./patches
|
||||
|
||||
## Dev deps
|
||||
FROM base AS dev-deps
|
||||
WORKDIR /triggerdotdev
|
||||
# Corepack is used to install pnpm with the exact version from packageManager
|
||||
RUN corepack enable && corepack prepare pnpm@10.33.2 --activate
|
||||
ENV NODE_ENV=development
|
||||
RUN --mount=type=cache,id=pnpm,target=/root/.local/share/pnpm/store pnpm install --no-frozen-lockfile
|
||||
# Generate Prisma client here where all deps are installed
|
||||
COPY --from=pruner --chown=node:node /triggerdotdev/internal-packages/database/prisma/schema.prisma /triggerdotdev/internal-packages/database/prisma/schema.prisma
|
||||
RUN pnpx prisma@6.14.0 generate --schema /triggerdotdev/internal-packages/database/prisma/schema.prisma
|
||||
COPY --from=pruner --chown=node:node /triggerdotdev/internal-packages/run-ops-database/prisma/schema.prisma /triggerdotdev/internal-packages/run-ops-database/prisma/schema.prisma
|
||||
RUN pnpx prisma@6.14.0 generate --schema /triggerdotdev/internal-packages/run-ops-database/prisma/schema.prisma
|
||||
|
||||
## Production deps
|
||||
FROM base AS production-deps
|
||||
WORKDIR /triggerdotdev
|
||||
# Corepack is used to install pnpm with the exact version from packageManager
|
||||
RUN corepack enable && corepack prepare pnpm@10.33.2 --activate
|
||||
ENV NODE_ENV=production
|
||||
RUN --mount=type=cache,id=pnpm,target=/root/.local/share/pnpm/store pnpm install --prod --no-frozen-lockfile
|
||||
|
||||
## Builder (builds the webapp)
|
||||
FROM base AS builder
|
||||
# This is needed for the sentry-cli binary while building the webapp
|
||||
RUN apt-get update && apt-get upgrade -y && apt-get install -y --no-install-recommends openssl dumb-init ca-certificates && rm -rf /var/lib/apt/lists/*
|
||||
WORKDIR /triggerdotdev
|
||||
# Corepack is used to install pnpm with the exact version from packageManager
|
||||
RUN corepack enable && corepack prepare pnpm@10.33.2 --activate
|
||||
|
||||
ARG SENTRY_RELEASE
|
||||
ARG SENTRY_ORG
|
||||
ARG SENTRY_PROJECT
|
||||
ENV SENTRY_RELEASE=${SENTRY_RELEASE} \
|
||||
SENTRY_ORG=${SENTRY_ORG} \
|
||||
SENTRY_PROJECT=${SENTRY_PROJECT}
|
||||
|
||||
# Goose and schemas
|
||||
COPY --from=goose_builder /go/bin/goose /usr/local/bin/goose
|
||||
RUN chmod +x /usr/local/bin/goose
|
||||
COPY --chown=node:node internal-packages/clickhouse/schema /triggerdotdev/internal-packages/clickhouse/schema
|
||||
|
||||
COPY --from=pruner --chown=node:node /triggerdotdev/out/full/ .
|
||||
COPY --from=dev-deps --chown=node:node /triggerdotdev/ .
|
||||
COPY --chown=node:node turbo.json turbo.json
|
||||
COPY --chown=node:node docker/scripts ./scripts
|
||||
RUN chmod +x ./scripts/wait-for-it.sh
|
||||
RUN chmod +x ./scripts/entrypoint.sh
|
||||
COPY --chown=node:node .configs/tsconfig.base.json .configs/tsconfig.base.json
|
||||
COPY --chown=node:node scripts/updateVersion.ts scripts/updateVersion.ts
|
||||
COPY --chown=node:node scripts/bundleSdkDocs.ts scripts/bundleSdkDocs.ts
|
||||
COPY --chown=node:node scripts/retry-prisma-generate.mjs scripts/retry-prisma-generate.mjs
|
||||
RUN pnpm run generate
|
||||
RUN --mount=type=secret,id=sentry_auth_token \
|
||||
SENTRY_AUTH_TOKEN=$(cat /run/secrets/sentry_auth_token) \
|
||||
pnpm run build --filter=webapp...
|
||||
|
||||
# Runner
|
||||
FROM ${NODE_IMAGE} AS runner
|
||||
RUN apt-get update && apt-get upgrade -y && apt-get install -y --no-install-recommends openssl netcat-openbsd ca-certificates && rm -rf /var/lib/apt/lists/*
|
||||
WORKDIR /triggerdotdev
|
||||
ENV NODE_ENV=production
|
||||
|
||||
COPY --from=base /usr/bin/dumb-init /usr/bin/dumb-init
|
||||
COPY --from=pruner --chown=node:node /triggerdotdev/out/full/ .
|
||||
COPY --from=production-deps --chown=node:node /triggerdotdev .
|
||||
# Copy generated Prisma client from dev-deps
|
||||
COPY --from=dev-deps --chown=node:node /triggerdotdev/internal-packages/database/generated ./internal-packages/database/generated
|
||||
# Run-ops Prisma client (query engine + client). Only constructed when the split is enabled,
|
||||
# but the image must carry it so a split-on deployment doesn't hit a missing query engine.
|
||||
COPY --from=dev-deps --chown=node:node /triggerdotdev/internal-packages/run-ops-database/generated ./internal-packages/run-ops-database/generated
|
||||
COPY --from=builder --chown=node:node /triggerdotdev/apps/webapp/build/server.js ./apps/webapp/build/server.js
|
||||
COPY --from=builder --chown=node:node /triggerdotdev/apps/webapp/build ./apps/webapp/build
|
||||
COPY --from=builder --chown=node:node /triggerdotdev/apps/webapp/public ./apps/webapp/public
|
||||
COPY --from=builder --chown=node:node /triggerdotdev/scripts ./scripts
|
||||
|
||||
# Goose and schemas
|
||||
COPY --from=builder /usr/local/bin/goose /usr/local/bin/goose
|
||||
COPY --from=builder --chown=node:node /triggerdotdev/internal-packages/clickhouse/schema /triggerdotdev/internal-packages/clickhouse/schema
|
||||
|
||||
# Build info
|
||||
ARG BUILD_APP_VERSION
|
||||
ARG BUILD_GIT_SHA
|
||||
ARG BUILD_GIT_REF_NAME
|
||||
ARG BUILD_TIMESTAMP_SECONDS
|
||||
ARG BUILD_TIMESTAMP_RFC3339
|
||||
ENV BUILD_APP_VERSION=${BUILD_APP_VERSION} \
|
||||
BUILD_GIT_SHA=${BUILD_GIT_SHA} \
|
||||
BUILD_GIT_REF_NAME=${BUILD_GIT_REF_NAME} \
|
||||
BUILD_TIMESTAMP_SECONDS=${BUILD_TIMESTAMP_SECONDS}
|
||||
|
||||
LABEL org.opencontainers.image.source="https://github.com/triggerdotdev/trigger.dev" \
|
||||
org.opencontainers.image.revision="${BUILD_GIT_SHA}" \
|
||||
org.opencontainers.image.version="${BUILD_APP_VERSION}" \
|
||||
org.opencontainers.image.created="${BUILD_TIMESTAMP_RFC3339}"
|
||||
|
||||
EXPOSE 3000
|
||||
|
||||
# Add global pnpm shims and install pnpm during build (root user)
|
||||
RUN corepack enable && corepack prepare pnpm@10.33.2 --activate
|
||||
|
||||
USER node
|
||||
|
||||
# Ensure pnpm is installed during build and not silently downloaded at runtime (node user)
|
||||
RUN corepack prepare pnpm@10.33.2 --activate
|
||||
|
||||
CMD ["./scripts/entrypoint.sh"]
|
||||
@@ -0,0 +1,5 @@
|
||||
FROM postgres:14
|
||||
|
||||
RUN apt-get update \
|
||||
&& apt-get install -y --no-install-recommends postgresql-14-partman \
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
@@ -0,0 +1,5 @@
|
||||
FROM postgres:17
|
||||
|
||||
RUN apt-get update \
|
||||
&& apt-get install -y --no-install-recommends postgresql-17-partman \
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
@@ -0,0 +1,3 @@
|
||||
# Internal Docker files
|
||||
|
||||
If you're looking for self-hosting files you're in the wrong place. Have a look [here](../hosting/).
|
||||
@@ -0,0 +1,13 @@
|
||||
<clickhouse>
|
||||
<metric_log remove="1"/>
|
||||
<asynchronous_metric_log remove="1"/>
|
||||
<part_log remove="1"/>
|
||||
<trace_log remove="1"/>
|
||||
<query_thread_log remove="1"/>
|
||||
<session_log remove="1"/>
|
||||
<text_log remove="1"/>
|
||||
<zookeeper_log remove="1"/>
|
||||
<processors_profile_log remove="1"/>
|
||||
<asynchronous_insert_log remove="1"/>
|
||||
<backup_log remove="1"/>
|
||||
</clickhouse>
|
||||
@@ -0,0 +1,755 @@
|
||||
{
|
||||
"annotations": {
|
||||
"list": []
|
||||
},
|
||||
"editable": true,
|
||||
"fiscalYearStartMonth": 0,
|
||||
"graphTooltip": 1,
|
||||
"links": [],
|
||||
"panels": [
|
||||
{
|
||||
"collapsed": false,
|
||||
"gridPos": { "h": 1, "w": 24, "x": 0, "y": 0 },
|
||||
"id": 1,
|
||||
"panels": [],
|
||||
"title": "Processing Health",
|
||||
"type": "row"
|
||||
},
|
||||
{
|
||||
"datasource": { "type": "prometheus", "uid": "prometheus" },
|
||||
"fieldConfig": {
|
||||
"defaults": {
|
||||
"color": { "mode": "palette-classic" },
|
||||
"mappings": [],
|
||||
"thresholds": { "mode": "absolute", "steps": [{ "color": "green", "value": null }] },
|
||||
"unit": "short"
|
||||
},
|
||||
"overrides": []
|
||||
},
|
||||
"gridPos": { "h": 6, "w": 6, "x": 0, "y": 1 },
|
||||
"id": 2,
|
||||
"options": {
|
||||
"colorMode": "value",
|
||||
"graphMode": "area",
|
||||
"justifyMode": "auto",
|
||||
"orientation": "auto",
|
||||
"reduceOptions": { "calcs": ["lastNotNull"], "fields": "", "values": false },
|
||||
"textMode": "auto"
|
||||
},
|
||||
"pluginVersion": "11.3.0",
|
||||
"targets": [
|
||||
{
|
||||
"expr": "sum(rate(triggerdotdev_batch_queue_items_processed_total[5m]))",
|
||||
"legendFormat": "Items/sec",
|
||||
"refId": "A"
|
||||
}
|
||||
],
|
||||
"title": "Items Processed Rate",
|
||||
"type": "stat"
|
||||
},
|
||||
{
|
||||
"datasource": { "type": "prometheus", "uid": "prometheus" },
|
||||
"fieldConfig": {
|
||||
"defaults": {
|
||||
"color": { "mode": "palette-classic" },
|
||||
"mappings": [],
|
||||
"thresholds": { "mode": "absolute", "steps": [{ "color": "green", "value": null }] },
|
||||
"unit": "short"
|
||||
},
|
||||
"overrides": []
|
||||
},
|
||||
"gridPos": { "h": 6, "w": 6, "x": 6, "y": 1 },
|
||||
"id": 3,
|
||||
"options": {
|
||||
"colorMode": "value",
|
||||
"graphMode": "area",
|
||||
"justifyMode": "auto",
|
||||
"orientation": "auto",
|
||||
"reduceOptions": { "calcs": ["lastNotNull"], "fields": "", "values": false },
|
||||
"textMode": "auto"
|
||||
},
|
||||
"pluginVersion": "11.3.0",
|
||||
"targets": [
|
||||
{
|
||||
"expr": "sum(rate(triggerdotdev_batch_queue_items_failed_total[5m]))",
|
||||
"legendFormat": "Failed/sec",
|
||||
"refId": "A"
|
||||
}
|
||||
],
|
||||
"title": "Items Failed Rate",
|
||||
"type": "stat"
|
||||
},
|
||||
{
|
||||
"datasource": { "type": "prometheus", "uid": "prometheus" },
|
||||
"fieldConfig": {
|
||||
"defaults": {
|
||||
"color": { "mode": "thresholds" },
|
||||
"mappings": [],
|
||||
"max": 1,
|
||||
"min": 0,
|
||||
"thresholds": {
|
||||
"mode": "absolute",
|
||||
"steps": [
|
||||
{ "color": "red", "value": null },
|
||||
{ "color": "yellow", "value": 0.9 },
|
||||
{ "color": "green", "value": 0.95 }
|
||||
]
|
||||
},
|
||||
"unit": "percentunit"
|
||||
},
|
||||
"overrides": []
|
||||
},
|
||||
"gridPos": { "h": 6, "w": 6, "x": 12, "y": 1 },
|
||||
"id": 4,
|
||||
"options": {
|
||||
"colorMode": "value",
|
||||
"graphMode": "none",
|
||||
"justifyMode": "auto",
|
||||
"orientation": "auto",
|
||||
"reduceOptions": { "calcs": ["lastNotNull"], "fields": "", "values": false },
|
||||
"textMode": "auto"
|
||||
},
|
||||
"pluginVersion": "11.3.0",
|
||||
"targets": [
|
||||
{
|
||||
"expr": "sum(rate(triggerdotdev_batch_queue_items_processed_total[5m])) / (sum(rate(triggerdotdev_batch_queue_items_processed_total[5m])) + sum(rate(triggerdotdev_batch_queue_items_failed_total[5m])))",
|
||||
"legendFormat": "Success Rate",
|
||||
"refId": "A"
|
||||
}
|
||||
],
|
||||
"title": "Success Rate",
|
||||
"type": "stat"
|
||||
},
|
||||
{
|
||||
"datasource": { "type": "prometheus", "uid": "prometheus" },
|
||||
"fieldConfig": {
|
||||
"defaults": {
|
||||
"color": { "mode": "palette-classic" },
|
||||
"mappings": [],
|
||||
"thresholds": { "mode": "absolute", "steps": [{ "color": "green", "value": null }] },
|
||||
"unit": "short"
|
||||
},
|
||||
"overrides": []
|
||||
},
|
||||
"gridPos": { "h": 6, "w": 6, "x": 18, "y": 1 },
|
||||
"id": 5,
|
||||
"options": {
|
||||
"colorMode": "value",
|
||||
"graphMode": "area",
|
||||
"justifyMode": "auto",
|
||||
"orientation": "auto",
|
||||
"reduceOptions": { "calcs": ["lastNotNull"], "fields": "", "values": false },
|
||||
"textMode": "auto"
|
||||
},
|
||||
"pluginVersion": "11.3.0",
|
||||
"targets": [
|
||||
{
|
||||
"expr": "sum(rate(triggerdotdev_batch_queue_batches_completed_total[5m]))",
|
||||
"legendFormat": "Batches/sec",
|
||||
"refId": "A"
|
||||
}
|
||||
],
|
||||
"title": "Batches Completed Rate",
|
||||
"type": "stat"
|
||||
},
|
||||
{
|
||||
"datasource": { "type": "prometheus", "uid": "prometheus" },
|
||||
"fieldConfig": {
|
||||
"defaults": {
|
||||
"color": { "mode": "palette-classic" },
|
||||
"custom": {
|
||||
"axisBorderShow": false,
|
||||
"axisCenteredZero": false,
|
||||
"axisColorMode": "text",
|
||||
"axisLabel": "",
|
||||
"axisPlacement": "auto",
|
||||
"barAlignment": 0,
|
||||
"drawStyle": "line",
|
||||
"fillOpacity": 10,
|
||||
"gradientMode": "none",
|
||||
"hideFrom": { "legend": false, "tooltip": false, "viz": false },
|
||||
"lineInterpolation": "linear",
|
||||
"lineWidth": 1,
|
||||
"pointSize": 5,
|
||||
"scaleDistribution": { "type": "linear" },
|
||||
"showPoints": "never",
|
||||
"spanNulls": false,
|
||||
"stacking": { "group": "A", "mode": "none" },
|
||||
"thresholdsStyle": { "mode": "off" }
|
||||
},
|
||||
"mappings": [],
|
||||
"thresholds": { "mode": "absolute", "steps": [{ "color": "green", "value": null }] },
|
||||
"unit": "short"
|
||||
},
|
||||
"overrides": []
|
||||
},
|
||||
"gridPos": { "h": 8, "w": 12, "x": 0, "y": 7 },
|
||||
"id": 6,
|
||||
"options": {
|
||||
"legend": {
|
||||
"calcs": ["mean", "max"],
|
||||
"displayMode": "table",
|
||||
"placement": "bottom",
|
||||
"showLegend": true
|
||||
},
|
||||
"tooltip": { "mode": "multi", "sort": "desc" }
|
||||
},
|
||||
"targets": [
|
||||
{
|
||||
"expr": "sum(rate(triggerdotdev_batch_queue_items_processed_total[5m])) by (envId)",
|
||||
"legendFormat": "Processed - {{envId}}",
|
||||
"refId": "A"
|
||||
},
|
||||
{
|
||||
"expr": "sum(rate(triggerdotdev_batch_queue_items_failed_total[5m])) by (envId)",
|
||||
"legendFormat": "Failed - {{envId}}",
|
||||
"refId": "B"
|
||||
}
|
||||
],
|
||||
"title": "Items Processed/Failed by Environment",
|
||||
"type": "timeseries"
|
||||
},
|
||||
{
|
||||
"datasource": { "type": "prometheus", "uid": "prometheus" },
|
||||
"fieldConfig": {
|
||||
"defaults": {
|
||||
"color": { "mode": "palette-classic" },
|
||||
"custom": {
|
||||
"axisBorderShow": false,
|
||||
"axisCenteredZero": false,
|
||||
"axisColorMode": "text",
|
||||
"axisLabel": "",
|
||||
"axisPlacement": "auto",
|
||||
"barAlignment": 0,
|
||||
"drawStyle": "line",
|
||||
"fillOpacity": 10,
|
||||
"gradientMode": "none",
|
||||
"hideFrom": { "legend": false, "tooltip": false, "viz": false },
|
||||
"lineInterpolation": "linear",
|
||||
"lineWidth": 1,
|
||||
"pointSize": 5,
|
||||
"scaleDistribution": { "type": "linear" },
|
||||
"showPoints": "never",
|
||||
"spanNulls": false,
|
||||
"stacking": { "group": "A", "mode": "none" },
|
||||
"thresholdsStyle": { "mode": "off" }
|
||||
},
|
||||
"mappings": [],
|
||||
"thresholds": { "mode": "absolute", "steps": [{ "color": "green", "value": null }] },
|
||||
"unit": "short"
|
||||
},
|
||||
"overrides": []
|
||||
},
|
||||
"gridPos": { "h": 8, "w": 12, "x": 12, "y": 7 },
|
||||
"id": 7,
|
||||
"options": {
|
||||
"legend": {
|
||||
"calcs": ["mean", "max"],
|
||||
"displayMode": "table",
|
||||
"placement": "bottom",
|
||||
"showLegend": true
|
||||
},
|
||||
"tooltip": { "mode": "multi", "sort": "desc" }
|
||||
},
|
||||
"targets": [
|
||||
{
|
||||
"expr": "sum(rate(triggerdotdev_batch_queue_batches_enqueued_total[5m]))",
|
||||
"legendFormat": "Enqueued",
|
||||
"refId": "A"
|
||||
},
|
||||
{
|
||||
"expr": "sum(rate(triggerdotdev_batch_queue_batches_completed_total[5m]))",
|
||||
"legendFormat": "Completed",
|
||||
"refId": "B"
|
||||
}
|
||||
],
|
||||
"title": "Batches Enqueued vs Completed",
|
||||
"type": "timeseries"
|
||||
},
|
||||
{
|
||||
"collapsed": false,
|
||||
"gridPos": { "h": 1, "w": 24, "x": 0, "y": 15 },
|
||||
"id": 8,
|
||||
"panels": [],
|
||||
"title": "Latency",
|
||||
"type": "row"
|
||||
},
|
||||
{
|
||||
"datasource": { "type": "prometheus", "uid": "prometheus" },
|
||||
"fieldConfig": {
|
||||
"defaults": {
|
||||
"color": { "mode": "palette-classic" },
|
||||
"custom": {
|
||||
"axisBorderShow": false,
|
||||
"axisCenteredZero": false,
|
||||
"axisColorMode": "text",
|
||||
"axisLabel": "",
|
||||
"axisPlacement": "auto",
|
||||
"barAlignment": 0,
|
||||
"drawStyle": "line",
|
||||
"fillOpacity": 10,
|
||||
"gradientMode": "none",
|
||||
"hideFrom": { "legend": false, "tooltip": false, "viz": false },
|
||||
"lineInterpolation": "linear",
|
||||
"lineWidth": 1,
|
||||
"pointSize": 5,
|
||||
"scaleDistribution": { "type": "linear" },
|
||||
"showPoints": "never",
|
||||
"spanNulls": false,
|
||||
"stacking": { "group": "A", "mode": "none" },
|
||||
"thresholdsStyle": { "mode": "off" }
|
||||
},
|
||||
"mappings": [],
|
||||
"thresholds": { "mode": "absolute", "steps": [{ "color": "green", "value": null }] },
|
||||
"unit": "ms"
|
||||
},
|
||||
"overrides": []
|
||||
},
|
||||
"gridPos": { "h": 8, "w": 12, "x": 0, "y": 16 },
|
||||
"id": 9,
|
||||
"options": {
|
||||
"legend": {
|
||||
"calcs": ["mean", "max"],
|
||||
"displayMode": "table",
|
||||
"placement": "bottom",
|
||||
"showLegend": true
|
||||
},
|
||||
"tooltip": { "mode": "multi", "sort": "desc" }
|
||||
},
|
||||
"targets": [
|
||||
{
|
||||
"expr": "histogram_quantile(0.50, sum(rate(triggerdotdev_batch_queue_item_queue_time_milliseconds_bucket[5m])) by (le))",
|
||||
"legendFormat": "p50",
|
||||
"refId": "A"
|
||||
},
|
||||
{
|
||||
"expr": "histogram_quantile(0.95, sum(rate(triggerdotdev_batch_queue_item_queue_time_milliseconds_bucket[5m])) by (le))",
|
||||
"legendFormat": "p95",
|
||||
"refId": "B"
|
||||
},
|
||||
{
|
||||
"expr": "histogram_quantile(0.99, sum(rate(triggerdotdev_batch_queue_item_queue_time_milliseconds_bucket[5m])) by (le))",
|
||||
"legendFormat": "p99",
|
||||
"refId": "C"
|
||||
}
|
||||
],
|
||||
"title": "Item Queue Time (time from enqueue to processing)",
|
||||
"type": "timeseries"
|
||||
},
|
||||
{
|
||||
"datasource": { "type": "prometheus", "uid": "prometheus" },
|
||||
"fieldConfig": {
|
||||
"defaults": {
|
||||
"color": { "mode": "palette-classic" },
|
||||
"custom": {
|
||||
"axisBorderShow": false,
|
||||
"axisCenteredZero": false,
|
||||
"axisColorMode": "text",
|
||||
"axisLabel": "",
|
||||
"axisPlacement": "auto",
|
||||
"barAlignment": 0,
|
||||
"drawStyle": "line",
|
||||
"fillOpacity": 10,
|
||||
"gradientMode": "none",
|
||||
"hideFrom": { "legend": false, "tooltip": false, "viz": false },
|
||||
"lineInterpolation": "linear",
|
||||
"lineWidth": 1,
|
||||
"pointSize": 5,
|
||||
"scaleDistribution": { "type": "linear" },
|
||||
"showPoints": "never",
|
||||
"spanNulls": false,
|
||||
"stacking": { "group": "A", "mode": "none" },
|
||||
"thresholdsStyle": { "mode": "off" }
|
||||
},
|
||||
"mappings": [],
|
||||
"thresholds": { "mode": "absolute", "steps": [{ "color": "green", "value": null }] },
|
||||
"unit": "ms"
|
||||
},
|
||||
"overrides": []
|
||||
},
|
||||
"gridPos": { "h": 8, "w": 12, "x": 12, "y": 16 },
|
||||
"id": 10,
|
||||
"options": {
|
||||
"legend": {
|
||||
"calcs": ["mean", "max"],
|
||||
"displayMode": "table",
|
||||
"placement": "bottom",
|
||||
"showLegend": true
|
||||
},
|
||||
"tooltip": { "mode": "multi", "sort": "desc" }
|
||||
},
|
||||
"targets": [
|
||||
{
|
||||
"expr": "histogram_quantile(0.50, sum(rate(triggerdotdev_batch_queue_batch_processing_duration_milliseconds_bucket[5m])) by (le))",
|
||||
"legendFormat": "p50",
|
||||
"refId": "A"
|
||||
},
|
||||
{
|
||||
"expr": "histogram_quantile(0.95, sum(rate(triggerdotdev_batch_queue_batch_processing_duration_milliseconds_bucket[5m])) by (le))",
|
||||
"legendFormat": "p95",
|
||||
"refId": "B"
|
||||
},
|
||||
{
|
||||
"expr": "histogram_quantile(0.99, sum(rate(triggerdotdev_batch_queue_batch_processing_duration_milliseconds_bucket[5m])) by (le))",
|
||||
"legendFormat": "p99",
|
||||
"refId": "C"
|
||||
}
|
||||
],
|
||||
"title": "Batch Processing Duration (creation to completion)",
|
||||
"type": "timeseries"
|
||||
},
|
||||
{
|
||||
"collapsed": false,
|
||||
"gridPos": { "h": 1, "w": 24, "x": 0, "y": 24 },
|
||||
"id": 11,
|
||||
"panels": [],
|
||||
"title": "Queue Depth",
|
||||
"type": "row"
|
||||
},
|
||||
{
|
||||
"datasource": { "type": "prometheus", "uid": "prometheus" },
|
||||
"fieldConfig": {
|
||||
"defaults": {
|
||||
"color": { "mode": "palette-classic" },
|
||||
"custom": {
|
||||
"axisBorderShow": false,
|
||||
"axisCenteredZero": false,
|
||||
"axisColorMode": "text",
|
||||
"axisLabel": "",
|
||||
"axisPlacement": "auto",
|
||||
"barAlignment": 0,
|
||||
"drawStyle": "line",
|
||||
"fillOpacity": 10,
|
||||
"gradientMode": "none",
|
||||
"hideFrom": { "legend": false, "tooltip": false, "viz": false },
|
||||
"lineInterpolation": "linear",
|
||||
"lineWidth": 1,
|
||||
"pointSize": 5,
|
||||
"scaleDistribution": { "type": "linear" },
|
||||
"showPoints": "never",
|
||||
"spanNulls": false,
|
||||
"stacking": { "group": "A", "mode": "none" },
|
||||
"thresholdsStyle": { "mode": "off" }
|
||||
},
|
||||
"mappings": [],
|
||||
"thresholds": { "mode": "absolute", "steps": [{ "color": "green", "value": null }] },
|
||||
"unit": "short"
|
||||
},
|
||||
"overrides": []
|
||||
},
|
||||
"gridPos": { "h": 8, "w": 8, "x": 0, "y": 25 },
|
||||
"id": 12,
|
||||
"options": {
|
||||
"legend": {
|
||||
"calcs": ["mean", "max"],
|
||||
"displayMode": "table",
|
||||
"placement": "bottom",
|
||||
"showLegend": true
|
||||
},
|
||||
"tooltip": { "mode": "multi", "sort": "desc" }
|
||||
},
|
||||
"targets": [
|
||||
{
|
||||
"expr": "sum(triggerdotdev_batch_queue_inflight_count_messages)",
|
||||
"legendFormat": "In-flight",
|
||||
"refId": "A"
|
||||
}
|
||||
],
|
||||
"title": "Messages In-Flight",
|
||||
"type": "timeseries"
|
||||
},
|
||||
{
|
||||
"datasource": { "type": "prometheus", "uid": "prometheus" },
|
||||
"fieldConfig": {
|
||||
"defaults": {
|
||||
"color": { "mode": "palette-classic" },
|
||||
"custom": {
|
||||
"axisBorderShow": false,
|
||||
"axisCenteredZero": false,
|
||||
"axisColorMode": "text",
|
||||
"axisLabel": "",
|
||||
"axisPlacement": "auto",
|
||||
"barAlignment": 0,
|
||||
"drawStyle": "line",
|
||||
"fillOpacity": 10,
|
||||
"gradientMode": "none",
|
||||
"hideFrom": { "legend": false, "tooltip": false, "viz": false },
|
||||
"lineInterpolation": "linear",
|
||||
"lineWidth": 1,
|
||||
"pointSize": 5,
|
||||
"scaleDistribution": { "type": "linear" },
|
||||
"showPoints": "never",
|
||||
"spanNulls": false,
|
||||
"stacking": { "group": "A", "mode": "none" },
|
||||
"thresholdsStyle": { "mode": "off" }
|
||||
},
|
||||
"mappings": [],
|
||||
"thresholds": { "mode": "absolute", "steps": [{ "color": "green", "value": null }] },
|
||||
"unit": "short"
|
||||
},
|
||||
"overrides": []
|
||||
},
|
||||
"gridPos": { "h": 8, "w": 8, "x": 8, "y": 25 },
|
||||
"id": 13,
|
||||
"options": {
|
||||
"legend": {
|
||||
"calcs": ["mean", "max"],
|
||||
"displayMode": "table",
|
||||
"placement": "bottom",
|
||||
"showLegend": true
|
||||
},
|
||||
"tooltip": { "mode": "multi", "sort": "desc" }
|
||||
},
|
||||
"targets": [
|
||||
{
|
||||
"expr": "sum(triggerdotdev_batch_queue_master_queue_length_queues)",
|
||||
"legendFormat": "Active Queues",
|
||||
"refId": "A"
|
||||
}
|
||||
],
|
||||
"title": "Active Queues in Master Queue",
|
||||
"type": "timeseries"
|
||||
},
|
||||
{
|
||||
"datasource": { "type": "prometheus", "uid": "prometheus" },
|
||||
"fieldConfig": {
|
||||
"defaults": {
|
||||
"color": { "mode": "thresholds" },
|
||||
"mappings": [],
|
||||
"thresholds": {
|
||||
"mode": "absolute",
|
||||
"steps": [
|
||||
{ "color": "green", "value": null },
|
||||
{ "color": "yellow", "value": 1 },
|
||||
{ "color": "red", "value": 10 }
|
||||
]
|
||||
},
|
||||
"unit": "short"
|
||||
},
|
||||
"overrides": []
|
||||
},
|
||||
"gridPos": { "h": 8, "w": 8, "x": 16, "y": 25 },
|
||||
"id": 14,
|
||||
"options": {
|
||||
"colorMode": "value",
|
||||
"graphMode": "area",
|
||||
"justifyMode": "auto",
|
||||
"orientation": "auto",
|
||||
"reduceOptions": { "calcs": ["lastNotNull"], "fields": "", "values": false },
|
||||
"textMode": "auto"
|
||||
},
|
||||
"pluginVersion": "11.3.0",
|
||||
"targets": [
|
||||
{
|
||||
"expr": "sum(triggerdotdev_batch_queue_dlq_length_messages)",
|
||||
"legendFormat": "DLQ Size",
|
||||
"refId": "A"
|
||||
}
|
||||
],
|
||||
"title": "Dead Letter Queue (should be 0)",
|
||||
"type": "stat"
|
||||
},
|
||||
{
|
||||
"collapsed": false,
|
||||
"gridPos": { "h": 1, "w": 24, "x": 0, "y": 33 },
|
||||
"id": 15,
|
||||
"panels": [],
|
||||
"title": "FairQueue Internals",
|
||||
"type": "row"
|
||||
},
|
||||
{
|
||||
"datasource": { "type": "prometheus", "uid": "prometheus" },
|
||||
"fieldConfig": {
|
||||
"defaults": {
|
||||
"color": { "mode": "palette-classic" },
|
||||
"custom": {
|
||||
"axisBorderShow": false,
|
||||
"axisCenteredZero": false,
|
||||
"axisColorMode": "text",
|
||||
"axisLabel": "",
|
||||
"axisPlacement": "auto",
|
||||
"barAlignment": 0,
|
||||
"drawStyle": "line",
|
||||
"fillOpacity": 10,
|
||||
"gradientMode": "none",
|
||||
"hideFrom": { "legend": false, "tooltip": false, "viz": false },
|
||||
"lineInterpolation": "linear",
|
||||
"lineWidth": 1,
|
||||
"pointSize": 5,
|
||||
"scaleDistribution": { "type": "linear" },
|
||||
"showPoints": "never",
|
||||
"spanNulls": false,
|
||||
"stacking": { "group": "A", "mode": "none" },
|
||||
"thresholdsStyle": { "mode": "off" }
|
||||
},
|
||||
"mappings": [],
|
||||
"thresholds": { "mode": "absolute", "steps": [{ "color": "green", "value": null }] },
|
||||
"unit": "short"
|
||||
},
|
||||
"overrides": []
|
||||
},
|
||||
"gridPos": { "h": 8, "w": 12, "x": 0, "y": 34 },
|
||||
"id": 16,
|
||||
"options": {
|
||||
"legend": {
|
||||
"calcs": ["mean", "max"],
|
||||
"displayMode": "table",
|
||||
"placement": "bottom",
|
||||
"showLegend": true
|
||||
},
|
||||
"tooltip": { "mode": "multi", "sort": "desc" }
|
||||
},
|
||||
"targets": [
|
||||
{
|
||||
"expr": "sum(rate(triggerdotdev_batch_queue_messages_completed_total[5m]))",
|
||||
"legendFormat": "Completed",
|
||||
"refId": "A"
|
||||
},
|
||||
{
|
||||
"expr": "sum(rate(triggerdotdev_batch_queue_messages_failed_total[5m]))",
|
||||
"legendFormat": "Failed",
|
||||
"refId": "B"
|
||||
},
|
||||
{
|
||||
"expr": "sum(rate(triggerdotdev_batch_queue_messages_retried_total[5m]))",
|
||||
"legendFormat": "Retried",
|
||||
"refId": "C"
|
||||
}
|
||||
],
|
||||
"title": "FairQueue Message Processing",
|
||||
"type": "timeseries"
|
||||
},
|
||||
{
|
||||
"datasource": { "type": "prometheus", "uid": "prometheus" },
|
||||
"fieldConfig": {
|
||||
"defaults": {
|
||||
"color": { "mode": "palette-classic" },
|
||||
"custom": {
|
||||
"axisBorderShow": false,
|
||||
"axisCenteredZero": false,
|
||||
"axisColorMode": "text",
|
||||
"axisLabel": "",
|
||||
"axisPlacement": "auto",
|
||||
"barAlignment": 0,
|
||||
"drawStyle": "line",
|
||||
"fillOpacity": 10,
|
||||
"gradientMode": "none",
|
||||
"hideFrom": { "legend": false, "tooltip": false, "viz": false },
|
||||
"lineInterpolation": "linear",
|
||||
"lineWidth": 1,
|
||||
"pointSize": 5,
|
||||
"scaleDistribution": { "type": "linear" },
|
||||
"showPoints": "never",
|
||||
"spanNulls": false,
|
||||
"stacking": { "group": "A", "mode": "none" },
|
||||
"thresholdsStyle": { "mode": "off" }
|
||||
},
|
||||
"mappings": [],
|
||||
"thresholds": { "mode": "absolute", "steps": [{ "color": "green", "value": null }] },
|
||||
"unit": "ms"
|
||||
},
|
||||
"overrides": []
|
||||
},
|
||||
"gridPos": { "h": 8, "w": 12, "x": 12, "y": 34 },
|
||||
"id": 17,
|
||||
"options": {
|
||||
"legend": {
|
||||
"calcs": ["mean", "max"],
|
||||
"displayMode": "table",
|
||||
"placement": "bottom",
|
||||
"showLegend": true
|
||||
},
|
||||
"tooltip": { "mode": "multi", "sort": "desc" }
|
||||
},
|
||||
"targets": [
|
||||
{
|
||||
"expr": "histogram_quantile(0.50, sum(rate(triggerdotdev_batch_queue_message_processing_time_milliseconds_bucket[5m])) by (le))",
|
||||
"legendFormat": "p50",
|
||||
"refId": "A"
|
||||
},
|
||||
{
|
||||
"expr": "histogram_quantile(0.95, sum(rate(triggerdotdev_batch_queue_message_processing_time_milliseconds_bucket[5m])) by (le))",
|
||||
"legendFormat": "p95",
|
||||
"refId": "B"
|
||||
},
|
||||
{
|
||||
"expr": "histogram_quantile(0.99, sum(rate(triggerdotdev_batch_queue_message_processing_time_milliseconds_bucket[5m])) by (le))",
|
||||
"legendFormat": "p99",
|
||||
"refId": "C"
|
||||
}
|
||||
],
|
||||
"title": "FairQueue Message Processing Time",
|
||||
"type": "timeseries"
|
||||
},
|
||||
{
|
||||
"collapsed": false,
|
||||
"gridPos": { "h": 1, "w": 24, "x": 0, "y": 42 },
|
||||
"id": 18,
|
||||
"panels": [],
|
||||
"title": "Items Enqueued",
|
||||
"type": "row"
|
||||
},
|
||||
{
|
||||
"datasource": { "type": "prometheus", "uid": "prometheus" },
|
||||
"fieldConfig": {
|
||||
"defaults": {
|
||||
"color": { "mode": "palette-classic" },
|
||||
"custom": {
|
||||
"axisBorderShow": false,
|
||||
"axisCenteredZero": false,
|
||||
"axisColorMode": "text",
|
||||
"axisLabel": "",
|
||||
"axisPlacement": "auto",
|
||||
"barAlignment": 0,
|
||||
"drawStyle": "line",
|
||||
"fillOpacity": 10,
|
||||
"gradientMode": "none",
|
||||
"hideFrom": { "legend": false, "tooltip": false, "viz": false },
|
||||
"lineInterpolation": "linear",
|
||||
"lineWidth": 1,
|
||||
"pointSize": 5,
|
||||
"scaleDistribution": { "type": "linear" },
|
||||
"showPoints": "never",
|
||||
"spanNulls": false,
|
||||
"stacking": { "group": "A", "mode": "none" },
|
||||
"thresholdsStyle": { "mode": "off" }
|
||||
},
|
||||
"mappings": [],
|
||||
"thresholds": { "mode": "absolute", "steps": [{ "color": "green", "value": null }] },
|
||||
"unit": "short"
|
||||
},
|
||||
"overrides": []
|
||||
},
|
||||
"gridPos": { "h": 8, "w": 24, "x": 0, "y": 43 },
|
||||
"id": 19,
|
||||
"options": {
|
||||
"legend": {
|
||||
"calcs": ["mean", "max"],
|
||||
"displayMode": "table",
|
||||
"placement": "bottom",
|
||||
"showLegend": true
|
||||
},
|
||||
"tooltip": { "mode": "multi", "sort": "desc" }
|
||||
},
|
||||
"targets": [
|
||||
{
|
||||
"expr": "sum(rate(triggerdotdev_batch_queue_items_enqueued_total[5m])) by (envId)",
|
||||
"legendFormat": "Enqueued - {{envId}}",
|
||||
"refId": "A"
|
||||
}
|
||||
],
|
||||
"title": "Items Enqueued Rate by Environment",
|
||||
"type": "timeseries"
|
||||
}
|
||||
],
|
||||
"refresh": "10s",
|
||||
"schemaVersion": 39,
|
||||
"tags": ["trigger.dev", "batch-queue"],
|
||||
"templating": { "list": [] },
|
||||
"time": { "from": "now-15m", "to": "now" },
|
||||
"timepicker": {},
|
||||
"timezone": "browser",
|
||||
"title": "Batch Queue Metrics",
|
||||
"uid": "batch-queue-metrics",
|
||||
"version": 3
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
# Grafana dashboard provisioning
|
||||
# Automatically loads dashboard JSON files from the dashboards folder
|
||||
|
||||
apiVersion: 1
|
||||
|
||||
providers:
|
||||
- name: "Trigger.dev Dashboards"
|
||||
orgId: 1
|
||||
folder: "Trigger.dev"
|
||||
folderUid: "triggerdotdev"
|
||||
type: file
|
||||
disableDeletion: false
|
||||
updateIntervalSeconds: 30
|
||||
allowUiUpdates: true
|
||||
options:
|
||||
path: /etc/grafana/provisioning/dashboards
|
||||
@@ -0,0 +1,468 @@
|
||||
{
|
||||
"annotations": {
|
||||
"list": []
|
||||
},
|
||||
"editable": true,
|
||||
"fiscalYearStartMonth": 0,
|
||||
"graphTooltip": 1,
|
||||
"links": [],
|
||||
"panels": [
|
||||
{
|
||||
"collapsed": false,
|
||||
"gridPos": { "h": 1, "w": 24, "x": 0, "y": 0 },
|
||||
"id": 1,
|
||||
"panels": [],
|
||||
"title": "Event Loop Health",
|
||||
"type": "row"
|
||||
},
|
||||
{
|
||||
"datasource": { "type": "prometheus", "uid": "prometheus" },
|
||||
"fieldConfig": {
|
||||
"defaults": {
|
||||
"color": { "mode": "thresholds" },
|
||||
"mappings": [],
|
||||
"max": 1,
|
||||
"min": 0,
|
||||
"thresholds": {
|
||||
"mode": "absolute",
|
||||
"steps": [
|
||||
{ "color": "green", "value": null },
|
||||
{ "color": "yellow", "value": 0.7 },
|
||||
{ "color": "red", "value": 0.9 }
|
||||
]
|
||||
},
|
||||
"unit": "percentunit"
|
||||
},
|
||||
"overrides": []
|
||||
},
|
||||
"gridPos": { "h": 6, "w": 6, "x": 0, "y": 1 },
|
||||
"id": 2,
|
||||
"options": {
|
||||
"colorMode": "value",
|
||||
"graphMode": "area",
|
||||
"justifyMode": "auto",
|
||||
"orientation": "auto",
|
||||
"reduceOptions": { "calcs": ["lastNotNull"], "fields": "", "values": false },
|
||||
"textMode": "auto"
|
||||
},
|
||||
"pluginVersion": "11.3.0",
|
||||
"targets": [
|
||||
{
|
||||
"expr": "triggerdotdev_nodejs_event_loop_utilization_ratio",
|
||||
"legendFormat": "ELU",
|
||||
"refId": "A"
|
||||
}
|
||||
],
|
||||
"title": "Event Loop Utilization",
|
||||
"type": "stat"
|
||||
},
|
||||
{
|
||||
"datasource": { "type": "prometheus", "uid": "prometheus" },
|
||||
"fieldConfig": {
|
||||
"defaults": {
|
||||
"color": { "mode": "thresholds" },
|
||||
"mappings": [],
|
||||
"thresholds": {
|
||||
"mode": "absolute",
|
||||
"steps": [
|
||||
{ "color": "green", "value": null },
|
||||
{ "color": "yellow", "value": 0.1 },
|
||||
{ "color": "red", "value": 0.5 }
|
||||
]
|
||||
},
|
||||
"unit": "s"
|
||||
},
|
||||
"overrides": []
|
||||
},
|
||||
"gridPos": { "h": 6, "w": 6, "x": 6, "y": 1 },
|
||||
"id": 3,
|
||||
"options": {
|
||||
"colorMode": "value",
|
||||
"graphMode": "area",
|
||||
"justifyMode": "auto",
|
||||
"orientation": "auto",
|
||||
"reduceOptions": { "calcs": ["lastNotNull"], "fields": "", "values": false },
|
||||
"textMode": "auto"
|
||||
},
|
||||
"pluginVersion": "11.3.0",
|
||||
"targets": [
|
||||
{
|
||||
"expr": "triggerdotdev_nodejs_eventloop_lag_p99_seconds",
|
||||
"legendFormat": "p99 Lag",
|
||||
"refId": "A"
|
||||
}
|
||||
],
|
||||
"title": "Event Loop Lag (p99)",
|
||||
"type": "stat"
|
||||
},
|
||||
{
|
||||
"datasource": { "type": "prometheus", "uid": "prometheus" },
|
||||
"fieldConfig": {
|
||||
"defaults": {
|
||||
"color": { "mode": "thresholds" },
|
||||
"mappings": [],
|
||||
"thresholds": {
|
||||
"mode": "absolute",
|
||||
"steps": [
|
||||
{ "color": "green", "value": null },
|
||||
{ "color": "yellow", "value": 0.05 },
|
||||
{ "color": "red", "value": 0.1 }
|
||||
]
|
||||
},
|
||||
"unit": "s"
|
||||
},
|
||||
"overrides": []
|
||||
},
|
||||
"gridPos": { "h": 6, "w": 6, "x": 12, "y": 1 },
|
||||
"id": 4,
|
||||
"options": {
|
||||
"colorMode": "value",
|
||||
"graphMode": "area",
|
||||
"justifyMode": "auto",
|
||||
"orientation": "auto",
|
||||
"reduceOptions": { "calcs": ["lastNotNull"], "fields": "", "values": false },
|
||||
"textMode": "auto"
|
||||
},
|
||||
"pluginVersion": "11.3.0",
|
||||
"targets": [
|
||||
{
|
||||
"expr": "triggerdotdev_nodejs_eventloop_lag_mean_seconds",
|
||||
"legendFormat": "Mean Lag",
|
||||
"refId": "A"
|
||||
}
|
||||
],
|
||||
"title": "Event Loop Lag (Mean)",
|
||||
"type": "stat"
|
||||
},
|
||||
{
|
||||
"datasource": { "type": "prometheus", "uid": "prometheus" },
|
||||
"fieldConfig": {
|
||||
"defaults": {
|
||||
"color": { "mode": "thresholds" },
|
||||
"mappings": [],
|
||||
"thresholds": {
|
||||
"mode": "absolute",
|
||||
"steps": [{ "color": "green", "value": null }]
|
||||
},
|
||||
"unit": "short"
|
||||
},
|
||||
"overrides": []
|
||||
},
|
||||
"gridPos": { "h": 6, "w": 6, "x": 18, "y": 1 },
|
||||
"id": 5,
|
||||
"options": {
|
||||
"colorMode": "value",
|
||||
"graphMode": "none",
|
||||
"justifyMode": "auto",
|
||||
"orientation": "auto",
|
||||
"reduceOptions": { "calcs": ["lastNotNull"], "fields": "", "values": false },
|
||||
"textMode": "auto"
|
||||
},
|
||||
"pluginVersion": "11.3.0",
|
||||
"targets": [
|
||||
{
|
||||
"expr": "triggerdotdev_nodejs_uv_threadpool_size_threads",
|
||||
"legendFormat": "UV Threadpool",
|
||||
"refId": "A"
|
||||
}
|
||||
],
|
||||
"title": "UV Threadpool Size",
|
||||
"type": "stat"
|
||||
},
|
||||
{
|
||||
"datasource": { "type": "prometheus", "uid": "prometheus" },
|
||||
"fieldConfig": {
|
||||
"defaults": {
|
||||
"color": { "mode": "palette-classic" },
|
||||
"custom": {
|
||||
"axisBorderShow": false,
|
||||
"axisCenteredZero": false,
|
||||
"axisColorMode": "text",
|
||||
"axisLabel": "",
|
||||
"axisPlacement": "auto",
|
||||
"barAlignment": 0,
|
||||
"drawStyle": "line",
|
||||
"fillOpacity": 10,
|
||||
"gradientMode": "none",
|
||||
"hideFrom": { "legend": false, "tooltip": false, "viz": false },
|
||||
"lineInterpolation": "linear",
|
||||
"lineWidth": 1,
|
||||
"pointSize": 5,
|
||||
"scaleDistribution": { "type": "linear" },
|
||||
"showPoints": "never",
|
||||
"spanNulls": false,
|
||||
"stacking": { "group": "A", "mode": "none" },
|
||||
"thresholdsStyle": { "mode": "off" }
|
||||
},
|
||||
"mappings": [],
|
||||
"max": 1,
|
||||
"min": 0,
|
||||
"thresholds": { "mode": "absolute", "steps": [{ "color": "green", "value": null }] },
|
||||
"unit": "percentunit"
|
||||
},
|
||||
"overrides": []
|
||||
},
|
||||
"gridPos": { "h": 8, "w": 12, "x": 0, "y": 7 },
|
||||
"id": 6,
|
||||
"options": {
|
||||
"legend": {
|
||||
"calcs": ["mean", "max"],
|
||||
"displayMode": "table",
|
||||
"placement": "bottom",
|
||||
"showLegend": true
|
||||
},
|
||||
"tooltip": { "mode": "multi", "sort": "desc" }
|
||||
},
|
||||
"targets": [
|
||||
{
|
||||
"expr": "triggerdotdev_nodejs_event_loop_utilization_ratio",
|
||||
"legendFormat": "Event Loop Utilization",
|
||||
"refId": "A"
|
||||
}
|
||||
],
|
||||
"title": "Event Loop Utilization Over Time",
|
||||
"type": "timeseries"
|
||||
},
|
||||
{
|
||||
"datasource": { "type": "prometheus", "uid": "prometheus" },
|
||||
"fieldConfig": {
|
||||
"defaults": {
|
||||
"color": { "mode": "palette-classic" },
|
||||
"custom": {
|
||||
"axisBorderShow": false,
|
||||
"axisCenteredZero": false,
|
||||
"axisColorMode": "text",
|
||||
"axisLabel": "",
|
||||
"axisPlacement": "auto",
|
||||
"barAlignment": 0,
|
||||
"drawStyle": "line",
|
||||
"fillOpacity": 10,
|
||||
"gradientMode": "none",
|
||||
"hideFrom": { "legend": false, "tooltip": false, "viz": false },
|
||||
"lineInterpolation": "linear",
|
||||
"lineWidth": 1,
|
||||
"pointSize": 5,
|
||||
"scaleDistribution": { "type": "linear" },
|
||||
"showPoints": "never",
|
||||
"spanNulls": false,
|
||||
"stacking": { "group": "A", "mode": "none" },
|
||||
"thresholdsStyle": { "mode": "off" }
|
||||
},
|
||||
"mappings": [],
|
||||
"thresholds": { "mode": "absolute", "steps": [{ "color": "green", "value": null }] },
|
||||
"unit": "s"
|
||||
},
|
||||
"overrides": []
|
||||
},
|
||||
"gridPos": { "h": 8, "w": 12, "x": 12, "y": 7 },
|
||||
"id": 7,
|
||||
"options": {
|
||||
"legend": {
|
||||
"calcs": ["mean", "max"],
|
||||
"displayMode": "table",
|
||||
"placement": "bottom",
|
||||
"showLegend": true
|
||||
},
|
||||
"tooltip": { "mode": "multi", "sort": "desc" }
|
||||
},
|
||||
"targets": [
|
||||
{
|
||||
"expr": "triggerdotdev_nodejs_eventloop_lag_p50_seconds",
|
||||
"legendFormat": "p50",
|
||||
"refId": "A"
|
||||
},
|
||||
{
|
||||
"expr": "triggerdotdev_nodejs_eventloop_lag_p90_seconds",
|
||||
"legendFormat": "p90",
|
||||
"refId": "B"
|
||||
},
|
||||
{
|
||||
"expr": "triggerdotdev_nodejs_eventloop_lag_p99_seconds",
|
||||
"legendFormat": "p99",
|
||||
"refId": "C"
|
||||
},
|
||||
{
|
||||
"expr": "triggerdotdev_nodejs_eventloop_lag_max_seconds",
|
||||
"legendFormat": "max",
|
||||
"refId": "D"
|
||||
}
|
||||
],
|
||||
"title": "Event Loop Lag Percentiles",
|
||||
"type": "timeseries"
|
||||
},
|
||||
{
|
||||
"collapsed": false,
|
||||
"gridPos": { "h": 1, "w": 24, "x": 0, "y": 15 },
|
||||
"id": 8,
|
||||
"panels": [],
|
||||
"title": "Handles & Requests",
|
||||
"type": "row"
|
||||
},
|
||||
{
|
||||
"datasource": { "type": "prometheus", "uid": "prometheus" },
|
||||
"fieldConfig": {
|
||||
"defaults": {
|
||||
"color": { "mode": "palette-classic" },
|
||||
"custom": {
|
||||
"axisBorderShow": false,
|
||||
"axisCenteredZero": false,
|
||||
"axisColorMode": "text",
|
||||
"axisLabel": "",
|
||||
"axisPlacement": "auto",
|
||||
"barAlignment": 0,
|
||||
"drawStyle": "line",
|
||||
"fillOpacity": 10,
|
||||
"gradientMode": "none",
|
||||
"hideFrom": { "legend": false, "tooltip": false, "viz": false },
|
||||
"lineInterpolation": "linear",
|
||||
"lineWidth": 1,
|
||||
"pointSize": 5,
|
||||
"scaleDistribution": { "type": "linear" },
|
||||
"showPoints": "never",
|
||||
"spanNulls": false,
|
||||
"stacking": { "group": "A", "mode": "none" },
|
||||
"thresholdsStyle": { "mode": "off" }
|
||||
},
|
||||
"mappings": [],
|
||||
"thresholds": { "mode": "absolute", "steps": [{ "color": "green", "value": null }] },
|
||||
"unit": "short"
|
||||
},
|
||||
"overrides": []
|
||||
},
|
||||
"gridPos": { "h": 8, "w": 12, "x": 0, "y": 16 },
|
||||
"id": 9,
|
||||
"options": {
|
||||
"legend": {
|
||||
"calcs": ["mean", "max"],
|
||||
"displayMode": "table",
|
||||
"placement": "bottom",
|
||||
"showLegend": true
|
||||
},
|
||||
"tooltip": { "mode": "multi", "sort": "desc" }
|
||||
},
|
||||
"targets": [
|
||||
{
|
||||
"expr": "triggerdotdev_nodejs_active_handles_total_handles",
|
||||
"legendFormat": "Total Handles",
|
||||
"refId": "A"
|
||||
}
|
||||
],
|
||||
"title": "Active Handles (Total)",
|
||||
"type": "timeseries"
|
||||
},
|
||||
{
|
||||
"datasource": { "type": "prometheus", "uid": "prometheus" },
|
||||
"fieldConfig": {
|
||||
"defaults": {
|
||||
"color": { "mode": "palette-classic" },
|
||||
"custom": {
|
||||
"axisBorderShow": false,
|
||||
"axisCenteredZero": false,
|
||||
"axisColorMode": "text",
|
||||
"axisLabel": "",
|
||||
"axisPlacement": "auto",
|
||||
"barAlignment": 0,
|
||||
"drawStyle": "line",
|
||||
"fillOpacity": 10,
|
||||
"gradientMode": "none",
|
||||
"hideFrom": { "legend": false, "tooltip": false, "viz": false },
|
||||
"lineInterpolation": "linear",
|
||||
"lineWidth": 1,
|
||||
"pointSize": 5,
|
||||
"scaleDistribution": { "type": "linear" },
|
||||
"showPoints": "never",
|
||||
"spanNulls": false,
|
||||
"stacking": { "group": "A", "mode": "none" },
|
||||
"thresholdsStyle": { "mode": "off" }
|
||||
},
|
||||
"mappings": [],
|
||||
"thresholds": { "mode": "absolute", "steps": [{ "color": "green", "value": null }] },
|
||||
"unit": "short"
|
||||
},
|
||||
"overrides": []
|
||||
},
|
||||
"gridPos": { "h": 8, "w": 12, "x": 12, "y": 16 },
|
||||
"id": 10,
|
||||
"options": {
|
||||
"legend": {
|
||||
"calcs": ["mean", "max"],
|
||||
"displayMode": "table",
|
||||
"placement": "bottom",
|
||||
"showLegend": true
|
||||
},
|
||||
"tooltip": { "mode": "multi", "sort": "desc" }
|
||||
},
|
||||
"targets": [
|
||||
{
|
||||
"expr": "triggerdotdev_nodejs_active_requests_total_requests",
|
||||
"legendFormat": "Total Requests",
|
||||
"refId": "A"
|
||||
}
|
||||
],
|
||||
"title": "Active Requests (Total)",
|
||||
"type": "timeseries"
|
||||
},
|
||||
{
|
||||
"datasource": { "type": "prometheus", "uid": "prometheus" },
|
||||
"fieldConfig": {
|
||||
"defaults": {
|
||||
"color": { "mode": "palette-classic" },
|
||||
"custom": {
|
||||
"axisBorderShow": false,
|
||||
"axisCenteredZero": false,
|
||||
"axisColorMode": "text",
|
||||
"axisLabel": "",
|
||||
"axisPlacement": "auto",
|
||||
"barAlignment": 0,
|
||||
"drawStyle": "line",
|
||||
"fillOpacity": 10,
|
||||
"gradientMode": "none",
|
||||
"hideFrom": { "legend": false, "tooltip": false, "viz": false },
|
||||
"lineInterpolation": "linear",
|
||||
"lineWidth": 1,
|
||||
"pointSize": 5,
|
||||
"scaleDistribution": { "type": "linear" },
|
||||
"showPoints": "never",
|
||||
"spanNulls": false,
|
||||
"stacking": { "group": "A", "mode": "normal" },
|
||||
"thresholdsStyle": { "mode": "off" }
|
||||
},
|
||||
"mappings": [],
|
||||
"thresholds": { "mode": "absolute", "steps": [{ "color": "green", "value": null }] },
|
||||
"unit": "short"
|
||||
},
|
||||
"overrides": []
|
||||
},
|
||||
"gridPos": { "h": 8, "w": 24, "x": 0, "y": 24 },
|
||||
"id": 11,
|
||||
"options": {
|
||||
"legend": {
|
||||
"calcs": ["mean", "max"],
|
||||
"displayMode": "table",
|
||||
"placement": "right",
|
||||
"showLegend": true
|
||||
},
|
||||
"tooltip": { "mode": "multi", "sort": "desc" }
|
||||
},
|
||||
"targets": [
|
||||
{
|
||||
"expr": "triggerdotdev_nodejs_active_handles_handles",
|
||||
"legendFormat": "{{type}}",
|
||||
"refId": "A"
|
||||
}
|
||||
],
|
||||
"title": "Active Handles by Type",
|
||||
"type": "timeseries"
|
||||
}
|
||||
],
|
||||
"refresh": "10s",
|
||||
"schemaVersion": 39,
|
||||
"tags": ["trigger.dev", "nodejs", "runtime"],
|
||||
"templating": { "list": [] },
|
||||
"time": { "from": "now-15m", "to": "now" },
|
||||
"timepicker": {},
|
||||
"timezone": "browser",
|
||||
"title": "Node.js Runtime",
|
||||
"uid": "nodejs-runtime",
|
||||
"version": 1
|
||||
}
|
||||
@@ -0,0 +1,498 @@
|
||||
{
|
||||
"title": "Realtime Native Backend",
|
||||
"uid": "realtime-native",
|
||||
"tags": ["trigger.dev", "realtime"],
|
||||
"timezone": "browser",
|
||||
"schemaVersion": 39,
|
||||
"refresh": "10s",
|
||||
"time": {
|
||||
"from": "now-30m",
|
||||
"to": "now"
|
||||
},
|
||||
"editable": true,
|
||||
"fiscalYearStartMonth": 0,
|
||||
"graphTooltip": 1,
|
||||
"links": [],
|
||||
"annotations": {
|
||||
"list": []
|
||||
},
|
||||
"templating": {
|
||||
"list": []
|
||||
},
|
||||
"panels": [
|
||||
{
|
||||
"id": 1,
|
||||
"type": "timeseries",
|
||||
"title": "Delivery lag (write \u2192 emission)",
|
||||
"datasource": {
|
||||
"type": "prometheus",
|
||||
"uid": "prometheus"
|
||||
},
|
||||
"gridPos": {
|
||||
"h": 8,
|
||||
"w": 8,
|
||||
"x": 0,
|
||||
"y": 0
|
||||
},
|
||||
"targets": [
|
||||
{
|
||||
"refId": "A",
|
||||
"datasource": {
|
||||
"type": "prometheus",
|
||||
"uid": "prometheus"
|
||||
},
|
||||
"expr": "histogram_quantile(0.5, sum(rate(triggerdotdev_realtime_native_delivery_lag_ms_milliseconds_bucket[$__rate_interval])) by (le))",
|
||||
"legendFormat": "p50"
|
||||
},
|
||||
{
|
||||
"refId": "B",
|
||||
"datasource": {
|
||||
"type": "prometheus",
|
||||
"uid": "prometheus"
|
||||
},
|
||||
"expr": "histogram_quantile(0.99, sum(rate(triggerdotdev_realtime_native_delivery_lag_ms_milliseconds_bucket[$__rate_interval])) by (le))",
|
||||
"legendFormat": "p99"
|
||||
}
|
||||
],
|
||||
"fieldConfig": {
|
||||
"defaults": {
|
||||
"unit": "ms",
|
||||
"custom": {
|
||||
"drawStyle": "line",
|
||||
"lineWidth": 1,
|
||||
"fillOpacity": 8,
|
||||
"showPoints": "never"
|
||||
}
|
||||
},
|
||||
"overrides": []
|
||||
},
|
||||
"options": {
|
||||
"legend": {
|
||||
"displayMode": "list",
|
||||
"placement": "bottom"
|
||||
},
|
||||
"tooltip": {
|
||||
"mode": "multi"
|
||||
}
|
||||
},
|
||||
"description": "The end-to-end SLI: now minus the newest emitted row's updatedAt. A p99 approaching the ~20s backstop hold means live wakes are being missed."
|
||||
},
|
||||
{
|
||||
"id": 2,
|
||||
"type": "timeseries",
|
||||
"title": "Live polls by path",
|
||||
"datasource": {
|
||||
"type": "prometheus",
|
||||
"uid": "prometheus"
|
||||
},
|
||||
"gridPos": {
|
||||
"h": 8,
|
||||
"w": 8,
|
||||
"x": 8,
|
||||
"y": 0
|
||||
},
|
||||
"targets": [
|
||||
{
|
||||
"refId": "A",
|
||||
"datasource": {
|
||||
"type": "prometheus",
|
||||
"uid": "prometheus"
|
||||
},
|
||||
"expr": "sum(rate(triggerdotdev_realtime_native_live_polls_total[$__rate_interval])) by (path)",
|
||||
"legendFormat": "{{path}}"
|
||||
}
|
||||
],
|
||||
"fieldConfig": {
|
||||
"defaults": {
|
||||
"custom": {
|
||||
"drawStyle": "line",
|
||||
"lineWidth": 1,
|
||||
"fillOpacity": 8,
|
||||
"showPoints": "never"
|
||||
}
|
||||
},
|
||||
"overrides": []
|
||||
},
|
||||
"options": {
|
||||
"legend": {
|
||||
"displayMode": "list",
|
||||
"placement": "bottom"
|
||||
},
|
||||
"tooltip": {
|
||||
"mode": "multi"
|
||||
}
|
||||
},
|
||||
"description": "fast-hydrate = router wake, no ClickHouse. full-resolve = backstop. cold-resolve = fresh env subscription probed (instance hop / first poll)."
|
||||
},
|
||||
{
|
||||
"id": 3,
|
||||
"type": "stat",
|
||||
"title": "Backstop DELIVERED (should be ~0)",
|
||||
"datasource": {
|
||||
"type": "prometheus",
|
||||
"uid": "prometheus"
|
||||
},
|
||||
"gridPos": {
|
||||
"h": 8,
|
||||
"w": 8,
|
||||
"x": 16,
|
||||
"y": 0
|
||||
},
|
||||
"targets": [
|
||||
{
|
||||
"refId": "A",
|
||||
"datasource": {
|
||||
"type": "prometheus",
|
||||
"uid": "prometheus"
|
||||
},
|
||||
"expr": "sum(rate(triggerdotdev_realtime_native_backstops_total{result=\"delivered\"}[5m])) or vector(0)",
|
||||
"legendFormat": "delivered/s"
|
||||
}
|
||||
],
|
||||
"fieldConfig": {
|
||||
"defaults": {
|
||||
"thresholds": {
|
||||
"mode": "absolute",
|
||||
"steps": [
|
||||
{
|
||||
"color": "green",
|
||||
"value": null
|
||||
},
|
||||
{
|
||||
"color": "red",
|
||||
"value": 0.01
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"overrides": []
|
||||
},
|
||||
"options": {
|
||||
"colorMode": "background",
|
||||
"graphMode": "area",
|
||||
"reduceOptions": {
|
||||
"calcs": ["lastNotNull"]
|
||||
}
|
||||
},
|
||||
"description": "A backstop that finds missed changes means the notify/replay path is leaking. Alert on sustained non-zero."
|
||||
},
|
||||
{
|
||||
"id": 4,
|
||||
"type": "timeseries",
|
||||
"title": "Wakeups by reason",
|
||||
"datasource": {
|
||||
"type": "prometheus",
|
||||
"uid": "prometheus"
|
||||
},
|
||||
"gridPos": {
|
||||
"h": 8,
|
||||
"w": 8,
|
||||
"x": 0,
|
||||
"y": 8
|
||||
},
|
||||
"targets": [
|
||||
{
|
||||
"refId": "A",
|
||||
"datasource": {
|
||||
"type": "prometheus",
|
||||
"uid": "prometheus"
|
||||
},
|
||||
"expr": "sum(rate(triggerdotdev_realtime_native_wakeups_total[$__rate_interval])) by (reason)",
|
||||
"legendFormat": "{{reason}}"
|
||||
}
|
||||
],
|
||||
"fieldConfig": {
|
||||
"defaults": {
|
||||
"custom": {
|
||||
"drawStyle": "line",
|
||||
"lineWidth": 1,
|
||||
"fillOpacity": 8,
|
||||
"showPoints": "never"
|
||||
}
|
||||
},
|
||||
"overrides": []
|
||||
},
|
||||
"options": {
|
||||
"legend": {
|
||||
"displayMode": "list",
|
||||
"placement": "bottom"
|
||||
},
|
||||
"tooltip": {
|
||||
"mode": "multi"
|
||||
}
|
||||
},
|
||||
"description": "notify = the architecture working. A rising timeout share with active traffic = publishes not routing."
|
||||
},
|
||||
{
|
||||
"id": 5,
|
||||
"type": "timeseries",
|
||||
"title": "Gap recovery: replays + evictions",
|
||||
"datasource": {
|
||||
"type": "prometheus",
|
||||
"uid": "prometheus"
|
||||
},
|
||||
"gridPos": {
|
||||
"h": 8,
|
||||
"w": 8,
|
||||
"x": 8,
|
||||
"y": 8
|
||||
},
|
||||
"targets": [
|
||||
{
|
||||
"refId": "A",
|
||||
"datasource": {
|
||||
"type": "prometheus",
|
||||
"uid": "prometheus"
|
||||
},
|
||||
"expr": "sum(rate(triggerdotdev_realtime_native_replays_total[$__rate_interval])) by (result)",
|
||||
"legendFormat": "replay {{result}}"
|
||||
},
|
||||
{
|
||||
"refId": "B",
|
||||
"datasource": {
|
||||
"type": "prometheus",
|
||||
"uid": "prometheus"
|
||||
},
|
||||
"expr": "sum(rate(triggerdotdev_realtime_native_replay_evictions_total[$__rate_interval])) by (reason)",
|
||||
"legendFormat": "evict {{reason}}"
|
||||
}
|
||||
],
|
||||
"fieldConfig": {
|
||||
"defaults": {
|
||||
"custom": {
|
||||
"drawStyle": "line",
|
||||
"lineWidth": 1,
|
||||
"fillOpacity": 8,
|
||||
"showPoints": "never"
|
||||
}
|
||||
},
|
||||
"overrides": []
|
||||
},
|
||||
"options": {
|
||||
"legend": {
|
||||
"displayMode": "list",
|
||||
"placement": "bottom"
|
||||
},
|
||||
"tooltip": {
|
||||
"mode": "multi"
|
||||
}
|
||||
},
|
||||
"description": "Replays recover records that landed between a connection's polls. 'evict cap' = an env churns more runs than the buffer window holds \u2014 retune REPLAY_MAX_RUNS / WINDOW_MS."
|
||||
},
|
||||
{
|
||||
"id": 6,
|
||||
"type": "timeseries",
|
||||
"title": "Rows per emission (p99)",
|
||||
"datasource": {
|
||||
"type": "prometheus",
|
||||
"uid": "prometheus"
|
||||
},
|
||||
"gridPos": {
|
||||
"h": 8,
|
||||
"w": 8,
|
||||
"x": 16,
|
||||
"y": 8
|
||||
},
|
||||
"targets": [
|
||||
{
|
||||
"refId": "A",
|
||||
"datasource": {
|
||||
"type": "prometheus",
|
||||
"uid": "prometheus"
|
||||
},
|
||||
"expr": "histogram_quantile(0.99, sum(rate(triggerdotdev_realtime_native_emitted_rows_bucket[$__rate_interval])) by (le))",
|
||||
"legendFormat": "p99 rows"
|
||||
}
|
||||
],
|
||||
"fieldConfig": {
|
||||
"defaults": {
|
||||
"custom": {
|
||||
"drawStyle": "line",
|
||||
"lineWidth": 1,
|
||||
"fillOpacity": 8,
|
||||
"showPoints": "never"
|
||||
}
|
||||
},
|
||||
"overrides": []
|
||||
},
|
||||
"options": {
|
||||
"legend": {
|
||||
"displayMode": "list",
|
||||
"placement": "bottom"
|
||||
},
|
||||
"tooltip": {
|
||||
"mode": "multi"
|
||||
}
|
||||
},
|
||||
"description": "Deltas should be small. A fat tail means working-set / offset-floor fallbacks are re-emitting full sets."
|
||||
},
|
||||
{
|
||||
"id": 7,
|
||||
"type": "timeseries",
|
||||
"title": "Held feeds by kind",
|
||||
"datasource": {
|
||||
"type": "prometheus",
|
||||
"uid": "prometheus"
|
||||
},
|
||||
"gridPos": {
|
||||
"h": 8,
|
||||
"w": 8,
|
||||
"x": 0,
|
||||
"y": 16
|
||||
},
|
||||
"targets": [
|
||||
{
|
||||
"refId": "A",
|
||||
"datasource": {
|
||||
"type": "prometheus",
|
||||
"uid": "prometheus"
|
||||
},
|
||||
"expr": "sum(triggerdotdev_realtime_native_held_feeds) by (kind)",
|
||||
"legendFormat": "{{kind}}"
|
||||
}
|
||||
],
|
||||
"fieldConfig": {
|
||||
"defaults": {
|
||||
"custom": {
|
||||
"drawStyle": "line",
|
||||
"lineWidth": 1,
|
||||
"fillOpacity": 8,
|
||||
"showPoints": "never"
|
||||
}
|
||||
},
|
||||
"overrides": []
|
||||
},
|
||||
"options": {
|
||||
"legend": {
|
||||
"displayMode": "list",
|
||||
"placement": "bottom"
|
||||
},
|
||||
"tooltip": {
|
||||
"mode": "multi"
|
||||
}
|
||||
},
|
||||
"description": "Long-polls currently held \u2014 the capacity unit."
|
||||
},
|
||||
{
|
||||
"id": 8,
|
||||
"type": "timeseries",
|
||||
"title": "Envs + channel subscriptions",
|
||||
"datasource": {
|
||||
"type": "prometheus",
|
||||
"uid": "prometheus"
|
||||
},
|
||||
"gridPos": {
|
||||
"h": 8,
|
||||
"w": 8,
|
||||
"x": 8,
|
||||
"y": 16
|
||||
},
|
||||
"targets": [
|
||||
{
|
||||
"refId": "A",
|
||||
"datasource": {
|
||||
"type": "prometheus",
|
||||
"uid": "prometheus"
|
||||
},
|
||||
"expr": "sum(triggerdotdev_realtime_native_active_envs)",
|
||||
"legendFormat": "routed envs"
|
||||
},
|
||||
{
|
||||
"refId": "B",
|
||||
"datasource": {
|
||||
"type": "prometheus",
|
||||
"uid": "prometheus"
|
||||
},
|
||||
"expr": "sum(triggerdotdev_realtime_notifier_active_subscriptions)",
|
||||
"legendFormat": "redis channels"
|
||||
}
|
||||
],
|
||||
"fieldConfig": {
|
||||
"defaults": {
|
||||
"custom": {
|
||||
"drawStyle": "line",
|
||||
"lineWidth": 1,
|
||||
"fillOpacity": 8,
|
||||
"showPoints": "never"
|
||||
}
|
||||
},
|
||||
"overrides": []
|
||||
},
|
||||
"options": {
|
||||
"legend": {
|
||||
"displayMode": "list",
|
||||
"placement": "bottom"
|
||||
},
|
||||
"tooltip": {
|
||||
"mode": "multi"
|
||||
}
|
||||
},
|
||||
"description": "Routed envs includes lingering subscriptions (kept alive briefly after the last feed closes)."
|
||||
},
|
||||
{
|
||||
"id": 9,
|
||||
"type": "timeseries",
|
||||
"title": "Resolve health",
|
||||
"datasource": {
|
||||
"type": "prometheus",
|
||||
"uid": "prometheus"
|
||||
},
|
||||
"gridPos": {
|
||||
"h": 8,
|
||||
"w": 8,
|
||||
"x": 16,
|
||||
"y": 16
|
||||
},
|
||||
"targets": [
|
||||
{
|
||||
"refId": "A",
|
||||
"datasource": {
|
||||
"type": "prometheus",
|
||||
"uid": "prometheus"
|
||||
},
|
||||
"expr": "sum(rate(triggerdotdev_realtime_native_runset_resolves_total[$__rate_interval])) by (result)",
|
||||
"legendFormat": "resolve {{result}}"
|
||||
},
|
||||
{
|
||||
"refId": "B",
|
||||
"datasource": {
|
||||
"type": "prometheus",
|
||||
"uid": "prometheus"
|
||||
},
|
||||
"expr": "sum(triggerdotdev_realtime_native_resolve_admission_in_use)",
|
||||
"legendFormat": "gate in use"
|
||||
},
|
||||
{
|
||||
"refId": "C",
|
||||
"datasource": {
|
||||
"type": "prometheus",
|
||||
"uid": "prometheus"
|
||||
},
|
||||
"expr": "sum(rate(triggerdotdev_realtime_native_concurrency_rejections_total[$__rate_interval]))",
|
||||
"legendFormat": "429/s"
|
||||
}
|
||||
],
|
||||
"fieldConfig": {
|
||||
"defaults": {
|
||||
"custom": {
|
||||
"drawStyle": "line",
|
||||
"lineWidth": 1,
|
||||
"fillOpacity": 8,
|
||||
"showPoints": "never"
|
||||
}
|
||||
},
|
||||
"overrides": []
|
||||
},
|
||||
"options": {
|
||||
"legend": {
|
||||
"displayMode": "list",
|
||||
"placement": "bottom"
|
||||
},
|
||||
"tooltip": {
|
||||
"mode": "multi"
|
||||
}
|
||||
},
|
||||
"description": "hit/coalesced vs miss = the single-flight cache collapsing same-filter herds. Gate in use near the limit = reconnect stampedes queueing."
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,576 @@
|
||||
{
|
||||
"annotations": {
|
||||
"list": []
|
||||
},
|
||||
"editable": true,
|
||||
"fiscalYearStartMonth": 0,
|
||||
"graphTooltip": 1,
|
||||
"links": [],
|
||||
"panels": [
|
||||
{
|
||||
"collapsed": false,
|
||||
"gridPos": { "h": 1, "w": 24, "x": 0, "y": 0 },
|
||||
"id": 1,
|
||||
"panels": [],
|
||||
"title": "Throughput",
|
||||
"type": "row"
|
||||
},
|
||||
{
|
||||
"datasource": { "type": "prometheus", "uid": "prometheus" },
|
||||
"fieldConfig": {
|
||||
"defaults": {
|
||||
"color": { "mode": "palette-classic" },
|
||||
"mappings": [],
|
||||
"thresholds": { "mode": "absolute", "steps": [{ "color": "green", "value": null }] },
|
||||
"unit": "short"
|
||||
},
|
||||
"overrides": []
|
||||
},
|
||||
"gridPos": { "h": 6, "w": 6, "x": 0, "y": 1 },
|
||||
"id": 2,
|
||||
"options": {
|
||||
"colorMode": "value",
|
||||
"graphMode": "area",
|
||||
"justifyMode": "auto",
|
||||
"orientation": "auto",
|
||||
"reduceOptions": { "calcs": ["lastNotNull"], "fields": "", "values": false },
|
||||
"textMode": "auto"
|
||||
},
|
||||
"pluginVersion": "11.3.0",
|
||||
"targets": [
|
||||
{
|
||||
"expr": "sum(rate(triggerdotdev_runs_replication_task_runs_inserted_inserts_total[5m]))",
|
||||
"legendFormat": "Runs/sec",
|
||||
"refId": "A"
|
||||
}
|
||||
],
|
||||
"title": "Task Runs Inserted Rate",
|
||||
"type": "stat"
|
||||
},
|
||||
{
|
||||
"datasource": { "type": "prometheus", "uid": "prometheus" },
|
||||
"fieldConfig": {
|
||||
"defaults": {
|
||||
"color": { "mode": "palette-classic" },
|
||||
"mappings": [],
|
||||
"thresholds": { "mode": "absolute", "steps": [{ "color": "green", "value": null }] },
|
||||
"unit": "short"
|
||||
},
|
||||
"overrides": []
|
||||
},
|
||||
"gridPos": { "h": 6, "w": 6, "x": 6, "y": 1 },
|
||||
"id": 3,
|
||||
"options": {
|
||||
"colorMode": "value",
|
||||
"graphMode": "area",
|
||||
"justifyMode": "auto",
|
||||
"orientation": "auto",
|
||||
"reduceOptions": { "calcs": ["lastNotNull"], "fields": "", "values": false },
|
||||
"textMode": "auto"
|
||||
},
|
||||
"pluginVersion": "11.3.0",
|
||||
"targets": [
|
||||
{
|
||||
"expr": "sum(rate(triggerdotdev_runs_replication_payloads_inserted_inserts_total[5m]))",
|
||||
"legendFormat": "Payloads/sec",
|
||||
"refId": "A"
|
||||
}
|
||||
],
|
||||
"title": "Payloads Inserted Rate",
|
||||
"type": "stat"
|
||||
},
|
||||
{
|
||||
"datasource": { "type": "prometheus", "uid": "prometheus" },
|
||||
"fieldConfig": {
|
||||
"defaults": {
|
||||
"color": { "mode": "palette-classic" },
|
||||
"mappings": [],
|
||||
"thresholds": { "mode": "absolute", "steps": [{ "color": "green", "value": null }] },
|
||||
"unit": "short"
|
||||
},
|
||||
"overrides": []
|
||||
},
|
||||
"gridPos": { "h": 6, "w": 6, "x": 12, "y": 1 },
|
||||
"id": 4,
|
||||
"options": {
|
||||
"colorMode": "value",
|
||||
"graphMode": "area",
|
||||
"justifyMode": "auto",
|
||||
"orientation": "auto",
|
||||
"reduceOptions": { "calcs": ["lastNotNull"], "fields": "", "values": false },
|
||||
"textMode": "auto"
|
||||
},
|
||||
"pluginVersion": "11.3.0",
|
||||
"targets": [
|
||||
{
|
||||
"expr": "sum(rate(triggerdotdev_runs_replication_batches_flushed_total[5m]))",
|
||||
"legendFormat": "Batches/sec",
|
||||
"refId": "A"
|
||||
}
|
||||
],
|
||||
"title": "Batches Flushed Rate",
|
||||
"type": "stat"
|
||||
},
|
||||
{
|
||||
"datasource": { "type": "prometheus", "uid": "prometheus" },
|
||||
"fieldConfig": {
|
||||
"defaults": {
|
||||
"color": { "mode": "thresholds" },
|
||||
"mappings": [],
|
||||
"max": 1,
|
||||
"min": 0,
|
||||
"thresholds": {
|
||||
"mode": "absolute",
|
||||
"steps": [
|
||||
{ "color": "red", "value": null },
|
||||
{ "color": "yellow", "value": 0.9 },
|
||||
{ "color": "green", "value": 0.99 }
|
||||
]
|
||||
},
|
||||
"unit": "percentunit"
|
||||
},
|
||||
"overrides": []
|
||||
},
|
||||
"gridPos": { "h": 6, "w": 6, "x": 18, "y": 1 },
|
||||
"id": 5,
|
||||
"options": {
|
||||
"colorMode": "value",
|
||||
"graphMode": "none",
|
||||
"justifyMode": "auto",
|
||||
"orientation": "auto",
|
||||
"reduceOptions": { "calcs": ["lastNotNull"], "fields": "", "values": false },
|
||||
"textMode": "auto"
|
||||
},
|
||||
"pluginVersion": "11.3.0",
|
||||
"targets": [
|
||||
{
|
||||
"expr": "sum(rate(triggerdotdev_runs_replication_batches_flushed_total{success=\"true\"}[5m])) / sum(rate(triggerdotdev_runs_replication_batches_flushed_total[5m]))",
|
||||
"legendFormat": "Success Rate",
|
||||
"refId": "A"
|
||||
}
|
||||
],
|
||||
"title": "Flush Success Rate",
|
||||
"type": "stat"
|
||||
},
|
||||
{
|
||||
"datasource": { "type": "prometheus", "uid": "prometheus" },
|
||||
"fieldConfig": {
|
||||
"defaults": {
|
||||
"color": { "mode": "palette-classic" },
|
||||
"custom": {
|
||||
"axisBorderShow": false,
|
||||
"axisCenteredZero": false,
|
||||
"axisColorMode": "text",
|
||||
"axisLabel": "",
|
||||
"axisPlacement": "auto",
|
||||
"barAlignment": 0,
|
||||
"drawStyle": "line",
|
||||
"fillOpacity": 10,
|
||||
"gradientMode": "none",
|
||||
"hideFrom": { "legend": false, "tooltip": false, "viz": false },
|
||||
"lineInterpolation": "linear",
|
||||
"lineWidth": 1,
|
||||
"pointSize": 5,
|
||||
"scaleDistribution": { "type": "linear" },
|
||||
"showPoints": "never",
|
||||
"spanNulls": false,
|
||||
"stacking": { "group": "A", "mode": "none" },
|
||||
"thresholdsStyle": { "mode": "off" }
|
||||
},
|
||||
"mappings": [],
|
||||
"thresholds": { "mode": "absolute", "steps": [{ "color": "green", "value": null }] },
|
||||
"unit": "short"
|
||||
},
|
||||
"overrides": []
|
||||
},
|
||||
"gridPos": { "h": 8, "w": 12, "x": 0, "y": 7 },
|
||||
"id": 6,
|
||||
"options": {
|
||||
"legend": {
|
||||
"calcs": ["mean", "max"],
|
||||
"displayMode": "table",
|
||||
"placement": "bottom",
|
||||
"showLegend": true
|
||||
},
|
||||
"tooltip": { "mode": "multi", "sort": "desc" }
|
||||
},
|
||||
"targets": [
|
||||
{
|
||||
"expr": "sum(rate(triggerdotdev_runs_replication_events_processed_total[5m])) by (event_type)",
|
||||
"legendFormat": "{{event_type}}",
|
||||
"refId": "A"
|
||||
}
|
||||
],
|
||||
"title": "Events Processed by Type",
|
||||
"type": "timeseries"
|
||||
},
|
||||
{
|
||||
"datasource": { "type": "prometheus", "uid": "prometheus" },
|
||||
"fieldConfig": {
|
||||
"defaults": {
|
||||
"color": { "mode": "palette-classic" },
|
||||
"custom": {
|
||||
"axisBorderShow": false,
|
||||
"axisCenteredZero": false,
|
||||
"axisColorMode": "text",
|
||||
"axisLabel": "",
|
||||
"axisPlacement": "auto",
|
||||
"barAlignment": 0,
|
||||
"drawStyle": "line",
|
||||
"fillOpacity": 10,
|
||||
"gradientMode": "none",
|
||||
"hideFrom": { "legend": false, "tooltip": false, "viz": false },
|
||||
"lineInterpolation": "linear",
|
||||
"lineWidth": 1,
|
||||
"pointSize": 5,
|
||||
"scaleDistribution": { "type": "linear" },
|
||||
"showPoints": "never",
|
||||
"spanNulls": false,
|
||||
"stacking": { "group": "A", "mode": "none" },
|
||||
"thresholdsStyle": { "mode": "off" }
|
||||
},
|
||||
"mappings": [],
|
||||
"thresholds": { "mode": "absolute", "steps": [{ "color": "green", "value": null }] },
|
||||
"unit": "short"
|
||||
},
|
||||
"overrides": []
|
||||
},
|
||||
"gridPos": { "h": 8, "w": 12, "x": 12, "y": 7 },
|
||||
"id": 7,
|
||||
"options": {
|
||||
"legend": {
|
||||
"calcs": ["mean", "max"],
|
||||
"displayMode": "table",
|
||||
"placement": "bottom",
|
||||
"showLegend": true
|
||||
},
|
||||
"tooltip": { "mode": "multi", "sort": "desc" }
|
||||
},
|
||||
"targets": [
|
||||
{
|
||||
"expr": "sum(rate(triggerdotdev_runs_replication_task_runs_inserted_inserts_total[5m]))",
|
||||
"legendFormat": "Task Runs",
|
||||
"refId": "A"
|
||||
},
|
||||
{
|
||||
"expr": "sum(rate(triggerdotdev_runs_replication_payloads_inserted_inserts_total[5m]))",
|
||||
"legendFormat": "Payloads",
|
||||
"refId": "B"
|
||||
}
|
||||
],
|
||||
"title": "Insert Rate Over Time",
|
||||
"type": "timeseries"
|
||||
},
|
||||
{
|
||||
"collapsed": false,
|
||||
"gridPos": { "h": 1, "w": 24, "x": 0, "y": 15 },
|
||||
"id": 8,
|
||||
"panels": [],
|
||||
"title": "Latency & Lag",
|
||||
"type": "row"
|
||||
},
|
||||
{
|
||||
"datasource": { "type": "prometheus", "uid": "prometheus" },
|
||||
"fieldConfig": {
|
||||
"defaults": {
|
||||
"color": { "mode": "palette-classic" },
|
||||
"custom": {
|
||||
"axisBorderShow": false,
|
||||
"axisCenteredZero": false,
|
||||
"axisColorMode": "text",
|
||||
"axisLabel": "",
|
||||
"axisPlacement": "auto",
|
||||
"barAlignment": 0,
|
||||
"drawStyle": "line",
|
||||
"fillOpacity": 10,
|
||||
"gradientMode": "none",
|
||||
"hideFrom": { "legend": false, "tooltip": false, "viz": false },
|
||||
"lineInterpolation": "linear",
|
||||
"lineWidth": 1,
|
||||
"pointSize": 5,
|
||||
"scaleDistribution": { "type": "linear" },
|
||||
"showPoints": "never",
|
||||
"spanNulls": false,
|
||||
"stacking": { "group": "A", "mode": "none" },
|
||||
"thresholdsStyle": { "mode": "off" }
|
||||
},
|
||||
"mappings": [],
|
||||
"thresholds": { "mode": "absolute", "steps": [{ "color": "green", "value": null }] },
|
||||
"unit": "ms"
|
||||
},
|
||||
"overrides": []
|
||||
},
|
||||
"gridPos": { "h": 8, "w": 12, "x": 0, "y": 16 },
|
||||
"id": 9,
|
||||
"options": {
|
||||
"legend": {
|
||||
"calcs": ["mean", "max"],
|
||||
"displayMode": "table",
|
||||
"placement": "bottom",
|
||||
"showLegend": true
|
||||
},
|
||||
"tooltip": { "mode": "multi", "sort": "desc" }
|
||||
},
|
||||
"targets": [
|
||||
{
|
||||
"expr": "histogram_quantile(0.50, sum(rate(triggerdotdev_runs_replication_replication_lag_ms_milliseconds_bucket[5m])) by (le))",
|
||||
"legendFormat": "p50",
|
||||
"refId": "A"
|
||||
},
|
||||
{
|
||||
"expr": "histogram_quantile(0.95, sum(rate(triggerdotdev_runs_replication_replication_lag_ms_milliseconds_bucket[5m])) by (le))",
|
||||
"legendFormat": "p95",
|
||||
"refId": "B"
|
||||
},
|
||||
{
|
||||
"expr": "histogram_quantile(0.99, sum(rate(triggerdotdev_runs_replication_replication_lag_ms_milliseconds_bucket[5m])) by (le))",
|
||||
"legendFormat": "p99",
|
||||
"refId": "C"
|
||||
}
|
||||
],
|
||||
"title": "Replication Lag (Postgres → ClickHouse)",
|
||||
"type": "timeseries"
|
||||
},
|
||||
{
|
||||
"datasource": { "type": "prometheus", "uid": "prometheus" },
|
||||
"fieldConfig": {
|
||||
"defaults": {
|
||||
"color": { "mode": "palette-classic" },
|
||||
"custom": {
|
||||
"axisBorderShow": false,
|
||||
"axisCenteredZero": false,
|
||||
"axisColorMode": "text",
|
||||
"axisLabel": "",
|
||||
"axisPlacement": "auto",
|
||||
"barAlignment": 0,
|
||||
"drawStyle": "line",
|
||||
"fillOpacity": 10,
|
||||
"gradientMode": "none",
|
||||
"hideFrom": { "legend": false, "tooltip": false, "viz": false },
|
||||
"lineInterpolation": "linear",
|
||||
"lineWidth": 1,
|
||||
"pointSize": 5,
|
||||
"scaleDistribution": { "type": "linear" },
|
||||
"showPoints": "never",
|
||||
"spanNulls": false,
|
||||
"stacking": { "group": "A", "mode": "none" },
|
||||
"thresholdsStyle": { "mode": "off" }
|
||||
},
|
||||
"mappings": [],
|
||||
"thresholds": { "mode": "absolute", "steps": [{ "color": "green", "value": null }] },
|
||||
"unit": "ms"
|
||||
},
|
||||
"overrides": []
|
||||
},
|
||||
"gridPos": { "h": 8, "w": 12, "x": 12, "y": 16 },
|
||||
"id": 10,
|
||||
"options": {
|
||||
"legend": {
|
||||
"calcs": ["mean", "max"],
|
||||
"displayMode": "table",
|
||||
"placement": "bottom",
|
||||
"showLegend": true
|
||||
},
|
||||
"tooltip": { "mode": "multi", "sort": "desc" }
|
||||
},
|
||||
"targets": [
|
||||
{
|
||||
"expr": "histogram_quantile(0.50, sum(rate(triggerdotdev_runs_replication_flush_duration_ms_milliseconds_bucket[5m])) by (le))",
|
||||
"legendFormat": "p50",
|
||||
"refId": "A"
|
||||
},
|
||||
{
|
||||
"expr": "histogram_quantile(0.95, sum(rate(triggerdotdev_runs_replication_flush_duration_ms_milliseconds_bucket[5m])) by (le))",
|
||||
"legendFormat": "p95",
|
||||
"refId": "B"
|
||||
},
|
||||
{
|
||||
"expr": "histogram_quantile(0.99, sum(rate(triggerdotdev_runs_replication_flush_duration_ms_milliseconds_bucket[5m])) by (le))",
|
||||
"legendFormat": "p99",
|
||||
"refId": "C"
|
||||
}
|
||||
],
|
||||
"title": "Flush Duration",
|
||||
"type": "timeseries"
|
||||
},
|
||||
{
|
||||
"collapsed": false,
|
||||
"gridPos": { "h": 1, "w": 24, "x": 0, "y": 24 },
|
||||
"id": 11,
|
||||
"panels": [],
|
||||
"title": "Batching & Queue",
|
||||
"type": "row"
|
||||
},
|
||||
{
|
||||
"datasource": { "type": "prometheus", "uid": "prometheus" },
|
||||
"fieldConfig": {
|
||||
"defaults": {
|
||||
"color": { "mode": "palette-classic" },
|
||||
"custom": {
|
||||
"axisBorderShow": false,
|
||||
"axisCenteredZero": false,
|
||||
"axisColorMode": "text",
|
||||
"axisLabel": "",
|
||||
"axisPlacement": "auto",
|
||||
"barAlignment": 0,
|
||||
"drawStyle": "line",
|
||||
"fillOpacity": 10,
|
||||
"gradientMode": "none",
|
||||
"hideFrom": { "legend": false, "tooltip": false, "viz": false },
|
||||
"lineInterpolation": "linear",
|
||||
"lineWidth": 1,
|
||||
"pointSize": 5,
|
||||
"scaleDistribution": { "type": "linear" },
|
||||
"showPoints": "never",
|
||||
"spanNulls": false,
|
||||
"stacking": { "group": "A", "mode": "none" },
|
||||
"thresholdsStyle": { "mode": "off" }
|
||||
},
|
||||
"mappings": [],
|
||||
"thresholds": { "mode": "absolute", "steps": [{ "color": "green", "value": null }] },
|
||||
"unit": "short"
|
||||
},
|
||||
"overrides": []
|
||||
},
|
||||
"gridPos": { "h": 8, "w": 12, "x": 0, "y": 25 },
|
||||
"id": 13,
|
||||
"options": {
|
||||
"legend": {
|
||||
"calcs": ["mean", "max"],
|
||||
"displayMode": "table",
|
||||
"placement": "bottom",
|
||||
"showLegend": true
|
||||
},
|
||||
"tooltip": { "mode": "multi", "sort": "desc" }
|
||||
},
|
||||
"targets": [
|
||||
{
|
||||
"expr": "histogram_quantile(0.50, sum(rate(triggerdotdev_runs_replication_batch_size_items_bucket[5m])) by (le))",
|
||||
"legendFormat": "p50",
|
||||
"refId": "A"
|
||||
},
|
||||
{
|
||||
"expr": "histogram_quantile(0.95, sum(rate(triggerdotdev_runs_replication_batch_size_items_bucket[5m])) by (le))",
|
||||
"legendFormat": "p95",
|
||||
"refId": "B"
|
||||
},
|
||||
{
|
||||
"expr": "histogram_quantile(0.99, sum(rate(triggerdotdev_runs_replication_batch_size_items_bucket[5m])) by (le))",
|
||||
"legendFormat": "p99",
|
||||
"refId": "C"
|
||||
}
|
||||
],
|
||||
"title": "Batch Size Distribution",
|
||||
"type": "timeseries"
|
||||
},
|
||||
{
|
||||
"datasource": { "type": "prometheus", "uid": "prometheus" },
|
||||
"fieldConfig": {
|
||||
"defaults": {
|
||||
"color": { "mode": "thresholds" },
|
||||
"mappings": [],
|
||||
"thresholds": {
|
||||
"mode": "absolute",
|
||||
"steps": [
|
||||
{ "color": "green", "value": null },
|
||||
{ "color": "yellow", "value": 1 },
|
||||
{ "color": "red", "value": 10 }
|
||||
]
|
||||
},
|
||||
"unit": "short"
|
||||
},
|
||||
"overrides": []
|
||||
},
|
||||
"gridPos": { "h": 8, "w": 12, "x": 12, "y": 25 },
|
||||
"id": 14,
|
||||
"options": {
|
||||
"colorMode": "value",
|
||||
"graphMode": "area",
|
||||
"justifyMode": "auto",
|
||||
"orientation": "auto",
|
||||
"reduceOptions": { "calcs": ["lastNotNull"], "fields": "", "values": false },
|
||||
"textMode": "auto"
|
||||
},
|
||||
"pluginVersion": "11.3.0",
|
||||
"targets": [
|
||||
{
|
||||
"expr": "sum(rate(triggerdotdev_runs_replication_insert_retries_total[5m]))",
|
||||
"legendFormat": "Retries/sec",
|
||||
"refId": "A"
|
||||
}
|
||||
],
|
||||
"title": "Insert Retries (should be low)",
|
||||
"type": "stat"
|
||||
},
|
||||
{
|
||||
"collapsed": false,
|
||||
"gridPos": { "h": 1, "w": 24, "x": 0, "y": 33 },
|
||||
"id": 15,
|
||||
"panels": [],
|
||||
"title": "Retries by Operation",
|
||||
"type": "row"
|
||||
},
|
||||
{
|
||||
"datasource": { "type": "prometheus", "uid": "prometheus" },
|
||||
"fieldConfig": {
|
||||
"defaults": {
|
||||
"color": { "mode": "palette-classic" },
|
||||
"custom": {
|
||||
"axisBorderShow": false,
|
||||
"axisCenteredZero": false,
|
||||
"axisColorMode": "text",
|
||||
"axisLabel": "",
|
||||
"axisPlacement": "auto",
|
||||
"barAlignment": 0,
|
||||
"drawStyle": "line",
|
||||
"fillOpacity": 10,
|
||||
"gradientMode": "none",
|
||||
"hideFrom": { "legend": false, "tooltip": false, "viz": false },
|
||||
"lineInterpolation": "linear",
|
||||
"lineWidth": 1,
|
||||
"pointSize": 5,
|
||||
"scaleDistribution": { "type": "linear" },
|
||||
"showPoints": "never",
|
||||
"spanNulls": false,
|
||||
"stacking": { "group": "A", "mode": "none" },
|
||||
"thresholdsStyle": { "mode": "off" }
|
||||
},
|
||||
"mappings": [],
|
||||
"thresholds": { "mode": "absolute", "steps": [{ "color": "green", "value": null }] },
|
||||
"unit": "short"
|
||||
},
|
||||
"overrides": []
|
||||
},
|
||||
"gridPos": { "h": 8, "w": 24, "x": 0, "y": 34 },
|
||||
"id": 16,
|
||||
"options": {
|
||||
"legend": {
|
||||
"calcs": ["mean", "max"],
|
||||
"displayMode": "table",
|
||||
"placement": "bottom",
|
||||
"showLegend": true
|
||||
},
|
||||
"tooltip": { "mode": "multi", "sort": "desc" }
|
||||
},
|
||||
"targets": [
|
||||
{
|
||||
"expr": "sum(rate(triggerdotdev_runs_replication_insert_retries_total[5m])) by (operation)",
|
||||
"legendFormat": "{{operation}}",
|
||||
"refId": "A"
|
||||
}
|
||||
],
|
||||
"title": "Insert Retries by Operation",
|
||||
"type": "timeseries"
|
||||
}
|
||||
],
|
||||
"refresh": "10s",
|
||||
"schemaVersion": 39,
|
||||
"tags": ["trigger.dev", "runs-replication", "clickhouse"],
|
||||
"templating": { "list": [] },
|
||||
"time": { "from": "now-15m", "to": "now" },
|
||||
"timepicker": {},
|
||||
"timezone": "browser",
|
||||
"title": "Runs Replication Service",
|
||||
"uid": "runs-replication-metrics",
|
||||
"version": 1
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
# Grafana datasource provisioning
|
||||
# Automatically configures Prometheus as the default datasource
|
||||
|
||||
apiVersion: 1
|
||||
|
||||
datasources:
|
||||
- name: Prometheus
|
||||
uid: prometheus
|
||||
type: prometheus
|
||||
access: proxy
|
||||
url: http://prometheus:9090
|
||||
isDefault: true
|
||||
editable: false
|
||||
jsonData:
|
||||
httpMethod: POST
|
||||
manageAlerts: true
|
||||
prometheusType: Prometheus
|
||||
@@ -0,0 +1,45 @@
|
||||
# nginx.conf (relevant bits)
|
||||
events {}
|
||||
|
||||
http {
|
||||
# This now governs idle close for HTTP/2, since http2_idle_timeout is obsolete.
|
||||
keepalive_timeout 75s; # ← set to 60–80s to reproduce your prod-ish drop
|
||||
|
||||
# Good defaults for streaming
|
||||
sendfile off; # avoid sendfile delays for tiny frames
|
||||
tcp_nodelay on;
|
||||
|
||||
upstream app_upstream {
|
||||
server host.docker.internal:3030;
|
||||
keepalive 16;
|
||||
}
|
||||
|
||||
server {
|
||||
listen 8443 ssl; # ← no ‘http2’ here…
|
||||
http2 on; # ← …use the standalone directive instead
|
||||
server_name localhost;
|
||||
|
||||
ssl_certificate /etc/nginx/certs/cert.pem;
|
||||
ssl_certificate_key /etc/nginx/certs/key.pem;
|
||||
|
||||
location / {
|
||||
# Make SSE actually stream through NGINX:
|
||||
proxy_buffering off; # don’t buffer
|
||||
gzip off; # don’t compress
|
||||
add_header X-Accel-Buffering no; # belt & suspenders for NGINX buffering
|
||||
proxy_set_header Accept-Encoding ""; # stop upstream gzip (SSE + gzip = sad)
|
||||
|
||||
# Plain h1 to upstream is fine for SSE
|
||||
proxy_http_version 1.1;
|
||||
proxy_set_header Connection "";
|
||||
|
||||
proxy_read_timeout 30s;
|
||||
proxy_send_timeout 30s;
|
||||
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header X-Forwarded-For $remote_addr;
|
||||
|
||||
proxy_pass http://app_upstream;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
# OpenTelemetry Collector configuration for local development
|
||||
# Receives OTLP metrics from the webapp and exposes them in Prometheus format
|
||||
|
||||
receivers:
|
||||
otlp:
|
||||
protocols:
|
||||
grpc:
|
||||
endpoint: 0.0.0.0:4317
|
||||
http:
|
||||
endpoint: 0.0.0.0:4318
|
||||
|
||||
processors:
|
||||
batch:
|
||||
timeout: 10s
|
||||
send_batch_size: 1024
|
||||
|
||||
exporters:
|
||||
prometheus:
|
||||
endpoint: 0.0.0.0:8889
|
||||
namespace: triggerdotdev
|
||||
const_labels:
|
||||
source: otel_collector
|
||||
resource_to_telemetry_conversion:
|
||||
enabled: true
|
||||
|
||||
# Debug exporter for troubleshooting (optional, uncomment to enable)
|
||||
# debug:
|
||||
# verbosity: detailed
|
||||
|
||||
service:
|
||||
pipelines:
|
||||
metrics:
|
||||
receivers: [otlp]
|
||||
processors: [batch]
|
||||
exporters: [prometheus]
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
# Prometheus configuration for local development
|
||||
# Scrapes metrics from OTEL Collector and the webapp /metrics endpoint
|
||||
|
||||
global:
|
||||
scrape_interval: 15s
|
||||
evaluation_interval: 15s
|
||||
|
||||
scrape_configs:
|
||||
# Scrape OpenTelemetry Collector's Prometheus exporter
|
||||
# This includes all OTel metrics (batch queue, fair queue, etc.)
|
||||
- job_name: "otel-collector"
|
||||
static_configs:
|
||||
- targets: ["otel-collector:8889"]
|
||||
metrics_path: /metrics
|
||||
|
||||
# Scrape webapp's /metrics endpoint
|
||||
# This includes Prisma metrics and prom-client default metrics
|
||||
# Note: The webapp runs on host machine, not in Docker network
|
||||
# Use host.docker.internal on Mac/Windows, or the actual host IP on Linux
|
||||
- job_name: "webapp"
|
||||
static_configs:
|
||||
- targets: ["host.docker.internal:3030"]
|
||||
metrics_path: /metrics
|
||||
# Uncomment if you set TRIGGER_METRICS_AUTH_PASSWORD
|
||||
# authorization:
|
||||
# type: Bearer
|
||||
# credentials: your-password-here
|
||||
|
||||
# Prometheus self-monitoring
|
||||
- job_name: "prometheus"
|
||||
static_configs:
|
||||
- targets: ["localhost:9090"]
|
||||
@@ -0,0 +1,12 @@
|
||||
{
|
||||
"$schema": "https://raw.githubusercontent.com/s2-streamstore/s2/main/cli/schema.json",
|
||||
"basins": [
|
||||
{
|
||||
"name": "trigger-local",
|
||||
"config": {
|
||||
"create_stream_on_append": true,
|
||||
"create_stream_on_read": true
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
[
|
||||
{
|
||||
"name": "trigger_webapp_local",
|
||||
"listen": "[::]:30303",
|
||||
"upstream": "host.docker.internal:3030",
|
||||
"enabled": true
|
||||
}
|
||||
]
|
||||
@@ -0,0 +1,133 @@
|
||||
version: "3"
|
||||
|
||||
volumes:
|
||||
database-data:
|
||||
redis-data:
|
||||
clickhouse:
|
||||
|
||||
networks:
|
||||
app_network:
|
||||
external: false
|
||||
|
||||
services:
|
||||
db:
|
||||
container_name: db-dev
|
||||
build:
|
||||
context: .
|
||||
dockerfile: Dockerfile.postgres
|
||||
restart: always
|
||||
volumes:
|
||||
- database-data:/var/lib/postgresql/data/
|
||||
environment:
|
||||
POSTGRES_USER: postgres
|
||||
POSTGRES_PASSWORD: postgres
|
||||
POSTGRES_DB: postgres
|
||||
networks:
|
||||
- app_network
|
||||
ports:
|
||||
- 5432:5432
|
||||
command:
|
||||
- -c
|
||||
- listen_addresses=*
|
||||
- -c
|
||||
- wal_level=logical
|
||||
- -c
|
||||
- shared_preload_libraries=pg_partman_bgw
|
||||
|
||||
electric:
|
||||
container_name: electric-dev
|
||||
image: electricsql/electric:1.2.4@sha256:20da3d0b0e74926c5623392db67fd56698b9e374c4aeb6cb5cadeb8fea171c36
|
||||
restart: always
|
||||
environment:
|
||||
DATABASE_URL: postgresql://postgres:postgres@db:5432/postgres?sslmode=disable
|
||||
networks:
|
||||
- app_network
|
||||
ports:
|
||||
- "3060:3000"
|
||||
depends_on:
|
||||
- db
|
||||
|
||||
clickhouse:
|
||||
image: bitnamilegacy/clickhouse:latest
|
||||
container_name: clickhouse-dev
|
||||
environment:
|
||||
CLICKHOUSE_ADMIN_USER: default
|
||||
CLICKHOUSE_ADMIN_PASSWORD: password
|
||||
ports:
|
||||
- "8123:8123"
|
||||
- "9000:9000"
|
||||
volumes:
|
||||
- clickhouse:/bitnami/clickhouse
|
||||
networks:
|
||||
- app_network
|
||||
healthcheck:
|
||||
test:
|
||||
[
|
||||
"CMD",
|
||||
"clickhouse-client",
|
||||
"--host",
|
||||
"localhost",
|
||||
"--port",
|
||||
"9000",
|
||||
"--user",
|
||||
"default",
|
||||
"--password",
|
||||
"password",
|
||||
"--query",
|
||||
"SELECT 1",
|
||||
]
|
||||
interval: 3s
|
||||
timeout: 5s
|
||||
retries: 5
|
||||
start_period: 10s
|
||||
|
||||
redis:
|
||||
container_name: redis-dev
|
||||
image: redis:7
|
||||
restart: always
|
||||
volumes:
|
||||
- redis-data:/data
|
||||
networks:
|
||||
- app_network
|
||||
ports:
|
||||
- 6379:6379
|
||||
|
||||
app:
|
||||
build:
|
||||
context: ../
|
||||
dockerfile: ./docker/Dockerfile
|
||||
ports:
|
||||
- 3030:3030
|
||||
depends_on:
|
||||
- db
|
||||
- electric
|
||||
- clickhouse
|
||||
- redis
|
||||
env_file:
|
||||
- ../.env
|
||||
environment:
|
||||
DATABASE_URL: postgres://postgres:postgres@db:5432/postgres?schema=public
|
||||
DIRECT_URL: postgres://postgres:postgres@db:5432/postgres?schema=public
|
||||
CLICKHOUSE_URL: http://default:password@clickhouse:8123
|
||||
SESSION_SECRET: secret123
|
||||
MAGIC_LINK_SECRET: secret123
|
||||
ENCRYPTION_KEY: dummy-encryption-keeeey-32-bytes
|
||||
REMIX_APP_PORT: 3030
|
||||
PORT: 3030
|
||||
networks:
|
||||
- app_network
|
||||
|
||||
ch-ui:
|
||||
image: ghcr.io/caioricciuti/ch-ui:latest
|
||||
container_name: ch-ui-dev
|
||||
restart: always
|
||||
ports:
|
||||
- "5521:5521"
|
||||
environment:
|
||||
VITE_CLICKHOUSE_URL: "http://clickhouse:8123"
|
||||
VITE_CLICKHOUSE_USER: "default"
|
||||
VITE_CLICKHOUSE_PASS: "password"
|
||||
depends_on:
|
||||
- clickhouse
|
||||
networks:
|
||||
- app_network
|
||||
@@ -0,0 +1,124 @@
|
||||
# Optional services for advanced local-dev workflows. Pair with
|
||||
# `docker-compose.yml` via `pnpm run docker:full`.
|
||||
#
|
||||
# Same `name:` so `docker compose` treats both files as one project — bring
|
||||
# them up together and they share the `app_network` and `triggerdotdev-docker`
|
||||
# volume namespace. Tear down with `pnpm run docker:full:stop`.
|
||||
#
|
||||
# Includes:
|
||||
# - electric-shard-1: second Electric instance for multi-shard testing
|
||||
# - ch-ui: ClickHouse browser UI
|
||||
# - toxiproxy: chaos / flake testing
|
||||
# - nginx-h2: HTTP/2 reverse proxy
|
||||
# - otel-collector + prometheus + grafana: observability stack
|
||||
name: triggerdotdev-docker
|
||||
|
||||
volumes:
|
||||
prometheus-data:
|
||||
grafana-data:
|
||||
|
||||
networks:
|
||||
app_network:
|
||||
external: false
|
||||
|
||||
services:
|
||||
electric-shard-1:
|
||||
container_name: ${CONTAINER_PREFIX:-}electric-shard-1
|
||||
image: electricsql/electric:1.2.4@sha256:20da3d0b0e74926c5623392db67fd56698b9e374c4aeb6cb5cadeb8fea171c36
|
||||
restart: always
|
||||
environment:
|
||||
DATABASE_URL: postgresql://postgres:postgres@database:5432/postgres?sslmode=disable
|
||||
ELECTRIC_INSECURE: true
|
||||
ELECTRIC_REPLICATION_STREAM_ID: "triggershard1"
|
||||
networks:
|
||||
- app_network
|
||||
ports:
|
||||
- "${ELECTRIC_SHARD_1_HOST_PORT:-3061}:3000"
|
||||
depends_on:
|
||||
- database
|
||||
|
||||
ch-ui:
|
||||
image: ghcr.io/caioricciuti/ch-ui:latest@sha256:288abf7103d6e0f45527ee835ee79bd1e0bfb82d55dc514fb3cf43816306b538
|
||||
restart: always
|
||||
ports:
|
||||
- "${CH_UI_HOST_PORT:-5521}:5521"
|
||||
environment:
|
||||
VITE_CLICKHOUSE_URL: "http://localhost:${CLICKHOUSE_HTTP_HOST_PORT:-8123}"
|
||||
VITE_CLICKHOUSE_USER: "default"
|
||||
VITE_CLICKHOUSE_PASS: "password"
|
||||
networks:
|
||||
- app_network
|
||||
|
||||
toxiproxy:
|
||||
container_name: ${CONTAINER_PREFIX:-}toxiproxy
|
||||
image: ghcr.io/shopify/toxiproxy:latest@sha256:9378ed52a28bc50edc1350f936f518f31fa95f0d15917d6eb40b8e376d1a214e
|
||||
restart: always
|
||||
volumes:
|
||||
- ./config/toxiproxy.json:/config/toxiproxy.json
|
||||
ports:
|
||||
- "${TOXIPROXY_PROXY_HOST_PORT:-30303}:30303" # Proxied webapp port
|
||||
- "${TOXIPROXY_API_HOST_PORT:-8474}:8474" # Toxiproxy API port
|
||||
networks:
|
||||
- app_network
|
||||
command: ["-host", "0.0.0.0", "-config", "/config/toxiproxy.json"]
|
||||
|
||||
nginx-h2:
|
||||
image: nginx:1.27@sha256:6784fb0834aa7dbbe12e3d7471e69c290df3e6ba810dc38b34ae33d3c1c05f7d
|
||||
container_name: ${CONTAINER_PREFIX:-}nginx-h2
|
||||
restart: unless-stopped
|
||||
ports:
|
||||
- "${NGINX_H2_HOST_PORT:-8443}:8443"
|
||||
volumes:
|
||||
- ./config/nginx.conf:/etc/nginx/nginx.conf:ro
|
||||
- ./config/certs:/etc/nginx/certs:ro
|
||||
networks:
|
||||
- app_network
|
||||
|
||||
# Observability stack for local development
|
||||
otel-collector:
|
||||
container_name: ${CONTAINER_PREFIX:-}otel-collector
|
||||
image: otel/opentelemetry-collector-contrib:0.96.0@sha256:7ef2a2ff46b9e432321fdd63df104bfeedaf7b4e276950f42c634d0f23521fc4
|
||||
restart: always
|
||||
command: ["--config", "/etc/otel-collector-config.yaml"]
|
||||
volumes:
|
||||
- ./config/otel-collector-config.yaml:/etc/otel-collector-config.yaml:ro
|
||||
ports:
|
||||
- "${OTEL_GRPC_HOST_PORT:-4317}:4317" # OTLP gRPC receiver
|
||||
- "${OTEL_HTTP_HOST_PORT:-4318}:4318" # OTLP HTTP receiver
|
||||
- "${OTEL_PROMETHEUS_HOST_PORT:-8889}:8889" # Prometheus exporter
|
||||
networks:
|
||||
- app_network
|
||||
|
||||
prometheus:
|
||||
container_name: ${CONTAINER_PREFIX:-}prometheus
|
||||
image: prom/prometheus:v2.54.1@sha256:f6639335d34a77d9d9db382b92eeb7fc00934be8eae81dbc03b31cfe90411a94
|
||||
restart: always
|
||||
volumes:
|
||||
- ./config/prometheus.yml:/etc/prometheus/prometheus.yml:ro
|
||||
- prometheus-data:/prometheus
|
||||
ports:
|
||||
- "${PROMETHEUS_HOST_PORT:-9090}:9090"
|
||||
networks:
|
||||
- app_network
|
||||
command:
|
||||
- "--config.file=/etc/prometheus/prometheus.yml"
|
||||
- "--storage.tsdb.path=/prometheus"
|
||||
- "--web.enable-lifecycle"
|
||||
|
||||
grafana:
|
||||
container_name: ${CONTAINER_PREFIX:-}grafana
|
||||
image: grafana/grafana:11.3.0@sha256:a0f881232a6fb71a0554a47d0fe2203b6888fe77f4cefb7ea62bed7eb54e13c3
|
||||
restart: always
|
||||
volumes:
|
||||
- grafana-data:/var/lib/grafana
|
||||
- ./config/grafana/provisioning:/etc/grafana/provisioning:ro
|
||||
ports:
|
||||
- "${GRAFANA_HOST_PORT:-4001}:3000"
|
||||
environment:
|
||||
GF_SECURITY_ADMIN_USER: admin
|
||||
GF_SECURITY_ADMIN_PASSWORD: admin
|
||||
GF_USERS_ALLOW_SIGN_UP: false
|
||||
networks:
|
||||
- app_network
|
||||
depends_on:
|
||||
- prometheus
|
||||
@@ -0,0 +1,262 @@
|
||||
# Core local-dev stack: the minimum a contributor needs to boot the webapp.
|
||||
# For optional services (object store, observability, HTTP/2 proxy, chaos
|
||||
# tooling, ClickHouse UI, extra electric shard) see ./docker-compose.extras.yml
|
||||
# and the `pnpm run docker:full` script.
|
||||
#
|
||||
# Every host port is overridable via env vars from the root `.env` so multiple
|
||||
# instances (worktrees, branch experiments) can run side by side. See the
|
||||
# "Multiple instances" block in `.env.example` for the full set of knobs.
|
||||
name: triggerdotdev-docker
|
||||
|
||||
volumes:
|
||||
database-data:
|
||||
database-data-alt:
|
||||
database-runops-data:
|
||||
database-replica-data:
|
||||
redis-data:
|
||||
minio-data:
|
||||
clickhouse-data:
|
||||
clickhouse-logs:
|
||||
|
||||
networks:
|
||||
app_network:
|
||||
external: false
|
||||
|
||||
services:
|
||||
database:
|
||||
container_name: ${CONTAINER_PREFIX:-}database
|
||||
build:
|
||||
context: .
|
||||
dockerfile: Dockerfile.postgres
|
||||
restart: always
|
||||
volumes:
|
||||
- ${DB_VOLUME:-database-data}:/var/lib/postgresql/data/
|
||||
environment:
|
||||
POSTGRES_USER: postgres
|
||||
POSTGRES_PASSWORD: postgres
|
||||
POSTGRES_DB: postgres
|
||||
networks:
|
||||
- app_network
|
||||
ports:
|
||||
- "${POSTGRES_HOST_PORT:-5432}:5432"
|
||||
command:
|
||||
- -c
|
||||
- listen_addresses=*
|
||||
- -c
|
||||
- wal_level=logical
|
||||
- -c
|
||||
- shared_preload_libraries=pg_partman_bgw
|
||||
# The webapp opens ~50 pooled connections per instance and Electric another
|
||||
# ~40, so the default 100 is exhausted by one webapp + Electric alone. Raise
|
||||
# it so multiple instances / load tests have headroom.
|
||||
- -c
|
||||
- max_connections=500
|
||||
|
||||
# Opt-in NEW run-ops database, PG17 (the `database` above is PG14) — a separate cluster
|
||||
# so the run-ops split's distinct-DB sentinel passes. Start with:
|
||||
# COMPOSE_PROFILES=runops pnpm run docker
|
||||
database-runops:
|
||||
container_name: ${CONTAINER_PREFIX:-}database-runops
|
||||
profiles: ["runops"]
|
||||
build:
|
||||
context: .
|
||||
dockerfile: Dockerfile.postgres17
|
||||
restart: always
|
||||
volumes:
|
||||
- ${DB_RUNOPS_VOLUME:-database-runops-data}:/var/lib/postgresql/data/
|
||||
environment:
|
||||
POSTGRES_USER: postgres
|
||||
POSTGRES_PASSWORD: postgres
|
||||
POSTGRES_DB: postgres
|
||||
networks:
|
||||
- app_network
|
||||
ports:
|
||||
- "${POSTGRES_RUNOPS_HOST_PORT:-5434}:5432"
|
||||
command:
|
||||
- -c
|
||||
- listen_addresses=*
|
||||
- -c
|
||||
- wal_level=logical
|
||||
- -c
|
||||
- shared_preload_libraries=pg_partman_bgw
|
||||
- -c
|
||||
- max_connections=500
|
||||
|
||||
# Opt-in streaming read replica with configurable apply lag — a dial-a-lag rig for
|
||||
# testing replica-race behavior (e.g. the realtime read-your-writes gate) locally.
|
||||
# Start with: COMPOSE_PROFILES=replica pnpm run docker
|
||||
# One-time primary prep (allows replication connections; additive, survives restarts):
|
||||
# docker exec database bash -c 'grep -q "host replication" "$PGDATA/pg_hba.conf" || echo "host replication all all md5" >> "$PGDATA/pg_hba.conf"'
|
||||
# docker exec database psql -U postgres -c "SELECT pg_reload_conf()"
|
||||
# Then point the webapp at it: DATABASE_READ_REPLICA_URL=postgresql://postgres:postgres@localhost:5433/postgres
|
||||
# Tune the lag via REPLICA_APPLY_DELAY (default 20ms ~ realistic prod lag; crank to 150ms/2s to
|
||||
# shake out replica races). Wipe database-replica-data to re-init.
|
||||
database-replica:
|
||||
container_name: ${CONTAINER_PREFIX:-}database-replica
|
||||
profiles: ["replica"]
|
||||
build:
|
||||
context: .
|
||||
dockerfile: Dockerfile.postgres
|
||||
restart: always
|
||||
depends_on:
|
||||
- database
|
||||
volumes:
|
||||
- ${DB_REPLICA_VOLUME:-database-replica-data}:/var/lib/postgresql/data/
|
||||
environment:
|
||||
PGPASSWORD: postgres
|
||||
REPLICA_APPLY_DELAY: ${REPLICA_APPLY_DELAY:-20ms}
|
||||
networks:
|
||||
- app_network
|
||||
ports:
|
||||
- "${POSTGRES_REPLICA_HOST_PORT:-5433}:5432"
|
||||
entrypoint: ["bash", "-c"]
|
||||
command:
|
||||
- |
|
||||
set -e
|
||||
if [ ! -s "$$PGDATA/PG_VERSION" ]; then
|
||||
echo "initializing streaming replica from 'database'..."
|
||||
mkdir -p "$$PGDATA"
|
||||
chown postgres:postgres "$$PGDATA"
|
||||
chmod 0700 "$$PGDATA"
|
||||
until gosu postgres pg_basebackup -h database -U postgres -D "$$PGDATA" -Fp -Xs -R; do
|
||||
echo "primary not ready for replication (did you run the one-time pg_hba prep above?); retrying..."
|
||||
rm -rf "$$PGDATA"/* 2>/dev/null || true
|
||||
sleep 2
|
||||
done
|
||||
fi
|
||||
# max_connections must be >= the primary's (hot-standby requirement).
|
||||
exec docker-entrypoint.sh postgres -c hot_standby=on -c max_connections=500 -c "recovery_min_apply_delay=$$REPLICA_APPLY_DELAY"
|
||||
|
||||
redis:
|
||||
container_name: ${CONTAINER_PREFIX:-}redis
|
||||
image: redis:7@sha256:3e1b24a1a8f24ff926b15e5ace8c38a03e5657fb66e1fc7e5188e315aa5fa094
|
||||
restart: always
|
||||
volumes:
|
||||
- redis-data:/data
|
||||
networks:
|
||||
- app_network
|
||||
ports:
|
||||
- "${REDIS_HOST_PORT:-6379}:6379"
|
||||
|
||||
# S3-compatible API for the local object store (large payloads / packet
|
||||
# offload). Host :${MINIO_API_HOST_PORT:-9005} = S3 API,
|
||||
# host :${MINIO_CONSOLE_HOST_PORT:-9006} = web console. The webapp only
|
||||
# routes to it when the OBJECT_STORE_* env vars are set (see .env.example).
|
||||
minio:
|
||||
container_name: ${CONTAINER_PREFIX:-}minio
|
||||
image: minio/minio:latest@sha256:14cea493d9a34af32f524e538b8346cf79f3321eff8e708c1e2960462bd8936e
|
||||
restart: always
|
||||
command: server /data --console-address ":9001"
|
||||
environment:
|
||||
MINIO_ROOT_USER: minioadmin
|
||||
MINIO_ROOT_PASSWORD: minioadmin
|
||||
volumes:
|
||||
- minio-data:/data
|
||||
ports:
|
||||
- "${MINIO_API_HOST_PORT:-9005}:9000"
|
||||
- "${MINIO_CONSOLE_HOST_PORT:-9006}:9001"
|
||||
networks:
|
||||
- app_network
|
||||
healthcheck:
|
||||
test: ["CMD", "curl", "-f", "http://localhost:9000/minio/health/live"]
|
||||
interval: 5s
|
||||
timeout: 5s
|
||||
retries: 5
|
||||
start_period: 5s
|
||||
|
||||
minio-init:
|
||||
image: minio/mc:latest@sha256:a7fe349ef4bd8521fb8497f55c6042871b2ae640607cf99d9bede5e9bdf11727
|
||||
depends_on:
|
||||
minio:
|
||||
condition: service_healthy
|
||||
networks:
|
||||
- app_network
|
||||
entrypoint: /bin/sh
|
||||
command:
|
||||
- -c
|
||||
- |
|
||||
mc alias set local http://minio:9000 minioadmin minioadmin
|
||||
mc mb -p local/packets || true
|
||||
restart: "no"
|
||||
|
||||
electric:
|
||||
container_name: ${CONTAINER_PREFIX:-}electric
|
||||
image: electricsql/electric:1.2.4@sha256:20da3d0b0e74926c5623392db67fd56698b9e374c4aeb6cb5cadeb8fea171c36
|
||||
restart: always
|
||||
environment:
|
||||
DATABASE_URL: postgresql://postgres:postgres@database:5432/postgres?sslmode=disable
|
||||
ELECTRIC_INSECURE: true
|
||||
ELECTRIC_ENABLE_INTEGRATION_TESTING: true
|
||||
networks:
|
||||
- app_network
|
||||
ports:
|
||||
- "${ELECTRIC_HOST_PORT:-3060}:3000"
|
||||
depends_on:
|
||||
- database
|
||||
|
||||
clickhouse:
|
||||
image: clickhouse/clickhouse-server:26.2.19.43@sha256:c2f2605585899d5103a0447daadbc0005f362200d5f0fcca7f40db3ca0dd36dd
|
||||
restart: always
|
||||
container_name: ${CONTAINER_PREFIX:-}clickhouse
|
||||
ulimits:
|
||||
nofile:
|
||||
soft: 262144
|
||||
hard: 262144
|
||||
environment:
|
||||
CLICKHOUSE_USER: default
|
||||
CLICKHOUSE_PASSWORD: password
|
||||
CLICKHOUSE_DEFAULT_ACCESS_MANAGEMENT: 1
|
||||
ports:
|
||||
- "${CLICKHOUSE_HTTP_HOST_PORT:-8123}:8123"
|
||||
- "${CLICKHOUSE_TCP_HOST_PORT:-9000}:9000"
|
||||
volumes:
|
||||
- clickhouse-data:/var/lib/clickhouse
|
||||
- clickhouse-logs:/var/log/clickhouse-server
|
||||
- ./config/clickhouse-disable-system-logs.xml:/etc/clickhouse-server/config.d/disable-system-logs.xml:ro
|
||||
networks:
|
||||
- app_network
|
||||
healthcheck:
|
||||
test:
|
||||
[
|
||||
"CMD",
|
||||
"clickhouse-client",
|
||||
"--host",
|
||||
"localhost",
|
||||
"--port",
|
||||
"9000",
|
||||
"--user",
|
||||
"default",
|
||||
"--password",
|
||||
"password",
|
||||
"--query",
|
||||
"SELECT 1",
|
||||
]
|
||||
interval: "3s"
|
||||
timeout: "5s"
|
||||
retries: "5"
|
||||
start_period: "10s"
|
||||
|
||||
clickhouse_migrator:
|
||||
build:
|
||||
context: ../internal-packages/clickhouse
|
||||
dockerfile: ./Dockerfile
|
||||
depends_on:
|
||||
clickhouse:
|
||||
condition: service_healthy
|
||||
networks:
|
||||
- app_network
|
||||
command: ["goose", "${GOOSE_COMMAND:-up}"]
|
||||
|
||||
# s2-lite: open-source S2 (https://s2.dev) for local realtime streams v2.
|
||||
# The image is distroless (no shell), so a `wget` / `curl` healthcheck
|
||||
# always reports unhealthy even when the API is responding. No other
|
||||
# service depends on this one, so the healthcheck is omitted.
|
||||
s2:
|
||||
image: ghcr.io/s2-streamstore/s2:latest@sha256:d6ded5ca7dd619fa7c946f06e39a98f9c95c6883c8bb884e5eaa129f232c920c
|
||||
command: ["lite", "--init-file", "/s2-spec.json"]
|
||||
volumes:
|
||||
- ./config/s2-spec.json:/s2-spec.json:ro
|
||||
ports:
|
||||
- "${S2_HOST_PORT:-4566}:80"
|
||||
networks:
|
||||
- app_network
|
||||
@@ -0,0 +1,28 @@
|
||||
receivers:
|
||||
otlp:
|
||||
protocols:
|
||||
grpc:
|
||||
endpoint: 0.0.0.0:4317
|
||||
http:
|
||||
endpoint: 0.0.0.0:4318
|
||||
|
||||
processors:
|
||||
batch:
|
||||
|
||||
exporters:
|
||||
logging:
|
||||
verbosity: normal
|
||||
otlphttp:
|
||||
endpoint: "http://host.docker.internal:3030/otel"
|
||||
compression: none
|
||||
|
||||
service:
|
||||
pipelines:
|
||||
traces:
|
||||
receivers: [otlp]
|
||||
processors: [batch]
|
||||
exporters: [otlphttp]
|
||||
logs:
|
||||
receivers: [otlp]
|
||||
processors: [batch]
|
||||
exporters: [otlphttp]
|
||||
Executable
+78
@@ -0,0 +1,78 @@
|
||||
#!/bin/sh
|
||||
set -xe
|
||||
|
||||
if [ -n "$DATABASE_HOST" ]; then
|
||||
scripts/wait-for-it.sh ${DATABASE_HOST} -- echo "database is up"
|
||||
fi
|
||||
|
||||
if [ "$SKIP_POSTGRES_MIGRATIONS" != "1" ]; then
|
||||
echo "Running prisma migrations"
|
||||
pnpm --filter @trigger.dev/database db:migrate:deploy
|
||||
echo "Prisma migrations done"
|
||||
else
|
||||
echo "SKIP_POSTGRES_MIGRATIONS=1, skipping Postgres migrations."
|
||||
fi
|
||||
|
||||
# Run-ops split: migrate the dedicated NEW run-ops database only when it is configured. Single-DB
|
||||
# installs never set the URL, so this is a no-op there.
|
||||
if [ -n "$RUN_OPS_DATABASE_URL" ]; then
|
||||
if [ "$SKIP_RUN_OPS_MIGRATIONS" != "1" ]; then
|
||||
echo "Running run-ops migrations"
|
||||
pnpm --filter @internal/run-ops-database db:migrate:deploy
|
||||
echo "Run-ops migrations done"
|
||||
else
|
||||
echo "SKIP_RUN_OPS_MIGRATIONS=1, skipping run-ops migrations."
|
||||
fi
|
||||
else
|
||||
echo "RUN_OPS_DATABASE_URL not set, skipping run-ops migrations."
|
||||
fi
|
||||
|
||||
if [ "$SKIP_DASHBOARD_AGENT_MIGRATIONS" != "1" ]; then
|
||||
echo "Running dashboard agent migrations"
|
||||
pnpm --filter @internal/dashboard-agent-db db:migrate:deploy
|
||||
echo "Dashboard agent migrations done"
|
||||
else
|
||||
echo "SKIP_DASHBOARD_AGENT_MIGRATIONS=1, skipping dashboard agent migrations."
|
||||
fi
|
||||
|
||||
if [ -n "$CLICKHOUSE_URL" ] && [ "$SKIP_CLICKHOUSE_MIGRATIONS" != "1" ]; then
|
||||
# Run ClickHouse migrations
|
||||
echo "Running ClickHouse migrations..."
|
||||
export GOOSE_DRIVER=clickhouse
|
||||
|
||||
# Ensure secure=true is in the connection string
|
||||
if echo "$CLICKHOUSE_URL" | grep -q "secure="; then
|
||||
# secure parameter already exists, use as is
|
||||
export GOOSE_DBSTRING="$CLICKHOUSE_URL"
|
||||
elif echo "$CLICKHOUSE_URL" | grep -q "?"; then
|
||||
# URL has query parameters, append secure=true
|
||||
export GOOSE_DBSTRING="${CLICKHOUSE_URL}&secure=true"
|
||||
else
|
||||
# URL has no query parameters, add secure=true
|
||||
export GOOSE_DBSTRING="${CLICKHOUSE_URL}?secure=true"
|
||||
fi
|
||||
|
||||
export GOOSE_MIGRATION_DIR=/triggerdotdev/internal-packages/clickhouse/schema
|
||||
/usr/local/bin/goose up
|
||||
echo "ClickHouse migrations complete."
|
||||
elif [ "$SKIP_CLICKHOUSE_MIGRATIONS" = "1" ]; then
|
||||
echo "SKIP_CLICKHOUSE_MIGRATIONS=1, skipping ClickHouse migrations."
|
||||
else
|
||||
echo "CLICKHOUSE_URL not set, skipping ClickHouse migrations."
|
||||
fi
|
||||
|
||||
# Copy over required prisma files
|
||||
cp internal-packages/database/prisma/schema.prisma apps/webapp/prisma/
|
||||
cp node_modules/@prisma/engines/*.node apps/webapp/prisma/
|
||||
|
||||
cd /triggerdotdev/apps/webapp
|
||||
|
||||
|
||||
# Decide how much old-space memory Node should get.
|
||||
# Use $NODE_MAX_OLD_SPACE_SIZE if it’s set; otherwise fall back to 8192.
|
||||
MAX_OLD_SPACE_SIZE="${NODE_MAX_OLD_SPACE_SIZE:-8192}"
|
||||
|
||||
echo "Setting max old space size to ${MAX_OLD_SPACE_SIZE}"
|
||||
|
||||
NODE_PATH='/triggerdotdev/node_modules/.pnpm/node_modules' exec dumb-init node --max-old-space-size=${MAX_OLD_SPACE_SIZE} ./build/server.js
|
||||
|
||||
Executable
+184
@@ -0,0 +1,184 @@
|
||||
#!/bin/sh
|
||||
|
||||
# The MIT License (MIT)
|
||||
#
|
||||
# Copyright (c) 2017 Eficode Oy
|
||||
#
|
||||
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
# of this software and associated documentation files (the "Software"), to deal
|
||||
# in the Software without restriction, including without limitation the rights
|
||||
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
# copies of the Software, and to permit persons to whom the Software is
|
||||
# furnished to do so, subject to the following conditions:
|
||||
#
|
||||
# The above copyright notice and this permission notice shall be included in all
|
||||
# copies or substantial portions of the Software.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
# SOFTWARE.
|
||||
|
||||
set -- "$@" -- "$TIMEOUT" "$QUIET" "$PROTOCOL" "$HOST" "$PORT" "$result"
|
||||
TIMEOUT=15
|
||||
QUIET=0
|
||||
# The protocol to make the request with, either "tcp" or "http"
|
||||
PROTOCOL="tcp"
|
||||
|
||||
echoerr() {
|
||||
if [ "$QUIET" -ne 1 ]; then printf "%s\n" "$*" 1>&2; fi
|
||||
}
|
||||
|
||||
usage() {
|
||||
exitcode="$1"
|
||||
cat << USAGE >&2
|
||||
Usage:
|
||||
$0 host:port|url [-t timeout] [-- command args]
|
||||
-q | --quiet Do not output any status messages
|
||||
-t TIMEOUT | --timeout=timeout Timeout in seconds, zero for no timeout
|
||||
-- COMMAND ARGS Execute command with args after the test finishes
|
||||
USAGE
|
||||
exit "$exitcode"
|
||||
}
|
||||
|
||||
wait_for() {
|
||||
case "$PROTOCOL" in
|
||||
tcp)
|
||||
if ! command -v nc >/dev/null; then
|
||||
echoerr 'nc command is missing!'
|
||||
exit 1
|
||||
fi
|
||||
;;
|
||||
wget)
|
||||
if ! command -v wget >/dev/null; then
|
||||
echoerr 'wget command is missing!'
|
||||
exit 1
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
|
||||
while :; do
|
||||
case "$PROTOCOL" in
|
||||
tcp)
|
||||
nc -w 1 -z "$HOST" "$PORT" > /dev/null 2>&1
|
||||
;;
|
||||
http)
|
||||
wget --timeout=1 -q "$HOST" -O /dev/null > /dev/null 2>&1
|
||||
;;
|
||||
*)
|
||||
echoerr "Unknown protocol '$PROTOCOL'"
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
|
||||
result=$?
|
||||
|
||||
if [ $result -eq 0 ] ; then
|
||||
if [ $# -gt 7 ] ; then
|
||||
for result in $(seq $(($# - 7))); do
|
||||
result=$1
|
||||
shift
|
||||
set -- "$@" "$result"
|
||||
done
|
||||
|
||||
TIMEOUT=$2 QUIET=$3 PROTOCOL=$4 HOST=$5 PORT=$6 result=$7
|
||||
shift 7
|
||||
exec "$@"
|
||||
fi
|
||||
exit 0
|
||||
fi
|
||||
|
||||
if [ "$TIMEOUT" -le 0 ]; then
|
||||
break
|
||||
fi
|
||||
TIMEOUT=$((TIMEOUT - 1))
|
||||
|
||||
sleep 1
|
||||
done
|
||||
echo "Operation timed out" >&2
|
||||
exit 1
|
||||
}
|
||||
|
||||
while :; do
|
||||
case "$1" in
|
||||
http://*|https://*)
|
||||
HOST="$1"
|
||||
PROTOCOL="http"
|
||||
shift 1
|
||||
;;
|
||||
*:* )
|
||||
HOST=$(printf "%s\n" "$1"| cut -d : -f 1)
|
||||
PORT=$(printf "%s\n" "$1"| cut -d : -f 2)
|
||||
shift 1
|
||||
;;
|
||||
-q | --quiet)
|
||||
QUIET=1
|
||||
shift 1
|
||||
;;
|
||||
-q-*)
|
||||
QUIET=0
|
||||
echoerr "Unknown option: $1"
|
||||
usage 1
|
||||
;;
|
||||
-q*)
|
||||
QUIET=1
|
||||
result=$1
|
||||
shift 1
|
||||
set -- -"${result#-q}" "$@"
|
||||
;;
|
||||
-t | --timeout)
|
||||
TIMEOUT="$2"
|
||||
shift 2
|
||||
;;
|
||||
-t*)
|
||||
TIMEOUT="${1#-t}"
|
||||
shift 1
|
||||
;;
|
||||
--timeout=*)
|
||||
TIMEOUT="${1#*=}"
|
||||
shift 1
|
||||
;;
|
||||
--)
|
||||
shift
|
||||
break
|
||||
;;
|
||||
--help)
|
||||
usage 0
|
||||
;;
|
||||
-*)
|
||||
QUIET=0
|
||||
echoerr "Unknown option: $1"
|
||||
usage 1
|
||||
;;
|
||||
*)
|
||||
QUIET=0
|
||||
echoerr "Unknown argument: $1"
|
||||
usage 1
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
if ! [ "$TIMEOUT" -ge 0 ] 2>/dev/null; then
|
||||
echoerr "Error: invalid timeout '$TIMEOUT'"
|
||||
usage 3
|
||||
fi
|
||||
|
||||
case "$PROTOCOL" in
|
||||
tcp)
|
||||
if [ "$HOST" = "" ] || [ "$PORT" = "" ]; then
|
||||
echoerr "Error: you need to provide a host and port to test."
|
||||
usage 2
|
||||
fi
|
||||
;;
|
||||
http)
|
||||
if [ "$HOST" = "" ]; then
|
||||
echoerr "Error: you need to provide a host to test."
|
||||
usage 2
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
|
||||
wait_for "$@"
|
||||
@@ -0,0 +1,64 @@
|
||||
version: "3"
|
||||
|
||||
volumes:
|
||||
database-data:
|
||||
|
||||
networks:
|
||||
app_network:
|
||||
external: false
|
||||
|
||||
services:
|
||||
db:
|
||||
container_name: devdb
|
||||
image: postgres:14
|
||||
restart: always
|
||||
volumes:
|
||||
- database-data:/var/lib/postgresql/data/
|
||||
environment:
|
||||
POSTGRES_USER: postgres
|
||||
POSTGRES_PASSWORD: postgres
|
||||
POSTGRES_DB: postgres
|
||||
networks:
|
||||
- app_network
|
||||
ports:
|
||||
- 5432:5432
|
||||
app:
|
||||
build:
|
||||
context: ../
|
||||
dockerfile: ./docker/Dockerfile
|
||||
ports:
|
||||
- 3030:3030
|
||||
depends_on:
|
||||
- db
|
||||
env_file:
|
||||
- ../.env
|
||||
environment:
|
||||
DATABASE_URL: postgres://postgres:postgres@db:5432/postgres?schema=public
|
||||
DIRECT_URL: postgres://postgres:postgres@db:5432/postgres?schema=public
|
||||
SESSION_SECRET: secret123
|
||||
MAGIC_LINK_SECRET: secret123
|
||||
ENCRYPTION_KEY: dummy-encryption-keeeey-32-bytes
|
||||
REMIX_APP_PORT: 3030
|
||||
PORT: 3030
|
||||
WORKER_ENABLED: "false"
|
||||
networks:
|
||||
- app_network
|
||||
worker:
|
||||
build:
|
||||
context: ../
|
||||
dockerfile: ./docker/Dockerfile
|
||||
depends_on:
|
||||
- db
|
||||
env_file:
|
||||
- ../.env
|
||||
environment:
|
||||
DATABASE_URL: postgres://postgres:postgres@db:5432/postgres?schema=public
|
||||
DIRECT_URL: postgres://postgres:postgres@db:5432/postgres?schema=public
|
||||
SESSION_SECRET: secret123
|
||||
MAGIC_LINK_SECRET: secret123
|
||||
ENCRYPTION_KEY: dummy-encryption-keeeey-32-bytes
|
||||
REMIX_APP_PORT: 3030
|
||||
PORT: 3030
|
||||
HTTP_SERVER_DISABLED: "true"
|
||||
networks:
|
||||
- app_network
|
||||
Reference in New Issue
Block a user