package com.peterphi.std.guice.restclient.resteasy.impl;

import com.peterphi.std.util.tracing.Tracing;
import com.peterphi.std.util.tracing.TracingConstants;
import org.apache.log4j.Logger;

import javax.ws.rs.client.ClientRequestContext;
import javax.ws.rs.client.ClientRequestFilter;
import javax.ws.rs.ext.Provider;
import java.io.IOException;

@Provider
public class TracingClientRequestFilter implements ClientRequestFilter
{
	private static final Logger log = Logger.getLogger(TracingClientRequestFilter.class);


	@Override
	public void filter(final ClientRequestContext requestContext) throws IOException
	{
		final String traceId = Tracing.log("HTTP:req", () -> "" + requestContext.getUri());

		if (traceId != null)
		{
			if (requestContext.getHeaders().containsKey(TracingConstants.HTTP_HEADER_CORRELATION_ID))
				log.warn("Duplicate call to tracing filter " +
				         this +
				         " for " +
				         requestContext +
				         " for " +
				         requestContext.getUri());

			requestContext.getHeaders().putSingle(TracingConstants.HTTP_HEADER_CORRELATION_ID, traceId);

			if (Tracing.isVerbose())
				requestContext.getHeaders().putSingle(TracingConstants.HTTP_HEADER_TRACE_VERBOSE, "true");
		}
	}
}

package com.peterphi.std.guice.restclient.resteasy.impl;

import com.peterphi.std.util.tracing.Tracing;
import com.peterphi.std.util.tracing.TracingConstants;

import javax.ws.rs.client.ClientRequestContext;
import javax.ws.rs.client.ClientRequestFilter;
import javax.ws.rs.ext.Provider;
import java.io.IOException;

@Provider
public class TracingClientRequestFilter implements ClientRequestFilter
{
	@Override
	public void filter(final ClientRequestContext requestContext) throws IOException
	{
		final String traceId = Tracing.log("HTTP:req", () -> "" + requestContext.getUri());

		if (traceId != null)
		{
			requestContext.getHeaders().add(TracingConstants.HTTP_HEADER_CORRELATION_ID, traceId);

			if (Tracing.isVerbose())
				requestContext.getHeaders().add(TracingConstants.HTTP_HEADER_TRACE_VERBOSE, "true");
		}
	}
}

--- 
+++ 
@@ -2,6 +2,7 @@
 
 import com.peterphi.std.util.tracing.Tracing;
 import com.peterphi.std.util.tracing.TracingConstants;
+import org.apache.log4j.Logger;
 
 import javax.ws.rs.client.ClientRequestContext;
 import javax.ws.rs.client.ClientRequestFilter;
@@ -11,6 +12,9 @@
 @Provider
 public class TracingClientRequestFilter implements ClientRequestFilter
 {
+	private static final Logger log = Logger.getLogger(TracingClientRequestFilter.class);
+
+
 	@Override
 	public void filter(final ClientRequestContext requestContext) throws IOException
 	{
@@ -18,10 +22,18 @@
 
 		if (traceId != null)
 		{
-			requestContext.getHeaders().add(TracingConstants.HTTP_HEADER_CORRELATION_ID, traceId);
+			if (requestContext.getHeaders().containsKey(TracingConstants.HTTP_HEADER_CORRELATION_ID))
+				log.warn("Duplicate call to tracing filter " +
+				         this +
+				         " for " +
+				         requestContext +
+				         " for " +
+				         requestContext.getUri());
+
+			requestContext.getHeaders().putSingle(TracingConstants.HTTP_HEADER_CORRELATION_ID, traceId);
 
 			if (Tracing.isVerbose())
-				requestContext.getHeaders().add(TracingConstants.HTTP_HEADER_TRACE_VERBOSE, "true");
+				requestContext.getHeaders().putSingle(TracingConstants.HTTP_HEADER_TRACE_VERBOSE, "true");
 		}
 	}
 }
Add logic to prevent the addition of duplicate X-Correlation-ID headers if the tracing filter is called multiple times (also logs a warning if this happens)
