No matter how complex or simple an application seems to be, there is always room for error, be it a connection issue, invalid input from a user, or a bug hidden deep within the code of the application itself.
Bad or even non-existent error handling makes an application annoying at best and downright awful or unusable at its worst. So, it makes sense to wonder about the “what if?” scenarios as a software engineer and handle them accordingly.
Instrumenting a third-party library or framework requires additional exception and error handling, since it introduces new features to an application, and, along with it, an increased potential for errors.
Exceptions and error handling pose unique requirements in OpenTelemetry.
As the official OpenTelemetry documentation states, OpenTelemetry implementations MUST NOT throw unhandled exceptions at runtime.
Whenever catching an exception, put it in an event on a span. The name of the event must be exception
.
For more specific guidance on background tasks and internal error handling, see the official OpenTelemetry documentation.
Error handling or extensive input validation can lead to a decrease in performance.
We therefore recommend that, following the guiding principles above, you define global exception handling logic to ensure exceptions do not leak into user code.
Luckily, OpenTelemetry has also implemented a self-diagnostics tool. All libraries can expose self-troubleshooting telemetry that can be enabled and filtered out. For instance, a span exporter can indicate how much time exporters spend uploading telemetry. Any time such an error is suppressed, the library should log the error with language-specific conventions.
SDK implementations must allow end users to change the default error handling behavior. This enables developers to run stricter or more specific error handling.
Generally, an exception can be caught on an event on a span after it was created but before it ends.
This example is a pseudo-Java code block to catch and record an exception on a span:
Span span = myTracer.startSpan(/*...*/);try {//Code that does the actual work that the Span represents} catch (Throwable e) {span.recordException(e, Attributes.of("exception.escaped", true));throw e;} finally {span.end();}
Specifically to Java, OpenTelemetry makes use of java.util.logging to handle logs and errors. Custom handlers can be registered in code as well as the Java logging configuration file.
This example is for Ruby:
rescue Exception => espan&.record_exception(e)span&.status = OpenTelemetry::Trace::Status.error("Unhandled exception of type: #{e.class}")raise eensurespan&.finishend
The name of the event on which the exception is caught must always be exception
.
You can add up to four different attributes to your event:
exception.type
exception.message
exception.stacktrace
(all strings)exception.escaped
(boolean)Of these, either exception.type
or exception.message
is required. For details, see the official OpenTelemetry documentation.