Saltar al contenido

Promtail: El eslabón perdido entre registros y métricas para tu plataforma de monitoreo

Promtail es la solución cuando necesitas proporcionar métricas que solo están presentes en los rastros de registro del software que necesitas monitorear para proporcionar una plataforma de monitoreo consistente

Promtail: El Vínculo Perdido entre Registros y Métricas para tu Plataforma de Monitoreo.
Foto de SOULSANA en Unsplash

Es un entendimiento común que tres pilares en el mundo de la observabilidad nos ayudan a obtener una vista completa del estado de nuestras propias plataformas y sistemas: Registros, Trazas y Métricas.

Para proporcionar un resumen de las diferencias entre cada uno de ellos:

  • Las métricas son los contadores sobre el estado de los diferentes componentes desde una vista técnica y de negocio. Así que aquí podemos ver cosas como el consumo de CPU, el número de solicitudes, el uso de memoria o disco…
  • Los registros son los diferentes mensajes que cada una de las piezas de software en nuestra plataforma proporciona para entender su comportamiento actual y detectar algunas situaciones no esperadas.
  • La traza es la diferente información sobre el flujo de solicitudes de extremo a extremo a través de la plataforma con los servicios y sistemas que han sido parte de ese flujo y datos relacionados con esa solicitud concreta.

Tenemos soluciones que afirman abordar todos ellos, principalmente en el software empresarial con Dynatrace, AppDynamics y similares. Y por otro lado, intentamos ir con una solución específica para cada uno de ellos que podamos integrar fácilmente juntos y hemos discutido mucho sobre esas opciones en artículos anteriores.

Pero, algunas situaciones en ese software no funcionan siguiendo este camino porque vivimos en la era más heterogénea. Todos abrazamos, en algún nivel, el enfoque políglota en las nuevas plataformas. En algunos casos, podemos ver que el software está utilizando rastros de registro para proporcionar datos relacionados con métricas u otros asuntos, y aquí es cuando necesitamos confiar en piezas de software que nos ayuden a «arreglar» esa situación, y Promtail hace específicamente eso.

Promtail es principalmente un reenviador de registros similar a otros como fluentd o fluent-bit de CNCF o logstash del stack ELK. En este caso, esta es la solución de Grafana Labs, y como puedes imaginar, esto es parte del stack de Grafana con Loki para ser el «cerebro» que cubrimos en este artículo que te recomiendo que eches un vistazo si aún no lo has leído:

Promtail tiene dos formas principales de comportarse como parte de esta arquitectura, y la primera es muy similar a otras en este espacio, como comentamos antes. Nos ayuda a enviar nuestros rastros de registro desde nuestros contenedores a la ubicación central que principalmente será Loki y puede ser una diferente y proporcionar las opciones habituales para jugar y transformar esos rastros como podemos hacer en otras soluciones. Puedes ver todas las opciones en el enlace a continuación, pero como puedes imaginar, esto incluye transformación, filtrado, análisis, y así sucesivamente.

Pero lo que hace a promtail tan diferente es solo una de las acciones que puedes hacer, y esa acción es metrics. Metrics proporciona una forma específica de, basado en los datos que estamos leyendo de los registros, crear métricas de Prometheus que un servidor de Prometheus puede recolectar. Eso significa que puedes usar los rastros de registro que estás procesando que pueden ser algo como esto:

[2021–06–06 22:02.12] Nueva solicitud recibida para customer_id: 123
[2021–06–06 22:02.12] Nueva solicitud recibida para customer_id: 191
[2021–06–06 22:02.12] Nueva solicitud recibida para customer_id: 522

Con esta información aparte de enviar esas métricas a la ubicación central para crear una llamada de métrica, por ejemplo: `total_request_count` que será generada por el agente promtail y también expuesta por él y siendo capaz también de usar un enfoque de métricas incluso para sistemas o componentes que no proporcionan una forma estándar de hacer eso como una API de métricas formal.

Y la forma de hacer esto está muy bien integrada con la configuración. Esto se hace con una etapa adicional (así es como llamamos a las acciones que podemos hacer en Promtail) que se llama metrics.

El esquema de esa etapa de métrica es sencillo, y si estás familiarizado con Prometheus, verás lo directo que es desde una definición de métricas de Prometheus a este fragmento:

# Un mapa donde la clave es el nombre de la métrica y el valor es un tipo de
# métrica específico.
metrics:
  [<string>: [ <metric_counter> | <metric_gauge> | <metric_histogram> ] ...]

Así que comenzamos definiendo el tipo de métricas que nos gustaría definir, y tenemos las habituales: contador, gauge o histograma, y para cada uno de ellos, tenemos un conjunto de opciones para poder declarar nuestras métricas como puedes ver aquí para una Métrica de Contador

# El tipo de métrica. Debe ser Counter.
type: Counter

# Describe la métrica.

[description: <string>]

# Define un nombre de prefijo personalizado para la métrica. Si no está definido, el nombre predeterminado «promtail_custom_» será prefijado.

[prefix: <string>]

# Clave del mapa de datos extraídos para usar en la métrica, # por defecto al nombre de la métrica si no está presente.

[source: <string>]

# Los valores de las etiquetas en las métricas son dinámicos, lo que puede causar que las métricas exportadas se vuelvan obsoletas (por ejemplo, cuando un flujo deja de recibir registros). # Para prevenir el crecimiento ilimitado del endpoint /metrics, cualquier métrica que no haya sido actualizada dentro de este tiempo será eliminada. # Debe ser mayor o igual a ‘1s’, si no está definido el valor predeterminado es ‘5m’

[max_idle_duration: <string>]

config: # Si está presente y es verdadero, todas las líneas de registro serán contadas sin # intentar coincidir la fuente con el mapa extraído. # Es un error especificar `match_all: true` y también especificar un `value`

[match_all: <bool>]

# Si está presente y es verdadero, todos los bytes de la línea de registro serán contados. # Es un error especificar `count_entry_bytes: true` sin especificar `match_all: true` # Es un error especificar `count_entry_bytes: true` sin especificar `action: add`

[count_entry_bytes: <bool>]

# Filtra los datos de origen y solo cambia la métrica # si el valor objetivo coincide exactamente con la cadena proporcionada. # Si no está presente, todos los datos coincidirán.

[value: <string>]

# Debe ser «inc» o «add» (insensible a mayúsculas). Si # se elige inc, el valor de la métrica aumentará en 1 por cada # línea de registro recibida que pase el filtro. Si se elige add, # el valor extraído debe ser convertible a un flotante positivo # y su valor se sumará a la métrica. action: <string>

Y con eso, tendrás tu métrica creada y expuesta, solo esperando que un servidor de Prometheus la recolecte. Si te gustaría ver todas las opciones disponibles, toda esta documentación está disponible en la documentación de Grafana Labs que puedes consultar en el enlace:

Espero que encuentres esto interesante y una forma útil de mantener toda tu información de observabilidad gestionada correctamente usando la solución adecuada y proporcionar una solución para estas piezas de software que no siguen tu paradigma.

Promtail: The Missing Link Logs and Metrics for your Monitoring Platform.

Promtail is the solution when you need to provide metrics that are only present on the log traces of the software you need to monitor to provide a consistent monitoring platform

Promtail: The Missing Link Logs and Metrics for your Monitoring Platform.
Photo by SOULSANA on Unsplash

It is a common understanding that three pillars in the observability world help us to get a complete view of the status of our own platforms and systems: Logs, Traces, and Metrics.

To provide a summary of the differences between each of them:

  • Metrics are the counters about the state of the different components from both a technical and a business view. So we can see here things like the CPU consumption, the number of requests, memory, or disk usage…
  • Logs are the different messages that each of the pieces of software in our platform provides to understand its current behavior and detect some non-expected situations.
  • Trace is the different data regarding the end-to-end request flow across the platform with the services and systems that have been part of that flow and data related to that concrete request.

We have solutions that claim to address all of them, mainly in the enterprise software with Dynatrace, AppDynamics, and similar. And on the other hand, we try to go with a specific solution for each of them that we can easily integrate together and we have discussed a lot about that options in previous articles.

But, some situations in that software don’t work following this path because we live in the most heterogeneous era. We all embrace, at some level, the polyglot approach on the new platforms. In some cases, we can see that software is using log traces to provide data related to metrics or other matters, and here is when we need to rely on pieces of software that help us “fix” that situation, and Promtail does specifically that.

Promtail is mainly a log forwarder similar to others like fluentd or fluent-bit from CNCF or logstash from the ELK stack. In this case, this is the solution from Grafana Labs, and as you can imagine, this is part of the Grafana stack with Loki to be the “master-mind” that we cover in this article that I recommend you to take a look at if you haven’t read it yet:

Promtail has two main ways of behaving as part of this architecture, and the first one is very similar to others in this space, as we commented before. It helps us ship our log traces from our containers to the central location that will mainly be Loki and can be a different one and provide the usual options to play and transform those traces as we can do in other solutions. You can look at all the options in the link below, but as you can imagine, this includes transformation, filtering, parsing, and so on.

But what makes promtail so different is just one of the actions that you can do, and that action is metrics. Metrics provides a specific way to, based on the data that we are reading from the logs, create Prometheus metrics that a Prometheus server can scrape. That means that you can use the log traces that you are processing that can something like this:

[2021–06–06 22:02.12] New request received for customer_id: 123
[2021–06–06 22:02.12] New request received for customer_id: 191
[2021–06–06 22:02.12] New request received for customer_id: 522

With this information apart to send those metrics to the central location to create a metric call, for example: `total_request_count` that will be generated by the promtail agent and also exposed by it and being able also to use a metrics approach even for systems or components that don’t provide a standard way to do that like a formal metrics API.

And the way to do this is very well integrated with the configuration. This is done with an additional stage (this is how we call the actions we can do in Promtail) that is namedmetrics.

The schema of that metric stage is straightforward, and if you are familiar with Prometheus, you will see how direct it is from a definition of Prometheus metrics to this snippet:

# A map where the key is the name of the metric and the value is a specific
# metric type.
metrics:
  [<string>: [ <metric_counter> | <metric_gauge> | <metric_histogram> ] ...]

So we start defining the kind of metrics that we would like to define, and we have the usual ones: counter, gauge, or histogram, and for each of them, we have a set of options to be able to declare our metrics as you can see here for a Counter Metrics

# The metric type. Must be Counter.
type: Counter

# Describes the metric.

[description: <string>]

# Defines custom prefix name for the metric. If undefined, default name «promtail_custom_» will be prefixed.

[prefix: <string>]

# Key from the extracted data map to use for the metric, # defaulting to the metric’s name if not present.

[source: <string>]

# Label values on metrics are dynamic which can cause exported metrics # to go stale (for example when a stream stops receiving logs). # To prevent unbounded growth of the /metrics endpoint any metrics which # have not been updated within this time will be removed. # Must be greater than or equal to ‘1s’, if undefined default is ‘5m’

[max_idle_duration: <string>]

config: # If present and true all log lines will be counted without # attempting to match the source to the extract map. # It is an error to specify `match_all: true` and also specify a `value`

[match_all: <bool>]

# If present and true all log line bytes will be counted. # It is an error to specify `count_entry_bytes: true` without specifying `match_all: true` # It is an error to specify `count_entry_bytes: true` without specifying `action: add`

[count_entry_bytes: <bool>]

# Filters down source data and only changes the metric # if the targeted value exactly matches the provided string. # If not present, all data will match.

[value: <string>]

# Must be either «inc» or «add» (case insensitive). If # inc is chosen, the metric value will increase by 1 for each # log line received that passed the filter. If add is chosen, # the extracted value most be convertible to a positive float # and its value will be added to the metric. action: <string>

And with that, you will have your metric created and exposed, just waiting for a Prometheus server to scrape it. If you would like to see all the options available, all this documentation is available in the Grafana Labs documentation that you can check in the link:

I hope you will find this interesting and a useful way to keep all your observability information managed correctly using the right solution and provide a solution for these pieces of software that don’t follow your paradigm.