6. Routing Data

10 minutes  

The Routing Connector in OpenTelemetry is a powerful feature that allows you to direct data (traces, metrics, or logs) to different pipelines/destinations based on specific criteria. This is especially useful in scenarios where you want to apply different processing or exporting logic to subsets of your telemetry data.

For example, you might want to send production data to one exporter while directing test or development data to another. Similarly, you could route certain spans based on their attributes, such as service name, environment, or span name, to apply custom processing or storage logic.

Exercise
Important

Change ALL terminal windows to the 6-routing-data directory and run the clear command.

Copy *.yaml from the 5-transform-data directory into 6-routing-data. Your updated directory structure will now look like this:

.
├── agent.yaml
└── gateway.yaml

Next, we will configure the routing connector and the respective pipelines.

Last Modified Jul 11, 2025

Subsections of 6. Routing Data

6.1 Configure the Routing Connector

In this exercise, you will configure the Routing Connector in the gateway.yaml. The Routing Connector can route metrics, traces, and logs based on any attributes, we will focus exclusively on trace routing based on the deployment.environment attribute (though any span/log/metirc attribute can be used).

Exercise

Add new file exporters: The routing connector requires different targets for routing. Create two new file exporters, file/traces/route1-regular and file/traces/route2-security, to ensure data is directed correctly in the exporters section of the gateway.yaml:

  file/traces/route1-regular:                     # Exporter for regular traces
    path: "./gateway-traces-route1-regular.out"   # Path for saving trace data
    append: false                                 # Overwrite the file each time
  file/traces/route2-security:                    # Exporter for security traces
    path: "./gateway-traces-route2-security.out"  # Path for saving trace data
    append: false                                 # Overwrite the file each time 

Enable Routing by adding the routing connector. In OpenTelemetry configuration files, connectors have their own dedicated section, similar to receivers and processors.

In the Gateway terminal window, edit gateway.yaml and find and uncomment the #connectors: section. Then, add the following below the connectors: section:

  routing:
    default_pipelines: [traces/route1-regular]  # Default pipeline if no rule matches
    error_mode: ignore                          # Ignore errors in routing
    table:                                      # Define routing rules
      # Routes spans to a target pipeline if the resourceSpan attribute matches the rule
      - statement: route() where attributes["deployment.environment"] == "security-applications"
        pipelines: [traces/route2-security]     # Security target pipeline 

The default pipeline in the configuration file works at a Catch all. It will be the routing target for any data (spans in our case) that do not match a rule in the routing rules table, In this table you find the pipeline that is the target for any span that matches the following rule: ["deployment.environment"] == "security-applications"

With the routing configuration complete, the next step is to configure the pipelines to apply these routing rules.

Last Modified Jul 11, 2025

6.2 Configuring the Pipelines

Exercise

Update the original traces pipeline to use routing:

  1. To enable routing, update the original traces pipeline to use routing as the only exporter. This ensures all span data is sent through the Routing Connector for evaluation and then onwards to connected pipelines. Also, remove all processors and replace it with an empty array ([]) as this will now behandeld in the traces/route1-regular and traces/route2-security pipelines, allowing for custom behaviour for each route. Your traces: configuration should look like this:

    traces:                       # Traces pipeline
      receivers:
      - otlp                      # OTLP receiver
      processors: []              # Processors for traces
      exporters:
      - routing

Add both the route1-regular and route2-security traces pipelines below the existing traces pipeline:

  1. Configure Route1-regular pipeline: This pipeline will handle all spans that have no match in the routing table in the connector. Notice this uses routing as its only receiver and will recieve data thought its connection from the original traces pipeline.

        traces/route1-regular:         # Default pipeline for unmatched spans
          receivers: 
          - routing                    # Receive data from the routing connector
          processors:
          - memory_limiter             # Memory Limiter Processor
          - resource/add_mode          # Adds collector mode metadata
          - batch
          exporters:
          - debug                      # Debug Exporter 
          - file/traces/route1-regular # File Exporter for unmatched spans 
  2. Add the route2-security pipeline: This pipeline processes all spans that do match our rule "[deployment.environment"] == "security-applications" in the the routing rule. This pipeline is also using routing as its receiver. Add this pipline below the traces/route1-regular one.

        traces/route2-security:         # Default pipeline for unmatched spans
          receivers: 
          - routing                     # Receive data from the routing connector
          processors:
          - memory_limiter              # Memory Limiter Processor
          - resource/add_mode           # Adds collector mode metadata
          - batch
          exporters:
          - debug                       # Debug exporter
          - file/traces/route2-security # File exporter for unmatched spans
Last Modified Jul 11, 2025

6.3 Test Routing Connector

Exercise

In this section, we will test the routing rule configured for the Gateway. The expected result is that a span generated by the loadgen that match the "[deployment.environment"] == "security-applications" rule will be sent to the gateway-traces-route2-security.out file.

Start the Gateway: In your Gateway terminal window start the Gateway.

../otelcol --config gateway.yaml

Start the Agent: In your Agent terminal window start the Agent.

../otelcol --config agent.yaml

Send a Regular Span: In the Loadgen terminal window send a regular span using the loadgen:

../loadgen -count 1

Both the Agent and Gateway will display debug information. The gateway will also generate a new gateway-traces-route1-regular.out file, as this is now the designated destination for regular spans.

Tip

If you check gateway-traces-route1-regular.out, it will contain the span sent by loadgen. You will also see an empty gateway-traces-route2-security..out file, as the routing configuration creates output files immediately, even if no matching spans have been processed yet.

Send a Security Span: In the Loadgen terminal window send a security span using the security flag:

../loadgen -security -count 1

Again, both the Agent and Gateway should display debug information, including the span you just sent. This time, the Gateway will write a line to the gateway-traces-route2-security.out file, which is designated for spans where the deployment.environment resource attribute matches "security-applications".

jq -c '.resourceSpans[] as $resource | $resource.scopeSpans[].spans[] | {spanId: .spanId, deploymentEnvironment: ($resource.resource.attributes[] | select(.key == "deployment.environment") | .value.stringValue)}' gateway-traces-route2-security.out
{"spanId":"cb799e92e26d5782","deploymentEnvironment":"security-applications"}

You can repeat this scenario multiple times, and each trace will be written to its corresponding output file.

Important

Stop the Agent and the Gateway processes by pressing Ctrl-C in their respective terminals.

Conclusion

In this section, we successfully tested the routing connector in the gateway by sending different spans and verifying their destinations.

  • Regular spans were correctly routed to gateway-traces-route1-regular.out, confirming that spans without a matching deployment.environment attribute follow the default pipeline.

  • Security-related spans were routed to gateway-traces-route2-security.out, demonstrating that the routing rule based on "deployment.environment": "security-applications" works as expected.

By inspecting the output files, we confirmed that the OpenTelemetry Collector correctly evaluates span attributes and routes them to the appropriate destinations. This validates that routing rules can effectively separate and direct telemetry data for different use cases.

You can now extend this approach by defining additional routing rules to further categorize spans, metrics, and logs based on different attributes.