¡Un cliente de Riemann completamente destinado basado en la fiabilidad de Poolboy y el increíble poder de Elixir!
Riemannx es un cliente de Riemann construido en Elixir, actualmente es el único cliente en Elixir que admite UDP y TLS (así como TCP). También hay un modo de lotes que puede usar que funcione con cualquiera de los transportes.
Tiene una opción combinada experimental que aprovecha lo mejor de TCP y UDP: en el modo combinado, UDP es el enfoque favorecido, pero si el tamaño del mensaje excede el tamaño máximo de UDP, se utilizará TCP.
Como siempre, se requieren requisitos previos antes de usar Riemannx, la mayoría de estos son obvios (Elixir, Erlang) pero contienen información sobre las versiones que se prueban y admiten.
Actualmente, todas las versiones de Erlang ~> 18 son compatibles. Esto incluye 20, 20.1 aún no se ha probado, pero no prevé que no hay grandes problemas allí.
Probado por Travis:
18.019.320.0He tratado de garantizar la compatibilidad desde 1.3.4 en adelante y continuaré haciéndolo cuando corresponda. Combinaciones probadas:
18.0 Elixir: 1.3.4 / 1.4.5 / 1.5.119.3 Elixir: 1.3.4 / 1.4.5 / 1.5.120.0 Elixir: 1.4.5 / 1.5.1Como suele ser el caso, un cliente es bastante inútil sin su contraparte del servidor, para obtener más información sobre Riemann, visite http://riemann.io.
El cliente solo ha sido probado en la batalla en: 0.2.11 . Desde la versión 4.0.0 del cliente, deberá establecer use_micro en falso si usa una versión de Riemann anterior a 0.2.13 y no está configurando el campo de tiempo usted mismo. Debería funcionar con 0.3.0 pero nuevamente no se ha probado anteriormente (cualquiera que quiera trabajar en pruebas de integración, lo agradecería mucho).
La instalación ocurre como cualquier otra biblioteca de elixir, agrégala a su archivo de mezcla y el resto es historial:
def deps do
[ { :riemannx , "~> 4.0" } ]
endAsegúrese de agregar Riemannx a la lista de aplicaciones en su archivo mix.exs también, esto garantiza que se inicie con su aplicación y que se incluirá en sus versiones (si usa un administrador de lanzamiento):
applications : [ :logger , :riemannx ] Para usar Riemannx, todo lo que necesita hacer es completar algunas entradas de configuración, después de eso, todo sucede automáticamente (salvo para el envío real, por supuesto). A continuación se muestra una lista completa de las opciones disponibles:
config :riemannx , [
host: "localhost" , # The riemann server
event_host: "my_app" , # You can override the host name sent to riemann if you want (see: Host Injection)
send_timeout: 30_000 , # Synchronous send timeout
checkout_timeout: 30_000 , # Timeout for checking out a poolboy worker
type: :batch , # The type of connection you want to run (:tcp, :udp, :tls, :combined, :batch)
settings_module: Riemannx.Settings.Default # The backend used for reading settings back
metrics_module: Riemannx . Metrics.Default # The backend used for sending metrics
use_micro: true # Set to false if you use a riemann version before 0.2.13
batch_settings: [
type : :combined # The underlying connection to use when using batching.
size: 50 , # The size of batches to send to riemann.
interval: { 1 , :seconds } , # The interval at which to send batches.
limit: :infinity # The max limit of batches allowed in the batching queue
]
tcp: [
port : 5555 ,
retry_count: 5 , # How many times to re-attempt a TCP connection
retry_interval: 1000 , # Interval to wait before the next TCP connection attempt (milliseconds).
priority: :high , # Priority to give TCP workers.
options: [ ] , # Specify additional options to be passed to gen_tcp (NOTE: [:binary, nodelay: true, packet: 4, active: true] will be added to whatever you type here as they are deemed essential)
pool_size: 5 , # How many TCP workers should be in the pool.
max_overflow: 5 , # Under heavy load how many more TCP workers can be created to meet demand?
strategy: :fifo # The poolboy strategy for retrieving workers from the queue
] ,
udp: [
port: 5555 ,
priority: :high ,
options: [ ] , # Specify additional options to be passed to gen_udp (NOTE: [:binary, sndbuf: max_udp_size()] will be added to whatever you type here as they are deemed essential)
max_size: 16_384 , # Maximum accepted packet size (this is configured in your Riemann server)
pool_size: 5 ,
max_overflow: 5 ,
strategy: :fifo
] ,
tls: [
port: 5554 ,
retry_count: 5 , # How many times to re-attempt a TLS connection
retry_interval: 1000 , # Interval to wait before the next TLS connection attempt (milliseconds).
priority: :high ,
options: [ ] , # Specify additional options to be passed to :ssl (NOTE: [:binary, nodelay: true, packet: 4, active: true] will be added to whatever you type here as they are deemed essential)
pool_size: 5 ,
max_overflow: 5 ,
strategy: :fifo
]
] Riemannx admite dos métodos send , uno asíncrono el otro sincrónico:
El envío sincrónico le permite manejar los errores que pueden ocurrir durante el envío, a continuación se muestra un ejemplo que muestra cómo se ve este error y qué sucede en un envío exitoso:
event = [ service: "riemannx-elixir" ,
metric: 1 ,
attributes: [ a: 1 ] ,
description: "test" ]
case Riemannx . send ( event ) do
:ok ->
"Success!"
[ error: error , msg: encoded_msg ] ->
# The error will always be a string so you can output it as it is.
#
# The encoded message is a binary blob but you can use the riemannx proto
# msg module to decode it if you wish to see it in human readable form.
msg = encoded_msg |> Riemannx.Proto.Msg . decode ( )
Logger . warn ( "Error: #{ error } Message: #{ inspect msg } " )
endEl envío asincrónico es mucho más rápido, pero nunca sabe realmente si su mensaje lo hizo, en muchos casos este tipo de envío es lo suficientemente seguro y para la mayoría de los casos de uso la opción recomendada. Es bastante simple de implementar:
event = [ service: "riemannx-elixir" ,
metric: 1 ,
attributes: [ a: 1 ] ,
description: "test" ]
Riemannx . send_async ( event )
# Who knows if it made it? Who cares? 60% of the time it works everytime!Nota: Si un trabajador no puede enviarlo, morirá y se reiniciará dándole la oportunidad de volver a un estado 'correcto'. En un envío asíncrono, esto se realiza mediante la coincidencia de patrones: OK con el comando SEND, para envíos sincrónicos si el valor de retorno es un error, matamos al trabajador antes de devolver el resultado.
El soporte de TLS le permite usar una conexión TCP segura con su servidor Riemann, para obtener más información sobre cómo configurar esto, eche un vistazo aquí: Tráfico seguro de Riemann usando TLS
Si elige usar TLS, usará una configuración puramente TCP, combinado no es compatible (y tampoco debería ser) con TLS:
config :riemannx , [
host: "127.0.0.1" ,
type: :tls ,
tls: [
port: 5554 ,
retry_count: 5 , # How many times to re-attempt a TLS connection
retry_interval: 1000 , # Interval to wait before the next TLS connection attempt (milliseconds).
priority: :high ,
# SSL Opts are passed to the underlying ssl erlang interface
# See available options here: http://erlang.org/doc/man/ssl.html
# (NOTE: [:binary, nodelay: true, packet: 4, active: true] will be added to whatever you type here as they are deemed essential)
options: [
keyfile: "path/to/key" ,
certfile: "path/to/cert" ,
verify_peer: true
] ,
pool_size: 5 ,
max_overflow: 5 ,
strategy: :fifo
]
]Suponiendo que haya configurado el lado del servidor correctamente, esto debería ser todo lo que necesita para comenzar.
Riemann tiene el concepto de un índice consultable que le permite buscar eventos específicos, los índices deben crearse especialmente en su configuración, de lo contrario, el servidor devolverá un error de "sin índice".
# Lets send an event that we can then query
Riemannx . send ( [ service: "riemannx" , metric: 5.0 , attributes: [ v: "2.2.0" ] ] )
# Let's fish it out
events = Riemannx . query ( 'service ~= "riemannx"' )
# [%{attributes: %{"v" => "2.2.0"}, description: nil, host: _,
# metric: nil, service: "riemannx", state: nil, tags: [],
# time: _, ttl: _}]Para obtener más información sobre la consulta y las características del idioma, eche un vistazo a los conceptos centrales.
Esta sección contiene algunas notas sobre el comportamiento de Riemannx que puede interesarle o responder preguntas que tiene sobre ciertas cosas.
El lote a partir de 4.0.0 es el comportamiento de conexión predeterminado: el tamaño de lote predeterminado es 50 y el intervalo es cada 1 segundo. El lote funciona así:
Lo que esté en la cola se enviará cada intervalo.
Si el tamaño de la cola alcanza el tamaño de lote establecido, se descargará independientemente del intervalo.
Los lotes se eliminarán si no hay trabajadores disponibles para manejar el lote a menos que checkout_timer esté configurado en :infinity
Hay un nuevo tipo llamado :batch y una clave de configuración llamada batch_settings: , Inside Batch_settings puede especificar un tipo para la conexión subyacente ( :tcp , :udp , :combined , :tls ). Como siempre combinado es el valor predeterminado.
Opcionalmente, se puede especificar un número de límite por lotes ( :limit ). Si se establece, una vez que la cola de lotes tiene la cantidad especificada de lotes, es decir, los eventos limit * batch_size , se eliminarán los nuevos eventos hasta que se envíe al menos un lote. El valor predeterminado es :infinity
De la versión 0.2.13 de Riemann era posible establecer tiempo en microsegundos: Riemannx ahora admite y usa el campo time_micros (a menos que haya establecido el campo Time o Time_Micros, Riemannx no sobrescribirá eso). Si está utilizando una versión anterior de Riemann, solo usará el campo Seconds.
Nota: Si establece TIME y Time_Micros Riemann, priorizará el tiempo micro y Riemannx tampoco se sobrescribirá.
Suena más elegante de lo que es, pero básicamente describe la funcionalidad que agrega una entrada de host a su evento si no ha especificado uno. Hay 3 formas de especificar un host:
Hazlo antes de enviar el evento (Agregue una clave de host a la lista de palabras clave)
Agregue la tecla :event_host a su configuración.
Deje que Riemannx lo haga usando :inet.gethostname() : solo lo llamamos una vez y guardamos el resultado, no se llama en cada evento.
Las últimas 2 opciones son las más favorables, ya que mantendrán su código limpio.
En este cliente, existe la oportunidad de establecer una prioridad para sus trabajadores que le permitan colocar una prioridad más alta o menos en el envío de sus estadísticas a Riemann.
La configuración de la diferencia que hace una prioridad depende en gran medida del hardware y cómo ha establecido sus otras prioridades en general, se puede encontrar más información aquí: http://erlang.org/doc/man/erlang.html#process_flag-2
Si intenta establecer la prioridad en: Max Riemannx elevará un TimeError de ejecución porque es una idea terrible. También elevará un TimeError de ejecución si lo intenta: Foo porque también es una idea terrible.
La migración a 3.0 es esencialmente un caso de cambiar su diseño de configuración: existen todas las mismas opciones, excepto que ahora tiene más control sobre sus trabajadores a nivel de tipo, esto es especialmente valioso cuando se usa la configuración combinada como podría, por ejemplo, tener un grupo más pequeño de trabajadores de TCP y un grupo de trabajadores de UDP más grande en lugar de ser antes (2x cualquier grupo que dio).
Puedes ver este nuevo diseño aquí: config
Si algo no tiene sentido aquí, siéntase libre de abrir un problema para que podamos expandir el ReadMe para arreglar la falta de claridad.
Si desea almacenar su configuración en otro lugar, puede crear un backend para leer la configuración desde una base de datos, por ejemplo. Mire el módulo de configuración predeterminado para las devoluciones de llamada requeridas.
Esto puede ser útil si desea almacenar la configuración de toda la empresa en un solo lugar.
No dude en abrir un problema si tiene preguntas.
Riemannx admite el envío de métricas básicas, puede crear un módulo personalizado para admitir cualquier infraestructura (grafito, afluencia, etc.). Actualmente hay 3 devoluciones de llamada:
udp_message_sent(size) : informa cuándo se envía un mensaje UDP y da el tamaño del mensaje.tcp_message_sent(size) : informa cuándo se envía un mensaje TCP y da el tamaño del mensaje.tls_message_sent(size) : informa cuándo se envía un mensaje TLS y da el tamaño del mensaje. Las contribuciones se reciben calurosamente, consulte la sección de proyectos para ver algunas ideas que he escrito y lo último sobre lo que está en marcha.
¡Este repositorio utiliza el flujo de trabajo Gitflow, lo que significa que todos los PR deben apuntar hacia la rama de desarrollo! . A continuación hay algunas cosas a considerar antes de crear un PR:
¡Me gustaría mantener la cobertura de prueba al 100%! - Puedo dejar que esto se deslice en casos urgentes (errores, etc.)
Para evitar la congestión de Travis innecesariamente, se agradecería si verifica lo siguiente localmente primero:
mix coveralls.html (apunte al 100%)mix dialyzer (lleva un tiempo y aprecio que no puedas probar todas las versiones de Erlang/Elixir)Considero que esta característica del cliente completa, si su PR rompe la compatibilidad hacia atrás por completo o cambia el comportamiento/valores predeterminados preexistentes, apreciaría que se avecinen y sus justificaciones :).
Se ha tomado prestada una parte del código del cliente original Elixir-Riemann. La mayoría de las cosas de ProtoBuf provienen de allí.