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.

Nota

Ao recarregar a configuração, uma zona criada por metric_zone ou metric_complex_zone mantém seus valores acumulados apenas enquanto seu layout de armazenamento não mudar. A zona começa vazia se o tamanho da zona, o número de métricas ou um modo diferirem da configuração anterior, se o count de average mean mudar, se o window de average mean for alternado para ou de off, ou se o número de buckets de histogram mudar; o motivo é então registrado no log de erro no nível info. Outros parâmetros, como o factor de average exp, o intervalo window de average mean ou os limites dos buckets de histogram, podem ser alterados sem perder os valores acumulados.

Ao compilar a partir do código-fonte, o módulo é compilado por padrão junto com o módulo Stream (habilitado com --with-stream); ele pode ser desabilitado com a opção de compilação --without-stream_metric_module.

Em pacotes e imagens de nossos repositórios, o módulo está incluído na compilação.

Exemplo de configuração#

Contando conexões por endereço de cliente:

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/;
        }
    }
}

Se uma conexão for estabelecida na porta 12345:

$ nc 127.0.0.1 12345 </dev/null

A métrica connections é atualizada em tempo real:

{
    "stream": {
       "metric_zones": {
           "connections": {
               "discarded": 0,
               "metrics": {
                   "127.0.0.1": 1
               }
           }
       }
    }
}

Diretivas#

metric#

Sintaxe

metric name key=value [on=connect | preread | end];

Padrão

—

Contexto

stream, server

Calcula o valor da métrica para a zona de memória compartilhada especificada name.

Parâmetros:

  • key — uma string arbitrária (frequentemente uma variável) usada para agrupar valores. O comprimento máximo é de 255 bytes; chaves mais longas são truncadas. Na saída da API, o Angie anexa ... 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;

  • value — um número (pode ser uma variável) processado pelo modo selecionado. Se omitido, o padrão é 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:

    • Se on=connect, o cálculo ocorre durante a fase Pre-access, antes que qualquer dado seja lido do cliente;

    • Se 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;

    • Se on=end (padrão), o cálculo ocorre durante a fase Log, quando a sessão termina.

Várias diretivas metric podem ser especificadas no mesmo nível de configuração. Essas diretivas são herdadas do nível de configuração anterior se e somente se não houver diretivas metric definidas no nível atual. Portanto, um único metric em um bloco server cancela todas as regras herdadas de stream, em todos os três estágios on e não apenas no seu próprio.

Exemplo de uso:

metric sessions $remote_addr=$session_time on=end;

Nota

Métricas com uma chave vazia ou com um par key=value inválido são ignoradas. Um value omitido é tratado como 0:

metric foo $bar;  # Equivalente a $bar=0

Isso é útil, por exemplo, para o modo count, que ignora valores numéricos e simplesmente reage ao fato de que uma métrica foi atualizada.

Nota

Lembre-se de que as variáveis são avaliadas em fases diferentes. Por exemplo, é impossível usar $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#

Sintaxe

metric_complex_zone name:size [expire=on | off] [discard_key=name] { ... }

Padrão

—

Contexto

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:

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;
}

Na árvore da API, tal modelo de métrica complexa se parece com o seguinte:

{
    "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#

Sintaxe

metric_zone name:size [expire=on | off] [discard_key=name] mode [parameters];

Padrão

—

Contexto

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 /status/stream/metric_zones/. O tamanho da zona deve ser de pelo menos oito páginas de memória do sistema.

Parâmetros:

  • expire=<on|off> — comportamento quando a zona está cheia:

    • Se on, as métricas mais antigas (por tempo de atualização) são descartadas para liberar memória para as novas;

    • Se off (padrão) — as novas métricas recebidas são descartadas, preservando as entradas existentes.

  • discard_key=<name> — define uma métrica com a chave name 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);

  • parameters — configurações adicionais para o modo selecionado (por exemplo, factor para average exp).

Exemplo de uso:

metric_zone session_time:1m max;

Na árvore da API, o modelo de zona de memória compartilhada se parece com o seguinte:

{
    "discarded": 0,
    "metrics": {
        "key1": 123,
        "key2": 10.5
    }
}

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.

Modos de operação#

Lista de modos de operação de métricas disponíveis:

  • 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).

Os exemplos abaixo usam o endpoint /status/ do exemplo de configuração. Cada resultado está disponível em /status/stream/metric_zones/<zone>/metrics/.

count#

Cada atualização da métrica incrementa o contador em 1, independentemente do valor fornecido.

Valor padrão — 0.

Exemplos:

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;
}

Atualizando a métrica:

$ 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

Valor esperado da métrica na API:

{
    "KEY": 4
}

gauge#

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 0 não altera o contador.

Valor padrão — 0.

Exemplos:

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;
}

Atualizando a métrica:

$ nc 127.0.0.1 12351 </dev/null

Valor esperado da métrica na API:

{
    "KEY": 0
}

Atualizações adicionais:

$ nc 127.0.0.1 12352 </dev/null
$ nc 127.0.0.1 12353 </dev/null
$ nc 127.0.0.1 12354 </dev/null

Valor esperado da métrica na API:

{
    "KEY": 8
}

last#

Armazena o último valor recebido sem qualquer agregação. Se value for omitido, 0 é usado.

Exemplos:

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;
}

Atualizando a métrica:

$ nc 127.0.0.1 12361 </dev/null

Valor esperado da métrica na API:

{
    "KEY": 0
}

Atualizações adicionais:

$ nc 127.0.0.1 12362 </dev/null
$ nc 127.0.0.1 12363 </dev/null
$ nc 127.0.0.1 12364 </dev/null

Valor esperado da métrica na API:

{
   "KEY": -3.5
}

min#

Salva o mínimo de dois valores — o valor atualmente armazenado e o novo.

Exemplos:

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;
}

Atualizando a métrica:

$ nc 127.0.0.1 12371 </dev/null
$ nc 127.0.0.1 12372 </dev/null
$ nc 127.0.0.1 12373 </dev/null

Valor esperado da métrica na API:

{
    "KEY": -512
}

max#

Salva o máximo de dois valores — o valor atualmente armazenado e o novo.

Exemplos:

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;
}

Atualizando a métrica:

$ nc 127.0.0.1 12381 </dev/null
$ nc 127.0.0.1 12382 </dev/null
$ nc 127.0.0.1 12383 </dev/null

Valor esperado da métrica na API:

{
    "KEY": 42.999
}

average exp#

Calcula o valor médio usando o algoritmo de suavização exponencial.

Aceita um parâmetro opcional 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.

Quanto maior o coeficiente, mais peso os novos valores têm. Se você especificar 90, o resultado será 90% do novo valor e 10% da média anterior.

Exemplos:

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;
}

Atualizando a métrica:

$ 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

Valor esperado da métrica na API:

{
    "KEY": 30.16
}

average mean#

Calcula a média aritmética. Aceita parâmetros opcionais 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.

Nota

Por exemplo, 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.

Exemplos:

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;
}

Atualizando a métrica:

$ 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

Valor esperado da métrica na API:

{
    "KEY": 2.1
}

Se você aguardar 5 segundos desde a última atualização, o valor esperado será:

{
    "KEY": 0
}

histogram#

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 inf ou +Inf pode ser usado para capturar todos os valores que excedem o bucket mais alto especificado.

Exemplos:

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;
}

Atualizando a métrica:

$ nc 127.0.0.1 12411 </dev/null

Valor esperado da métrica na API:

{
    "KEY": {
        "0.1": 0,
        "0.2": 0,
        "0.5": 1,
        "1": 1,
        "2": 1,
        "inf": 1
    }
}

Atualizações adicionais:

$ nc 127.0.0.1 12412 </dev/null

Valor esperado da métrica na API:

{
    "KEY": {
        "0.1": 0,
        "0.2": 0,
        "0.5": 1,
        "1": 1,
        "2": 2,
        "inf": 2
    }
}

Atualização adicional:

$ nc 127.0.0.1 12413 </dev/null

Valor esperado da métrica na API:

{
    "KEY": {
       "0.1": 0,
       "0.2": 0,
       "0.5": 1,
       "1": 1,
       "2": 2,
       "inf": 3
    }
}

Variáveis integradas#

Variáveis são criadas para cada métrica:

  • $metric_<name>

  • $metric_<name>_key

  • $metric_<name>_value

Para métricas complexas, uma variável adicional é adicionada:

  • $metric_<name>_value_<metric>

$metric_<name>#

De forma semelhante à diretiva metric, o setter da variável $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 Stream JS, por exemplo em um manipulador js_access.

O setter aceita uma chave com um sufixo opcional =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.

Exemplo de uso:

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";
    }
}

Após três conexões à porta 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

Nota

Ao ler $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.

Além disso, o valor armazenado na variável $metric_<name>_key passa a ser a chave especificada.

$metric_<name>_key e $metric_<name>_value#

As variáveis $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.

Nota

Para métricas complexas, os valores das submétricas na variável $metric_<name>_value são unidos usando um separador ", ".

Exemplo de uso:

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";
    }
}

Com esta configuração, uma conexão à porta 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'

Uma conexão à porta 12347 produz:

$ nc 127.0.0.1 12347 </dev/null
Updated with 'bar=1, 9, 9'
Values='1, 9, 9'

Nota

Se uma string vazia for atribuída a $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.

O cálculo ocorre somente depois que tanto $metric_<name>_key quanto $metric_<name>_value tiverem sido definidas.

Nesse caso, o valor armazenado em $metric_<name> passa a ser igual ao novo par calculado key=value, e não aos valores literais recém-atribuídos.

O valor em $metric_<name>_key representa a última chave especificada por meio de variáveis.

O valor em $metric_<name>_value representa o último valor calculado para a chave definida em $metric_<name>_key.

$metric_<name>_value_<metric>#

Para métricas complexas, o valor de uma submétrica específica pode ser obtido usando a variável $metric_<name>_value_<metric>, onde <metric> é o nome da submétrica.

Exemplo de uso:

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";
    }
}

Com esta configuração, uma conexão à porta 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;
}

Resposta:

{
    "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;
}

Resposta:

{
    "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/;
        }
    }
}

Resposta:

{
    "service_a": 42,
    "service_b": 17
}

Suporte ao Prometheus#

O Angie inclui um módulo Prometheus 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 http, fazendo referência à zona de métricas stream por meio da mesma árvore unificada da API /status/.

Como exemplo de integração, considere a seguinte configuração:

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;
        }
    }
}

Após cinco conexões à porta 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

Os valores da métrica serão:

{
    "stats": {
        "64": 1,
        "256": 1,
        "1024": 1,
        "4096": 3,
        "16384": 4,
        "+Inf": 5
    },

    "sum": 82952,
    "count": 5,
    "avg_size": 1077.9376
}

No formato Prometheus, a métrica está disponível em /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