Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve docs and add error log related to illegal activation of transaction #850

Open
cdalexndr opened this issue Sep 18, 2019 · 3 comments
Labels
docs Documentation good first issue Good for newcomers

Comments

@cdalexndr
Copy link

Using multiple nested transactions, ElasticApm.currentTransaction() returns oldest transaction instead of newest created.

Activating a transaction transaction.activate() pushes the transaction to the head of the active stack:
ElasticApmTracer.java:

    public void activate(TraceContextHolder<?> holder) {
        if (logger.isDebugEnabled()) {
            logger.debug("Activating {} on thread {}", holder, Thread.currentThread().getId());
        }

        ((Deque)this.activeStack.get()).push(holder);
    }

But when retrieving it, the last element of the stack is checked:
ElasticApmTracer.java:

  public Transaction currentTransaction() {
        TraceContextHolder<?> bottomOfStack = (TraceContextHolder)((Deque)this.activeStack.get()).peekLast();
        if (bottomOfStack instanceof Transaction) {
            return (Transaction)bottomOfStack;
       ....................

In the above method, peekLast() returns the oldest transaction instead of newly pushed one.

As multiple methods use Deque::peek(first element) to get active transaction, the logic inside currentTransaction() method should be change to iterate from first to last element:

     @Nullable
     public Transaction currentTransaction() {
-        TraceContextHolder<?> bottomOfStack = (TraceContextHolder)((Deque)this.activeStack.get()).peekLast();
+        TraceContextHolder<?> bottomOfStack = (TraceContextHolder)((Deque)this.activeStack.get()).peek();
         if (bottomOfStack instanceof Transaction) {
             return (Transaction)bottomOfStack;
         } else {
-            Iterator it = ((Deque)this.activeStack.get()).descendingIterator();
+            Iterator it = ((Deque)this.activeStack.get()).iterator();

             TraceContextHolder context;
             do {

elastic-apm-agent-1.9.0

@eyalkoren
Copy link
Contributor

There shouldn't be multiple nested transactions active on a thread.
At any given time, only a single transaction should be active on the thread at most. Anything nested within it should be a span.
See more in our data model documentation.

@cdalexndr
Copy link
Author

Shouldn't this be enforced in code, such as throwing an exception when trying to call transaction.activate() when a transaction already exists?

Also, transaction.activate() javadocs don't mention anything about the behaviour when there is already an active transaction.
Currently, the javadoc is wrong, because ElasticApm.currentTransaction() doesn't get me the activated transaction from code, but instead it returns the root transaction.

@eyalkoren eyalkoren reopened this Sep 18, 2019
@eyalkoren
Copy link
Contributor

eyalkoren commented Sep 18, 2019

So let's make this issue about [updated]:

  1. Log an error when attempting to activate a transaction while something is already active on the thread
  2. Document that this is invalid

I am not 100% sure about that, as there are many invalid scenarios people can invoke without any possibility for the agent to be aware (eg failing to deactivate or end a transaction/span). The basic requirement for using the API is fully understand the data model and lifecycle of the used objects.

We had a short discussion, agreed on the above.

@eyalkoren eyalkoren changed the title ElasticApm.currentTransaction() doesn't return active nested transaction Improve docs and add error log related to illegal activation of transaction Sep 18, 2019
@lreuven lreuven added the good first issue Good for newcomers label Oct 7, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
docs Documentation good first issue Good for newcomers
Projects
None yet
Development

No branches or pull requests

5 participants