Skip to main content Startseite Ersteller jeremylongshore claude-code-plugins-plus-skills webflow-observability
webflow-observability Set up observability for Webflow integrations — Prometheus metrics for API calls,
OpenTelemetry tracing, structured logging with pino, Grafana dashboards,
and alerting for rate limits, errors, and latency.
Trigger with phrases like "webflow monitoring", "webflow metrics",
"webflow observability", "monitor webflow", "webflow alerts", "webflow tracing".
Zur Installation springen Skills Marktplatz Entdecken und erkunden Sie KI-Skills, die von der Community erstellt wurden.
Mit Codex oder Claude installieren Kopieren Sie diesen Prompt, fügen Sie ihn in Codex, Claude oder einen anderen Assistant ein und lassen Sie die Skill-Seite prüfen und installieren.
Prompt kopierenPrompt-Details anzeigen Ein direkter Befehl überspringt den Prüf-Prompt. Prüfen Sie die Quelle, bevor Sie ihn ausführen.
npx skills add https://github.com/jeremylongshore/claude-code-plugins-plus-skills --skill webflow-observabilityDer Befehl bleibt in einer Zeile. Scrollen Sie horizontal, um ihn vor dem Kopieren vollständig zu prüfen.
Sie bevorzugen eine lokale Kopie? Laden Sie die Dateien herunter, die SkillsMP derzeit vorliegen.
ZIP herunterladen Herunterladen... Mehr aus diesem Repository
Verwandte Berufe SOC
Basierend auf der SOC-Berufsklassifikation
name webflow-observability description Set up observability for Webflow integrations — Prometheus metrics for API calls,
OpenTelemetry tracing, structured logging with pino, Grafana dashboards,
and alerting for rate limits, errors, and latency.
Trigger with phrases like "webflow monitoring", "webflow metrics",
"webflow observability", "monitor webflow", "webflow alerts", "webflow tracing".
allowed-tools Read, Write, Edit version 1.5.0 license MIT author Jeremy Longshore <jeremy@intentsolutions.io> tags ["saas","design","no-code","webflow"] compatibility Designed for Claude Code
Webflow Observability
Overview
Full observability stack for Webflow Data API v2 integrations: Prometheus metrics
for API call counting and latency, OpenTelemetry distributed tracing, structured
JSON logging, and alerting rules for error rate and rate limit exhaustion.
Prerequisites
prom-client for Prometheus metrics
@opentelemetry/api for tracing (optional)
pino for structured logging
Prometheus + Grafana (or compatible backend)
Instructions
Step 1: Prometheus Metrics
import { Registry , Counter , Histogram , Gauge } from "prom-client" ;
export const registry = new Registry ();
export const apiRequests = new Counter ({
name : "webflow_api_requests_total" ,
help : "Total Webflow API requests" ,
labelNames : ["operation" , "status_code" , "method" ] as const ,
registers : [registry],
});
export const apiDuration = new Histogram ({
name : "webflow_api_request_duration_seconds" ,
help : "Webflow API request duration in seconds" ,
: [ ] ,
: [ , , , , , , , ],
: [registry],
});
apiErrors = ({
: ,
: ,
: [ , , ] ,
: [registry],
});
rateLimitRemaining = ({
: ,
: ,
: [registry],
});
cmsItemCount = ({
: ,
: ,
: [ , ] ,
: [registry],
});
webhookEvents = ({
: ,
: ,
: [ , ] ,
: [registry],
});
labelNames
"operation"
as
const
buckets
0.05
0.1
0.25
0.5
1
2
5
10
registers
export
const
new
Counter
name
"webflow_api_errors_total"
help
"Webflow API errors by status code"
labelNames
"operation"
"status_code"
"error_type"
as
const
registers
export
const
new
Gauge
name
"webflow_rate_limit_remaining"
help
"Remaining API calls before rate limit"
registers
export
const
new
Gauge
name
"webflow_cms_items_total"
help
"Total CMS items by collection"
labelNames
"collection"
"site"
as
const
registers
export
const
new
Counter
name
"webflow_webhook_events_total"
help
"Received webhook events by trigger type"
labelNames
"trigger_type"
"status"
as
const
registers
Step 2: Instrumented Client Wrapper
import { WebflowClient } from "webflow-api" ;
import { apiRequests, apiDuration, apiErrors, rateLimitRemaining } from "./metrics.js" ;
export async function instrumentedCall<T>(
operation : string ,
method : string ,
fn : () => Promise <T>
): Promise <T> {
const timer = apiDuration.startTimer ({ operation });
try {
const result = await fn ();
apiRequests.inc ({ operation, status_code : "200" , method });
timer ();
return result;
} catch (error : any ) {
const statusCode = String (error.statusCode || error.status || "unknown" );
apiRequests.inc ({ operation, status_code : statusCode, method });
apiErrors.inc ({
operation,
status_code : statusCode,
error_type : statusCode === "429" ? "rate_limit" : statusCode >= "500" ? "server" : "client" ,
});
timer ();
throw error;
}
}
const { sites } = await instrumentedCall ("sites.list" , "GET" , () =>
webflow.sites .list ()
);
const { items } = await instrumentedCall ("items.listLive" , "GET" , () =>
webflow.collections .items .listItemsLive (collectionId)
);
const item = await instrumentedCall ("items.create" , "POST" , () =>
webflow.collections .items .createItem (collectionId, {
fieldData : { name : "Test" , slug : "test" },
})
);
Step 3: Metrics Endpoint
import express from "express" ;
import { registry } from "../observability/metrics.js" ;
const app = express ();
app.get ("/metrics" , async (req, res) => {
res.set ("Content-Type" , registry.contentType );
res.send (await registry.metrics ());
});
Step 4: OpenTelemetry Distributed Tracing
import { trace, SpanStatusCode , context } from "@opentelemetry/api" ;
const tracer = trace.getTracer ("webflow-integration" , "1.0.0" );
export async function tracedCall<T>(
operationName : string ,
attributes : Record <string , string >,
fn : () => Promise <T>
): Promise <T> {
return tracer.startActiveSpan (`webflow.${operationName} ` , async (span) => {
span.setAttributes ({
"webflow.operation" : operationName,
...attributes,
});
try {
const result = await fn ();
span.setStatus ({ code : SpanStatusCode .OK });
return result;
} catch (error : any ) {
span.setStatus ({
code : SpanStatusCode .ERROR ,
message : error.message ,
});
span.recordException (error);
span.setAttributes ({
"webflow.error.status_code" : String (error.statusCode || "unknown" ),
});
throw error;
} finally {
span.end ();
}
});
}
const { collections } = await tracedCall (
"collections.list" ,
{ "webflow.site_id" : siteId },
() => webflow.collections .list (siteId)
);
Step 5: Structured Logging
import pino from "pino" ;
export const logger = pino ({
name : "webflow-integration" ,
level : process.env .LOG_LEVEL || "info" ,
serializers : {
err : pino.stdSerializers .err ,
},
redact : {
paths : ["accessToken" , "apiToken" , "*.authorization" , "req.headers.authorization" ],
censor : "[REDACTED]" ,
},
});
export function logApiCall (
operation : string ,
durationMs : number ,
status : "success" | "error" ,
metadata ?: Record <string , any >
) {
const logFn = status === "error" ? logger.error .bind (logger) : logger.info .bind (logger);
logFn ({
service : "webflow" ,
operation,
durationMs,
status,
...metadata,
}, `webflow.${operation} ${status} (${durationMs} ms)` );
}
export function logWebhook (triggerType : string , status : "processed" | "failed" | "skipped" ) {
logger.info ({
service : "webflow" ,
event : "webhook" ,
triggerType,
status,
}, `webhook.${triggerType} ${status} ` );
}
Step 6: AlertManager Rules
groups:
- name: webflow
rules:
- alert: WebflowHighErrorRate
expr: |
(
rate(webflow_api_errors_total[5m]) /
rate(webflow_api_requests_total[5m])
) > 0.05
for: 5m
labels:
severity: warning
annotations:
summary: "Webflow API error rate > 5%"
description: "{{ $value | humanizePercentage }} errors in last 5m"
- alert: WebflowRateLimited
expr: |
rate(webflow_api_errors_total{status_code="429"}[5m]) > 0
for: 2m
labels:
severity: warning
annotations:
summary: "Webflow API rate limited"
- alert: WebflowHighLatency
expr: |
histogram_quantile(0.95,
rate(webflow_api_request_duration_seconds_bucket[5m])
) > 3
for: 5m
labels:
severity: warning
annotations:
summary: "Webflow P95 latency > 3s"
- alert: WebflowDown
expr: |
sum(rate(webflow_api_requests_total{status_code=~"5.."}[5m])) /
sum(rate(webflow_api_requests_total[5m])) > 0.5
for: 2m
labels:
severity: critical
annotations:
summary: "Webflow API > 50% server errors"
- alert: WebflowRateLimitLow
expr: webflow_rate_limit_remaining < 10
for: 1m
labels:
severity: warning
annotations:
summary: "Webflow rate limit nearly exhausted"
Step 7: Grafana Dashboard Queries {
"panels" : [
{
"title" : "Request Rate by Operation" ,
"targets" : [ { "expr" : "sum by (operation) (rate(webflow_api_requests_total[5m]))" } ]
} ,
{
"title" : "Error Rate" ,
"targets" : [ { "expr" : "sum(rate(webflow_api_errors_total[5m])) / sum(rate(webflow_api_requests_total[5m]))" } ]
} ,
{
"title" : "Latency P50 / P95 / P99" ,
"targets" : [
{ "expr" : "histogram_quantile(0.5, rate(webflow_api_request_duration_seconds_bucket[5m]))" , "legendFormat" : "p50" } ,
{ "expr" : "histogram_quantile(0.95, rate(webflow_api_request_duration_seconds_bucket[5m]))" , "legendFormat" : "p95" } ,
{ "expr" : "histogram_quantile(0.99, rate(webflow_api_request_duration_seconds_bucket[5m]))" , "legendFormat" : "p99" }
]
} ,
{
"title" : "Rate Limit Remaining" ,
"targets" : [ { "expr" : "webflow_rate_limit_remaining" } ]
} ,
{
"title" : "Webhook Events by Type" ,
"targets" : [ { "expr" : "sum by (trigger_type) (rate(webflow_webhook_events_total[5m]))" } ]
}
]
}
Output
Prometheus metrics: request count, latency histogram, error rate, rate limit gauge
OpenTelemetry tracing for end-to-end request visibility
Structured JSON logging with PII redaction
AlertManager rules for error rate, latency, and rate limits
Grafana dashboard panels
Error Handling Issue Cause Solution Missing metrics Calls not instrumented Wrap with instrumentedCall() High cardinality Too many label values Limit operation to known set Trace gaps Missing context propagation Pass OTel context in async calls Alert storms Thresholds too sensitive Increase for duration
Resources
Next Steps For incident response, see webflow-incident-runbook.