Gestione delle tracce di intestazione personalizzate in Spring Boot 3.4
Immagina di avere un servizio Web Spring Boot 3.4 che funziona perfettamente con due client. Il primo client utilizza Spring Boot 3+, rendendo la propagazione della traccia un gioco da ragazzi. Senza alcuno sforzo aggiuntivo, ottieni una bellissima continuità di traccia end-to-end 🪄. I registri appaiono puliti e collegati, come per magia.
Tuttavia, le cose cambiano quando entra in gioco il cliente due. Invece delle intestazioni di traccia standard, inviano intestazioni personalizzate come "ot-custom-traceid" e "ot-custom-spanid". Sebbene queste intestazioni personalizzate contengano informazioni di traccia valide, Spring Boot non riesce a propagare queste tracce. Il risultato? Perderai la possibilità di connettere le tracce client con i log sul lato server.
Ciò crea un divario di osservabilità. Per il client uno, viene visualizzato il percorso completo di una richiesta tra i servizi. Per il client due, vengono visualizzati solo i log lato server, manca la traccia client critica. È come vedere la metà di un puzzle: sai che manca qualcosa ma non riesci a mettere insieme i pezzi. 😓
In questo articolo esploreremo come risolvere questo problema senza fare affidamento su Spring Cloud Sleuth, rimanendo fedeli all'ecosistema Spring Boot 3.4. Alla fine, saprai come propagare e continuare le tracce dalle intestazioni personalizzate, garantendo un'osservabilità perfetta nel tuo sistema.
Comando | Esempio di utilizzo |
---|---|
MDC.put | Questo comando aggiunge coppie chiave-valore al Contesto diagnostico mappato (MDC), consentendo l'inclusione di ID di traccia personalizzati nei log. Ad esempio, MDC.put("traceId", "12345"). |
MDC.clear | Cancella tutte le voci da MDC dopo l'elaborazione di una richiesta per evitare la contaminazione delle tracce tra le richieste. Ad esempio, MDC.clear(). |
OncePerRequestFilter | Un filtro Spring Boot che garantisce che la logica del filtro venga eseguita solo una volta per richiesta HTTP, ideale per tracciare le intestazioni. Esempio: la classe pubblica CustomTraceFilter estende OncePerRequestFilter. |
filterChain.doFilter | Procede al filtro successivo nella catena, assicurando che la richiesta continui attraverso altri filtri. Ad esempio, filterChain.doFilter(richiesta, risposta). |
RestTemplate.getInterceptors() | Recupera l'elenco degli interceptor per un'istanza RestTemplate, consentendo l'aggiunta di interceptor personalizzati. Esempio: restTemplate.getInterceptors().add(new CustomInterceptor()). |
ClientHttpRequestInterceptor | Un'interfaccia per intercettare le richieste HTTP in uscita e aggiungere intestazioni personalizzate. Ad esempio, implementando ClientHttpRequestInterceptor per inserire gli ID di traccia. |
HttpServletRequest.getHeader | Estrae il valore di un'intestazione HTTP specifica dalla richiesta in ingresso. Esempio: request.getHeader("ot-custom-traceid"). |
FilterRegistrationBean | Registra i filtri personalizzati nell'applicazione Spring Boot. Ad esempio: RegistrationBean.setFilter(new CustomTraceFilter()). |
MockMvc.perform | Simula le richieste HTTP negli unit test per le applicazioni Spring Boot. Esempio: mockMvc.perform(get("/test-endpoint").header("ot-custom-traceid", "12345")). |
ClientHttpRequestExecution.execute | Esegue la richiesta HTTP intercettata con il corpo e le intestazioni della richiesta forniti. Esempio: esecuzione.execute(richiesta, corpo). |
Propagazione della traccia di intestazione personalizzata in Spring Boot
Uno dei componenti chiave per risolvere questo problema è CustomTraceFilter. Questo filtro estende il OncePerRequestFilter classe, garantendo che la logica dell'intestazione di traccia venga eseguita solo una volta per ogni richiesta HTTP. I filtri in Spring Boot sono incredibilmente utili quando si modificano richieste o risposte a livello globale. Ad esempio, se il client invia informazioni di tracciamento come ot-custom-traceid O ot-custom-spanid nelle intestazioni personalizzate, questo filtro intercetta la richiesta, estrae queste intestazioni e le propaga nel Contesto diagnostico mappato (MDC). Aggiungendo gli ID di traccia all'MDC, garantiamo che questi identificatori siano visibili nei log generati durante l'elaborazione della richiesta.
L'MDC è una parte fondamentale dei framework di registrazione come SLF4J e Logback. Ci consente di archiviare informazioni contestuali per il thread corrente, come gli ID di traccia personalizzati. Usando comandi come MDC.put E MDC.clear, ci assicuriamo che il sistema di registrazione includa i dettagli di traccia ed eviti la contaminazione tra richieste simultanee. Ad esempio, se il client due invia `ot-custom-traceid` come `8f7ebd8a73f9a8f50e6a00a87a20952a`, questo ID viene archiviato in MDC e incluso in tutti i log downstream, creando un percorso di traccia coerente.
D'altra parte, per le richieste HTTP in uscita, l'interceptor RestTemplate svolge un ruolo essenziale. Implementando ClientHttpRequestInterceptor, possiamo allegare le stesse intestazioni di traccia (`ot-custom-traceid` e `ot-custom-spanid`) alle richieste in uscita. Ciò garantisce che la continuità della traccia venga mantenuta quando l'applicazione chiama altri microservizi. Ad esempio, quando il server elabora una richiesta con ID di traccia "8f7ebd8a73f9a8f50e6a00a87a20952a", allega questo ID alle intestazioni in uscita, in modo che i servizi downstream possano riconoscere e propagare la traccia senza problemi.
Infine, gli unit test scritti con MockMvc convalidano l'intera configurazione simulando richieste HTTP e verificando la propagazione dell'intestazione. Nelle applicazioni del mondo reale, il test è fondamentale per garantire che le intestazioni di traccia siano gestite correttamente. Ad esempio, inviando una richiesta GET con intestazioni personalizzate e controllando la risposta o i log, possiamo confermare che il filtro e l'intercettatore funzionano come previsto. Questo approccio completo risolve la sfida senza fare affidamento su dipendenze legacy come Spring Cloud Sleuth. In definitiva, la combinazione di filtri, intercettori e MDC garantisce la continuità della traccia anche quando i client utilizzano intestazioni personalizzate, rendendo il sistema robusto e completamente osservabile. 🌟
Propagazione delle intestazioni di traccia personalizzate in Spring Boot 3.4
Utilizzo di Java con Spring Boot 3.4 e Micrometer per l'elaborazione backend
// Solution 1: Extract and Propagate Custom Trace Headers Manually
// Import necessary Spring Boot and Micrometer libraries
import org.slf4j.MDC;
import org.springframework.http.HttpHeaders;
import org.springframework.web.filter.OncePerRequestFilter;
import javax.servlet.FilterChain;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
public class CustomTraceFilter extends OncePerRequestFilter {
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
throws IOException {
String traceId = request.getHeader("ot-custom-traceid");
String spanId = request.getHeader("ot-custom-spanid");
try {
if (traceId != null) {
MDC.put("traceId", traceId); // Add traceId to Mapped Diagnostic Context
}
if (spanId != null) {
MDC.put("spanId", spanId);
}
filterChain.doFilter(request, response); // Continue request processing
} finally {
MDC.clear(); // Ensure MDC is cleared after processing
}
}
}
// Register the filter in your configuration class
@Configuration
public class FilterConfig {
@Bean
public FilterRegistrationBean<CustomTraceFilter> traceFilter() {
FilterRegistrationBean<CustomTraceFilter> registrationBean = new FilterRegistrationBean<>();
registrationBean.setFilter(new CustomTraceFilter());
registrationBean.addUrlPatterns("/*");
return registrationBean;
}
}
Test unitario per la propagazione dell'intestazione della traccia personalizzata
Test con JUnit e MockMvc per convalidare la propagazione dell'intestazione della traccia
// Import necessary libraries
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
import org.springframework.test.web.servlet.MockMvc;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
@WebMvcTest
public class CustomTraceFilterTest {
@Autowired
private MockMvc mockMvc;
@Test
public void testCustomTraceHeaders() throws Exception {
mockMvc.perform(get("/test-endpoint")
.header("ot-custom-traceid", "12345")
.header("ot-custom-spanid", "67890"))
.andExpect(status().isOk());
}
}
Propagazione di intestazioni personalizzate nelle richieste HTTP utilizzando RestTemplate
Utilizzo degli intercettori RestTemplate per aggiungere intestazioni personalizzate nelle richieste in uscita
// Import necessary libraries
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpRequest;
import org.springframework.http.client.ClientHttpRequestExecution;
import org.springframework.http.client.ClientHttpRequestInterceptor;
import org.springframework.http.client.ClientHttpResponse;
import org.springframework.web.client.RestTemplate;
import java.io.IOException;
public class CustomHeaderInterceptor implements ClientHttpRequestInterceptor {
@Override
public ClientHttpResponse intercept(HttpRequest request, byte[] body, ClientHttpRequestExecution execution) throws IOException {
HttpHeaders headers = request.getHeaders();
headers.add("ot-custom-traceid", "12345");
headers.add("ot-custom-spanid", "67890");
return execution.execute(request, body);
}
}
// Register the interceptor with RestTemplate
@Configuration
public class RestTemplateConfig {
@Bean
public RestTemplate restTemplate() {
RestTemplate restTemplate = new RestTemplate();
restTemplate.getInterceptors().add(new CustomHeaderInterceptor());
return restTemplate;
}
}
Gestione delle tracce di intestazione personalizzate con OpenTelemetry in Spring Boot 3.4
Quando si lavora con Spring Boot 3.4, un altro approccio efficace per propagare le tracce dalle intestazioni personalizzate è l'integrazione OpenTelemetria. OpenTelemetry, un framework di osservabilità open source, aiuta a strumentare, raccogliere ed esportare tracce senza problemi. Fornisce meccanismi per estrarre e inserire il contesto di traccia, incluse intestazioni personalizzate come ot-custom-traceid E ot-custom-spanid, nella tua applicazione. Sfruttando TextMapPropagator di OpenTelemetry, puoi colmare il divario tra client non standard e il tuo sistema di osservabilità.
Per utilizzare OpenTelemetry in Spring Boot 3.4, è possibile implementare un propagatore personalizzato per estrarre informazioni di traccia dalle intestazioni personalizzate e allegarle al contesto di traccia corrente. Ad esempio, quando il server riceve una richiesta in entrata dal client due, OpenTelemetry può analizzare intestazioni personalizzate e ricostruire il contesto di traccia originale. Ciò garantisce che i servizi downstream visualizzino gli stessi ID di traccia, consentendo la visibilità end-to-end. A differenza delle soluzioni precedenti come Spring Cloud Sleuth, OpenTelemetry è leggero e si allinea ai moderni standard di osservabilità.
Combinando il propagatore di OpenTelemetry con Micrometer, puoi arricchire i tuoi parametri e la registrazione con informazioni di traccia. Immagina di vedere le tracce delle richieste provenienti sia dal Cliente Uno che dal Cliente Due senza soluzione di continuità nel tuo strumento di osservabilità. OpenTelemetry supporta automaticamente le integrazioni con Prometheus, Zipkin o Jaeger, consentendoti di centralizzare la visualizzazione delle tracce. Questo approccio garantisce che anche quando sono coinvolte intestazioni personalizzate, nessun dato di traccia viene perso e il debug diventa notevolmente più semplice. 🚀
Domande frequenti sulla propagazione delle tracce personalizzate in Spring Boot
- Come posso estrarre manualmente le intestazioni di traccia personalizzate in Spring Boot?
- Puoi utilizzare request.getHeader("custom-header") per recuperare manualmente un'intestazione specifica e aggiungerla a MDC utilizzando MDC.put("traceId", value).
- Qual è il vantaggio di utilizzare OpenTelemetry per la propagazione della traccia personalizzata?
- OpenTelemetry fornisce un approccio moderno e indipendente dal fornitore per propagare le tracce, incluse le intestazioni personalizzate, tra i microservizi.
- Posso propagare intestazioni personalizzate con RestTemplate in Spring Boot?
- Sì, implementando un ClientHttpRequestInterceptor, puoi allegare intestazioni personalizzate come traceid e spanid alle richieste in uscita.
- Come posso registrare un filtro per acquisire intestazioni a livello globale?
- Puoi creare un filtro che estende OncePerRequestFilter e registrarlo utilizzando FilterRegistrationBean per acquisire intestazioni per tutti gli endpoint.
- Quali strumenti posso utilizzare per visualizzare le tracce da Spring Boot?
- Strumenti come Zipkin, Jaeger e Prometheus possono integrarsi con Spring Boot e OpenTelemetry per visualizzare tracce end-to-end.
Garantire la continuità della traccia senza soluzione di continuità
Nei sistemi moderni, la gestione delle intestazioni di traccia personalizzate è fondamentale per un'osservabilità affidabile. Utilizzando filtri e intercettori, puoi acquisire informazioni di traccia fornite dal client e propagarle correttamente nei tuoi servizi. Ciò evita log frammentati e tracce mancanti. 🔍
Spring Boot 3.4, combinato con Micrometer o OpenTelemetry, consente soluzioni robuste senza fare affidamento su strumenti meno recenti come Spring Cloud Sleuth. Sia che tu abbia a che fare con le intestazioni standard del Client One o con le intestazioni personalizzate del Client Two, l'implementazione di queste tecniche colma le lacune di traccia in modo efficiente. 🚀
Fonti e riferimenti
- Documentazione ufficiale di Spring Boot: propagazione dei contesti di tracciamento. Documentazione sull'avvio primaverile
- OpenTelemetry per sviluppatori Java: guida alla propagazione della traccia. OpenTelemetry Java
- Documentazione sull'osservabilità micrometrica: integrazione di intestazioni di traccia personalizzate. Osservabilità micrometrica
- API di registrazione SLF4J: casi d'uso del contesto diagnostico mappato (MDC). Manuale SLF4J