Menangani Jejak Header Kustom di Spring Boot 3.4
Bayangkan Anda memiliki layanan web Spring Boot 3.4 yang bekerja secara lancar dengan dua klien. Klien pertama menggunakan Spring Boot 3+, membuat propagasi jejak menjadi mudah. Tanpa usaha ekstra, Anda mendapatkan kontinuitas jejak ujung ke ujung yang indah đȘ. Log tampak bersih dan terhubung, seolah-olah disulap.
Namun, keadaan berubah ketika klien kedua ikut bermain. Alih-alih header penelusuran standar, mereka mengirimkan header khusus seperti `ot-custom-traceid` dan `ot-custom-spanid`. Meskipun header khusus ini berisi informasi pelacakan yang valid, Spring Boot gagal menyebarkan jejak ini. Hasilnya? Anda kehilangan kemampuan untuk menghubungkan jejak klien dengan log sisi server.
Hal ini menciptakan kesenjangan observasi. Untuk klien pertama, Anda melihat jalur lengkap permintaan di seluruh layanan. Untuk klien dua, Anda hanya melihat log sisi server, tidak ada jejak klien penting. Ini seperti melihat setengah teka-tekiâAnda tahu ada sesuatu yang hilang tetapi tidak dapat menyatukannya. đ
Dalam artikel ini, kita akan mempelajari cara mengatasi masalah ini tanpa bergantung pada Spring Cloud Sleuth, dan tetap setia pada ekosistem Spring Boot 3.4. Pada akhirnya, Anda akan mengetahui cara menyebarkan dan melanjutkan jejak dari header khusus, memastikan observabilitas yang lancar di seluruh sistem Anda.
Memerintah | Contoh penggunaan |
---|---|
MDC.put | Perintah ini menambahkan pasangan nilai kunci ke Konteks Diagnostik yang Dipetakan (MDC), sehingga ID pelacakan khusus dapat disertakan dalam log. Misalnya, MDC.put("traceId", "12345"). |
MDC.clear | Menghapus semua entri dari MDC setelah permintaan diproses untuk menghindari kontaminasi jejak antar permintaan. Misalnya, MDC.clear(). |
OncePerRequestFilter | Filter Spring Boot yang memastikan logika filter dijalankan hanya sekali per permintaan HTTP, ideal untuk menelusuri header. Contoh: CustomTraceFilter kelas publik memperluas OncePerRequestFilter. |
filterChain.doFilter | Lanjutkan ke filter berikutnya dalam rantai, memastikan permintaan berlanjut melalui filter lainnya. Misalnya, filterChain.doFilter(permintaan, respons). |
RestTemplate.getInterceptors() | Mengambil daftar pencegat untuk instans RestTemplate, yang memungkinkan pencegat khusus ditambahkan. Contoh: restTemplate.getInterceptors().add(New CustomInterceptor()). |
ClientHttpRequestInterceptor | Antarmuka untuk mencegat permintaan HTTP keluar dan menambahkan header khusus. Misalnya, mengimplementasikan ClientHttpRequestInterceptor untuk memasukkan ID jejak. |
HttpServletRequest.getHeader | Mengekstrak nilai header HTTP tertentu dari permintaan masuk. Contoh: request.getHeader("ot-custom-traceid"). |
FilterRegistrationBean | Mendaftarkan filter khusus di aplikasi Spring Boot. Misalnya: registrasiBean.setFilter(CustomTraceFilter() baru). |
MockMvc.perform | Mensimulasikan permintaan HTTP dalam pengujian unit untuk aplikasi Spring Boot. Contoh: mockMvc.perform(get("/test-endpoint").header("ot-custom-traceid", "12345")). |
ClientHttpRequestExecution.execute | Mengeksekusi permintaan HTTP yang dicegat dengan isi dan header permintaan yang disediakan. Contoh: eksekusi.eksekusi(permintaan, isi). |
Propagasi Jejak Header Kustom di Spring Boot
Salah satu komponen kunci dalam memecahkan masalah ini adalah CustomTraceFilter. Filter ini memperluas Filter SekaliPerRequest kelas, memastikan logika header jejak hanya berjalan satu kali untuk setiap permintaan HTTP. Filter di Spring Boot sangat berguna saat mengubah permintaan atau respons secara global. Misalnya jika klien mengirimkan informasi penelusuran seperti atau-custom-traceid atau ot-custom-spanid di header khusus, filter ini mencegat permintaan, mengekstrak header ini, dan menyebarkannya ke Konteks Diagnostik yang Dipetakan (MDC). Dengan menambahkan ID jejak ke MDC, kami memastikan pengidentifikasi ini terlihat di log yang dihasilkan selama pemrosesan permintaan.
MDC adalah bagian penting dari kerangka logging seperti SLF4J dan Logback. Ini memungkinkan kami menyimpan informasi kontekstual untuk thread saat ini, seperti ID jejak khusus. Menggunakan perintah seperti MDC.put Dan MDC.jelas, kami memastikan bahwa sistem pencatatan menyertakan detail penelusuran dan menghindari kontaminasi di antara permintaan yang dilakukan secara bersamaan. Misalnya, jika Klien Dua mengirimkan `ot-custom-traceid` sebagai `8f7ebd8a73f9a8f50e6a00a87a20952a`, ID ini disimpan di MDC dan disertakan dalam semua log hilir, sehingga menciptakan jalur pelacakan yang konsisten.
Di sisi lain, untuk permintaan HTTP keluar, pencegat RestTemplate memainkan peran penting. Dengan menerapkan ClientHttpRequestInterceptor, kita dapat melampirkan header jejak yang sama (`ot-custom-traceid` dan `ot-custom-spanid`) ke permintaan keluar. Hal ini memastikan kontinuitas penelusuran tetap terjaga saat aplikasi memanggil layanan mikro lainnya. Misalnya, ketika server memproses permintaan dengan ID jejak `8f7ebd8a73f9a8f50e6a00a87a20952a`, server akan melampirkan ID ini ke header keluar, sehingga layanan hilir dapat mengenali dan menyebarkan jejak dengan lancar.
Terakhir, pengujian unit yang ditulis dengan MockMvc memvalidasi seluruh penyiapan dengan menyimulasikan permintaan HTTP dan memverifikasi propagasi header. Dalam aplikasi dunia nyata, pengujian sangat penting untuk memastikan header pelacakan ditangani dengan benar. Misalnya, dengan mengirimkan permintaan GET dengan header khusus dan memeriksa respons atau log, kami dapat mengonfirmasi bahwa filter dan interseptor berfungsi seperti yang diharapkan. Pendekatan komprehensif ini memecahkan tantangan tanpa bergantung pada dependensi lama seperti Spring Cloud Sleuth. Pada akhirnya, kombinasi filter, pencegat, dan MDC memastikan kontinuitas pelacakan bahkan ketika klien menggunakan header khusus, menjadikan sistem kuat dan dapat diamati sepenuhnya. đ
Menyebarkan Header Pelacakan Kustom di Spring Boot 3.4
Menggunakan Java dengan Spring Boot 3.4 dan Mikrometer untuk Pemrosesan 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;
}
}
Uji Unit untuk Propagasi Header Jejak Kustom
Pengujian dengan JUnit dan MockMvc untuk Memvalidasi Propagasi Trace Header
// 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());
}
}
Menyebarkan Header Kustom dalam Permintaan HTTP Menggunakan RestTemplate
Menggunakan RestTemplate Interceptors untuk Menambahkan Header Kustom di Permintaan Keluar
// 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;
}
}
Menangani Jejak Header Kustom dengan OpenTelemetry di Spring Boot 3.4
Saat bekerja dengan Spring Boot 3.4, pendekatan ampuh lainnya untuk menyebarkan jejak dari header khusus adalah dengan mengintegrasikan OpenTelemetri. OpenTelemetry, kerangka observasi sumber terbuka, membantu menginstrumentasikan, mengumpulkan, dan mengekspor jejak dengan lancar. Ini menyediakan mekanisme untuk mengekstrak dan memasukkan konteks jejak, termasuk header khusus seperti atau-custom-traceid Dan ot-custom-spanid, ke dalam aplikasi Anda. Dengan memanfaatkan TextMapPropagator OpenTelemetry, Anda dapat menjembatani kesenjangan antara klien non-standar dan sistem observasi Anda.
Untuk menggunakan OpenTelemetry di Spring Boot 3.4, penyebar khusus dapat diterapkan untuk mengekstrak informasi pelacakan dari header khusus dan melampirkannya ke konteks pelacakan saat ini. Misalnya, ketika server Anda menerima permintaan masuk dari Klien Dua, OpenTelemetry dapat mengurai header khusus dan merekonstruksi konteks pelacakan asli. Hal ini memastikan bahwa layanan hilir melihat ID jejak yang sama, sehingga memungkinkan visibilitas ujung ke ujung. Tidak seperti solusi lama seperti Spring Cloud Sleuth, OpenTelemetry ringan dan selaras dengan standar observasi modern.
Dengan menggabungkan propagator OpenTelemetry dengan Micrometer, Anda dapat memperkaya metrik dan logging dengan informasi jejak. Bayangkan melihat jejak permintaan yang datang dari Klien Satu dan Klien Dua dengan lancar di alat observasi Anda. OpenTelemetry secara otomatis mendukung integrasi dengan Prometheus, Zipkin, atau Jaeger, memungkinkan Anda memusatkan visualisasi jejak. Pendekatan ini memastikan bahwa meskipun header khusus terlibat, tidak ada data jejak yang hilang, dan proses debug menjadi jauh lebih mudah. đ
Pertanyaan Umum tentang Menyebarkan Jejak Kustom di Spring Boot
- Bagaimana cara mengekstrak header jejak khusus secara manual di Spring Boot?
- Anda dapat menggunakan request.getHeader("custom-header") untuk mengambil header tertentu secara manual dan menambahkannya ke MDC menggunakan MDC.put("traceId", value).
- Apa manfaat menggunakan OpenTelemetry untuk propagasi jejak kustom?
- OpenTelemetry memberikan pendekatan modern dan netral terhadap vendor untuk menyebarkan jejak, termasuk header khusus, di seluruh layanan mikro.
- Bisakah saya menyebarkan header khusus dengan RestTemplate di Spring Boot?
- Ya, dengan menerapkan ClientHttpRequestInterceptor, Anda dapat melampirkan header khusus seperti traceid dan spanid ke permintaan keluar.
- Bagaimana cara mendaftarkan filter untuk menangkap header secara global?
- Anda dapat membuat filter yang memperluas OncePerRequestFilter dan mendaftarkannya menggunakan FilterRegistrationBean untuk menangkap header untuk semua titik akhir.
- Alat apa yang dapat saya gunakan untuk memvisualisasikan jejak dari Spring Boot?
- Alat seperti Zipkin, Jaeger, dan Prometheus dapat berintegrasi dengan Spring Boot dan OpenTelemetry untuk memvisualisasikan jejak end-to-end.
Memastikan Kontinuitas Jejak yang Mulus
Dalam sistem modern, menangani header pelacakan khusus sangat penting agar observasi dapat diandalkan. Dengan menggunakan filter dan interseptor, Anda dapat menangkap informasi penelusuran yang disediakan klien dan menyebarkannya dengan benar ke seluruh layanan Anda. Hal ini untuk menghindari log yang terfragmentasi dan jejak yang hilang. đ
Spring Boot 3.4, dikombinasikan dengan Micrometer atau OpenTelemetry, memungkinkan solusi tangguh tanpa bergantung pada alat lama seperti Spring Cloud Sleuth. Baik Anda berurusan dengan header standar Klien Satu atau header kustom Klien Dua, penerapan teknik ini akan menjembatani kesenjangan pelacakan secara efisien. đ
Sumber dan Referensi
- Dokumentasi Resmi Spring Boot: Penyebaran Konteks Penelusuran. Dokumentasi Boot Musim Semi
- OpenTelemetry untuk Pengembang Java: Panduan untuk Melacak Propagasi. OpenTelemetri Java
- Dokumentasi Observabilitas Mikrometer: Mengintegrasikan Header Jejak Kustom. Observabilitas Mikrometer
- API Logging SLF4J: Kasus Penggunaan Konteks Diagnostik yang Dipetakan (MDC). Panduan SLF4J