Unmasking the Mystery: When Calling a Backend API Server through a Reverse Proxy, it’s Not Written to Elastic APM
Image by Calianna - hkhazo.biz.id

Unmasking the Mystery: When Calling a Backend API Server through a Reverse Proxy, it’s Not Written to Elastic APM

Posted on

Are you frustrated with the lack of visibility into your application’s interactions with a backend API server through a reverse proxy? You’re not alone! Many developers have stumbled upon this issue, wondering why their API calls seemingly vanish into thin air, leaving behind no traces in Elastic APM. Fear not, dear reader, for we’re about to embark on a journey to demystify this enigma and provide a comprehensive guide on how to overcome this hurdle.

The Problem: Invisibility in Elastic APM

Imagine you’re working on a complex application that relies heavily on API calls to a backend server. You’ve set up a reverse proxy to handle communication between your app and the backend, ensuring a smooth and secure experience for your users. However, when you try to monitor these API calls using Elastic APM, you notice that they’re not being captured. It’s as if they never happened.

This conundrum can be attributed to the way Elastic APM instruments your application. By default, APM agents are configured to capture transactions originating from within the application itself, not from the reverse proxy. Since the API calls are being routed through the reverse proxy, APM doesn’t consider them part of the application’s transaction flow, resulting in the invisibility we’re trying to solve.

Understanding the Role of Reverse Proxies

A reverse proxy sits between your application and the backend API server, acting as an intermediary that forwards incoming requests to the backend and returns responses to the client. This setup provides several benefits, including:
  • Load balancing: distributing incoming traffic across multiple backend instances
  • Security: shielding the backend server from direct client access
  • Caching: reducing the load on the backend by caching frequently requested resources
  • Content filtering: modifying or filtering responses from the backend server

However, as we’ve seen, this layer of abstraction can make it challenging to monitor API calls using Elastic APM.

Solution: Configuring Elastic APM to Capture API Calls

Now that we understand the problem and the role of reverse proxies, let’s explore the solutions to make these API calls visible in Elastic APM. We’ll cover two approaches: configuring the APM agent and using APM’s `capture_transaction` API.

Approach 1: Configuring the APM Agent

The first approach involves modifying the APM agent’s configuration to capture transactions originating from the reverse proxy. You can achieve this by setting the `apm-server-url` property in your agent configuration file.


# apm-agent.yml (example for Node.js)
apm-server-url: 'http://your-apm-server:8200'
capture_body: 'all'
transaction_max_spans: 2000
ignore_urls: []
instrument: true

In this example, we’re telling the APM agent to send transactions to the APM server running on `http://your-apm-server:8200`. Make sure to update the `apm-server-url` property to point to your APM server instance.

Node.js Agent Configuration

If you’re using the Node.js APM agent, you’ll need to add the `proxy` option to your configuration:


// apm-agent.js
const apm = require('elastic-apm-node');

apm.init({
// ...
proxy: 'http://your-reverse-proxy:8080',
// ...
});

In this example, we’re specifying the reverse proxy URL (`http://your-reverse-proxy:8080`) as the `proxy` option. This tells the APM agent to capture transactions originating from the reverse proxy.

Approach 2: Using APM’s `capture_transaction` API

The second approach involves using APM’s `capture_transaction` API to manually capture transactions from within your application code. This method provides more fine-grained control over which transactions are captured and how they’re handled.

In your application code, you can use the `capture_transaction` API to create a new transaction and specify the reverse proxy as the `parent`:

  // Example in Node.js
  const apm = require('elastic-apm-node');

  const transaction = apm.captureTransaction({
    name: 'API Call',
    type: 'request',
    parent: 'http://your-reverse-proxy:8080', // specify the reverse proxy URL
  });

  // Perform the API call
  const response = await fetch('http://your-backend-api:8081/api/data');

  // End the transaction
  transaction.end();

In this example, we’re creating a new transaction using `apm.captureTransaction` and specifying the reverse proxy URL as the `parent` property. We then perform the API call and manually end the transaction using `transaction.end()`.

Additional Considerations

When implementing either approach, keep the following considerations in mind:

  • Transaction naming: Be mindful of the transaction names you choose, as they’ll impact how the data is displayed in Elastic APM. Use descriptive names that accurately reflect the API calls being made.

  • Sampling: If you’re dealing with a high volume of API calls, you may want to implement sampling to reduce the amount of data sent to Elastic APM. This can help prevent performance issues and reduce storage costs.

  • Error handling: Make sure to handle errors properly within your application code. This includes catching and logging errors, as well as propagating them to the client when necessary.

Conclusion

In conclusion, making API calls visible in Elastic APM when using a reverse proxy requires some configuration and creative problem-solving. By understanding the role of reverse proxies and configuring the APM agent or using the `capture_transaction` API, you can gain visibility into these API calls and unlock valuable insights into your application’s performance.

Remember to consider transaction naming, sampling, and error handling when implementing these solutions. With the right approach, you’ll be able to uncover the mystery of the invisible API calls and take your application’s performance to the next level.

APM Configuration Description
apm-server-url Specifies the URL of the APM server
proxy Specifies the reverse proxy URL for Node.js APM agent
capture_body Specifies whether to capture request and response bodies
transaction_max_spans Specifies the maximum number of spans per transaction

By mastering the art of API call visibility, you’ll be able to:

  • Optimize your application’s performance
  • Identify bottlenecks and areas for improvement
  • Enhance the overall user experience

Happy troubleshooting, and may your API calls be forever visible in Elastic APM!

Frequently Asked Question

Get the inside scoop on Elastic APM and reverse proxies!

Why does my Elastic APM agent not capture API calls made through a reverse proxy?

That’s because the agent only tracks outgoing requests made directly from your application. Since the reverse proxy acts as an intermediary, the API calls are not originating from your app, so they’re not captured. To fix this, you can configure your reverse proxy to forward the necessary headers, allowing the APM agent to detect and track the requests.

What headers do I need to forward from my reverse proxy to enable Elastic APM tracking?

You should forward the `X-Trace-Id` and `X-Span-Id` headers from the incoming request to the outgoing request. This way, the Elastic APM agent can connect the dots and associate the API call with the original transaction. Consult your reverse proxy’s documentation for specific guidance on how to achieve this.

Can I use a specific Elastic APM configuration to capture API calls made through a reverse proxy?

Yes, you can configure the Elastic APM agent to capture outgoing requests based on specific criteria, such as the URL or HTTP method. This way, you can selectively capture API calls made through the reverse proxy while ignoring others. Check the Elastic APM documentation for more information on customizing the agent’s behavior.

Will enabling Elastic APM tracking for reverse proxy API calls impact performance?

The impact on performance should be minimal, as the APM agent only adds a small overhead to the request processing. However, this might depend on your specific use case and the volume of API calls. To mitigate any potential performance concerns, consider implementing sampling or other optimization strategies.

Are there any security implications to forwarding headers from my reverse proxy to enable Elastic APM tracking?

When forwarding headers, ensure you’re not exposing sensitive information. The `X-Trace-Id` and `X-Span-Id` headers are harmless, but be cautious when forwarding other headers that might contain confidential data. Always validate and sanitize the headers to prevent potential security vulnerabilities.