Set custom traceId in spring sleuth - spring

I have an angular application using a tracing library to trace each operation (user bouton click).
This application after SPA is loaded sends a list of traces in the request body to the backend microservice to log them.
In the backend microservice, I am using the spring boot 2.3.7, the spring cloud Hoxton.SR9 and logback 1.2.3.
This is the method:
#PostMapping("/traces")
public ResponseEntity<List<Trace>> addTrace(#RequestBody List<Trace> traces) {
traces.forEach(trace -> {
RtLog log = RtLog.builder.parentSpanId(trace.getParentId()).traceId(trace.getTraceId()).spanId(trace.getSpanId)).operationName(trace.getOperationName())
.businessJourney(trace.getBaggages().getBusinessJourney())
.componentId(trace.getBaggages().getComponentId()).componentType(trace.getBaggages().getComponentType())
.sessionId(trace.getBaggages().getSessionId()).userId(trace.getBaggages().getUserId())
.duration(trace.getDuration())
.time(!Null.isNullOrEmpty(datetime) ? datetime.format(DateTimeFormatter.ofPattern(TIMESTAMP_PATTERN))
: EMPTY)
.tags(trace.getTags()).build();
logger.info("spa_log", StructuredArguments.fields(log));
An example of traces send by the application:
The problem is when logging the information, the spring sleuth adds on the log another traceId and spanId that I don't need, and it causes conflict with the correct Ids.
So how can I override the traceId and spanId or is it possible to disable the tracing in this method?
There is the traceContext or brave Tracing but I found that I can builder a new trace but I didn't find a way to change the current trace.

Related

Spring boot common logging

I'm very new to the spring boot..
I understood that Spring Boot uses Commons Logging for all internal logging.
logging.level.root=warn
logging.level.org.springframework.web=debug
logging.level.org.hibernate=error
after adding this into application.properties file, application logs all the output and exceptions in the console..
so I have a requirement to print the logs only when the system throws the error not for the success response..
so I have a requirement to print the logs only when the system throws the error not for the success response..
The implementation of this requirement IMO heavily depends on your system
From the word "response" I understand that you're working with some kind of controller (like in spring mvc). But the controller method is only an entry point to your backend.
What if the controller calls the service that logs something (message logA), then (after logging) it calls another service that again logs something (message logB) and then in turn calls, dao to call the datatbase?
If, say, DB threw an error, the logA and logB messages are already logged and you can't "take that back".
So, in general, you can log that there was an error by explicitly catching the exception in controller and logging the error, or using Controller advice to intercept and log the exceptions "globally".
When you reach the point where you log the message you can log it with severity, say, ERROR and the logging framework will log it as long as its configured to log messages of that level from that logger.

Why are details not being returned for spring health indicator?

I am currently using spring boot 2.1.4 and jackson 2.9.8
When hitting the health endpoint the details are not displayed.
{
status: "UP"
}
I have added the following property to my configuration.
management.endpoint.health.show-details=always
When I look at the environment management.endpoint.health.show-details it is set.
When I monitor org.springframework.boot.actuate.health.HealthWebEndpointResponseMapper.HealthWebEndpointResponseMapper(HealthStatusHttpMapper, ShowDetails, Set<String>) it is showing that ALWAYS is in fact being used, and details is not being stripped out.
However, when it gets to com.fasterxml.jackson.databind.introspect.POJOPropertiesCollector it doesn't add details, because the method getDetails has not been annotated in org.springframework.boot.actuate.health.Health like it has with getStatus (being #JsonWrapped)
How do I get details to be serialized by Jackson, so they can be returned via the health endpoint?
EDIT: This appears to be getting caused by a custom ObjectMapper that is being injected into the spring environment at startup which sets both AUTO_DETECT_GETTERS and AUTO_DETECT_IS_GETTERS to disabled. While this may of worked in spring 4, it no longer appears to work in spring 5.

Zipkin With Spring Boot

I am using spring boot and zipkin.
And using spring slueth to generate trace Id.
Is there a way I can generate this trace Id on my own?
Also I want to log only specific requests say with 500 error or response time > threshold, how to do this?
To log only request with particular error you can add the log in your exception mapper where you are handling those error.
To show the log for error response you can set like below,
#Autowired
private Tracer tracer;
and set
tracer.addTag("error","Your message")

Spring Sleuth | Create fresh new (detached/orphaned) Trace

I got a Spring Boot application making use of Spring Sleuth for tracing inter-service calls. Within that application a ScheduledExecutorService exists that performs http requests in a loop (pseudo-code below):
class HttpCaller implements Runnable {
public void run() {
performHttpCall();
// "loop"
executor.submit(this::run);
}
}
// start it once
scheduler.submit(new HttpCaller());
If I now have a look at the traces produced by Sleuth and stored in Zipkin I can see that all http calls are associated to a single Trace. Most likely because the trace context is handed over during the call to ScheduledExecutorService::submit.
How can I clear the current trace before starting the next iteration so that each http call will result in a new detached/orphaned trace?
If you're using Sleuth 2.0 you can call on the Tracer a method to create a new trace. In the older version of sleuth I guess what I'd do is to use an executor that is NOT a bean. That way you would lose the trace and it would get restarted at some point (by rest template or sth like that).

Integrating Spring Cloud Sleuth with Spring boot amqp

Looking for an example that shows integrating spring cloud sleuth with spring boot amqp (rabbit) publisher and subscriber.
I do see the following messages in the log
2016-10-21 08:35:15.708 INFO [producer,9148f56490e5742f,943ed050691842ab,false] 30928 --- [nio-8080-exec-1] a.b.c.controllers.MessagingController : Received Request to pulish with Activity OrderShipped
2016-10-21 08:35:15.730 INFO [producer,9148f56490e5742f,943ed050691842ab,false] 30928 --- [nio-8080-exec-1] a.b.c.service.ProducerService : Message published
When I look at messages on Queue, I don't see traceId or any other details added to the header. Should I use MessagePostProcessor to add these to the header?
Also what should be done on the receiving service?
We don't instrument Spring AMQP out of the box. You can however use Spring Integration or Spring Cloud Stream that we do support and then everything will work out of the box. If you need to use Spring AMQP for some reason you'll have to instrument the code yourself (and sends us a PR ;) ).
Using Spring AMQP you can set MessagePostProcessor on the RabbitTemplateusing the setBeforePublishPostProcessors method.
We implemented the org.springframework.amqp.core.MessagePostProcessor and Overrided the postProcessMessage method this way:
#Override
public org.springframework.amqp.core.Message postProcessMessage(org.springframework.amqp.core.Message message)
throws AmqpException {
MessagingMessageConverter converter = new MessagingMessageConverter();
MessageBuilder<?> mb = MessageBuilder.fromMessage((Message<?>) converter.fromMessage(message));
inject(tracer.getCurrentSpan(), mb);
return converter.toMessage(mb.build(), message.getMessageProperties());
}
The inject method can now set all the required headers on the message, and it will be passed to the rabbitMq with the changes.
You have a great example of how to implement such inject method in org.springframework.cloud.sleuth.instrument.messaging.MessagingSpanInjector
We are using v1.1.1 of spring-cloud-sleuth-stream so my example is based on this version, in next release(1.2) it will be easier.

Resources