Customize application errors with Programmatic Log Errors

Programmatic Errors allow you to customize errors, monitor and troubleshoot issues that should not necessarily interfere with the service. For example, an application trying to remove a user who doesn't exist. These custom errors can be handled by adding just a few lines of code.

Programmatic Errors are labelled as warnings to indicate that a non fatal error occurred, such as application error. You can log programmatic errors, track custom error issues, and trigger Alerts.

Lambda

Configuring a Generic Error

Programmatic Errors can be configured from anywhere within your Lambda handler’s code. Below are some examples using the Lumigo tracer integrations.

print("[LUMIGO_LOG] <YOUR MESSAGE>")
console.log("[LUMIGO_LOG] <YOUR_MESSAGE>");
System.out.println("[LUMIGO_LOG] <YOUR_MESSAGE>");

Configuring a Custom Error

To configure custom types of errors, use one of the two options listed below:

import lumigo_tracer
lumigo_tracer.error("a description of the error", "My Custom Type")
const lumigo = require('@lumigo/tracer');
lumigo.error("a description of the error", { type: "My Custom Type" });

Alternatively custom errors can also support language variable outputs:

error = {
    'message': 'a description of the error',
    'type': 'My Custom Type'}
print("[LUMIGO_LOG]", json.dumps(error))
let error = {
    'message': 'a description of the error',
    'type': 'My Custom Type'
};
console.log(`[LUMIGO_LOG] ${JSON.stringify(error)}`);

📘

Note that when configuring programmatic errors the type error field is case sensitive and length specific. For example, setting an error with the type “Error 42 “ will cause the associated errors to aggregate differently to “error 42” on the issues page.

OpenTelemetry and Containers

Programmatic errors are created by adding span events with a custom attribute being set with the key name lumigo.type.

For example, you could add a programmatic error as follows:

from opentelemetry.trace import get_current_span
get_current_span().add_event('<error-message>', {'lumigo.type': '<error-type>'})
const { trace } = require('@opentelemetry/api');
trace.getActiveSpan()?.addEvent('<error-message>', {'lumigo.type': '<error-type>'});
Attributes eventAttributes = Attributes.of(
    AttributeKey.stringKey("lumigo.type"), "<error-type>"
);
Span.current().addEvent("<error-message>", eventAttributes);

Example

A Twilio SMS API discards outgoing SMS requests that contain an empty message body, but does not return an error indication, this can be handled using programmatic errors.

Twilio returns multiple error messages for different cases. Since you may care more about some of these errors and less about others, looking at all of the errors through a single lens (for example, as generic 4xx or "client errors") could be very inefficient. You can use a custom programmatic error type for each of the cases.

If we look at a 400 response returned from Twilio as part of the example:

{
    "code": 14108,
    "message": "Invalid Phone Number",
    "more_info": "https://www.twilio.com/docs/errors/14108",
    "status": 400
}

Then the code can use that to report Lumigo Programmatic Errors in the following way:

.
.
.
response = twilio_client.messages.create(body=sms.message,
        from_=sms.sender, to=sms.recepient)

if response.status == 400:
    if response.code == 14108:
        lumigo.error(response.message, 'Twilio: Invalid Phone Number')
    elif response.code == 32103:
        lumigo.error(response.message, 'Twilio: Empty SMS Body')
    .
    .
    .
    else:
        lumigo.error(response.message, 'Twilio: Client Error')
.
.
.

Resulting in multiple issues grouped by issue type as defined from our code example above.

2644

Example: Custom programmatic errors propagated to Lumigo