question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

w3c tracestate header not propagated

See original GitHub issue

Describe the bug

Using:

  • spring-boot-starter-parent 2.4.4
  • spring-cloud-dependencies 2020.0.3
  • spring-cloud-sleuth: 3.0.3
  • spring-cloud-starter-openfeign: 3.0.3

I have a simple RestController in service A that receives a POST request containing traceparent as well as tracestate header. The RestController calls another service B via a FeignClient. The traceparent header gets propagated correctly from service A to B. However, tracestate header is not propagated from service A to B.

According to w3c standard (https://www.w3.org/TR/trace-context/#mutating-the-tracestate-field) the tracestate header should be propagated (“Vendors receiving a tracestate request header MUST send it to outgoing requests. It MAY mutate the value of this header before passing to outgoing requests.”)

Sample

Reproduce with: curl -X POST -H "Content-Type: application/json" -H "traceparent: 00-8df82d9e560f4c318f2c3c1ce7d69a0a-8dc0d640e5c62ebe-01" -H "tracestate: sappp=CwAAmEnGj0gThK52TCXZ270X8nBhc3Nwb3J0LWFwcABQT1NU" localhost:8003/notify

pom.xml (parent)

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>2.4.4</version>
    <relativePath />
  </parent>

  <groupId>com.bugtracking.sample</groupId>
  <artifactId>tracestate</artifactId>
  <version>${revision}</version>
  <packaging>pom</packaging>

  <name>Parent POM</name>
  <description>The parent POM
  </description>

  <properties>
    <revision>0.0.1-SNAPSHOT</revision>
    <java.version>11</java.version>
    <spring-cloud.version>2020.0.3</spring-cloud.version>
    <zipkin-version>2.2.8.RELEASE</zipkin-version>
    <hystrix-version>2.2.8.RELEASE</hystrix-version>
  </properties>

  <modules>
    <module>service-a</module>
    <module>service-b</module>
  </modules>

  <dependencyManagement>
    <dependencies>
      <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-dependencies</artifactId>
        <version>${spring-cloud.version}</version>
        <type>pom</type>
        <scope>import</scope>
      </dependency>
    </dependencies>
  </dependencyManagement>

  <build>
    <plugins>
      <plugin>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-maven-plugin</artifactId>
      </plugin>
    </plugins>
  </build>

</project>

Service A

pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <parent>
    <groupId>com.bugtracking.sample</groupId>
    <artifactId>tracestate</artifactId>
    <version>${revision}</version>
    <relativePath>../pom.xml</relativePath>
  </parent>

  <artifactId>service-a</artifactId>
  
  <name>service-a</name>
  <description>A Spring Boot sample</description>

  <dependencies>
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-actuator</artifactId>
    </dependency>
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <dependency>
      <groupId>org.springframework.cloud</groupId>
      <artifactId>spring-cloud-starter-openfeign</artifactId>
    </dependency>
    <dependency>
      <groupId>org.springframework.cloud</groupId>
      <artifactId>spring-cloud-starter-sleuth</artifactId>
    </dependency>
    <dependency>
      <groupId>org.springframework.cloud</groupId>
      <artifactId>spring-cloud-starter-zipkin</artifactId>
      <version>${zipkin-version}</version>
    </dependency>

    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-test</artifactId>
      <scope>test</scope>
      <exclusions>
        <exclusion>
          <groupId>org.junit.vintage</groupId>
          <artifactId>junit-vintage-engine</artifactId>
        </exclusion>
      </exclusions>
    </dependency>
  </dependencies>

</project>

Application.java

@EnableFeignClients
@SpringBootApplication
public class Application {
    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
}

BClient.java

@FeignClient(name = "feign-client", url = "http://localhost:8001")
public interface BClient {

    @PostMapping(path = "/serviceb", produces = "application/json", consumes = "application/json")
    void outgoingRequest();
}

WebController.java

@RestController
public class WebController {
    private final BClient feignClient;

    @Autowired
    public WebController(BClient feignClient) {
        this.feignClient = feignClient;
    }

    @PostMapping(value = "/notify", consumes = MediaType.APPLICATION_JSON_VALUE)
    public void notifyAllocation() {
        feignClient.outgoingRequest();
    }
}

application.yaml

server.port: 8003

# Actuator Endpoint Configurations
info: # /actuator/info
  app:
    name: ${spring.application.name}

management:
  endpoints:
    web:
      exposure:
        include:
        - "*"

spring:
  application:
    name: service a
  #zipkin:
  #  baseUrl: http://localhost:9411
  sleuth:
    sampler:
      probability: 1.0

spring.sleuth.propagation.type: W3C

Service B

pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <parent>
    <groupId>com.bugtracking.sample</groupId>
    <artifactId>tracestate</artifactId>
    <version>${revision}</version>
    <relativePath>../pom.xml</relativePath>
  </parent>

  <artifactId>service-b</artifactId>

  <name>service-b</name>
  <description>A Spring Boot sample</description>

  <dependencies>
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-actuator</artifactId>
    </dependency>
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-web</artifactId>
    </dependency>

    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-test</artifactId>
      <scope>test</scope>
      <exclusions>
        <exclusion>
          <groupId>org.junit.vintage</groupId>
          <artifactId>junit-vintage-engine</artifactId>
        </exclusion>
      </exclusions>
    </dependency>

  </dependencies>
</project>

Application.java

public class Application {
    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
}

WebController.java

@RestController
public class WebController {
    private static final Logger LOGGER = LoggerFactory.getLogger(WebController.class);

    @PostMapping(value = "/serviceb", consumes = MediaType.APPLICATION_JSON_VALUE)
    public void preference(@RequestHeader("traceparent") String traceparent, @RequestHeader("tracestate") String tracestate) {
        LOGGER.info("traceparent: {}", traceparent);
        LOGGER.info("tracestate: {}", tracestate);
    }
}

application.yaml

server.port: 8001

# Actuator Endpoint Configurations
info: # /actuator/info
  app:
    name: ${spring.application.name}

management:
  endpoints:
    web:
      exposure:
        include:
        - "*"

spring:
  application:
    name: service b
  sleuth:
    sampler:
      probability: 1.0

spring.sleuth.propagation.type: W3C

Result

2021-07-27 15:01:57.471 WARN 34296 --- [nio-8001-exec-4] .w.s.m.s.DefaultHandlerExceptionResolver : Resolved [org.springframework.web.bind.MissingRequestHeaderException: Missing request header 'tracestate' for method parameter of type String] in Service B

Issue Analytics

  • State:closed
  • Created 2 years ago
  • Comments:11 (7 by maintainers)

github_iconTop GitHub Comments

1reaction
chippmentcommented, Jul 27, 2021

As a workaround can’t you just set spring.sleuth.baggage.remote-fields=tracestate ? That way the header called tracestate will be automatically propagated.

Tried this. tracestate header still missing.

0reactions
marcingrzejszczakcommented, Jul 28, 2021

Yeah and the same on the extractor. Let me see what I can do about this.

Read more comments on GitHub >

github_iconTop Results From Across the Web

Trace Context - W3C
At a minimum they MUST propagate the traceparent and tracestate headers and guarantee traces are not broken. This behavior is also referred ...
Read more >
Trace Context HTTP Request Headers Format - GitHub
The tracestate HTTP header MUST NOT be used for any properties that are not defined by a tracing system. [[BAGGAGE]] MAY be used...
Read more >
How is tracestate header propagated to Application Insights?
In a Java application deployed to Azure we have customized the W3C tracestate header by adding a custom item to the list.
Read more >
Difference between Opentracing and W3C Trace Context (with ...
OpenTracing, by design, did not define a format for propagating tracing headers. It was the responsibility of libraries who implemented ...
Read more >
Spring Cloud Sleuth Features
The value can be a list in which case you will propagate more tracing headers. For Brave we support AWS , B3 ,...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found