Metric#
Adicionado na versão 1.12.0.
O módulo ngx_stream_metric_module permite criar métricas
arbitrárias calculadas em tempo real para tráfego stream (TCP e UDP).
Esses valores de métricas são armazenados em memória compartilhada e
exibidos em tempo real no ramo da API /status/stream/metric_zones/.
Vários tipos de agregação de dados são suportados (contadores,
histogramas, médias móveis, etc.) com agrupamento por chaves arbitrárias.
Para o esquema da resposta, consulte a
referência da API de zona de métricas stream. Contando conexões por endereço de cliente: Se uma conexão for estabelecida na porta A métrica Calcula o valor da métrica para a zona de memória compartilhada especificada name. Parâmetros: O comprimento máximo é de 255 bytes; chaves mais longas são truncadas.
Na saída da API, o Angie anexa selecionado. Se omitido, o padrão é Se Se Se Exemplo de uso: Nota Métricas com uma chave vazia ou com um par Isso é útil, por exemplo, para o modo Nota Lembre-se de que as variáveis são avaliadas em fases diferentes. Por
exemplo, é impossível usar Padrão — stream Define uma métrica complexa — um conjunto de métricas com modos
independentes. Cada linha no corpo do bloco define um nome de
submétrica, um modo e parâmetros opcionais do modo. O tamanho da
zona deve ser de pelo menos oito páginas de memória do sistema. Exemplo de uso: Na árvore da API, tal modelo de métrica complexa se parece com o seguinte: Padrão — stream Cria uma zona de memória compartilhada do size especificado com o
name fornecido para armazenar métricas. O nome da zona serve como um
nó no ramo Parâmetros: são descartadas para liberar memória para as novas; descartadas, preservando as entradas existentes. onde os valores das métricas descartadas são acumulados. Por padrão,
nenhuma métrica desse tipo é criada. A chave reservada não pode ser
atualizada manualmente. mode — algoritmo de processamento de dados (veja a seção Modos de Operação); (por exemplo, Exemplo de uso: Na árvore da API, o modelo de zona de memória compartilhada se parece com o seguinte: Nota Em uma zona de 1 MB, com um tamanho de chave de 39 bytes e um único
modo de métrica, aproximadamente 8.000 entradas de chaves únicas
podem ser armazenadas. Lista de modos de operação de métricas disponíveis: Os exemplos abaixo usam o endpoint Cada atualização da métrica incrementa o contador em Valor padrão — Exemplos: Atualizando a métrica: Valor esperado da métrica na API: O gauge aumenta ou diminui seu valor dependendo do sinal do número
informado. Um valor positivo aumenta o contador, enquanto um valor
negativo o diminui. Um valor de Valor padrão — Exemplos: Atualizando a métrica: Valor esperado da métrica na API: Atualizações adicionais: Valor esperado da métrica na API: Armazena o último valor recebido sem qualquer agregação. Se value for
omitido, Exemplos: Atualizando a métrica: Valor esperado da métrica na API: Atualizações adicionais: Valor esperado da métrica na API: Salva o mínimo de dois valores — o valor atualmente armazenado e o novo. Exemplos: Atualizando a métrica: Valor esperado da métrica na API: Salva o máximo de dois valores — o valor atualmente armazenado e o novo. Exemplos: Atualizando a métrica: Valor esperado da métrica na API: Calcula o valor médio usando o algoritmo de
suavização exponencial. Aceita um parâmetro opcional Quanto maior o coeficiente, mais peso os novos valores têm. Se você
especificar Exemplos: Atualizando a métrica: Valor esperado da métrica na API: Calcula a média aritmética. Aceita parâmetros opcionais
Nota Por exemplo, Exemplos: Atualizando a métrica: Valor esperado da métrica na API: Se você aguardar 5 segundos desde a última atualização, o valor esperado será: Cria um conjunto de "buckets", incrementando o contador correspondente
se o novo valor não exceder o limite do bucket. Os parâmetros são
fornecidos como uma lista de limites numéricos. Útil para analisar
distribuições, como durações de sessão. Os parâmetros obrigatórios são numbers — os valores de limite dos
buckets, normalmente listados em ordem crescente. Nota O valor de bucket Exemplos: Atualizando a métrica: Valor esperado da métrica na API: Atualizações adicionais: Valor esperado da métrica na API: Atualização adicional: Valor esperado da métrica na API: Variáveis são criadas para cada métrica: Para métricas complexas, uma variável adicional é adicionada: De forma semelhante à diretiva metric, o setter da
variável O setter aceita uma chave com um sufixo opcional Exemplo de uso: Após três conexões à porta Nota Ao ler Além disso, o valor armazenado na variável As variáveis Nota Para métricas complexas, os valores das submétricas na variável
Exemplo de uso: Com esta configuração, uma conexão à porta Uma conexão à porta Nota Se uma string vazia for atribuída a O cálculo ocorre somente depois que tanto Nesse caso, o valor armazenado em O valor em O valor em Para métricas complexas, o valor de uma submétrica específica pode ser
obtido usando a variável Exemplo de uso: Com esta configuração, uma conexão à porta Resposta: Resposta: Resposta: O Angie inclui um módulo integrado para exibir
métricas no
formato Prometheus,
que suporta métricas personalizadas, incluindo aquelas coletadas no
lado stream. Como a exposição do Prometheus é um recurso exclusivo de
HTTP, as diretivas prometheus_template e
prometheus são configuradas em um bloco
Como exemplo de integração, considere a seguinte configuração: Após cinco conexões à porta Os valores da métrica serão: No formato Prometheus,
a métrica está disponível em Exemplo de Configuração#
stream {
metric_zone connections:1m count;
server {
listen 12345;
metric connections $remote_addr on=connect;
}
}
http {
server {
listen 80;
location /status/ {
allow 127.0.0.1;
deny all;
api /status/;
}
}
}
12345:$ nc 127.0.0.1 12345 </dev/null
connections é atualizada em tempo real:{
"stream": {
"metric_zones": {
"connections": {
"discarded": 0,
"metrics": {
"127.0.0.1": 1
}
}
}
}
}
Diretivas#
metric#
... a toda chave de 255 bytes,
incluindo aquela cujo comprimento original era exatamente 255 bytes.
Uma chave pode, ela própria, conter caracteres = — apenas o
texto posterior ao último = é tratado como o valor, de modo
que tudo o que vem antes dele (incluindo qualquer =
incorporado) passa a fazer parte da chave;0. Se o parâmetro não
puder ser convertido para um número, o padrão é 1;on — um parâmetro opcional que especifica em qual ponto do
processamento da sessão a métrica é calculada:on=connect, o cálculo ocorre durante a fase
Pre-access, antes que qualquer dado seja lido do cliente;on=preread, o cálculo ocorre uma vez por sessão, quando os
primeiros dados do lado upstream — recebidos do servidor para o qual
foi feito proxy com proxy_pass, ou gerados por
return — são enviados ao cliente; nesse ponto,
módulos como proxy_protocol, ssl_preread
e mqtt_preread já processaram os dados iniciais do cliente;on=end (padrão), o cálculo ocorre durante a fase
Log, quando a sessão termina.metric sessions $remote_addr=$session_time on=end;
key=value inválido
são ignoradas. Um value omitido é tratado como 0:metric foo $bar; # Equivalente a $bar=0
count, que ignora
valores numéricos e simplesmente reage ao fato de que uma métrica foi
atualizada.$upstream_bytes_sent (bytes
enviados ao upstream) com on=connect (antes que a conexão
tenha sido encaminhada via proxy para algum destino).metric_complex_zone#
metric_complex_zone name:size [expire=on| off] [discard_key=name] { ... }metric_complex_zone sessions:1m expire=on discard_key="old" {
# nome submétrica modo parâmetros
min_time min;
avg_time average exp factor=60;
max_time max;
total count;
}
{
"discarded": 3,
"metrics": {
"key1": {
"min_time": 20,
"avg_time": 50,
"max_time": 80,
"total": 2
},
"old": {
"min_time": 3,
"avg_time": 40,
"max_time": 152,
"total": 80
}
}
}
metric_zone#
metric_zone name:size [expire=on| off] [discard_key=name] mode [parameters];/status/stream/metric_zones/.
O tamanho da zona deve ser de pelo menos oito páginas de memória do
sistema.expire=<on|off> — comportamento quando a zona está cheia:on, as métricas mais antigas (por tempo de atualização)off (padrão) — as novas métricas recebidas sãodiscard_key=<name> — define uma métrica com a chave namefactor para average exp).metric_zone session_time:1m max;
{
"discarded": 0,
"metrics": {
"key1": 123,
"key2": 10.5
}
}
Modos de Operação#
count — contador;gauge — medidor (incremento/decremento);last — o último valor recebido;min — valor mínimo;max — valor máximo;average exp — média móvel exponencial (EMA) (parâmetro factor);average mean — média sobre uma janela (parâmetros window e count);histogram — distribuição em "buckets" (uma lista de valores de limite)./status/ do
exemplo de configuração. Cada
resultado está disponível em
/status/stream/metric_zones/<zone>/metrics/.count#
1,
independentemente do valor fornecido.0.metric_zone count:1m count;
# Como parte de uma métrica complexa:
#
# metric_complex_zone count:1m {
# some_metric_name count;
# }
server {
listen 12345;
metric count KEY;
}
$ nc 127.0.0.1 12345 </dev/null
$ nc 127.0.0.1 12345 </dev/null
$ nc 127.0.0.1 12345 </dev/null
$ nc 127.0.0.1 12345 </dev/null
{
"KEY": 4
}
gauge#
0 não altera o contador.0.metric_zone gauge:1m gauge;
# Como parte de uma métrica complexa:
#
# metric_complex_zone gauge:1m {
# some_metric_name gauge;
# }
server {
listen 12351;
metric gauge KEY;
}
server {
listen 12352;
metric gauge KEY=5;
}
server {
listen 12353;
metric gauge KEY=-5;
}
server {
listen 12354;
metric gauge KEY=8;
}
$ nc 127.0.0.1 12351 </dev/null
{
"KEY": 0
}
$ nc 127.0.0.1 12352 </dev/null
$ nc 127.0.0.1 12353 </dev/null
$ nc 127.0.0.1 12354 </dev/null
{
"KEY": 8
}
last#
0 é usado.metric_zone last:1m last;
# Como parte de uma métrica complexa:
#
# metric_complex_zone last:1m {
# some_metric_name last;
# }
server {
listen 12361;
metric last KEY;
}
server {
listen 12362;
metric last KEY=8000;
}
server {
listen 12363;
metric last KEY=37;
}
server {
listen 12364;
metric last KEY=-3.5;
}
$ nc 127.0.0.1 12361 </dev/null
{
"KEY": 0
}
$ nc 127.0.0.1 12362 </dev/null
$ nc 127.0.0.1 12363 </dev/null
$ nc 127.0.0.1 12364 </dev/null
{
"KEY": -3.5
}
min#
metric_zone min:1m min;
# Como parte de uma métrica complexa:
#
# metric_complex_zone min:1m {
# some_metric_name min;
# }
server {
listen 12371;
metric min KEY=42.999;
}
server {
listen 12372;
metric min KEY=-512;
}
server {
listen 12373;
metric min KEY=1;
}
$ nc 127.0.0.1 12371 </dev/null
$ nc 127.0.0.1 12372 </dev/null
$ nc 127.0.0.1 12373 </dev/null
{
"KEY": -512
}
max#
metric_zone max:1m max;
# Como parte de uma métrica complexa:
#
# metric_complex_zone max:1m {
# some_metric_name max;
# }
server {
listen 12381;
metric max KEY=42.999;
}
server {
listen 12382;
metric max KEY=-512;
}
server {
listen 12383;
metric max KEY=1;
}
$ nc 127.0.0.1 12381 </dev/null
$ nc 127.0.0.1 12382 </dev/null
$ nc 127.0.0.1 12383 </dev/null
{
"KEY": 42.999
}
average exp#
factor=<number> — um coeficiente que
determina o quanto o novo valor influencia a média. Valores inteiros de
0 a 99 são permitidos. O padrão é 90.90, o resultado será 90% do novo valor e
10% da média anterior.metric_zone avg_exp:1m average exp factor=60;
# Como parte de uma métrica complexa:
#
# metric_complex_zone avg_exp:1m {
# some_metric_name average exp factor=60;
# }
server {
listen 12391;
metric avg_exp KEY=100;
}
server {
listen 12392;
metric avg_exp KEY=200;
}
server {
listen 12393;
metric avg_exp KEY=0;
}
server {
listen 12394;
metric avg_exp KEY=8;
}
server {
listen 12395;
metric avg_exp KEY=30;
}
$ nc 127.0.0.1 12391 </dev/null
$ nc 127.0.0.1 12392 </dev/null
$ nc 127.0.0.1 12393 </dev/null
$ nc 127.0.0.1 12394 </dev/null
$ nc 127.0.0.1 12395 </dev/null
{
"KEY": 30.16
}
average mean#
window=<off|time> e count=<number>, definindo o
intervalo de tempo e o tamanho da amostra para cálculo da média,
respectivamente. Padrões: window=off (toda a amostra é usada) e
count=10.window=5s considerará apenas eventos dos
últimos 5 segundos. O parâmetro window não pode ser
0. O parâmetro count=number controla o tamanho da
amostra (valores em cache) para um cálculo de média mais suave.metric_zone avg_mean:1m average mean window=5s count=8;
# Como parte de uma métrica complexa:
#
# metric_complex_zone avg_mean:1m {
# some_metric_name average mean window=5s count=8;
# }
server {
listen 12401;
metric avg_mean KEY=0.1;
}
server {
listen 12402;
metric avg_mean KEY=0.4;
}
server {
listen 12403;
metric avg_mean KEY=10;
}
server {
listen 12404;
metric avg_mean KEY=1;
}
$ nc 127.0.0.1 12401 </dev/null
$ nc 127.0.0.1 12401 </dev/null
$ nc 127.0.0.1 12402 </dev/null
$ nc 127.0.0.1 12403 </dev/null
$ nc 127.0.0.1 12404 </dev/null
$ nc 127.0.0.1 12404 </dev/null
{
"KEY": 2.1
}
{
"KEY": 0
}
histogram#
inf ou +Inf pode ser usado para
capturar todos os valores que excedem o bucket mais alto
especificado.metric_zone hist:1m histogram 0.1 0.2 0.5 1 2 inf;
# Como parte de uma métrica complexa:
#
# metric_complex_zone hist:1m {
# some_metric_name histogram 0.1 0.2 0.5 1 2 inf;
# }
server {
listen 12411;
metric hist KEY=0.25;
}
server {
listen 12412;
metric hist KEY=2;
}
server {
listen 12413;
metric hist KEY=1000;
}
$ nc 127.0.0.1 12411 </dev/null
{
"KEY": {
"0.1": 0,
"0.2": 0,
"0.5": 1,
"1": 1,
"2": 1,
"inf": 1
}
}
$ nc 127.0.0.1 12412 </dev/null
{
"KEY": {
"0.1": 0,
"0.2": 0,
"0.5": 1,
"1": 1,
"2": 2,
"inf": 2
}
}
$ nc 127.0.0.1 12413 </dev/null
{
"KEY": {
"0.1": 0,
"0.2": 0,
"0.5": 1,
"1": 1,
"2": 2,
"inf": 3
}
}
Variáveis Integradas#
$metric_<name>$metric_<name>_key$metric_<name>_value$metric_<name>_value_<metric>$metric_<name>#$metric_<name> pode ser usado para atualizar uma
métrica. O cálculo ocorre quando a variável é definida — por exemplo,
por meio da diretiva set, que é avaliada durante a
fase Pre-access (a mesma etapa que
on=connect), ou de forma programática a partir do módulo
njs, por exemplo em um manipulador
js_access.=value. O
último = separa a chave do valor; sem o sufixo, o valor é
0. A chave e o valor podem conter texto, variáveis, ou
combinações de ambos. Essas são as mesmas regras de análise usadas em
metric.stream {
metric_zone hits:1m count;
# Neste ponto, a variável $metric_hits é adicionada
server {
listen 12345;
metric hits client=1 on=connect;
}
server {
listen 12346;
set $metric_hits client=1;
return "$metric_hits\n";
}
}
12345 e uma conexão à porta
12346:$ nc 127.0.0.1 12345 </dev/null
$ nc 127.0.0.1 12345 </dev/null
$ nc 127.0.0.1 12345 </dev/null
$ nc 127.0.0.1 12346 </dev/null
client=4
$metric_<name> de volta, obtém-se a chave junto com o
valor calculado atual da métrica, na forma key=value — e
não a string literal que foi atribuída. No exemplo acima, a conexão
atribui o valor literal client=1, mas como o modo
count ignora o valor atribuído e simplesmente incrementa a
cada atualização, ler $metric_hits posteriormente retorna
client=4 — o novo total do contador, que já inclui as três
atualizações anteriores feitas pela porta 12345.$metric_<name>_key
passa a ser a chave especificada.$metric_<name>_key e $metric_<name>_value#$metric_<name>_key e $metric_<name>_value
definem a chave e o valor, respectivamente. A atualização da métrica
ocorre quando $metric_<name>_value é definida, desde que a
chave em $metric_<name>_key já tenha sido definida.$metric_<name>_value são unidos usando um separador
", ".stream {
metric_zone level:1m gauge;
# As variáveis $metric_level, $metric_level_key e $metric_level_value são adicionadas aqui.
metric_complex_zone stats:1m {
count count;
min min;
avg average exp;
}
# $metric_stats, $metric_stats_key e $metric_stats_value são adicionadas aqui.
server {
listen 12345;
metric level sensor=10 on=connect;
}
server {
listen 12346;
set $metric_level_key "sensor";
set $metric_level_value 5;
# Ou: set $metric_level sensor=5;
return "Updated with '$metric_level'\nValue='$metric_level_value'\n";
}
server {
listen 12347;
set $metric_stats_key bar;
set $metric_stats_value 9;
# Ou: set $metric_stats bar=9;
return "Updated with '$metric_stats'\nValues='$metric_stats_value'\n";
}
}
12345 (que define o
valor inicial do gauge como 10) seguida de uma conexão à porta
12346 produz:$ nc 127.0.0.1 12345 </dev/null
$ nc 127.0.0.1 12346 </dev/null
Updated with 'sensor=15'
Value='15'
12347 produz:$ nc 127.0.0.1 12347 </dev/null
Updated with 'bar=1, 9, 9'
Values='1, 9, 9'
$metric_<name>_value, o
valor é reconhecido como 0. Se a string for composta por
caracteres que não podem ser convertidos em um número, ela é
reconhecida como 1.$metric_<name>_key
quanto $metric_<name>_value tiverem sido definidas.$metric_<name> passa a ser
igual ao novo par calculado key=value, e não aos valores
literais recém-atribuídos.$metric_<name>_key representa a última chave
especificada por meio de variáveis.$metric_<name>_value representa o último valor
calculado para a chave definida em $metric_<name>_key.$metric_<name>_value_<metric>#$metric_<name>_value_<metric>, onde
<metric> é o nome da submétrica.stream {
metric_complex_zone foo:1m {
count count;
min min;
avg average exp;
}
# Adiciona $metric_foo, $metric_foo_key, $metric_foo_value,
# e $metric_foo_value_count, $metric_foo_value_min, $metric_foo_value_avg.
server {
listen 12345;
set $metric_foo_key bar;
set $metric_foo_value 9;
# Ou: set $metric_foo bar=9;
return "Updated with '$metric_foo'\nValues='$metric_foo_value'\nCount='$metric_foo_value_count'\n";
}
}
12345 produz:$ nc 127.0.0.1 12345 </dev/null
Updated with 'bar=1, 9, 9'
Values='1, 9, 9'
Count='1'
Exemplos Adicionais#
Monitorando Conexões por Protocolo#
metric_zone protocols:1m count;
server {
listen 12345;
listen 12346 udp;
metric protocols $protocol;
}
{
"TCP": 340,
"UDP": 58
}
Distribuição do Tempo de Sessão do Upstream#
metric_zone upstream_time:10m expire=on histogram
0.05 0.1 0.3 0.5 1 2 5 10 inf;
server {
listen 12345;
proxy_pass backend;
metric upstream_time $upstream_addr=$upstream_session_time on=end;
}
{
"discarded": 0,
"metrics": {
"backend1:8080": {
"0.05": 12,
"0.1": 28,
"0.3": 56,
"0.5": 78,
"1": 92,
"2": 97,
"5": 99,
"10": 100,
"inf": 100
}
}
}
Conexões Ativas#
stream {
metric_zone active_connections:2m gauge;
server {
listen 12345;
metric active_connections service_a=1 on=connect;
metric active_connections service_a=-1 on=end;
}
server {
listen 12346;
metric active_connections service_b=1 on=connect;
metric active_connections service_b=-1 on=end;
}
}
http {
server {
listen 8080;
location /connections/ {
allow 127.0.0.1;
deny all;
api /status/stream/metric_zones/active_connections/metrics/;
}
}
}
{
"service_a": 42,
"service_b": 17
}
Suporte ao Prometheus#
http, fazendo referência à zona de métricas stream por meio da
mesma árvore unificada da API /status/.stream {
# Criando a métrica "upload"
metric_complex_zone upload:1m discard_key="other" {
stats histogram 64 256 1024 4096 16384 +Inf;
sum gauge;
count count;
avg_size average exp;
}
upstream backend {
server 127.0.0.1:15001;
}
server {
listen 12345;
# Atualizando a métrica ao final da sessão com o total
# de bytes recebidos do cliente
proxy_pass backend;
metric upload angie=$bytes_received on=end;
}
}
http {
# Descrevendo o template Prometheus para a métrica "upload"
prometheus_template upload_metric {
'stats{le="$1"}' $p8s_value
path=~^/stream/metric_zones/upload/metrics/angie/stats/(.+)$
type=histogram;
'stats_sum' $p8s_value
path=/stream/metric_zones/upload/metrics/angie/sum;
'stats_count' $p8s_value
path=/stream/metric_zones/upload/metrics/angie/count;
'avg_size' $p8s_value
path=/stream/metric_zones/upload/metrics/angie/avg_size;
}
server {
listen 80;
# Destino para coleta de métricas
location /prometheus/upload_metric/ {
prometheus upload_metric;
}
}
}
12345, enviando payloads de
16384, 64448, 64, 1028 e 1028
bytes:$ head -c 16384 /dev/urandom | nc 127.0.0.1 12345
$ head -c 64448 /dev/urandom | nc 127.0.0.1 12345
$ head -c 64 /dev/urandom | nc 127.0.0.1 12345
$ head -c 1028 /dev/urandom | nc 127.0.0.1 12345
$ head -c 1028 /dev/urandom | nc 127.0.0.1 12345
{
"stats": {
"64": 1,
"256": 1,
"1024": 1,
"4096": 3,
"16384": 4,
"+Inf": 5
},
"sum": 82952,
"count": 5,
"avg_size": 1077.9376
}
/prometheus/upload_metric/:# Angie Prometheus template "upload_metric"
# TYPE stats histogram
stats{le="64"} 1
stats{le="256"} 1
stats{le="1024"} 1
stats{le="4096"} 3
stats{le="16384"} 4
stats{le="+Inf"} 5
stats_sum 82952
stats_count 5
avg_size 1077.9376