feat(obs): enable Workers Observability (logs + traces)

- wrangler.toml: [observability] block with logs + traces at
  head_sampling_rate=1 (200k free events/day on free plan).
- src/index.js: structured request log emitted on every fetch
  (method/path/status/ms) — JSON shape so Observability's filter UI
  can index individual fields.
- Refactored fetch body into a route() helper so the log line sees the
  final response status.
This commit is contained in:
2026-04-20 17:36:16 +07:00
parent 2c201a4fc3
commit 12345e9aba
2 changed files with 54 additions and 17 deletions
+38 -17
View File
@@ -56,25 +56,46 @@ export default {
* @param {any} _ctx
*/
async fetch(request, env, _ctx) {
const start = Date.now();
const { pathname } = new URL(request.url);
const method = request.method;
if (request.method === "GET" && pathname === "/") {
return new Response("miti99bot ok", {
status: 200,
headers: { "content-type": "text/plain" },
});
}
const response = await route(request, env, pathname);
if (request.method === "POST" && pathname === "/webhook") {
try {
const handler = await getWebhookHandler(env);
return await handler(request);
} catch (err) {
console.error("webhook handler failed", err);
return new Response("internal error", { status: 500 });
}
}
return new Response("not found", { status: 404 });
// Structured request log for Workers Observability dashboard.
console.log(JSON.stringify({
msg: "req",
method,
path: pathname,
status: response.status,
ms: Date.now() - start,
}));
return response;
},
};
/**
* @param {Request} request
* @param {any} env
* @param {string} pathname
*/
async function route(request, env, pathname) {
if (request.method === "GET" && pathname === "/") {
return new Response("miti99bot ok", {
status: 200,
headers: { "content-type": "text/plain" },
});
}
if (request.method === "POST" && pathname === "/webhook") {
try {
const handler = await getWebhookHandler(env);
return await handler(request);
} catch (err) {
console.error("webhook handler failed", err);
return new Response("internal error", { status: 500 });
}
}
return new Response("not found", { status: 404 });
}
+16
View File
@@ -35,6 +35,22 @@ database_id = "261b54e7-0fdb-4fe7-8ed9-2e8a8bcf459c"
[triggers]
crons = ["0 17 * * *"]
# Workers Observability — captures console.* logs, request metadata, and
# invocation traces in the Cloudflare dashboard (Observability → Logs).
# 200k events/day included on free plan. `head_sampling_rate = 1` keeps
# all invocations; drop to 0.1 for 10% sampling if volume grows.
[observability]
enabled = true
head_sampling_rate = 1
[observability.logs]
enabled = true
invocation_logs = true
[observability.traces]
enabled = true
head_sampling_rate = 1
# Secrets (set via `wrangler secret put <name>`, NOT in this file):
# TELEGRAM_BOT_TOKEN — bot token from @BotFather
# TELEGRAM_WEBHOOK_SECRET — arbitrary high-entropy string, also set in .env.deploy