Spring cloud sleuth 2.x custom trace id - java

I'm currently working on a spring webflux project using Spring cloud sleuth dependency.
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-sleuth</artifactId>
<version>2.2.8.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-webflux</artifactId>
<version>2.5.1</version>
</dependency>
I'm working on a set of APIs which get a request payload that contains 3 Strings. I want to concatenate these 3 strings to use as my custom trace id. I also want to achieve the following requirement.
This custom_trace_id should be able to be added to every log. (We are getting sleuth trace id in logs by adding %X{traceId} within our log4j.xml file to print the traceId in all logs)
This custom trace id must be sent to the calls that are made by WebClient (Sleuth sets the X-B3-TraceId header to all calls made by WebClient, I want the same but using the custom_trace_id)
If possible I want to change the name of X-B3-TraceId header to a different value such as correlation-id so that if someone makes a request to our spring webflux application the sleuth should first check the correlation-id and use it as trace id. (Note: custom_trace_id = correlation-id)
Note that the spring sleuth already does the above 3 things. I want to have custom value for the trace id instead. Can someone please help or suggest something for my usecase

Spring Boot 2.5.x is not compatible with Spring Cloud Hoxton (Sleuth 2.2.x).
You need to use Spring Cloud 2020.0.x aka Ilford (Sleuth 3.0.x).
You can set spring.sleuth.propagation.type to CUSTOM and implement your own Propagation and Propagation.Factory, please see the docs: How to Change The Context Propagation Mechanism?.
This should help you achieving your goals above, however, there are some downsides. This is mostly my opinion, please feel free to ignore it and do whatever you would like to:
B3, W3C and AWS propagation types are standards with support of other projects/tooling
You are trying to create a 4th "standard" that is not supported by anything (but maybe by an internal system)
You need to add support for this custom propagation type to every new component so that they will also understand this "standard"
Sometimes it worth consider moving to a universal standard rather than using a custom one even if there is a legacy system behind it

Related

Spring Webflux - Actuator - Netty thread metrics?

Small question regarding Netty metrics for a Spring Webflux + actuator project please.
In the Spring MVC world, combined with actuator, we have metrics such as:
tomcat_threads_busy_threads
tomcat_threads_current_threads
tomcat_threads_config_max_threads
jetty_threads_busy
jetty_threads_current
jetty_threads_config_max
Which helps a lot to get the overall status of the application.
However, in Webflux, it seems there is no equivalent.
I was expecting something like netty_threads_busy or something equivalent, but could not find anything related.
May I ask what would be the equivalent in Netty Webflux world please?
Thank you
The metrics expose by reactor-netty are not enabled by default in spring boot. There was a previous discussion on this github issue and the decision was not to enable these by default.
If you wanted to enable the netty server metrics in your own application, you can add the following bean to customise the Netty HttpServer.
#Bean
public NettyServerCustomizer nettyServerCustomizer(){
return httpServer -> httpServer.metrics(true, uriMappingFunction);
}
Caveat:
If you have path parameters in any of your URIs you should provide a uriMappingFunction that converts them to templated URIs ie. /user/1 -> /user/{id}. Failure to do so could lead to cardinality explosion in your MeterRegistry.
Enabling this feature also comes with the following recommendation:
It is strongly recommended applications to configure an upper limit for the number of the URI tags.
Reference Documentation
Java Doc

How to check logging implementation details in Spring Boot

I am using Spring boot.
I want to check which logging implementation is printing the message - I know with Spring boot default is Logback, and I have excluded it as mentioned in this post so mostly Logback will not be printing the messages, but I want to show it as a proof that Logback implementation is not printing and probably Log4j is printing.
Basically I need an API which I can call and I can get the details of which is the logging implementation, the way we can know Java version etc.
You can enforce Spring Boot to use a certain implementation by setting this property:
org.springframework.boot.logging.LoggingSystem
with any of:
org.springframework.boot.logging.logback.LogbackLoggingSystem
org.springframework.boot.logging.log4j2.Log4J2LoggingSystem
org.springframework.boot.logging.java.JavaLoggingSystem
none (to swith off completely)
This explicit configuration would be your proof.
To check configuration you can install spring actuator framework. Through web endpoints all config params can be queried.

Workflow mechanism for exception and error handling scenarios in Spring Boot or Spring

I am working on design where the requirement is as follows
The application would be built using spring boot
As part of the requirement we would have to build some orchestration where we would end up calling multiple SOAP and REST services and we would perform aggregation, transformation etc.
When an exception/error occurs during the orchestration, we need to capture and persist the state and retry it from the same point where the error occurred.
For example, Lets say there is a Java method in which we have multiple calls to external components say 1 soap call and 2 rest calls i.e.
String doOrchestration(InputObject obj){
Line 1: Object obj = soap call[ input is XML format];
Line 2: Object obj1 = rest1 call [the input is obj in JSON format]
Line 3: Object obj3 = rest2 call[the input is obj1 in JOSN format]
//do something
return str
}
The error occurred on Line 2. We need to capture/persist the state and continue the execution from the Line 2 later.
Is there any workflow library, orchestration patterns and/or framework that we can integrate with spring/Spring-boot
Thanks,
well, one tecnology that i use to handle this kind of problems is apache camel, whith camel you can set routes,for instance in your requirement, you can build the main route who will orchest other routes such as yours endpoints, if one endpoint has an exception you can call the route who will persist that and call again the route of the endpoint, or something like that.
http://camel.apache.org/getting-started.html
edit: camel has a lot of potencial transforming messages such as json, xml, objects.
i have a very simple project on github with spring boot and camel if you want to check it.
https://github.com/chill-hub/spring_boot_camel_base_archetype
The Apache Camel version spring like is spring-integration at
https://spring.io/projects/spring-integration
Apache Camel and Spring Integration implements enterprise integration pattern called EIP. Please look at https://www.enterpriseintegrationpatterns.com/ first.
It is basically design patterns for workflow and orchestration !
You have an integration (starter) with spring boot made by spring named spring-boot-starter-integration.
You should probably look at Java Spring Config dsl reference at https://github.com/spring-projects/spring-integration-java-dsl/wiki/spring-integration-java-dsl-reference
which will show you a nice overview, with the more modern approach (xml, and annotation starts to disapear).
With what you need to do you will probably need https://docs.spring.io/spring-integration/reference/html/ws.html which is the web extension for spring integration.
Be careful it is a very elegant solution but with lot of abstraction and can be difficult at the beginning. Keep in mind EIP defines building block and vocabulary to build workflows, Apache Camel and Spring Integration are frameworks that implements these building blocks and offer a threading model abstraction (also queue persistant abstraction), and both have several extensions to adapt easily these building blocks to real word (web, ldap, databases, ...)
Both frameworks are good with pros and cons, but you will probably prefer spring integration in a spring ecosysteme team, same conventions than other spring modules !
Again theses framework are really elegant but abstraction has always a cost!
Disclaimer : I was a trainer for spring integration course - Official

Dynamic | User case Based logging

Is there any logging framework, which helps me change logging levels dynamically based on the request parameters received ?
If request has a parameter with debug enabled to true, then only it should log, else not.
Does spring sleuth provide this feature in cloud environment?
You can use Spring Boot & Spring Cloud Config and standard Slf4j logging mechanism. You can check out this answer for more information - Managing logging.level using ConfigServer
If you just want conditional logging you would use a NDC/MDC and a filter using the frameworks that support that feature.
If you want something more general then for instance, setup a com.foo.request that is set to say INFO and a com.foo.request.debug that is set to some lower level. Pick and choose the logger on request parameter.

Custom "Simple" Error Messages in Spring Boot

A Spring Boot 1.5.1 (non-web) application was written to extract database rows. Tomcat datasource is auto configured because it is included in the pom.xml i.e.
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
<version>${spring-boot.version}</version>
</dependency>
Therefore, these keys are required,
spring.datasource.driver-class-name=${db.driver}
spring.datasource.url=${db.url}
spring.datasource.username=${db.username}
spring.datasource.password=${db.password}
and when any of these variables, e.g. ${db.driver} or ${db.url}, is missing, the application would dump the whole error stack.
Caused by: java.lang.IllegalArgumentException: Could not resolve placeholder 'db.driver' in string value "${db.driver}"
at org.springframework.util.PropertyPlaceholderHelper.parseStringValue(PropertyPlaceholderHelper.java:174)
at org.springframework.util.PropertyPlaceholderHelper.replacePlaceholders(PropertyPlaceholderHelper.java:126)
at org.springframework.core.env.AbstractPropertyResolver.doResolvePlaceholders(AbstractPropertyResolver.java:236)
at org.springframework.core.env.AbstractPropertyResolver.resolveRequiredPlaceholders(AbstractPropertyResolver.java:210)
...
This made fixing simple problems difficult because lots of text were churned and cluttered the actual problems.
How do I make Spring Boot report custom simple error messages defined by me when, say, ${db.driver} or any of the variables is not defined anywhere in, for example, application.properties or JVM environment? Thanks
Update 1
I given some thoughts after the 1st comment. I am not so much as to look to change the exception messages nor prevent them from thrown out into the log. I want to check or intercept the required parameters before they are passed to the actual module to access. Case in point, the data source.
If you supply a default value, non existing placeholders will not lead to an exception. Instead the default value is used.
You could set the default for the properties in the properties file where you use them
spring.datasource.url=${db.url?localhost:123//whatever}
You can than check the properties in a #PostConstruct annotated method or an ApplicationListener and report the error however you want.
But this does not make too much sense, because when spring tries to create a connection to the database it will fail without correct configuration.
Depending on your application, this may already happen during application startup.

Categories

Resources