apm-agent-rum-js icon indicating copy to clipboard operation
apm-agent-rum-js copied to clipboard

infomations of the request headers

Open zhaoShijuan opened this issue 3 years ago • 3 comments

Hi, we try to add infos of a request headers to the 'external' span to through overwrite the 'setRequestHeader' method, but we can't associate the request header information with the corresponding span. What can we do?

zhaoShijuan avatar Jul 31 '22 08:07 zhaoShijuan

Hi @zhaoShijuan,

Thank you for using the RUM agent!!

I would need more info in order to help you properly.

Questions:

  1. Are you creating the "external" span manually? or is it being created automatically by the agent?

  2. What do you mean with "overwrite the 'setRequestHeader' method"? Are you overwriting the native API of the XHR object or are you using the method to add the headers?

  3. Could you share the code you have written to achieve the span-header association?

Let me share two examples that may help you somehow, although they assume scenarios that might not be yours, so please, when you have time share with us the information requested above.

I'm also going to assume that your website performs network requests with XHR rather than with Fetch. (since you mentioned setRequestHeader which belongs to XHR)

Example that assumes that span is created manually:

                const transaction = elasticApm.startTransaction('test', 'custom')
                const url = 'http://localhost:3000/api_test_2'
                const httpSpan = transaction.startSpan('GET ' + url, 'external.http')

                const xhr = new XMLHttpRequest()
                xhr.open('GET', url);
                xhr.onload = function () {

                    httpSpan.addLabels({ 'x-custom-header': "value", 'x-custom-header-2': "value2"})

                    httpSpan.end()
                    transaction.end()
                }
                xhr.send(null)

On the example above you can see how I added labels that correspond to custom headers.

Kibana provides that information when seeing the details of the span

Screenshot 2022-08-01 at 13 04 47

Labels:

Screenshot 2022-08-01 at 13 06 06

Example that assumes that span is created automatically:

You can leverage the transaction:end event to extract the span you are mentioning:

elasticApm.observe("transaction:end", tr => {
   if (tr && tr.type === "the type of your transaction") {
      const [mySpan] = tr.spans
                       .filter(span => span.type === 'external' && span.context.http.url === 'your-endpoint-url')

                        if (!mySpan.context.tags) {
                            mySpan.context.tags = {}
                        }

                        mySpan.context.tags['x-custom-header'] = 'value'
   }

})

To be honest, I wouldn't you to recommend to do that since relies on internal API properties and you might have issues in future versions of the RUM agent. Although, if for you it's crucial to have the headers on the span that's the way.

--

Bear in mind that you can also associate the headers to the transaction, too

Thanks, Alberto

devcorpio avatar Aug 01 '22 12:08 devcorpio

Sorry for taking so long to reply!Below is the answer to your questions:

  1. The span is created automatically by the agent

  2. We want to get the headers

  3. We added the following code to xhr-patch.js, XHR_REQUEST_HEADER is a constant

  const setRequestHeaderNative = XMLHttpRequestPrototype.setRequestHeader
  XMLHttpRequestPrototype.setRequestHeader = function() {
    const args = arguments
    this[XHR_REQUEST_HEADER] = {
      ...this[XHR_REQUEST_HEADER],
      [args[0]]: args[1]
    }
    setRequestHeaderNative.apply(this, args)
  }

zhaoShijuan avatar Sep 10 '22 01:09 zhaoShijuan

Hi @zhaoShijuan,

Thanks for providing those details!

Overwriting setRequestHeader will not add the header you want to the "external" span.

--

Since the span is created automatically by the agent the most recommended way you have to add custom information on the fly is using elasticApm.observe.

I don't know the details of your endpoint, but let me put an example with an arbitrary one:

Example:

  • endpoint: http://localhost:3000/api_test_2
  • header name: "hello"
  • header value: "world"

RUM agent allows you to add custom information via labels.

   elasticApm.observe("transaction:end", tr => {
          const externalSpans = tr.spans.filter(span => {
             return span.type === 'external' && span.context.http.url.includes("api_test_2")
          })

            externalSpans.map(span => {
                    span.addLabels({ "hello": "world" })
           })
    })

As you can see at the code above, I'm observing the end of the transaction and:

  • extracting all the external spans of such transaction and filtering by the endpoint
  • add the header info via labels

The code is just an example, but it's quite lightweight and malleable, so you can modify to meet your requirements if needed

Doing so, you will be able to see the labels on the span details:

Screenshot 2022-09-12 at 17 18 56

You can search spans with such label via Kibana Discover:

Screenshot 2022-09-12 at 17 22 32

and

Screenshot 2022-09-12 at 17 28 35

Thanks, Alberto

devcorpio avatar Sep 12 '22 15:09 devcorpio

Hi @zhaoShijuan,

Have you managed to get this working?

Thanks, Alberto

devcorpio avatar Sep 29 '22 17:09 devcorpio