I can't add custom data to the custom transaction

Hello, I'm new to Elastic, I created an account to test the power of the tool.

What I'm trying to do is the following:

  1. Capture all RestFul requests;

  2. Capture all Socket connections;

  3. Capture all route change events, etc.;

  4. Capture customized transactions;

The problem I encountered is the following, I am trying to forward specific data from a transaction to Elastic, but I cannot find it when opening the transaction details, it seems that it is not receiving it and no error occurs in the console.

Versions being used:

angular: 11X
@elastic/apm-rum-angular: ^2.1.7

Real code example:

// START IN APP-INITIALIZER
const ELASTIC_APM = this._apmSvc.init({
serviceName: "HOMEBROKER - WEB",
serverUrl: environment.ELASTIC_APM.SERVER_URL,
environment: environment.TYPE,
});

ELASTIC_APM.setCustomContext({ sessionID, token, ...data });
ELASTIC_APM.setUserContext({ username: data.number, id: data.clientId });

// ON CLICK IN BUTTON
private _changeStorageData(data: ITradeModeData): void {
try {
const NEW_STORAGE_DATA = JSON.stringify(data);
const LOG = this._apmSvc.apm.startTransaction("TRADEMODE [CHANGED]", "TRADEMODE");
LOG.addContext({ data: NEW_STORAGE_DATA });
LOG.end();

window.localStorage.setItem(this._STORAGEKEY, NEW_STORAGE_DATA);
} catch (error) {
console.error(error);
}
}

EVIDENCE

Hi @thiagobr,

Welcome to the community and thanks for using Elastic!

The problem I encountered is the following, I am trying to forward specific data from a transaction to Elastic, but I cannot find it when opening the transaction details, it seems that it is not receiving it and no error occurs in the console.

I've been checking the snippet you posted, if I understand properly, you would expect to see the value of the property data but you are not.

LOG.addContext({ data: NEW_STORAGE_DATA });

Despite the transaction instance (LOG) having the ability to invoke addContext, it's not a documented functionality. It's more of an "internal function".

Having said that, if you want to keep using it you will need a slight change in the usage, the data property should be under custom (which represents custom context):

LOG.addContext({ custom: { data: NEW_STORAGE_DATA }});

You can see a working example in the screenshot below:

Although unlikely in the short/mid-term, bear in mind that this non-documented function might change in future versions of the agent.

--

I would like to provide you with an additional point:

the transaction API offers the addLabels capability. I'm mentioning this to you because of this note from the docs:

Labels are key/value pairs that are indexed by Elasticsearch and therefore searchable (as opposed to data set via apm.setCustomContext()).

if one of your goals is to query that custom data in the future, please, bear that in mind.

--
Hope this helps you,

Cheers,
Alberto

1 Like

Thank you very much, in fact I was now able to forward the data and view our transaction details.

However, note that only some transactions are being displayed in Elastic, others are not, the code for these that are not appearing is the same as shown above (the same as what is being displayed in Elastic).

What could this “anomaly” be?

PS: These are click events on li that do not have a RestFul request.

Glad to see that now you are seeing the data property

--

However, note that only some transactions are being displayed in Elastic, others are not, the code for these that are not appearing is the same as shown above (the same as what is being displayed in Elastic).

What could this “anomaly” be?

PS: These are click events on li that do not have a RestFul request.

one of the requirements we have for transactions is that they should have at least one span.

In this particular case, it means that if the transaction corresponding to a click event doesn't have a span (for example one related to a restful request) it will be discarded. There are two main reasons for this:

  1. For performance reasons we don't want to send every click on a page (unless there is a span related of course)

  2. transactions have a start and an end, in certain scenarios that's something simple to handle, the page load is a clear example since the browser emits the onload event (which means, the end). In other scenarios like click events, things are different, we know when a click takes place (that's how we start the transaction), but there is no simple way to know when that transaction should end, the scenarios are endless. In that case, we decided to bind the end of a Restful request to the end of a click transaction. (the same thing happens with the route-change transaction). In fact, a click transaction without span will remain open until a new transaction starts, this is the process:

  • Agent creates transaction after a click
  • -- if there is no network request, it will remain idle --
  • If there is another click:
    - the previous transaction will end (without span, hence will be discarded)
    - a new transaction will be created
    - --same process as before again--

With custom transactions, you have total control of this (you can create the spans and end them as you wish).

But for the click transactions automatically created by the agent, you will need to "hook" the ongoing transaction and it's a bit tricky, you would need to do something like this:

// below the agent initalization
window.addEventListener("click", (e) => {
    const tr = elasticApm.getCurrentTransaction()
    if (tr) {
          // Add the span that makes sense to you
         // See more details here: https://www.elastic.co/guide/en/apm/agent/rum-js/current/agent-api.html#apm-start-span
       const span = tr.startSpan("name", "type")
       // span should also have a duration of more than 0 seconds
       setTimeout(() => {
            // end the span using span.end()
            // you can also end the transaction if you want calling tr.end()
        }, 100); // just an example
    }
})

The problem with this is that as I said before, the click transaction will not end until there is another transaction (given that there is no network request). So you would need to end the transaction yourself, using a timeout for instance. Although it can increase the complexity of your code a bit, if not having click transactions without a Restful request in Elastic is not a big deal, then I wouldn't do this, if it's imperative, then I would recommend being careful since you would be "tampering" with the by default behaviour of the agent.

Hope this gives you the context of why things happen (you can see that it's not a bug but a design decision for particular reasons)

Thanks,
Alberto

1 Like

So let me see if I understand.

startTransaction refers to transactions with HTTP requests;

does startSpan refer to interaction with UI without HTTP requests?

The following transactions:

  • route-change
  • user-interaction (commonly known as "click transactions")

they will only be reported to APM (hence, visible in Kibana) if there is a network activity detected. (That's why I mentioned before, that you would need to do some tampering if you wanted to send even the ones without network activity), which I wouldn't recommend. The other option is to disable the click instrumentation and make everything a custom transaction, but I don't recommend doing that, it would force you to create a lot of code to handle everything from your side)

--

startTransaction allows you to create custom transactions for the particular requirements you might have.

Please see this if you have time, I believe it can be helpful: Custom Transactions | APM Real User Monitoring JavaScript Agent Reference [5.x] | Elastic

startSpan" allows you to attach a span to an existing transaction.

Also, I would like to share with you generic documentation about Transaction and Span:

--

What I mentioned about HTTP requests only applies to certain types of transactions that the agent automatically creates (the ones I mentioned above:route-change, click transaction)

Hope this gives you more context

Cheers,
Alberto

This topic was automatically closed 28 days after the last reply. New replies are no longer allowed.