Symbolicate iOS Stack Traces with the OpenTelemetry Collector


Use the symbolicator processor in your OpenTelemetry Collector to symbolicate iOS stack traces.

Important
This feature is in beta, and we would love your feedback!

The symbolicator processor replaces obfuscated names and addresses in your iOS stack traces with symbols from provided dSYM files.

Before You Start 

The symbolicator processor is compatible with Honeycomb OpenTelemetry Swift SDK version 0.0.14 and later.

To use the symbolicator processor, you need:

  • OpenTelemetry Collector built with CGO enabled.

  • An environment or container image with glibc support.

    We recommend gcr.io/distroless/cc, a secure and lightweight container image with CGO and glibc support.

If you’re not using the Honeycomb OpenTelemetry Swift SDK, make sure your exception data is in the format the processor expects.

Install 

By default, the Honeycomb OpenTelemetry Collector distribution includes the symbolicator processor, so you can skip to the next section if you’re using it. If you use another collector distribution or build your own, it must be built with CGO enabled.

You can install the symbolicator processor by adding it to your OpenTelemetry Collector build configuration file:

processors:
  - gomod: github.com/honeycombio/opentelemetry-collector-symbolicator/symbolicatorprocessor v0.0.0
    name: symbolicatorprocessor
    path: ./symbolicatorprocessor

dSYM Files 

The symbolicator requires access to the dSYM file generated by your build process. This file can be stored in your local file system, Amazon S3, or Google Cloud Storage.

To support symbolication, your dSYM file must be versioned with the generated build UUID in the file name. For example: 6A8CB813-45F6-3652-AD33-778FD1EAB196.dSYM.

Getting the Build UUID 

You can use the dwarfdump tool to get the build UUID from an an .xcarchive file generated by Xcode. The following example script finds the latest build and uploads it to the app-archives Amazon S3 bucket with the ios prefix.

# Get the App Name
if [[ -z "$1" ]]; then
  echo "❌ Usage: $0 <TargetName>"
  exit 1
fi

TARGET_NAME=$1

export ARCHIVE_PATH=$(ls -dt ~/Library/Developer/Xcode/Archives/*/"$TARGET_NAME"*.xcarchive | head -1)
echo "📦 Using Archive Path: $ARCHIVE_PATH"

if [[ ! -d "$ARCHIVE_PATH" ]]; then
  echo "❌ Archive not found for target: $TARGET_NAME! Please archive the project first in Xcode."
  exit 1
fi

find "$ARCHIVE_PATH/dSYMs" -name "*.dSYM" | while read line ; do
   echo "🔍 Found dsym at: $line"
   dsymuuid=$(dwarfdump -u "$line" | awk '{ print $2 }').dSYM
   echo "⬆️ Uploading dsym to: $dsymuuid"
   aws s3 cp --recursive "$line" s3://app-archives/ios/$dsymuuid
done

Configure a File Store 

Add the dsym_symbolicator as a processor in your OpenTelemetry Collector configuration:

processors:
  dsym_symbolicator:

You can then configure where your source maps are stored.

Local File Store 

By default, the symbolicator processor loads dSYM files from a local directory. You can set the file path in your collector configuration:

processors:
  dsym_symbolicator:
    # dsym_store is sets which store to use, in this case local disk
    dsym_store: file_store
    local_dsyms:
        # (optional) path sets the base path of the files, defaults to `.`
        path: /tmp/dsyms

Make sure your collector can access the path directory you set, and that file paths in stack traces match the structure of your configured file store.

How the Processor Retrieves Files from Local Disk 

When retrieving files from local disk, the processor:

  1. Gets the base file name from the URL included in the stack trace.
  2. Joins the base file name with the path, if configured.
  3. Reads the file using the joined path from disk.

Amazon S3 Store 

Optionally, you can load dSYM files from an Amazon S3 bucket. Add to your OpenTelemetry Collector configuration:

processors:
  dsym_symbolicator:
    # dsym_store sets which store to use, in this case S3
    dsym_store: s3_store
    s3_dsyms:
        # name of the bucket the files are stored in
        bucket: dsyms-bucket
        # (optional) the bucket's region
        region: us-east-1
        # (optional) prefix is used to nest the files in a sub key of the bucket
        prefix: dsyms

Make sure your collector has permission to access the S3 bucket. Also, ensure the file paths in stack traces match the structure used in your file store.

Private Amazon S3 Bucket Authentication 

To use a private Amazon S3 bucket as your file store, set the AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY environment variables.

How the Processor Retrieves Files from S3 

When retrieving files from an Amazon S3 bucket, the processor:

  1. Gets the base file name from the URL included in the stack trace.
  2. Joins the base file name with the prefix, if configured.
  3. Uses this joined path as the key to retrieve the file from the bucket.

Google Cloud Storage Store 

Optionally, you can load dSYM files from a Google Cloud Storage (GCS) bucket. Add to your OpenTelemetry Collector configuration:

processors:
  dsym_symbolicator:
    # dsym_store sets which store to use, in this case GCS
    dsym_store: gcs_store
    gcs_dsyms:
        # the name of the bucket the files are stored in
        bucket: dsyms-bucket
        # (optional) prefix is used to nest the files in a sub key of the bucket
        prefix: dsyms

Make sure your collector has permission to access the GCS bucket. Also, ensure the file paths in stack traces match the structure used in your file store.

Private Google Cloud Storage Bucket Authentication 

To use a private Google Cloud Storage bucket as your file store, set the GOOGLE_APPLICATION_CREDENTIALS environment variable.

How the Processor Retrieves Files from GCS 

When retrieving files from a Google Cloud Storage bucket, the processor:

  1. Gets the base file name from the URL included in the stack trace.
  2. Joins the base file name with the prefix, if configured.
  3. Uses this joined path as the key to retrieve the file from the bucket.

Advanced Configuration 

In addition to basic setup, you can customize how the symbolicator processor handles stack traces by configuring attribute mappings and additional processing options.

Tip
After updating the configuration file, restart the OpenTelemetry Collector to apply the changes.

Mapping Attributes 

Use these configuration options to specify which attributes the processor should read from and write to when handling stack traces:

Config Key Description Example Value
symbolicator_failure_attribute_key Signals if the symbolicator fails to fully symbolicate the stack trace exception.symbolicator.failed
symbolicator_failure_message_attribute_key Contains the error message if the symbolicator fails to fully symbolicate the stack trace exception.symbolicator.error
stack_trace_attribute_key Which attribute should the stack trace of a generic stacktrace log be sourced from exception.stacktrace
original_stack_trace_key If the stack trace is being preserved, which key should it be copied to exception.stacktrace.original
build_uuid_attribute_key Which resource attribute should the binary UUID of a generic stacktrace log be sourced from app.debug.build_uuid
app_executable_attribute_key Which resource attribute should the name of the app executable of a generic stacktrace log be sourced from app.bundle.executable
metrickit_stack_trace_attribute_key Which attribute should the json representation of a metrickit stacktrace log be sourced from metrickit.diagnostic.crash.exception.stacktrace_json
output_metrickit_stack_trace_attribute_key Which attribute should the symbolicated metrickit stack trace be populated into exception.stacktrace
output_metrickit_exception_type_attribute_key Which attribute should the exception type be populated into exception.type.
output_metrickit_exception_message_attribute_key Which attribute should the exception message be populated into exception.message.
preserve_stack_trace After the stack trace has been symbolicated, determines if the original values be preserved as attributes true

Additional Processing Options 

Use these configuration options to control how stack traces are processed and managed:

Config Key Description Example Value
timeout Max duration to wait to symbolicate a stack trace in seconds. 5
dsym_cache_size The maximum number of dSYMs to cache. Reduce this if you are running into memory issues with the collector. 128