Skip to main content
Good logs answer a question without a text parser. Emit one final event for each important operation. Put the result, duration, and business context on that event.

Use one canonical operation event

Do not emit started, processing, and completed logs for routine work. Keep child work as spans. Keep counters and durations as metrics. Emit one final operation event in a finally block.
The Squasher SDK converts this event to a correlated log, span, and measurement set. You do not need three application calls for the same operation.

Use stable field names

Use low-cardinality fields such as route, region, provider, result, and release for breakdowns. Use high-cardinality fields such as request, user, order, or monitor IDs only for direct filtering. Do not group large time windows by a unique ID.

Keep attribute types

Send numbers and booleans as numbers and booleans. The JavaScript SDKs flatten safe nested objects to dotted keys.
This produces cache.hit=true, cache.age_ms=42, and result_count=8. Sensitive attribute names, such as passwords, tokens, cookies, and authorization values, are redacted. Attribute depth, count, and string length are bounded.

Sample by outcome

Use deterministic outcome-aware sampling. Keep failures and slow operations. Sample routine success. Squasher keeps operation measurements when it samples out the related log and trace, so counts and latency data stay exact.
The SDK uses a stable trace, session, user, or event key. Rate-based decisions with the same key and outcome class are identical; a user or release allowlist can override the rate. Outcome classes use separate rates, so the SDK can keep a failure or slow event after it drops routine work from the same trace. This is event sampling, not whole-trace tail sampling. Use Collector tail sampling when every span in a trace must receive one decision. Debug mode keeps all events so you can verify instrumentation.

Protect private data

  • Do not record credentials, session cookies, raw authorization headers, prompts, or payment data.
  • Record route templates instead of raw URLs with customer identifiers.
  • Put an internal ID in an attribute only when an operator must find one exact operation.
  • Use beforeSend for product-specific redaction and allowlists.

Verify quality

For each service, check that operation events have service, environment, release, route or operation, outcome, status, duration, and trace correlation. Also check for orphan logs, duplicate final events, and attribute type changes. Use the Logs API for narrow searches and the Logs Patterns and Changes views for bounded comparisons. Run squasher observe quality --project <project_id> --service-name <service> or use the Telemetry Quality API for a content-free, bounded report of these checks.