GeoNames observability field guide
Prepared · forwarding OFF until credentials

A practical guide for the next setup session

See what the search service is doing.

The code is prepared to emit safe structured observations locally and optionally send them to a Better Stack source. No source has been created, no endpoint or token is configured, and no log is currently being forwarded there. The app does not need a token to run.

Today's state: Workers console observations are available; Cloudflare Workers Logs is enabled in the local Wrangler configuration for both Workers. Better Stack forwarding remains inactive unless BETTER_STACK_SOURCE_TOKEN and a real BETTER_STACK_INGEST_URL are both supplied as runtime bindings. Neither secret nor remote service was created or deployed for this guide.

What are we observing?

Logs · events

A timestamped record of something that happened: a search succeeded, hit cache, or failed. Best for “what happened to this request?”

Metrics · aggregates

Numbers summarized over time: request rate, error percentage, p95 latency. Best for “is the system getting slower?” This implementation emits event logs, not a metrics pipeline.

Traces · connected spans

A trace follows one operation across components with parent/child spans. The code has timing spans internally, but this is not yet OpenTelemetry trace export or a distributed trace product.

The actual request path

Browser traffic reaches the web Worker; its service binding calls the separate service Worker RPC. The service talks to D1 and optionally KV cache. Logs from each Worker belong to their respective runtime/source.

flowchart LR
  B[Browser] --> W[Web Worker\nAPI / UI]
  W -->|GEONAMES service binding / RPC| S[GeoNames service Worker]
  S --> K[(KV search cache)]
  S --> D[(D1 database)]
  W -. console structured observations .-> C[Cloudflare Workers Logs]
  S -. console structured observations .-> C
  S -. optional HTTPS POST when both bindings exist .-> BT[Better Stack source]
  W -. optional HTTPS POST when both bindings exist .-> BTW[Better Stack source]
  BTW --> BT

Diagram arrows to Better Stack describe the prepared optional capability, not a live connection today. Cloudflare log storage is separate from Better Stack forwarding.

What event fields mean

The shared emitter writes structured records to the Worker console and adds betterStackForwarding. Current call sites emit service operations (get, getMany, search, searchPage) and demo HTTP request events. Representative field sets; timestamps and measurements vary.

{
  "dt": "2026-10-01T12:00:00.000Z",
  "message": "http_request",
  "event": "http_request",
  "service": "geonames-global-demo",
  "requestId": "generated UUID",
  "route": "/api/search",
  "method": "GET",
  "status": 200,
  "durationMs": 12,
  "betterStackForwarding": "not_configured"
}
{
  "dt": "2026-10-01T12:00:00.010Z",
  "message": "rpc_request",
  "event": "rpc_request",
  "service": "geonames-global-service",
  "operation": "searchPage",
  "outcome": "ok",
  "cacheStatus": "MISS",
  "resultCount": 2,
  "limit": 2,
  "offset": 0,
  "durationMs": 8,
  "d1Ms": 4,
  "d1Queries": 3,
  "ftsMs": 3,
  "fuzzyMs": null,
  "betterStackForwarding": "not_configured"
}

HTTP events include request ID, bounded route/method/status; RPC events include operation, outcome, duration, and applicable result/cache/search timing fields. Forwarding status records configuration presence, not delivery success. No raw query, aliases, authorization headers, request/response bodies, source tokens, or raw exception messages belong in events.

This integration forwards event logs only; metrics and distributed traces are not implemented. Shipping logs does not create a Better Stack source, dashboard, saved query, alert, or retention policy; operators must provision and configure these separately.

Create a dedicated source and configure safely

On the observed Sources page, click Connect source to create a separate source named geonames-production. Choose HTTP/JSON log ingestion in the source setup and copy that source's exact token and HTTPS ingest endpoint. HTTP/JSON describes the ingestion format; follow the current setup UI rather than relying on an unobserved platform selector label. Do not reuse the existing sachit-production or sachit-staging OpenTelemetry sources. Never paste the token into chat or repository files.

From Git Bash at the repository root, run these commands one at a time. Each Wrangler prompt accepts a value; keep the source token and endpoint out of command arguments, chat, and repository files.

bunx wrangler secret put BETTER_STACK_SOURCE_TOKEN --config apps/service/wrangler.jsonc
bunx wrangler secret put BETTER_STACK_INGEST_URL --config apps/service/wrangler.jsonc
bunx wrangler secret put BETTER_STACK_SOURCE_TOKEN --config apps/web/wrangler.jsonc
bunx wrangler secret put BETTER_STACK_INGEST_URL --config apps/web/wrangler.jsonc

Wrangler secret prompts store both values securely. The first pair targets geonames-global-service; the second targets geonames-global-demo. Enter the same new source's token and exact HTTPS endpoint for each Worker. No named production environment or --env production is used. Each Worker needs both bindings; saving the secrets deploys a new Worker version and enables forwarding without requiring a source-code redeploy.

Confirm delivery, then explore

Open the new source's Live tail first and confirm an event arrives. Then, optionally explore structured log search and create dashboards or alerts using fields observed in real events. Product labels can change; follow the current UI rather than pasting unverified query syntax.

Build optional charts and alerts in Better Stack using fields actually observed in a real event. Delivery does not mean a dashboard, alert policy, or retained history exists.

Verify the first event

With both bindings set on both Workers, open /api/search?q=Bengaluru&limit=2&countryCode=IN on the demo and find the resulting http_request and service search observations in the new source. HTTP responses include X-Request-ID for finding the web event. This is log forwarding, not distributed trace propagation between Workers.

Troubleshooting checklist

No Better Stack events

  • Check betterStackForwarding: not_configured means a binding is absent.
  • Confirm the correct Worker/environment has both bindings; service and web are separate deployments.
  • Verify source token and exact source-specific HTTPS URL, then inspect Worker logs for the generic delivery warning/status.
  • Check Cloudflare Worker logs and invocation errors independently.

Search slow or failing

  • Separate web request time from service/RPC latency where both events are present.
  • Inspect service duration and database/cache timing spans when emitted; high D1 time suggests query/DB investigation.
  • Repeated cache misses suggest key churn, cold cache, or bypass; errors need safe category/status detail.
  • Pagination: compare page latency and result counts; do not infer a global empty search from an empty later page.

Forwarding uses a finite 2-second timeout, no retry, and reports only generic failure plus HTTP status (never response body). Delivery is best-effort and can be dropped during outages or execution shutdown.

Costs, sampling, privacy, deployment

Deployment requires the owner’s explicit approval for the exact external changes first.

  1. Review merged code and intended Worker bindings.
  2. Deploy service Worker configuration/code first, then the web Worker configuration/code; configure per-Worker bindings and production environment carefully.
  3. Only after approval, deploy and verify each Worker in Cloudflare; then trigger a safe non-sensitive request and confirm a real source event.

Verification tomorrow

  1. Token-free: run a harmless search with both bindings absent. It must return the same result behavior; observe local structured logging and confirm no Better Stack delivery attempt.
  2. Delivery: configure valid source credentials in a non-production environment, issue one harmless operation, and verify the event appears in that exact source’s live tail. Do not use real user search text.
  3. Failure: temporarily use a revoked/invalid token or controlled unreachable HTTPS endpoint in a non-production environment; verify RPC/request result still succeeds or fails only according to its normal application behavior, while forwarding reports a generic warning and does not retry. Restore correct settings afterward.
  4. Safety: inspect the received event and verify it contains no raw query, aliases, headers, bodies, source token, or raw exception message.

This guide does not claim any of those delivery scenarios have been run. They require the real source and user-authorized environment configuration.

Official references