Track Backend Errors

Overview

If you aren’t already collecting logs with Datadog, see the Logs documentation to set up logs. Ensure that the source tag (specifying language) is properly configured. Datadog recommends setting up Agent-based log collection.

Setup

For languages such as Python, Java, and Ruby, no additional configuration is needed if the source tag in your logs is configured correctly. All required attributes are automatically tagged and sent to Datadog.

For backend languages such as C#, .NET, Go, and NodeJS, the code examples in each section demonstrate how to properly configure an error log and attach the required stack trace in the log’s error.stack.

If you are already sending stack traces to Datadog but they are not in error.stack, you can set up a generic log remapper to remap the stack trace to the correct attribute in Datadog.

To configure inline code snippets in issues, set up the source code integration. Adding code snippets in Error Tracking for Logs does not require APM; the enrichment tags and linked repository is the same for both.

C# and .NET

If you have not setup log collection for C#, see the C# Log Collection documentation.

To log a caught exception yourself, you may optionally use:

var log = new LoggerConfiguration()
    .WriteTo.File(new JsonFormatter(renderMessage: true), "log.json")
    .Enrich.WithExceptionDetails() 
    .CreateLogger();
try {
  // …
} catch (Exception ex) {
  // pass exception as first argument of log call
  log.Error(ex, "an exception occurred");
}

If you have not setup log collection for C#, see the C# Log Collection documentation.

To log a caught exception yourself, you may optionally use:

private static Logger log = LogManager.GetCurrentClassLogger();

static void Main(string[] args)
{
  try {
    // …
  } catch (Exception ex) {
    // pass exception as second argument of log call
    log.ErrorException("an exception occurred", ex);
  }
}

If you have not setup log collection for C#, see the C# Log Collection documentation.

To log a caught exception yourself, you may optionally use:

class Program
{
  private static ILog logger = LogManager.GetLogger(typeof(Program));

  static void Main(string[] args)
  {
    try {
      // …
    } catch (Exception ex) {
      // pass exception as second argument of log call
      log.Error("an exception occurred", ex);
    }
  }
}

Go

Logrus

If you have not setup log collection for Go, see the Go Log Collection documentation.

To log a caught exception yourself, you may optionally use:

// for https://github.com/pkg/errors
type stackTracer interface {
	StackTrace() errors.StackTrace
}

type errorField struct {
  kind    string `json:"kind"`
  stack   string `json:"stack"`
  message string `json:"message"`
}

func ErrorField(err error) errorField {
    var stack string
	if serr, ok := err.(stackTracer); ok {
        st := serr.StackTrace()
		stack = fmt.Sprintf("%+v", st)
		if len(stack) > 0 && stack[0] == '\n' {
			stack = stack[1:]
		}
    }
    return ErrorField{
        kind: reflect.TypeOf(err).String(),
        stack: stack,
        message: err.Error(),
    }
}


log.WithFields(log.Fields{
    "error": ErrorField(err)
}).Error("an exception occurred")

Java (parsed)

If you have not setup log collection for Java, see the Java Log Collection documentation. Ensure your logs are tagged with source:java.

To log a caught exception yourself, you may optionally use:

Logger logger = LogManager.getLogger("HelloWorld");
try {
  // …
} catch (Exception e) {
  // pass exception as last argument of log call
  logger.error("an exception occurred", e)
}

To log a caught exception yourself, you may optionally use:

Logger logger = LoggerFactory.getLogger(NameOfTheClass.class);
try {
  // …
} catch (Exception e) {
  // pass exception as last argument of log call
  logger.error("an exception occurred", e)
}

NodeJS

Winston (JSON)

If you have not setup log collection for NodeJS, see the NodeJS Log Collection documentation.

To log a caught exception yourself, you may optionally use:

try {
  // …
} catch (e) {
  logger.error("an exception occurred", {
    error: {
      message: e.message,
      stack: e.stack
    }
  });
}

Python

Logging

If you have not setup log collection for Python, see the Python Log Collection documentation. Ensure your logs are tagged with source:python.

To log a caught exception yourself, you may optionally use:

try:
  // 
except:
  logging.exception('an exception occurred')

Ruby on Rails

Lograge (JSON)

If you have not setup log collection for Ruby on Rails, see the Ruby on Rails Log Collection documentation.

To log a caught exception yourself, you may optionally use:

# Lograge config
config.lograge.enabled = true

# This specifies to log in JSON format
config.lograge.formatter = Lograge::Formatters::Json.new

# Disables log coloration
config.colorize_logging = false

# Log to a dedicated file
config.lograge.logger = ActiveSupport::Logger.new(Rails.root.join('log', "#{Rails.env}.log"))

# Configure logging of exceptions to the correct fields
config.lograge.custom_options = lambda do |event|
    {
      error: {
        type: event.payload[:exception][0],
        message: event.payload[:exception][1],
        stack: event.payload[:exception_object].backtrace
      }
    }
  end  
end

Further Reading