APM manual distributed tracing

Problem Description
I have a client application that makes http get request to server. With auto instrumentation, I am getting this as a single trace. But with manual instrumentation, I am getting 2 different traces. How to capture everything in one trace?

#my client side code

Transaction transaction = ElasticApm.startTransaction();
    
    Span span = ElasticApm.currentSpan()
                 .startSpan("external", "http", null)
                 .setName("Myspan");
    
     try (final Scope scope = transaction.activate()) {
         transaction.setName("MyTransaction");
         transaction.setType(Transaction.TYPE_REQUEST);

        try {
                URL urlForGetRequest;
                urlForGetRequest = new URL("url to server function");
                
                String readLine = null;
                HttpURLConnection conn = 
                          (HttpURLConnection)urlForGetRequest.openConnection();

                
                span.injectTraceHeaders((name, value) -> 
                    conn.setRequestProperty("Myspan", "100"));
                conn.setRequestMethod("GET");
                
                int responseCode = conn.getResponseCode();
                if (responseCode == HttpURLConnection.HTTP_OK) {
                    BufferedReader in = new BufferedReader(
                        new InputStreamReader(conn.getInputStream()));

                    while ((readLine = in .readLine()) != null) {
                            response.append(readLine);
                    } in .close();

                    conn.disconnect();

                    
                } 
                else
                	throw new RuntimeException("Failed : HTTP error code : "
                                    + conn.getResponseCode());

        }
         catch (IOException e) {
                e.printStackTrace();      
        }
		Thread.sleep(1000);
     } catch (Exception e) {
    	    transaction.captureException(e);
    	    
	} finally {
	    transaction.end();
	}

My server code
Transaction transaction =ElasticApm.startTransactionWithRemoteParent(key>
request.getHeader("Myspan"));

		try (final Scope scope = transaction.activate()) {
			transaction.setName("MyTransaction2");
		        transaction.setType(Transaction.TYPE_REQUEST);
		    
		        //my code
			
			
		} catch (Exception e) {
		    transaction.captureException(e);
		    throw e;
		} finally {
		    transaction.end();
		}

Actual output
Getting 2 seperate traces

Expected Ouput
Want 'MyTransaction2' to be created as a child of 'MyTransaction'

Welcome to the forum and thanks for the question :slight_smile:

You are using the distributed-tracing APIs wrong. You found the right documentation, but misinterpreted the code - it uses lambdas that only implement the way of setting and getting the header, without knowing the header name and value. Those are the responsibility of the agent.

Try changing

span.injectTraceHeaders((name, value) -> 
                    conn.setRequestProperty("Myspan", "100"));

to

span.injectTraceHeaders((name, value) -> 
                    conn.addRequestProperty(name, value));

and

Transaction transaction =ElasticApm.startTransactionWithRemoteParent(key>
                    request.getHeader("Myspan"));

to

Transaction transaction = ElasticApm.startTransactionWithRemoteParent(key ->
                    request.getHeader(key));
2 Likes

Thank you very much

1 Like