PromQL - Lenguaje de Consulta
https://prometheus.io/docs/prometheus/latest/configuration/recording_rules/
Lectura adicional en el libro PromQL
Prometheus proporciona un lenguaje de consulta funcional llamado PromQL (Prometheus Query Language) que permite al usuario seleccionar y agregar datos de series temporales en tiempo real. El resultado de una expresión puede mostrarse como un gráfico, visualizarse como datos tabulares en el navegador de expresiones de Prometheus o consumirse por sistemas externos a través de la API HTTP.
¿Por qué es necesario saber esto?
¡Porque lo usarás en Grafana!
Consultas
Devuelve todas las series temporales de la métrica.
node_memory_MemFree_bytes
Devuelve todas las series temporales con la métrica http_requests_total y las etiquetas job y handler proporcionadas.
node_memory_MemFree_bytes{instance="localhost:9100", job="david-pc"}
Devuelve todo un rango de tiempo (en este caso 5 minutos hasta el momento de la consulta) para el mismo vector, convirtiéndolo en un vector de rango.
node_memory_MemFree_bytes{instance="localhost:9100", job="david-pc"}[5m]
El tiempo puede definirse en:
- ms milisegundos
- s segundos
- m minutos
- h horas
- d días - asumiendo que un día siempre tiene 24h
- w semanas - asumiendo que una semana siempre tiene 7d
- y años - asumiendo que un año siempre tiene 365d
Ten en cuenta que una expresión que resulta en un vector de rango no puede representarse gráficamente directamente, pero puede visualizarse en la vista tabular ("Consola") del navegador de expresiones.
Usando expresiones regulares, puedes seleccionar series temporales solo para trabajos cuyo nombre coincida con un determinado patrón, en este caso, todos los trabajos que terminan con pc:
node_cpu_scaling_frequency_hertz{job=~".*pc"}
- = selecciona etiquetas que sean exactamente iguales a la cadena proporcionada.
- != selecciona etiquetas que no sean iguales a la cadena proporcionada.
- =~ selecciona etiquetas que coincidan con la expresión regular de la cadena proporcionada. Prácticamente vas a usar este.
- !~ selecciona etiquetas que no coincidan con la expresión regular de la cadena proporcionada.
Todas las expresiones regulares en Prometheus usan la sintaxis RE2. Para aprender regex recomiendo el sitio https://regexlearn.com/
Para seleccionar todos los códigos de estado HTTP excepto los 4xx, puedes ejecutar:
prometheus_http_requests_total{code!~"4.."}
Operadores
Operadores binarios aritméticos
- + (Suma)
- - (Resta)
- * (Multiplicación)
- / (División)
- % (Módulo)
- ^ (Potencia/Exponenciación)
Los operadores aritméticos binarios están definidos entre pares de valores escalar/escalar, vector/escalar y vector/vector.
Entre dos escalares, el comportamiento es obvio: evalúan a otro escalar que es el resultado del operador aplicado a los dos operandos escalares.
Entre un vector instantáneo y un escalar, el operador se aplica al valor de cada muestra de datos en el vector. Por ejemplo, si un vector instantáneo de series temporales se multiplica por 2, el resultado es otro vector en el que cada valor de muestra del vector original se multiplica por 2. El nombre de la métrica se descarta.
Entre dos vectores instantáneos, un operador aritmético binario se aplica a cada entrada en el vector del lado izquierdo y su elemento correspondiente en el vector del lado derecho. El resultado se propaga en el vector de resultados con las etiquetas de agrupación convirtiéndose en el conjunto de etiquetas de salida. El nombre de la métrica se descarta. Las entradas para las que no se puede encontrar ninguna entrada correspondiente en el vector de la derecha no forman parte del resultado.
Operadores binarios de comparación
- == igual
- != no igual
- > mayor que
- < menor que
- >= mayor o igual
- <= menor o igual
Los operadores de comparación están definidos entre pares de valores escalar/escalar, vector/escalar y vector/vector. Por defecto, filtran, pero su comportamiento puede modificarse proporcionando un bool (booleano) después del operador, que devolverá 0 o 1 para el valor en lugar de filtrar.
Entre dos escalares, el modificador bool debe proporcionarse y estos operadores resultan en otro escalar que es 0 (false) o 1 (true), dependiendo del resultado de la comparación.
Entre un vector instantáneo y un escalar, estos operadores se aplican al valor de cada muestra de datos en el vector y los elementos vectoriales entre los cuales el resultado de la comparación es false se descartan del vector resultante. Si se proporciona el modificador bool, los elementos del vector que serían descartados tendrán el valor 0 y los elementos del vector que serían mantenidos tendrán el valor 1. El nombre de la métrica se descartará si se proporciona el modificador bool.
Entre dos vectores instantáneos, estos operadores se comportan como un filtro por defecto, aplicado a las entradas correspondientes. Los elementos de vector para los cuales la expresión no es verdadera o que no encuentran una coincidencia en el otro lado de la expresión se descartan del resultado, mientras que los otros se propagan en un vector de resultado con las etiquetas de agrupación convirtiéndose en el conjunto de etiquetas de salida. Si se proporciona el modificador bool, los elementos del vector que serían descartados tendrán el valor 0 y los elementos del vector que serían mantenidos tendrán el valor 1, con las etiquetas de agrupación convirtiéndose nuevamente en el conjunto de etiquetas de salida. El nombre de la métrica se descartará si se proporciona el modificador bool.
Operadores binarios lógicos/de conjuntos
Estos operadores binarios lógicos/de conjuntos están definidos solo entre vectores instantáneos:
- and intersección
- or unión
- unless complemento
vector1 and vector2 resulta en un vector que consiste en los elementos de vector1 para los cuales existen elementos en vector2 con conjuntos de etiquetas exactamente coincidentes. Otros elementos se descartan. El nombre y los valores de la métrica se transfieren del vector del lado izquierdo.
vector1 or vector2 resulta en un vector que contiene todos los elementos originales (conjuntos de etiquetas + valores) de vector1 y, adicionalmente, todos los elementos de vector2 que no poseen conjuntos de etiquetas correspondientes en vector1.
vector1 unless vector2 resulta en un vector que consiste en los elementos de vector1 para los cuales no hay elementos en vector2 con conjuntos de etiquetas exactamente coincidentes. Todos los elementos coincidentes en ambos vectores se descartan.
Precedencia del operador binario
La siguiente lista muestra la precedencia de operadores binarios en Prometheus, del mayor al menor.
- ^
- *, /, %, atan2
- +, -
- ==, !=, <=, <, >=, >
- and, unless
- or
Los operadores en el mismo nivel de precedencia son asociativos a la izquierda. Por ejemplo, 2 * 3 % 2 es equivalente a (2 * 3) % 2. Sin embargo ^ es asociativo a la derecha, así que 2 ^ 3 ^ 2 es equivalente a 2 ^ (3 ^ 2).
Correspondencia de vectores
Las operaciones entre vectores intentan encontrar un elemento correspondiente en el vector del lado derecho para cada entrada en el lado izquierdo. Existen dos tipos básicos de comportamiento de correspondencia: uno a uno y muchos a uno/uno a muchos.
Palabras clave de correspondencia de vectores
Estas palabras clave de correspondencia de vectores permiten la correspondencia entre series con diferentes conjuntos de etiquetas, proporcionando:
- on
- ignoring
Las listas de etiquetas proporcionadas a las palabras clave de correspondencia determinarán cómo se combinan los vectores. Se pueden encontrar ejemplos en Correspondencias de vectores uno a uno y en Correspondencias de vectores muchos a uno y uno a muchos.
Modificadores de grupo
Estos modificadores de grupo permiten la correspondencia de vectores muchos a uno/uno a muchos:
- group_left
- group_right
Las listas de etiquetas pueden proporcionarse al modificador de grupo que contiene etiquetas del lado "uno" a incluirse en las métricas de resultado.
La correspondencia muchos a uno y uno a muchos son casos de uso avanzados que deben considerarse cuidadosamente. Frecuentemente, el uso adecuado de ignoring(<labels>) proporciona el resultado deseado.
Los modificadores de agrupación solo pueden usarse para comparación y aritmética. Las operaciones como and, unless y or operan corresponden a todas las entradas posibles en el vector correcto por defecto.
Correspondencias vectoriales uno a uno
Uno a uno localiza un par exclusivo de entradas de cada lado de la operación. En el caso predeterminado, esta es una operación siguiendo el formato vector1 <operator> vector2. Dos entradas corresponden si tienen exactamente el mismo conjunto de etiquetas y valores correspondientes. La palabra clave ignoring permite ignorar ciertas etiquetas durante la correspondencia, mientras que la palabra clave on permite reducir el conjunto de etiquetas consideradas a una lista proporcionada:
method_code:http_errors:rate5m{code="500"} / ignoring(code) method:http_requests:rate5m
Esto devuelve un vector de resultado que contiene la fracción de solicitudes HTTP con código de estado de 500 para cada método, medido en los últimos 5 minutos. Sin ignoring(code), no habría correspondencia, ya que las métricas no comparten el mismo conjunto de etiquetas. Las entradas con métodos put y del no tienen correspondencia y no aparecerán en el resultado:
{method="get"} 0.04 // 24 / 600
{method="post"} 0.05 // 6 / 120
Correspondencias vectoriales muchos a uno y uno a muchos
Las correspondencias muchos a uno y uno a muchos se refieren al caso en que cada elemento del vector en el lado "uno" puede corresponder a varios elementos en el lado "muchos". Esto debe solicitarse explícitamente usando los modificadores group_left o group_right, donde left/right determina qué vector tiene la mayor cardinalidad.
<vector expr> <bin-op> ignoring(<label list>) group_left(<label list>) <vector expr>
<vector expr> <bin-op> ignoring(<label list>) group_right(<label list>) <vector expr>
<vector expr> <bin-op> on(<label list>) group_left(<label list>) <vector expr>
<vector expr> <bin-op> on(<label list>) group_right(<label list>) <vector expr>
La lista de etiquetas proporcionada con el modificador de grupo contiene etiquetas adicionales del lado "uno" a incluirse en las métricas de resultado. Para on, una etiqueta solo puede aparecer en una de las listas. Cada serie temporal del vector de resultado debe ser identificable exclusivamente.
Consulta de ejemplo:
method_code:http_errors:rate5m / ignoring(code) group_left method:http_requests:rate5m
En este caso, el vector izquierdo contiene más de una entrada por valor de etiqueta method. Así, lo indicamos usando group_left. Los elementos del lado derecho ahora corresponden a varios elementos con la misma etiqueta method a la izquierda:
{method="get", code="500"} 0.04 // 24 / 600
{method="get", code="404"} 0.05 // 30 / 600
{method="post", code="500"} 0.05 // 6 / 120
{method="post", code="404"} 0.175 // 21 / 120
Operadores de agregación
Prometheus soporta los siguientes operadores de agregación integrados que pueden usarse para agregar los elementos de un único vector instantáneo, resultando en un nuevo vector de menos elementos con valores agregados:
- sum (calcula la suma sobre las dimensiones)
- min (selecciona el mínimo sobre las dimensiones)
- max (selecciona el máximo sobre las dimensiones)
- avg (calcula el promedio sobre las dimensiones)
- group (todos los valores en el vector resultante son 1)
- stddev (calcula la desviación estándar de la población sobre las dimensiones)
- stdvar (calcula la varianza estándar de la población sobre las dimensiones)
- count (cuenta el número de elementos en el vector)
- count_values (cuenta el número de elementos con el mismo valor)
- bottomk (k elementos más pequeños por valor de muestra)
- topk (k elementos más grandes por valor de muestra)
- quantile (calcula el cuantil φ (0
≤φ≤1) sobre las dimensiones)
Estos operadores pueden usarse para agregar todas las dimensiones de la etiqueta o preservar dimensiones distintas incluyendo una cláusula without o by. Estas cláusulas pueden usarse antes o después de la expresión.
<aggr-op> [without|by (<label list>)] ([parameter,] <vector expression>)
o
<aggr-op>([parameter,] <vector expression>) [without|by (<label list>)]
label list es una lista de etiquetas sin comillas que pueden incluir una coma final, es decir, tanto (label1, label2) como (label1, label2,) son sintaxis válidas.
without elimina las etiquetas listadas del vector de resultado, mientras que todas las otras etiquetas se preservan en la salida. by hace lo opuesto y descarta etiquetas que no están listadas en la cláusula by, incluso si sus valores de etiqueta son idénticos entre todos los elementos del vector.
parameter solo es necesario para count_values, quantile, topk y bottomk.
count_values genera una serie temporal por valor de muestra exclusivo. Cada serie tiene una etiqueta adicional. El nombre de esa etiqueta es proporcionado por el parámetro de agregación y el valor de la etiqueta es el valor de muestra exclusivo. El valor de cada serie temporal es el número de veces que el valor de la muestra estuvo presente.
topk y bottomk son diferentes de otros agregadores porque un subconjunto de las muestras de entrada, incluyendo las etiquetas originales, se devuelve en el vector de resultado. by y without solo se usan para agrupar el vector de entrada.
quantile calcula el cuantil φ, el valor clasificado en el número φ*N entre los N valores métricos de las dimensiones agregadas. φ se proporciona como el parámetro de agregación. Por ejemplo, quantile(0.5, ...) calcula la mediana, quantile(0.95, ...) el percentil 95. Para φ = NaN, se devuelve NaN. Para φ < 0, se devuelve -Inf. Para φ > 1, se devuelve +Inf.
Ejemplo:
Si la métrica http_requests_total tuviera series temporales que se distribuyen por etiquetas application, instance y group, podríamos calcular el número total de solicitudes HTTP vistas por aplicación y grupo en todas las instancias mediante:
sum without (instance) (http_requests_total)
Lo que equivale a:
sum by (application, group) (http_requests_total)
Si estamos interesados solo en el total de solicitudes HTTP que vimos en todas las aplicaciones, podríamos simplemente escribir:
sum(http_requests_total)
Para contar el número de binarios ejecutando cada versión de compilación, podríamos escribir:
count_values("version", build_version)
Para obtener las 5 mayores conteos de solicitudes HTTP en todas las instancias, podríamos escribir:
topk(5, http_requests_total)
Operadores para histogramas nativos
Los histogramas nativos son una característica experimental. La ingesta de histogramas nativos debe habilitarse mediante un indicador de característica. Una vez que los histogramas nativos hayan sido ingeridos, pueden consultarse (incluso después de que el indicador de característica haya sido deshabilitado nuevamente). Sin embargo, el soporte del operador para histogramas nativos aún es muy limitado.
Los operadores lógicos/binarios de conjunto funcionan como se esperaba, incluso si muestras de histograma están involucradas. Solo verifican la existencia de un elemento del vector y no cambian su comportamiento dependiendo del tipo de muestra de un elemento (float o histograma).
El operador binario + entre dos histogramas nativos y el operador de agregación sum para agregar histogramas nativos son totalmente soportados. Incluso si los histogramas involucrados tienen diseños de bucket diferentes, los buckets se convierten automáticamente de forma apropiada para que la operación pueda ejecutarse. (Con los esquemas de bucket actualmente soportados, esto siempre es posible.) Si cualquiera de los operadores tiene que sumar una combinación de muestras de histograma y muestras flotantes, el elemento de vector correspondiente se elimina totalmente del vector de salida.
Todos los otros operadores no se comportan de manera significativa. Tratan la muestra del histograma como si fuera una muestra flotante de valor 0 o (en el caso de operaciones aritméticas entre un escalar y un vector) dejan la muestra del histograma inalterada. Este comportamiento cambiará a uno significativo antes de que los histogramas nativos sean una característica estable.
Esta documentación es de código abierto. Por favor, ayuda a mejorarla registrando problemas o pull requests.
Subconsulta
Devuelve la tasa de 5 minutos de la métrica http_requests_total para los últimos 30 minutos, con una resolución de 1 minuto.
rate(http_requests_total[5m])[30m:1m]
Este es un ejemplo de una subconsulta anidada. La subconsulta de la función deriv usa la resolución predeterminada. Ten en cuenta que usar subconsultas innecesariamente no es sensato.
max_over_time(deriv(rate(distance_covered_total[5s])[30s:5s])[10m:])
Usando funciones, operadores, etc.
Devuelve la tasa por segundo para todas las series temporales con el nombre de métrica http_requests_total, medido en los últimos 5 minutos:
rate(http_requests_total[5m])
Suponiendo que todas las series temporales http_requests_total tengan las etiquetas job (dispersión por nombre del trabajo) e instance (dispersión por instancia del trabajo), podemos querer sumar la tasa de todas las instancias, para obtener menos series temporales de salida, pero aún preservar la dimensión job:
sum by (job) (
rate(http_requests_total[5m])
)
Si tenemos dos métricas diferentes con las mismas etiquetas dimensionales, podemos aplicar operadores binarios a ellas y los elementos de ambos lados con el mismo conjunto de etiquetas se corresponderán y propagarán a la salida. Por ejemplo, esta expresión devuelve la memoria no utilizada en MiB para cada instancia (en un planificador de clúster ficticio que expone estas métricas sobre las instancias que ejecuta):
(instance_memory_limit_bytes - instance_memory_usage_bytes) / 1024 / 1024
La misma expresión, pero sumada por aplicación, podría escribirse así:
sum by (app, proc) (
instance_memory_limit_bytes - instance_memory_usage_bytes
) / 1024 / 1024
Si el mismo planificador de clúster ficticio expusiera métricas de uso de CPU como las siguientes para cada instancia:
instance_cpu_time_ns{app="lion", proc="web", rev="34d0f99", env="prod", job="cluster-manager"}
instance_cpu_time_ns{app="elephant", proc="worker", rev="34d0f99", env="prod", job="cluster-manager"}
instance_cpu_time_ns{app="turtle", proc="api", rev="4d3a513", env="prod", job="cluster-manager"}
instance_cpu_time_ns{app="fox", proc="widget", rev="4d3a513", env="prod", job="cluster-manager"}
...
Podríamos obtener los 3 principales usuarios de CPU agrupados por aplicación (app) y tipo de proceso (proc) así:
topk(3, sum by (app, proc) (rate(instance_cpu_time_ns[5m])))
Suponiendo que esta métrica contenga una serie temporal por instancia en ejecución, puedes contar el número de instancias en ejecución por aplicación de la siguiente forma:
count by (app) (instance_cpu_time_ns)
Funciones
https://prometheus.io/docs/prometheus/latest/querying/functions/
No sirve de nada abordar todas las funciones aquí, basta con mirar el enlace anterior. Pero para conocimiento creo que las principales para el mundo DevOps pueden abordarse abajo. No sirve de nada memorizarlas, pero conocer algunas y según lo que se vaya necesitando consulta la documentación. Veremos más cuando abordemos Grafana.
Usamos funciones para generar un nuevo grupo de muestras. A continuación sigue la función y la entrada que necesita función(params).
abs(v instant-vector): devuelve el vector de entrada con todos los valores de muestra convertidos a su valor absoluto.absent(v instant-vector): devuelve un vector vacío si el vector pasado a él tiene cualquier elemento o el valor 1 si el vector pasado a él no tiene elementos. Esto es útil para alertar cuando no existe ninguna serie temporal para un determinado nombre de métrica y combinación de etiqueta.absent(nonexistent{job="myjob"})
absent_over_time(v range-vector): devuelve un vector vacío si el vector de rango pasado a él tiene cualquier elemento o un vector de 1 elemento con el valor 1 si el vector de rango pasado a él no tiene elementos.ceil(v instant-vector): redondea los valores de muestra de todos los elementos v hasta el entero más cercano.changes(v range-vector): Para cada serie temporal de entrada, changes(v range-vector) devuelve el número de veces que su valor fue cambiado dentro del rango de tiempo dado como un vector instantáneo.clamp(v instant-vector, min scalar, max scalar): fija los valores de muestra de todos los elementos v para tener un límite inferior de min y un límite superior de max.clamp_max(v instant-vector, max scalar): fija los valores de muestra de todos los elementos v para tener un límite superior de max.clamp_min(v instant-vector, min scalar): fija los valores de muestra de todos los elementos v para tener un límite inferior de min.day_of_month(v=vector(time()) instant-vector): devuelve el día del mes para cada uno de los horarios dados en UTC. Los valores devueltos son de 1 a 31.day_of_week(v=vector(time()) instant-vector): devuelve el día de la semana para cada uno de los horarios especificados en UTC. Los valores devueltos son de 0 a 6, donde 0 significa domingo, etc.day_of_year(v=vector(time()) instant-vector): devuelve el día del año para cada una de las horas especificadas en UTC. Los valores devueltos son de 1 a 365 para años no bisiestos y de 1 a 366 para años bisiestos.days_in_month(v=vector(time()) instant-vector): devuelve el número de días en el mes para cada uno de los horarios dados en UTC.minute(v=vector(time()) instant-vector): devuelve el minuto de la hora para cada uno de los horarios dados en UTC. Los valores devueltos son de 0 a 59.hour(v=vector(time()) instant-vector): devuelve la hora del día para cada uno de los horarios dados en UTC. Los valores devueltos son de 0 a 23.month(v=vector(time()) instant-vector): devuelve el mes del año para cada uno de los horarios dados en UTC. Los valores devueltos son de 1 a 12, donde 1 significa enero, etc.year(v=vector(time()) instant-vector): devuelve el año para cada uno de los horarios dados en UTC.time(): devuelve el número de segundos desde el 1 de enero de 1970 UTC. Ten en cuenta que esto no devuelve la hora actual, sino la hora en que la expresión debe ser evaluada.timestamp(v instant-vector): devuelve la marca de tiempo de cada una de las muestras del vector dado como el número de segundos desde el 1 de enero de 1970 UTC.delta(v range-vector): calcula la diferencia entre el primer y el último valor de cada elemento de la serie temporal en un vector, devolviendo un vector instantáneo con los deltas dados y etiquetas equivalentes. La expresión de muestra siguiente devuelve la diferencia en la temperatura de CPU entre ahora y hace 2 horas:delta(cpu_temp_celsius{host="zeus"}[2h])- solo debe usarse con métricas del tipo gauge
idelta(v range-vector): calcula la diferencia entre las dos últimas muestras en el vector de rango v, devolviendo un vector instantáneo con los deltas dados y etiquetas equivalentes.floor(v instant-vector): redondea los valores de muestra de todos los elementos v hacia abajo hasta el entero más cercano.holt_winters(v range-vector, sf scalar, tf scalar): produce un valor suavizado para series temporales basado en el rango en v. Cuanto menor sea el factor de suavizado sf, más importancia se da a los datos antiguos. Cuanto mayor sea el factor de tendencia tf, más se consideran las tendencias en los datos. Tantosfcomotfdeben estar entre 0 y 1.increase(v range-vector): calcula el aumento en la serie temporal en el vector de rango. Las rupturas en la monotonicidad (como reinicios del contador debido a reinicios de destino) se ajustan automáticamente. El aumento se extrapola para cubrir todo el rango de tiempo según lo especificado en el selector de vector de rango, de modo que sea posible obtener un resultado no entero incluso si un contador aumenta solo en incrementos de número entero.label_join(v instant-vector, dst_label string, separator string, src_label_1 string, src_label_2 string, ...): une todos los valores de todos los src_labels usando separator y devuelve la serie temporal con la etiqueta dst_label que contiene el valor asociado. Puede haber cualquier número de src_labels en esta función.- Este ejemplo devolverá un vector con cada serie temporal teniendo una etiqueta foo con el valor a,b,c agregado a ella:
label_join(up{job="api-server",src1="a",src2="b",src3="c"}, "foo", ",", "src1", "src2", "src3")
- Este ejemplo devolverá un vector con cada serie temporal teniendo una etiqueta foo con el valor a,b,c agregado a ella:
label_replace(v instant-vector, dst_label string, replacement string, src_label string, regex string): coincide la expresión regular regex con el valor de la etiqueta src_label. Si coincide, el valor de la etiqueta dst_label en la serie temporal devuelta será la expansión de replacement, junto con las etiquetas originales en la entrada. Los grupos de captura en la expresión regular pueden referenciarse con $1, $2, etc. Si la expresión regular no coincide, la serie temporal se devuelve sin cambios.rate(v range-vector): calcula la tasa promedio por segundo de aumento de la serie temporal en el vector de alcance. Las rupturas en la monotonicidad (como reinicios del contador debido a reinicios de destino) se ajustan automáticamente. Además, el cálculo extrapola al final del rango de tiempo, permitiendo raspados perdidos o alineación imperfecta de los ciclos de raspado con el período de tiempo del rango.irate(v range-vector): calcula la tasa instantánea por segundo de aumento de la serie temporal en el vector de alcance. Esto se basa en los dos últimos puntos de datos. Las rupturas en la monotonicidad (como reinicios del contador debido a reinicios de destino) se ajustan automáticamente.resets(v range-vector): devuelve el número de reinicios del contador dentro del rango de tiempo dado como un vector instantáneo. Cualquier disminución en el valor entre dos muestras consecutivas se interpreta como un reinicio del contador.- resets solo debe usarse con counters.
round(v instant-vector, to_nearest=1 scalar): redondea los valores de muestra de todos los elementos v al entero más cercano. Los empates se resuelven por redondeo. El argumento opcional to_nearest permite especificar el múltiplo más cercano al que los valores de muestra deben redondearse. Este múltiplo también puede ser una fracción.sgn(v instant-vector): devuelve un vector con todos los valores de muestra convertidos a sus signos, definidos como: 1 si v es positivo, -1 si v es negativo y 0 si v es igual a cero.sort(v instant-vector): devuelve elementos de vector clasificados por sus valores de muestra, en orden creciente.sort_desc(v instant-vector): Lo mismo que sort, pero clasificado en orden decreciente.vector(s scalar): devuelve el escalar s como un vector sin etiquetas.
Las siguientes funciones permiten agregar cada serie de un determinado vector de rango a lo largo del tiempo y devolver un vector instantáneo con resultados de agregación por serie:
avg_over_time(range-vector): el valor promedio de todos los puntos en el rango especificado.min_over_time(range-vector): el valor mínimo de todos los puntos en el rango especificado.max_over_time(range-vector): el valor máximo de todos los puntos en el rango especificado.sum_over_time(range-vector): la suma de todos los valores en el rango especificado.count_over_time(range-vector): el conteo de todos los valores en el rango especificado.quantile_over_time(scalar, range-vector): el cuantil φ (0≤φ≤1) de los valores en el rango especificado.stddev_over_time(range-vector): la desviación estándar poblacional de los valores en el rango especificado.stdvar_over_time(range-vector): la varianza estándar de la población de los valores en el rango especificado.last_over_time(range-vector): el valor de punto más reciente en el rango especificado.present_over_time(range-vector): el valor 1 para cualquier serie en el rango especificado.
Ten en cuenta que todos los valores en el rango especificado tienen el mismo peso en la agregación, incluso si los valores no están igualmente espaciados a lo largo del rango.
Aún existen funciones logarítmicas, trigonométricas, entre otras.