PageSourceSearch

https://armeria.dev/assets/js/f784c0f2.e7bf0310.js

js armeria.dev collected 2026-10-03 23:25:58 UTC 10,383 bytes, 1 lines download raw bytes

1"use strict";(self.webpackChunkarmeria_site=self.webpackChunkarmeria_site||[]).push([["5208"],{58351(e,r,a){a.r(r),a.d(r,{metadata:()=>n,default:()=>p,frontMatter:()=>o,contentTitle:()=>c,toc:()=>l,assets:()=>s});var n=JSON.parse('{"id":"advanced/zipkin","title":"Zipkin integration","description":"If you want to troubleshoot latency problems in microservice architecture, you will want to use distributed","source":"@site/src/content/docs/advanced/zipkin.mdx","sourceDirName":"advanced","slug":"/advanced/zipkin","permalink":"/docs/advanced/zipkin","draft":false,"unlisted":false,"editUrl":"https://github.com/line/armeria/edit/main/site/src/content/docs/advanced/zipkin.mdx","tags":[],"version":"current","frontMatter":{},"sidebar":"docsSidebar","previous":{"title":"Configuring global flags","permalink":"/docs/advanced/flags-provider"},"next":{"title":"Client interoperability","permalink":"/docs/advanced/client-interoperability"}}'),t=a(74848),i=a(28453);let o={},c="Zipkin integration",s={},l=[{value:"See also",id:"see-also",level:2}];function d(e){let r={a:"a",code:"code",h1:"h1",h2:"h2",header:"header",img:"img",li:"li",p:"p",pre:"pre",ul:"ul",...(0,i.R)(),...e.components},{RequiredDependencies:n}=r;return n||function(e,r){throw Error("Expected "+(r?"component":"object")+" `"+e+"` to be defined: you likely forgot to import, pass, or provide it.")}("RequiredDependencies",!0),(0,t.jsxs)(t.Fragment,{children:[(0,t.jsx)(r.header,{children:(0,t.jsx)(r.h1,{id:"zipkin-integration",children:"Zipkin integration"})}),"\n",(0,t.jsxs)(r.p,{children:["If you want to troubleshoot latency problems in microservice architecture, you will want to use distributed\ntracing system such as ",(0,t.jsx)(r.a,{href:"https://zipkin.io/",children:"Zipkin"}),". It gathers timing data and shows which component is\nfailing or taking more time than others in a distributed environment. Armeria supports distributed tracing via\n",(0,t.jsx)(r.a,{href:"https://github.com/openzipkin/brave/",children:"Brave"}),", which is a Java tracing library compatible with\n",(0,t.jsx)(r.a,{href:"https://zipkin.io/",children:"Zipkin"}),". Let's find out how to use it to trace requests."]}),"\n",(0,t.jsxs)(r.p,{children:["First, You need the ",(0,t.jsx)(r.code,{children:"armeria-brave"})," dependency:"]}),"\n",(0,t.jsx)(n,{boms:[{groupId:"com.linecorp.armeria",artifactId:"armeria-bom"}],dependencies:[{groupId:"com.linecorp.armeria",artifactId:"armeria-brave"}]}),"\n",(0,t.jsxs)(r.p,{children:["Then, you need to create the ",(0,t.jsx)(r.code,{children:"HttpTracing"}),":"]}),"\n",(0,t.jsx)(r.pre,{children:(0,t.jsx)(r.code,{className:"language-java",children:'    import com.linecorp.armeria.common.brave.RequestContextCurrentTraceContext;\n\n    import brave.Tracing;\n    import brave.http.HttpTracing;\n    import zipkin2.reporter.brave.AsyncZipkinSpanHandler;\n\n    AsyncZipkinSpanHandler spanHandler = ...\n    Tracing tracing = Tracing.newBuilder()\n                             .localServiceName("myService")\n                             .currentTraceContext(RequestContextCurrentTraceContext.ofDefault())\n                             .addSpanHandler(spanHandler)\n                             .build();\n    HttpTracing httpTracing = HttpTracing.create(tracing);\n'})}),"\n",(0,t.jsxs)(r.p,{children:["Please note that we specified ",(0,t.jsx)(r.a,{href:"type://https://javadoc.io/doc/com.linecorp.armeria/armeria-javadoc/latest/com/linecorp/armeria/common/brave/RequestContextCurrentTraceContext.html",children:"RequestContextCurrentTraceContext"}),". It stores the trace context into a\n",(0,t.jsx)(r.a,{href:"type://https://javadoc.io/doc/com.linecorp.armeria/armeria-javadoc/latest/com/linecorp/armeria/common/RequestContext.html",children:"RequestContext"})," and loads the trace context from the ",(0,t.jsx)(r.a,{href:"type://https://javadoc.io/doc/com.linecorp.armeria/armeria-javadoc/latest/com/linecorp/armeria/common/RequestContext.html",children:"RequestContext"})," automatically. Because of that,\nwe don't need to use a thread local variable which can lead to unpredictable behavior in asynchronous\nprogramming. If you want to send timing data to the span collecting server, you should specify ",(0,t.jsx)(r.code,{children:"spanHandler"}),".\nFor more information about the ",(0,t.jsx)(r.code,{children:"spanHandler"}),", please refer to\n",(0,t.jsx)(r.a,{href:"https://github.com/openzipkin/zipkin-reporter-java/tree/master/brave",children:"Zipkin Reporter Brave"})," or\n",(0,t.jsx)(r.a,{href:"https://github.com/openzipkin/brave-example/tree/master/armeria",children:"the fully working example"}),"."]}),"\n",(0,t.jsxs)(r.p,{children:["Now, you can specify ",(0,t.jsx)(r.a,{href:"type://https://javadoc.io/doc/com.linecorp.armeria/armeria-javadoc/latest/com/linecorp/armeria/server/brave/BraveService.html",children:"BraveService"})," using ",(0,t.jsx)(r.a,{href:"/docs/server/decorator",children:"Decorating a service"})," with the\n",(0,t.jsx)(r.code,{children:"HttpTracing"})," you just built:"]}
1),"\n",(0,t.jsx)(r.pre,{children:(0,t.jsx)(r.code,{className:"language-java",children:'    import com.linecorp.armeria.common.HttpResponse;\n    import com.linecorp.armeria.server.Server;\n    import com.linecorp.armeria.server.brave.BraveService;\n\n    Tracing tracing = ...\n    Server server = Server.builder()\n                          .http(8081)\n                          .service("/", (ctx, res) -> HttpResponse.of(200))\n                          .decorator(BraveService.newDecorator(httpTracing))\n                          .build();\n'})}),"\n",(0,t.jsxs)(r.p,{children:["If the requests come to Armeria server and go to another backend, you can trace them using\n",(0,t.jsx)(r.a,{href:"type://https://javadoc.io/doc/com.linecorp.armeria/armeria-javadoc/latest/com/linecorp/armeria/client/brave/BraveClient.html",children:"BraveClient"}),":"]}),"\n",(0,t.jsx)(r.pre,{children:(0,t.jsx)(r.code,{className:"language-java",children:'    import com.linecorp.armeria.client.WebClient;\n    import com.linecorp.armeria.client.brave.BraveClient;\n    import com.linecorp.armeria.server.brave.BraveService;\n\n    Tracing tracing = ...\n    WebClient client = WebClient\n            .builder("https://myBackend.com")\n            .decorator(BraveClient.newDecorator(httpTracing.clientOf("myBackend")))\n            .build();\n\n    Server server = Server.builder()\n                          .http(8081)\n                          .service("/", (ctx, res) -> client.get("/api"))\n                          .decorator(BraveService.newDecorator(httpTracing))\n                          .build();\n'})}),"\n",(0,t.jsxs)(r.p,{children:["Please note that our ",(0,t.jsx)(r.code,{children:"HttpTracing"})," instance used the same ",(0,t.jsx)(r.code,{children:"Tracing"})," instance when we\ncreate ",(0,t.jsx)(r.a,{href:"type://https://javadoc.io/doc/com.linecorp.armeria/armeria-javadoc/latest/com/linecorp/armeria/client/brave/BraveClient.html",children:"BraveClient"})," and ",(0,t.jsx)(r.a,{href:"type://https://javadoc.io/doc/com.linecorp.armeria/armeria-javadoc/latest/com/linecorp/armeria/server/brave/BraveService.html",children:"BraveService"}),". Otherwise, there might be problems if the instances are not\nconfigured exactly the same.\nIn the same manner, you can use the ",(0,t.jsx)(r.code,{children:"Tracing"})," instance with any\n",(0,t.jsx)(r.a,{href:"https://github.com/openzipkin/brave/tree/master/instrumentation",children:"Brave instrumentation libraries"}),".\nFor example, you can use it with ",(0,t.jsx)(r.a,{href:"https://kafka.apache.org/",children:"Kafka"})," producer:"]}),"\n",(0,t.jsx)(r.pre,{children:(0,t.jsx)(r.code,{className:"language-java",children:'    import org.apache.kafka.clients.producer.KafkaProducer;\n    import org.apache.kafka.clients.producer.Producer;\n    import org.apache.kafka.clients.producer.ProducerRecord;\n\n    import brave.kafka.clients.KafkaTracing;\n\n    Tracing tracing = ...\n    KafkaTracing kafkaTracing = KafkaTracing.newBuilder(tracing)\n                                            .remoteServiceName("backend")\n                                            .writeB3SingleFormat(true)\n                                            .build();\n\n    Properties props = new Properties();\n    props.put("bootstrap.servers", "https://myKafka.com");\n    props.put("acks", "all");\n    ...\n\n    Producer<String, String> kafkaProducer = kafkaTracing.producer(new KafkaProducer<>(props));\n\n    Server server = Server.builder()\n                          .http(8081)\n                          .service("/", (ctx, req) -> {\n                              kafkaProducer.send(new ProducerRecord<>("test", "foo", "bar"));\n                              return HttpResponse.of(200);\n                          })\n                          .decorator(BraveService.newDecorator(tracing))\n                          .build();\n'})}),"\n",(0,t.jsxs)(r.p,{children:["This will trace all the requests sent from the client to the above example server to\n",(0,t.jsx)(r.a,{href:"https://kafka.apache.org/",children:"Kafka"}),", and report timing data using the ",(0,t.jsx)(r.code,{children:"spanHandler"})," you specified.\nThe following screenshot shows a trace of a request:"]}),"\n",(0,t.jsx)(r.p,{children:(0,t.jsx)(r.img,{src:a(87014).A+"",width:"2394",height:"1110"})}),"\n",(0,t.jsx)(r.h2,{id:"see-also",children:"See also"}),"\n",(0,t.jsxs)(r.ul,{children:["\n",(0,t.jsx)(r.li,{children:(0,t.jsx)(r.a,{href:"https://github.com/openzipkin/brave-example/tree/master/armeria",children:"Brave example Armeria"})}),"\n",(0,t.jsx)(r.li,{children:(0,t.jsx)(r.a,{href:"https://github.com/openzipkin/brave-example/tree/master/armeria-kafka",children:"Brave example Armeria with Kafka"})}),"\n"]})]})}function p(e={}){let{wrapper:r}={...(0,i.R)(),...e.components};return r?(0,t.jsx)(r,{...e,children:(0,t.jsx)(d,{...e})}):d(e)}},87014(e,r,a){a.d(r,{A:()=>n});let n=a.p+"assets/images/zipkin_1-77fcad76a9d215db1c9115d071027ad4.png"},28453(e,r,a){a.d(r,{R:()=>o,x:()=>c});var n=a(96540);let t={},i=n.createContext(t);function o(e){let r=n.useContext(i);return n.useMemo(function(){return"function"==typeof e?e(r):{...r,...e}},[r,e])}function c(e){let r;return r=e.disableParentContext?"function"==typeof e.components?e.components(t):e.components||t:o(e.components),n.createElement(i.Provider,{value:r},e.children)}}}]);

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.