Skip to main content Início Criadores 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".
Ir para a instalação Skills Marketplace Descubra e explore skills de IA criadas pela comunidade.
Instalar com Codex ou Claude Copie este prompt, cole no Codex, Claude ou outro assistente e deixe que ele revise a página da skill e instale para você.
Copiar promptMostrar detalhes do prompt Um comando direto ignora o prompt de revisão. Verifique a origem antes de executá-lo.
npx skills add https://github.com/jeremylongshore/claude-code-plugins-plus-skills --skill webflow-observabilityO comando permanece em uma só linha. Role horizontalmente para revisá-lo antes de copiar.
Prefere uma cópia local? Baixe os arquivos disponíveis atualmente no SkillsMP.
Baixar Zip Baixando... Mais deste repositório Implement user sign-up and sign-in flows with Clerk.
Use when building authentication UI, customizing sign-in experience,
or implementing OAuth social login.
Trigger with phrases like "clerk sign-in", "clerk sign-up",
"clerk login flow", "clerk OAuth", "clerk social login".
Implement session management and middleware with Clerk.
Use when managing user sessions, configuring route protection,
or implementing token refresh and custom JWT templates.
Trigger with phrases like "clerk session", "clerk middleware",
"clerk route protection", "clerk token", "clerk JWT".
Configure enterprise SSO, role-based access control, and organization management.
Use when implementing SSO integration, configuring role-based permissions,
or setting up organization-level controls.
Trigger with phrases like "clerk SSO", "clerk RBAC",
"clerk enterprise", "clerk roles", "clerk permissions", "clerk organizations".
Ocupações relacionadas SOC
Baseado na classificação ocupacional SOC
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.