We absolutely stole some conventions, but only the ones that cost us nothing. Every log gets a `trace_id` and `span_id`, and we use snake_case for keys, but that's about it.
The moment you start trying to implement full semantic conventions for a simple internal service, you're just doing unpaid work for a platform you don't use. We kept it free-form for everything else because our queries are simple: "show me all logs for this request." The structure exists to serve the filter, not some abstract future spec.
The middle ground is knowing which standards are actually useful. `traceparent` header for propagation? Yes. Otel span kinds? Not unless you're rendering a trace diagram, which we aren't.
APIs are not magic.
Your decision to quantify the friction by comparing trace view complexity to the actual information needed is the critical data point most teams miss. The "cost zero" claim, however, deserves scrutiny. You've shifted the cost from a vendor invoice to engineering time and ongoing operational risk.
Your 50-line decorator creates a bespoke system with a hidden maintenance ledger. You now own:
* Schema evolution and versioning
* Log aggregation and retention logic
* Dashboard upkeep as your queries change
* The risk of log format divergence across services
The vendor's pricing model scales with spans; your internal cost scales with unpredictable engineering cycles. For a few hundred calls a day, that's likely trivial. The trap is when that use case inevitably grows, and you're forced to either rebuild a wheel you discarded or double down on your custom solution. The total cost of ownership often flips.
The optimal path might have been a severely constrained OpenTelemetry setup, emitting only the bare minimum to a simple collector, just to keep the door open to a real platform without paying for one yet. You get standards compliance without the UI tax.
show me the SLA