Percentil 95 no Zabbix: medir tráfego para cobrar trânsito IP

Quase todo contrato de trânsito IP com banda excedente é cobrado pelo percentil 95. A operadora mede o tráfego da sua porta a cada cinco minutos, joga fora os 5% de amostras mais altas do mês e cobra pelo maior valor que sobrou. Se você não mede do mesmo jeito do seu lado, a fatura chega e não há com o que comparar.
Este guia mostra como montar a medição no Zabbix 7.0: coleta com contadores de 64 bits, item calculado com a função percentile para acompanhar o mês, um script curto pela API para fechar o mês do calendário e as armadilhas que fazem o seu número divergir do da operadora. O mesmo método serve para cobrar clientes dedicados com banda excedente.
Resposta rápida
- Colete
ifHCInOctetseifHCOutOctets(64 bits) a cada 5 minutos, com Change per second e Custom multiplier 8 para ter bps. - Guarde pelo menos 35 dias de histórico desses itens.
- Crie um item calculado com
percentile(//chave,30d,95)para acompanhar o percentil 95 dos últimos 30 dias. - Para a fatura, calcule o mês fechado pela API: ordene as amostras, descarte os 5% maiores e pegue o maior valor restante.
- Compare com o contrato: entrada, saída ou o maior dos dois, e o intervalo de coleta da operadora.
O que é o percentil 95 na cobrança de trânsito
O percentil 95 é o valor abaixo do qual ficam 95% das amostras. Na cobrança de banda ele funciona como um perdão de picos: você pode passar do compromisso por algumas horas no mês sem pagar por isso. O que pesa é o tráfego sustentado, aquele que aparece todo dia no horário de pico.
A conta é simples. Cada amostra é a taxa média de cinco minutos, em bits por segundo. Um dia tem 288 amostras, e o mês inteiro vai para uma lista. A lista é ordenada do maior para o menor, as primeiras 5% saem, e o primeiro valor que sobra é o percentil 95. A tabela mostra quanto tempo de pico cada mês perdoa:
| Mês | Amostras de 5 min | Amostras descartadas | Tempo de pico perdoado |
|---|---|---|---|
| 30 dias | 8.640 | 432 | 36 horas |
| 31 dias | 8.928 | 446 | 37 horas e 10 minutos |
| 28 dias | 8.064 | 403 | 33 horas e 35 minutos |
Repare que o descarte é contado em amostras, não em dias. Um pico de duas horas por dia, todos os dias, soma 60 horas no mês e passa do limite de 36 horas. Esse pico entra na conta. Já uma madrugada inteira de atualização de jogos, num único dia, cabe com folga nas 36 horas e some.
Percentil 95, média e máximo
A média do mês fica bem abaixo do percentil 95, porque inclui as madrugadas vazias. O máximo fica acima, porque inclui o maior pico. O percentil 95 fica entre os dois e é o que mais se parece com o horário de pico de um dia comum. Por isso ele é o critério mais usado para trânsito com excedente.
Coleta: contadores de 64 bits a cada 5 minutos
O percentil 95 é tão bom quanto as amostras. Antes de mexer no Zabbix, confirme que o roteador de borda responde os contadores de 64 bits da interface de trânsito. No exemplo, o ifIndex da porta é 10:
snmpget -v2c -c COMUNIDADE 192.0.2.1 1.3.6.1.2.1.31.1.1.1.1.10 snmpget -v2c -c COMUNIDADE 192.0.2.1 1.3.6.1.2.1.31.1.1.1.6.10 snmpget -v2c -c COMUNIDADE 192.0.2.1 1.3.6.1.2.1.31.1.1.1.10.10
A primeira linha devolve o ifName, para garantir que o índice é mesmo a porta certa. As duas seguintes são o ifHCInOctets e o ifHCOutOctets, os contadores de bytes de 64 bits do IF-MIB. Rode duas vezes com alguns segundos de intervalo e confira se os valores sobem.
Por que 64 bits
O contador antigo, ifInOctets, tem 32 bits e volta a zero depois de 4.294.967.296 bytes. A 1 Gbps isso acontece em cerca de 34 segundos, a 10 Gbps em menos de 4. Com coleta a cada 5 minutos, o contador dá várias voltas entre duas leituras e a taxa calculada não tem relação com o tráfego real. O template genérico de rede do Zabbix usa o contador de 32 bits, então confira qual template está aplicado no roteador. O template Huawei VRP, por exemplo, já usa o de 64 bits.
Os itens de tráfego
Os templates oficiais criam esses itens por descoberta. Se você quer um item dedicado ao trânsito, com intervalo e histórico próprios, a configuração fica assim:
Item 1 (tipo SNMP agent)
Nome: Trânsito A: bits recebidos
Chave: net.if.in[ifHCInOctets.10]
Tipo: Numérico (sem sinal)
SNMP OID: get[1.3.6.1.2.1.31.1.1.1.6.10]
Intervalo: 5m
Unidade: bps
Histórico: 90d
Pré-processamento:
1. Change per second
2. Custom multiplier: 8
Item 2 (tipo SNMP agent)
Nome: Trânsito A: bits enviados
Chave: net.if.out[ifHCOutOctets.10]
SNMP OID: get[1.3.6.1.2.1.31.1.1.1.10.10]
(demais campos iguais ao item 1)O get[] no campo SNMP OID é a forma do Zabbix 7.0 para ler um OID. O Change per second transforma o contador em bytes por segundo, e o Custom multiplier 8 converte bytes em bits. É o mesmo par de passos do template oficial. A chave segue o padrão dos templates oficiais, o que deixa gráficos e dashboards reaproveitáveis. Se a OLT ou os switches já estão no Zabbix, o processo de SNMP é o mesmo do guia para monitorar OLT Huawei no Zabbix via SNMP.
O intervalo de 5 minutos não é detalhe. Os templates oficiais usam 3 minutos, e amostras mais curtas suavizam menos os picos. O percentil 95 de amostras de 3 minutos tende a sair um pouco acima do de 5 minutos. Use o mesmo intervalo que a operadora usa, que normalmente está no contrato ou no portal do cliente.
Item calculado com a função percentile
A função percentile é uma função de histórico do Zabbix. A sintaxe é percentile(/host/chave,período,percentual), e o percentual aceita valores de 0 a 100. Com ela, três itens calculados resolvem o acompanhamento diário:
Item 3 (tipo Calculated) Nome: Trânsito A: percentil 95 de entrada, 30 dias Chave: transito.a.p95.in Fórmula: percentile(//net.if.in[ifHCInOctets.10],30d,95) Intervalo: 1h Unidade: bps Item 4 (tipo Calculated) Nome: Trânsito A: percentil 95 de saída, 30 dias Chave: transito.a.p95.out Fórmula: percentile(//net.if.out[ifHCOutOctets.10],30d,95) Intervalo: 1h Unidade: bps Item 5 (tipo Calculated) Nome: Trânsito A: percentil 95 cobrado Chave: transito.a.p95.max Fórmula: max(last(//transito.a.p95.in),last(//transito.a.p95.out)) Intervalo: 1h Unidade: bps
Linha a linha: o item 3 calcula o percentil 95 da entrada nos últimos 30 dias, o item 4 faz o mesmo para a saída, e o item 5 pega o maior dos dois com a função matemática max. As duas barras no começo da chave, //, dizem que o item está no mesmo host. Intervalo de 1 hora basta: o valor anda devagar e cada cálculo lê milhares de amostras do banco.
Por que 30 dias e não o mês do calendário
O Zabbix tem deslocamento de tempo com períodos absolutos, como now/d para o dia e now/w para a semana. O mês, M, só vale para funções de trend, e o percentile é função de histórico. Na prática, o item calculado acompanha uma janela móvel de 30 dias. Para a semana fechada, a sintaxe funciona:
percentile(//net.if.in[ifHCInOctets.10],1w:now/w,95)
A janela móvel serve para o dia a dia: mostra se o mês caminha para estourar o compromisso. Para conferir a fatura, que fecha no primeiro dia do mês, use o script da próxima seção.
Alerta antes da fatura
Com o item 5 pronto, um trigger avisa quando a janela de 30 dias passa do compromisso contratado:
Macro do host: {$TRANSITO.COMMIT} = 1000000000
Trigger
Nome: Trânsito A: percentil 95 acima do compromisso
Expressão: last(/borda-01/transito.a.p95.max)>{$TRANSITO.COMMIT}
Severidade: WarningUm cuidado com a macro: escreva o valor em números. Os sufixos K, M e G do Zabbix são de memória, em base 1024. 1G vira 1.073.741.824, quase 74 Mbps acima de 1 Gbps, e o alerta atrasa.
Linha de percentil no gráfico
Para quem prefere ver, o gráfico clássico do Zabbix tem as opções Percentile line (left) e Percentile line (right). Marque 95 e o gráfico desenha a linha do percentil do período exibido. Serve para apresentação, mas o número da linha depende do período que está na tela.
Fechando o mês pela API
O script abaixo busca o histórico do mês anterior pela API, calcula o percentil 95 de entrada e de saída e mostra o valor cobrado. Usa só a biblioteca padrão do Python e um token de API do Zabbix:
#!/usr/bin/env python3
"""Percentil 95 do mês anterior a partir do histórico do Zabbix."""
import datetime as dt
import json
import os
import sys
import urllib.request
URL = 'https://192.0.2.5/zabbix/api_jsonrpc.php'
TOKEN = os.environ.get('ZBX_TOKEN', '')
POR_DIA = 288 # amostras de 5 minutos
def api(method, params):
body = json.dumps({'jsonrpc': '2.0', 'method': method,
'params': params, 'id': 1}).encode()
req = urllib.request.Request(URL, body, {
'Content-Type': 'application/json-rpc',
'Authorization': 'Bearer ' + TOKEN})
with urllib.request.urlopen(req, timeout=120) as r:
resp = json.load(r)
if 'error' in resp:
raise SystemExit(resp['error'])
return resp['result']
def mes_anterior(hoje):
fim = dt.datetime(hoje.year, hoje.month, 1)
ini = (fim - dt.timedelta(days=1)).replace(day=1)
return ini, fim
def serie(itemid, ini, fim):
rows = api('history.get', {
'output': ['clock', 'value'], 'history': 3,
'itemids': itemid, 'sortfield': 'clock',
'time_from': int(ini.timestamp()),
'time_till': int(fim.timestamp()) - 1})
return [int(r['value']) for r in rows]
def p95(valores):
v = sorted(valores, reverse=True)
return v[int(len(v) * 0.05)] # descarta os 5% maiores
def main(item_in, item_out):
ini, fim = mes_anterior(dt.date.today())
esperado = (fim - ini).days * POR_DIA
res = {}
for nome, item in (('entrada', item_in), ('saida', item_out)):
s = serie(item, ini, fim)
if len(s) < esperado * 0.98:
print(f'aviso: {nome} com {len(s)} de {esperado} amostras')
res[nome] = p95(s)
print(f'{nome}: {res[nome] / 1e6:.1f} Mbps')
print(f'cobrado: {max(res.values()) / 1e6:.1f} Mbps '
f'({ini:%Y-%m-%d} a {fim:%Y-%m-%d})')
if __name__ == '__main__':
main(sys.argv[1], sys.argv[2])O que cada parte faz:
api()manda a chamada JSON-RPC para oapi_jsonrpc.phpcom o token no cabeçalhoAuthorization: Bearer.mes_anterior()devolve o primeiro dia do mês passado e o primeiro dia do mês atual, à meia-noite. Rode o script numa máquina com o fuso de São Paulo, ou o mês começa três horas antes.serie()chama ohistory.getcomhistory: 3, o tipo numérico sem sinal dos itens de tráfego, entre o início do mês e um segundo antes do fim.p95()ordena do maior para o menor e devolve a amostra logo depois dos 5% descartados.- O aviso de amostras aparece quando falta mais de 2% da coleta esperada. Nesse caso o seu número perde força numa contestação.
Para rodar, passe os IDs dos itens de entrada e saída, que aparecem na URL do item no frontend:
export ZBX_TOKEN='seu-token-de-api' python3 p95_mensal.py 45810 45811
entrada: 1380.0 Mbps saida: 412.6 Mbps cobrado: 1380.0 Mbps (2026-09-01 a 2026-10-01)
Um exemplo com números
Contrato de 1 Gbps de compromisso, excedente cobrado por Mbps. O percentil 95 de entrada ficou em 1.380 Mbps e o de saída em 412,6 Mbps. Um provedor de acesso recebe muito mais do que envia, então a entrada manda. Se o contrato cobra pelo maior dos dois, o excedente é de 380 Mbps. Com um preço fictício de R$ 1,50 por Mbps, são R$ 570 a mais na fatura. O pico do mês, que bateu 2,1 Gbps numa noite de jogo, não entrou na conta.
Como fica no gráfico
No desenho, cada ponto é uma amostra de 5 minutos. Tudo acima da linha dourada foi descartado, e a linha é o valor cobrado:

Armadilhas que distorcem o percentil 95
Falha de coleta
Quando o Zabbix fica sem coletar, a amostra seguinte usa a diferença do contador sobre um intervalo maior, e o resultado é a média do buraco inteiro. Picos somem dentro dessa média. E, com menos amostras, o número de amostras descartadas também cai. Coleta falhando no horário de pico puxa o seu percentil para baixo, e o da operadora continua certo.
Reinício do roteador ou zeragem do contador
Se o contador volta para trás, o Change per second descarta aquela diferença e espera a próxima leitura. Isso evita um valor negativo absurdo, mas também deixa um buraco. Anote reinícios da borda no mês, porque eles explicam diferenças pequenas.
Entrada, saída e o lado de quem mede
A operadora mede na porta dela. O que é entrada para você é saída para ela. Confira no contrato qual sentido é cobrado, ou se é o maior dos dois, que é o arranjo mais comum. Na cobrança de clientes dedicados vale o mesmo raciocínio ao contrário: o download do cliente sai pela sua interface.
Vários links com a mesma operadora
Se a operadora soma dois links ou uma agregação de portas, o percentil 95 é calculado sobre a soma das amostras de cada intervalo. Somar o percentil de cada link dá um valor maior que o real, porque os picos dos dois links raramente acontecem no mesmo minuto. No script, some as duas séries amostra a amostra antes de chamar p95().
Tráfego que poderia ter saído por outro caminho
O percentil 95 alto às vezes é tráfego que poderia sair pelo PTT ou por outro trânsito. Ajustar a política de saída com local-preference e communities é assunto do guia de communities BGP no Huawei. Se BGP ainda é novidade, comece por o que é BGP e como ele funciona.
Cobrando clientes dedicados pelo mesmo critério
O mesmo conjunto de itens serve para o lado de venda. Para cada cliente com link dedicado e banda excedente, crie os itens de tráfego na interface ou subinterface dele, o item calculado de 30 dias e rode o script no fechamento. Usar o mesmo método da operadora tem uma vantagem: quando o cliente contesta, você explica a conta com a mesma régua que usa para conferir a sua fatura.
- Coloque no contrato o intervalo de amostragem, o percentual e o sentido medido.
- Guarde o arquivo de saída do script de cada mês, com a contagem de amostras.
- Mostre ao cliente o gráfico com a linha de percentil do mês fechado.
Perguntas frequentes
O que é o percentil 95 de tráfego?
É o valor de tráfego abaixo do qual ficam 95% das amostras de 5 minutos do mês. Os 5% mais altos, cerca de 36 horas num mês de 30 dias, são descartados antes da cobrança.
O Zabbix calcula o percentil 95 sozinho?
Sim. A função percentile(//chave,30d,95) num item calculado devolve o percentil 95 dos últimos 30 dias. Para o mês do calendário, calcule pela API, porque o deslocamento em meses só vale para funções de trend.
Posso usar ifInOctets para medir o percentil 95?
Não em links de 1 Gbps ou mais. O contador de 32 bits volta a zero em cerca de 34 segundos a 1 Gbps, e com coleta a cada 5 minutos o resultado fica errado. Use ifHCInOctets e ifHCOutOctets.
Por que o meu percentil 95 não bate com a fatura?
As causas mais comuns são intervalo de coleta diferente, falha de coleta no horário de pico, sentido medido trocado e soma de links feita do jeito errado. Confira a contagem de amostras do mês antes de contestar.
A cobrança usa entrada ou saída?
Depende do contrato. O arranjo mais comum é cobrar pelo maior dos dois. Provedor de acesso quase sempre tem a entrada maior, então é ela que define a fatura.
Conclusão
Medir o percentil 95 no Zabbix dá trabalho uma vez e economiza discussão todo mês. Com contadores de 64 bits, coleta de 5 minutos e histórico guardado, o item calculado mostra a tendência do mês e o script fecha a conta com o mesmo critério da operadora. Quando os números divergirem, a contagem de amostras e o sentido medido explicam quase tudo.
Leitura recomendada: Como monitorar 95th percentile, do Brasil Peering Forum (CC BY-NC 4.0).

[…] Esse painel ajuda a enxergar a tendência, mas não substitui a conta de cobrança. Para conferir a fatura de trânsito, use o método do guia de percentil 95 no Zabbix. […]