Um cliente Riemann totalmente em destaque construído sobre a confiabilidade do Poolboy e o incrível poder do Elixir!
O Riemannx é um cliente Riemann construído no Elixir, atualmente é o único cliente do Elixir que suporta UDP e TLS (assim como TCP). Há também um modo de lote que você pode usar que funciona com qualquer um dos transportes.
Ele possui uma opção combinada experimental que aproveita o melhor do TCP e do UDP - no modo combinado UDP, será a abordagem favorecida, mas se o tamanho da mensagem exceder o conjunto de tamanho máximo UDP TCP será usado.
Como sempre, são necessários pré -requisitos antes de usar o Riemannx, a maioria deles é óbvia (Elixir, Erlang), mas contém algumas informações sobre quais versões são testadas e suportadas.
Atualmente, todas as versões Erlang ~> 18 são suportadas. Isso inclui 20, 20,1 ainda não foi testado, mas não prevejo grandes problemas por lá.
Testado por Travis:
18.019.320.0Tentei garantir a compatibilidade a partir de 1.3.4 e continuarei a fazê -lo quando apropriado. Combinações testadas:
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 costuma ser o caso, um cliente é bastante inútil sem o seu equivalente ao servidor - para obter mais informações sobre o Riemann, visite http://riemann.io.
O cliente foi testado apenas em: 0.2.11 . Na versão 4.0.0 do cliente, você precisará definir use_micro como false se usar uma versão de Riemann com mais de 0.2.13 e não estiver definindo o campo de tempo. Ele deve funcionar com 0.3.0 , mas novamente não foi testado anteriormente (alguém querendo trabalhar em testes de integração que eu apreciaria muito).
A instalação acontece como qualquer outra biblioteca Elixir, adicione -a ao seu arquivo de mixagem e o resto é história:
def deps do
[ { :riemannx , "~> 4.0" } ]
endCertifique -se de adicionar riemannx à lista de aplicativos no seu arquivo mix.exs também, isso garante que ele seja iniciado com seu aplicativo e que ele será incluído em seus lançamentos (se você usar um gerenciador de liberação):
applications : [ :logger , :riemannx ] Para usar o Riemannx, tudo o que você precisa fazer é preencher algumas entradas de configuração - depois disso tudo acontece automaticamente (exceto o envio real, é claro). Abaixo está uma lista abrangente de opções disponíveis:
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
]
] O Riemannx suporta dois métodos send , um assíncrono o outro síncrono:
O envio síncrono permite lidar com os erros que podem ocorrer durante o envio, abaixo é um exemplo que mostra a aparência desse erro e o que acontece em um envio bem -sucedido:
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 } " )
endO envio assíncrono é muito mais rápido, mas você nunca sabe se sua mensagem fez isso, em muitos casos, esse tipo de envio é seguro o suficiente e, para a maioria dos casos de uso, a escolha recomendada. É bastante simples 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: Se um trabalhador não puder enviá -lo, morrerá e será reiniciado, dando -lhe a chance de retornar a um estado 'correto'. Em um envio assíncrono, isso é feito pelo padrão correspondente: OK com o comando send, para envio síncrono se o valor de retorno for um erro, matamos o trabalhador antes de retornar o resultado.
O suporte ao TLS permite que você use uma conexão TCP segura com o seu servidor Riemann, para saber mais sobre como configurar isso, dê uma olhada aqui: o tráfego Riemann seguro usando TLS
Se você optar por usar o TLS, usará uma configuração puramente TCP, combinado não é suportado (e também não deve ser) com o 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
]
]Supondo que você tenha configurado o lado do servidor corretamente, isso deve ser tudo o que você precisa para começar.
Riemann tem o conceito de um índice consultável que permite pesquisar eventos específicos, os índices devem ser criados especialmente em sua configuração, caso contrário, o servidor retornará um erro "sem í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 obter mais informações sobre consulta e os recursos do idioma, dê uma olhada nos conceitos principais.
Esta seção contém algumas notas sobre o comportamento do Riemannx que pode lhe interessar ou responder a perguntas que você tem sobre certas coisas.
O lote a partir de 4.0.0 é o comportamento de conexão padrão - o tamanho do lote padrão é 50 e o intervalo é a cada 1 segundo. O lote funciona assim:
O que quer que esteja na fila, será enviado a cada intervalo.
Se o tamanho da fila atingir o tamanho do lote definido, ela será liberada, independentemente do intervalo.
Os lotes serão descartados se nenhum trabalhador estiver disponível para lidar com o lote, a menos que checkout_timer esteja definido como :infinity
Existe um novo tipo chamado :batch e uma tecla de configurações chamada batch_settings: , Inside batch_settings Você pode especificar um tipo para a conexão subjacente ( :tcp , :udp , :combined , :tls ). Como sempre combinado, é o padrão.
Opcionalmente, um número de limite de lote pode ser especificado ( :limit ). Se definido, uma vez que a fila em lote tenha a quantidade especificada de lotes, que é limit * batch_size eventos, novos eventos serão descartados até que pelo menos um lote seja enviado. O valor padrão é :infinity
Na versão 0.2.13 de Riemann, foi possível definir o tempo em microssegundos - o Riemannx agora suporta e usa o campo time_micros (a menos que você tenha definido o tempo ou o time_micros em campo, o riemannx não substituirá isso). Se você estiver usando uma versão mais antiga do Riemann, ele usará apenas o campo segundos.
NOTA: Se você definir o tempo e o time_micros Riemann priorizarão o horário micro e o Riemannx substituirá nenhum.
Parece mais sofisticado do que é, mas basicamente descreve a funcionalidade que adiciona uma entrada no seu evento, se você não especificou um. Existem 3 maneiras de especificar um host:
Faça isso antes de enviar o evento (adicione a: chave do host para a lista de palavras -chave)
Adicione a chave :event_host para sua configuração.
Deixe o Riemannx fazer isso usando :inet.gethostname() - Chamamos apenas isso uma vez e salvará o resultado, ele não é chamado em todos os eventos.
As duas últimas opções são as mais favoráveis, pois manterão seu código limpo.
Nesse cliente, há a oportunidade de estabelecer uma prioridade para seus funcionários, permitindo que você dê uma prioridade mais alta ou menor no envio de suas estatísticas para Riemann.
A diferença de definição de prioridade depende muito do hardware e de como você definiu suas outras prioridades em geral, mais informações podem ser encontradas aqui: http://erlang.org/doc/man/erlang.html#process_flag-2
Se você tentar definir a prioridade para: Max Riemannx aumentará um terror de tempo de execução, porque essa é uma ideia terrível. Ele também aumentará um terror de tempo de execução se você tentar: Foo, porque isso também é uma ideia terrível.
Migrar para 3.0 é essencialmente apenas um caso de alteração do layout da sua configuração - todas as mesmas opções existem, exceto agora que você tem mais controle sobre seus trabalhadores no nível do tipo, isso é especialmente valioso ao usar a configuração combinada como você poderia, por exemplo, ter um pool menor de trabalhadores de TCP e um pool de trabalhadores de UDP maior, em vez de ser antes (2x qualquer pool de pool _
Você pode ver este novo layout aqui: Config
Se alguma coisa não faz sentido aqui, sinta -se à vontade para abrir um problema, para que possamos expandir o ReadMe para corrigir a esclarecimento.
Se você deseja armazenar suas configurações em outro lugar, poderá criar um back -end para ler as configurações de um banco de dados, por exemplo. Veja o módulo de configurações padrão para os retornos de chamada necessários.
Isso pode ser útil se você deseja armazenar configurações em toda a empresa em um só lugar.
Sinta -se à vontade para abrir um problema se tiver dúvidas.
O Riemannx suporta o envio de métricas básicas, você pode criar um módulo personalizado para suportar qualquer infraestrutura (grafite, influxo etc.). Atualmente, existem 3 retornos de chamada:
udp_message_sent(size) - informa quando uma mensagem UDP é enviada e fornece o tamanho da mensagem.tcp_message_sent(size) - informa quando uma mensagem TCP é enviada e fornece o tamanho da mensagem.tls_message_sent(size) - informa quando uma mensagem TLS é enviada e fornece o tamanho da mensagem. As contribuições são recebidas calorosamente, confira a seção de projetos para obter algumas idéias que escrevi e as últimas novidades sobre o que está em andamento.
Este repositório usa o fluxo de trabalho Gitflow, o que significa que todos os PRs devem ser apontados para o ramo de desenvolvimento! . Abaixo estão algumas coisas a considerar antes de criar um PR:
Eu gostaria de manter a cobertura do teste a 100%! - Posso deixar isso deslizar em casos urgentes (bugs etc.)
Para evitar o congestionamento de Travis desnecessariamente, seria apreciado se você verificar o seguinte localmente primeiro:
mix coveralls.html (mira para 100%)mix dialyzer (demora um pouco e eu aprecio que você não possa testar todas as versões Erlang/Elixir)Considero esse recurso do cliente completo, se o seu PR quebrar completamente a compatibilidade com o comportamento/inadimplência pré-existente, eu apreciaria um alerta e suas justificativas :).
Uma parte do código foi emprestada do cliente Elixir-Riemann original. A maioria das coisas do Protobuf vem a partir daí.