Info |
---|
Disponible desde versión Available from version 5.1.0 de of Onesait Platform (Survivor). |
Table of Contents |
---|
Introducción
En la release de Q2 de 2023 se ha incluido la capacidad de Tracing distribuido en Plataforma.
Esto nos permite obtener la trazabilidad distribuida entre sus componentes y otros componentes como microservicios que pueden invocar un API REST de plataforma y poder ver esta trazabilidad completa desde este microservicio.
Cómo acceder a la funcionalidad
Estas trazas pueden verse desde el Control Panel en la opción TRACING:
...
En este ejemplo se muestran las trazas de un microservicio que invoca a otro microservicio y este a su vez a un servicio REST expuesto desde el API Manager de plataforma. En las trazas se ve cuanto tiempo se ha empleado en cada span, lo cual es útil para detectar cuellos de botella, interrupciones entre componentes,…
...
¿Cómo configurar mi microservicio para que tracee?
Instrumentación del microservicio
La instrumentación de mi microservicio permitirá que este genere una información de trazas y span que enviará al colector, estas trazas y span comparten un contexto por lo que puede trazarse desde el inicio hasta el fin el camino recorrido, el tiempo en cada punto del camino y además contiene información del tipo clave valor, para luego poder interpretar todo y poder sacar conclusiones.
En Plataforma se utiliza Open Telemetry para crear las trazas y spans y enviarla al colector para su tratamiento.
Tipos de instrumentación
Existen 2 tipos de instrumentación,
Está la instrumentación automática, consiste en utilizar el agente de Open Telemetry para que de forma no intrusiva obtener las trazas sin tener que tocar el código del micro servicio, aplicación,.. desde el que se pretendan obtener las trazas, ya que el agente se encarga de escuchar las distintas librerías más importantes que se suelen utilizar y de estas generar las trazas. Es la que usaremos por defecto.
Luego también está la instrumentalización manual, en este caso hay que añadir en la aplicación, micro servicio las librerías con el SDK de Opentelemetry e implementar como se van a generar las distintas trazas. Este caso es más útil cuando se pretenden generar ciertos tipos de trazas con información especifica o más customizada.
Ejemplo de Instrumentación
Para los ejemplo crearemos 2 microservicios Spring Boot, uno en el que configuraré la instrumentación automática y otro para la manual.
Instrumentación automática
Para este tipo de instrumentación tan sólo hay que arrancar junto a la aplicación el agente de Open Telemetry, el cual es altamente configurable por parametría.
...
Introduction
In the Q2 2023 release, we have included the capability of distributed Tracing in the Platform.
This allows to get distributed traceability between its components and other components like microservices that can call a platform REST API and be able to see this full traceability from within this microservice.
How to access the functionality
These traces can be seen from the Control Panel in the TRACING option:
...
This example shows the traces of a microservice that calls another microservice, and this in turn calls a REST service exposed from the Platform’s API Manager. In the traces you can see how much time has been spent in each span, which is useful to detect bottlenecks, interruptions between components,...
...
How to configure your microservice to trace?
Microservice instrumentation
The instrumentation of yourmicroservice will allow it to generate trace and span information that it will send to the collector. These traces and spans share a context so that, from the beginning to the end, the path traveled, the time at each point of the path, and the time can all be traced. It also contains information of the key-value type, to later be able to interpret everything and be able to draw conclusions.
The Platform uses Open Telemetry to create the traces and spans and send it to the collector for processing.
Instrumentation Types
There are 2 types of instrumentation:
There is the automatic instrumentation. It consists of using the Open Telemetry agent to, in a non-intrusive way, obtain the traces without having to touch the code of the microservice, application, etc., from which the traces are intended to be obtained, since the agent is in charge of listening to the different, most important libraries that are usually used, and from these it generates the traces. It is the one we will use by default.
Then there is also the manual instrumentation. In this case, you have to add the libraries with the Open Telemetry SDK to the application, microservice, and implement how the different traces are going to be generated. This case is more useful when it is intended to generate certain types of traces with specific or more customized information.
Instrumentation Example
For the examples, you will create two Spring Boot microservices, one in which you will configure the automatic instrumentation, and another for the manual one.
Automatic instrumentation
For this type of instrumentation, all you have to do is start the Open Telemetry agent together with the application, which is highly configurable by parameters.
In the simplest example, you only have to specify where the jar is located in the JVM parameters:
-javaagent:/path/opentelemetry-javaagent.jar
Además de añadir las siguientes variables de entornoand add the following environment variables:
Code Block |
---|
OTEL_JAVAAGENT_ENABLED=false #(DesDis)ActivaEnables el agente OTEL_EXPORTER_OTLP_ENDPOINT=http://jaeger-service:4317 #endpoint#collector del collectorendpoint OTEL_SERVICE_NAME=microservice #Nombre#service delname servicio OTEL_METRICS_EXPORTER=none #So that #Parait quedoes nonot exporteexport métricasmetrics, yasince quethis nofeature estáis activadanot esta featureactivated |
...
El agente puede descargarse con esta urlThe agent can be downloaded with this url:
download java agent. (opentelemetry-javaagent-1.27.0.jar)
También existen agentes para otras tecnología.
Instrumentación manual
En este caso habría que añadir código a la aplicación para generar las trazas, añadiendo estas dependencias al fichero pom.xmlThere are also agents for other technologies.
Manual instrumentation
In this case, you have to add code to the application to generate the traces, adding these dependencies to the pom.xml file:
Code Block |
---|
<dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> <dependency> <groupId>io.opentelemetry</groupId> <artifactId>opentelemetry-api</artifactId> </dependency> <dependency> <groupId>io.opentelemetry</groupId> <artifactId>opentelemetry-sdk</artifactId> </dependency> <dependency> <groupId>io.opentelemetry</groupId> <artifactId>opentelemetry-exporter-otlp</artifactId> </dependency> <dependency> <groupId>io.opentelemetry</groupId> <artifactId>opentelemetry-semconv</artifactId> <version>1.27.0-alpha</version> </dependency> </dependencies> <dependencyManagement> <dependencies> <dependency> <groupId>io.opentelemetry</groupId> <artifactId>opentelemetry-bom</artifactId> <version>1.27.0</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement> |
Definir cierta información en el fichero and define some information in the application.properties file:
Code Block |
---|
otel.config.trace-id-ratio-based: 1.0 otel.exporter.otlp.endpoint: https://lab.onesaitplatform.com/otelcollector/ service.name: Onesait-Platform-Microservice |
En este caso se configura el ratio base , la url donde se encuentra el colector de OTel y en nombre del servicio.
Finalmente en el microservicio lo que se hace es invocar un servicio rest generado con el API Manager de plataforma, entonces la finalidad es crear una traza que envuelva esta llamadaIn this case, configure the base ratio, the url where the Otel collector is located, and the name of the service.
Finally, in the microservice, what is done is to invoke a REST service generated with the platform API Manager, so the purpose is to create a trace that wraps this call.
Code Block | ||
---|---|---|
| ||
@Autowired private TracingConfiguration tracingConfiguration; private static final Logger log = LoggerFactory.getLogger(ExampleRestController.class); private Tracer tracer; @PostConstruct public void init() { tracer = tracingConfiguration.getOpenTelemetry().getTracer(ExampleRestController.class.getPackageName()); } @Autowired HttpServletRequest request; //@RequestHeader(required = false) HttpHeaders headers @GetMapping(value = "/getAll") public void getAll() throws IOException { request.getHeaderNames(); Context extractedContext = tracingConfiguration.getOpenTelemetry().getPropagators().getTextMapPropagator() .extract(Context.current(), request, Utils.getter); // the span is created try (Scope scope = extractedContext.makeCurrent()) { Span span = tracer.spanBuilder("example span with context propagation").setSpanKind(SpanKind.SERVER) .startSpan(); try (Scope ignored = span.makeCurrent()) { URL url = new URL("https://lab.onesaitplatform.com/api-manager/server/api/v1/customer/"); // from here you would be making a call to a platform rest api that queries the // information of an entity for example HttpURLConnection con = (HttpURLConnection) url.openConnection(); // adding information to the span is optional but recommended span.setAttribute(SemanticAttributes.HTTP_URL, url.toString()); span.setAttribute(SemanticAttributes.HTTP_METHOD, "GET"); span.setAttribute("component", "http"); // Inject the request with the *current* Context, which contains our current // Span. tracingConfiguration.getOpenTelemetry().getPropagators().getTextMapPropagator() .inject(Context.current(), con, Utils.setter); // the necessary information is added to the request con.setRequestProperty("accept", "application/json"); con.setRequestProperty("X-OP-APIKey", "6bfb064cb62548b78d7...."); con.setRequestMethod("GET"); int status = con.getResponseCode(); log.info("status: " + status); } finally { // the span is closed span.end(); } } } |
En este ejemplo
Se obtiene la traza In this example, the trace is obtained:
Code Block | ||
---|---|---|
| ||
@PostConstruct public void init() { tracer = tracingConfiguration.getOpenTelemetry().getTracer(ExampleRestController.class.getPackageName()); } |
Luego se obtiene el contexto por si este microservicio fuese invocado desde otro que ya hubiese creado una traza previa, con esto se consigue que no se parta la traza en fragmentos que partan de distintos servicios y todos parten desde una llamada incialThen the context is obtained, in case this microservice was invoked from another one that had already created a previous trace. With this, we achieve that the trace is not divided into fragments that start from different services, and that all start from an initial call.
Code Block | ||
---|---|---|
| ||
Context extractedContext = tracingConfiguration.getOpenTelemetry().getPropagators().getTextMapPropagator() .extract(Context.current(), request, Utils.getter); |
Después dentro del contexto se crea un span con información especifica que el desarrollador quiere que se muestre en las trazasThen, within the context, a span is created with specific information that the developer wants to be shown in the traces.
Code Block | ||
---|---|---|
| ||
try (Scope scope = extractedContext.makeCurrent()) { Span span = tracer.spanBuilder("example span with context propagation").setSpanKind(SpanKind.SERVER) .startSpan(); |
Al invocar al servicio rest se añade la información del contexto actual para que el próximo componente de la traza tenga el contexto previo y pueda decidir si crear una traza nueva o continuar con la actual, esto se consigue con los propagatorsWhen invoking the REST service, the current context information is added, so that the next component of the trace has the previous context and can decide whether to create a new trace or continue with the current one. This is achieved with the propagators.
Code Block | ||
---|---|---|
| ||
tracingConfiguration.getOpenTelemetry().getPropagators().getTextMapPropagator() .inject(Context.current(), con, Utils.setter); |
Para finalizar es siempre recomendable cerrar el Finally, it is always advisable to close the span.
Code Block | ||
---|---|---|
| ||
} finally { // the span is closed span.end(); } |
Si vamos a las trazas y expandimos el detalle se comprueba que la información especifica añadida por el desarrollador es visible.
...
Para comprobar que no se pierde el contexto con esta implementación se creo otro micro servicio Onesait-Platform-Microservice2 idéntico al mostrado pero que llamaba a Onesait-Platform-Microservice en lugar de invocar al servicio rest de plataforma, con lo que se muestra en las trazas primero el servicio If we go to the traces and expand the detail, you can check that the specific information added by the developer is visible.
...
To verify that the context is not lost with this implementation, we created another microservice, Onesait-Platform-Microservice2, identical to the one shown but that called Onesait-Platform-Microservice instead of invoking the platform REST service, which is it shows in the first trace the service Onesait-Platform-Microservice2 → Onesait-Platform-Microservice → api-manager.
...