5 Preprocesamiento de JavaScript

Descripción general

Esta sección proporciona detalles del preprocesamiento mediante JavaScript.

No utilice asignaciones no declaradas en el JavaScript de preprocesamiento. Utilice var para declarar variables locales.

Preprocesamiento de JavaScript

El preprocesamiento de JavaScript se realiza invocando una función de JavaScript con un único parámetro 'value' y un cuerpo de función proporcionado por el usuario. El resultado del paso de preprocesamiento es el valor devuelto por esta función; por ejemplo, para realizar la conversión de Fahrenheit a Celsius, introduzca:

return (value - 32)  * 5 / 9

en los parámetros de preprocesamiento de JavaScript, que serán envueltos en una función de JavaScript por el server:

function (value)
{
   return (value - 32) * 5 / 9
}

El parámetro de entrada 'value' siempre se pasa como una cadena. El valor de retorno se convierte automáticamente a cadena mediante el método toString() (si falla, el error se devuelve como un valor de cadena), con algunas excepciones:

  • devolver un valor undefined provocará un error;
  • devolver un valor null hará que el valor de entrada se descarte, de forma similar al preprocesamiento 'Discard value' en la acción 'Custom on fail'.

Los errores pueden devolverse lanzando valores/objetos (normalmente cadenas u objetos Error).

Por ejemplo:

if (value == 0)
    throw "Zero input value"
return 1/value

Cada script tiene un tiempo de ejecución máximo de 10 segundos (según el script, el tiempo necesario para que se active el límite puede ser mayor); si se supera, se devolverá un error. Se aplica un límite de heap de 512 megabytes.

El bytecode del paso de preprocesamiento de JavaScript se almacena en caché y se reutiliza la próxima vez que se aplique el paso. Cualquier cambio en los pasos de preprocesamiento del item hará que el script almacenado en caché se restablezca y se vuelva a compilar más adelante.

Los fallos consecutivos en tiempo de ejecución (3 seguidos) harán que el motor se reinicialice para mitigar la posibilidad de que un script rompa el entorno de ejecución para los siguientes scripts (esta acción se registra con DebugLevel 4 y superior).

El preprocesamiento de JavaScript está implementado con el motor de JavaScript Duktape.

Las definiciones de métodos integrados de objetos de JavaScript no pueden redefinirse en los scripts de preprocesamiento de item.

Véase también: Additional JavaScript objects and global functions

Uso de macros en scripts

Es posible usar macros de usuario (así como macros LLD en el contexto de la detección de bajo nivel) en código JavaScript. Si un script contiene macros, estas macros se resuelven por server/proxy antes de ejecutar pasos de preprocesamiento específicos. Tenga en cuenta que al probar pasos de preprocesamiento en el frontend, los valores de las macros no se obtendrán y deberán introducirse manualmente.

El contexto se ignora cuando una macro se reemplaza por su valor. El valor de la macro se inserta en el código tal cual; no es posible añadir un escape adicional antes de colocar el valor en el código JavaScript. Tenga en cuenta que esto puede causar errores de JavaScript en algunos casos.

En el ejemplo siguiente, si el valor recibido supera un valor de macro {$THRESHOLD}, se devolverá en su lugar el valor del umbral (si está presente):

var threshold = '{$THRESHOLD}';
return (!isNaN(threshold) && value > threshold) ? threshold : value;

Ejemplos

Los siguientes ejemplos ilustran cómo puede utilizar el preprocesamiento de JavaScript.

Cada ejemplo contiene una breve descripción, un cuerpo de función para los parámetros de preprocesamiento de JavaScript y el resultado del paso de preprocesamiento: el valor devuelto por la función.

Ejemplo 1: Convertir un número (notación científica a entero)

Convierte el número "2.62128e+07" de notación científica a un entero.

return (Number(value))

Valor devuelto por la función: 26212800.

Ejemplo 2: Convertir un número (binario a decimal)

Convertir el número binario "11010010" a un número decimal.

return(parseInt(value,2))

Valor devuelto por la función: 210.

Ejemplo 3: Redondear un número

Redondear el número "18.2345" a 2 dígitos.

return(Math.round(value* 100) / 100)

Valor devuelto por la función: 18.23.

Ejemplo 4: Contar letras en una cadena

Cuenta el número de letras en la cadena "Zabbix".

return (value.length)

Valor devuelto por la función: 6.

Ejemplo 5: Obtener el tiempo restante

Obtener el tiempo restante (en segundos) hasta la fecha de expiración de un certificado (12 de febrero 12:33:56 2022 GMT).

var split = value.split(' '),
    MONTHS_LIST = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'],
    month_index = ('0' + (MONTHS_LIST.indexOf(split[0]) + 1)).slice(-2),
    ISOdate = split[3] + '-' + month_index + '-' + split[1] + 'T' + split[2],
    now = Date.now();

return parseInt((Date.parse(ISOdate) - now) / 1000);

Valor devuelto por la función: 44380233.

Ejemplo 6: Eliminar propiedades JSON

Modifica la estructura de datos JSON eliminando cualquier propiedad con la clave "data_size" o "index_size".

var obj=JSON.parse(value);

for (i = 0; i < Object.keys(obj).length; i++) {
    delete obj[i]["data_size"];
    delete obj[i]["index_size"];
}

return JSON.stringify(obj)

Valor aceptado por la función:

[
    {
        "table_name":"history",
        "data_size":"326.05",
        "index_size":"174.34"
    },
    {
        "table_name":"history_log",
        "data_size":"6.02",
        "index_size":"3.45"
    }
]

Valor devuelto por la función:

[
    {
        "table_name":"history"
    },
    {
        "table_name":"history_log"
    }
]
Ejemplo 7: Convertir el estado de Apache a JSON

Convierta el valor recibido de un item de Zabbix agent web.page.get (por ejemplo, web.page.get[http://127.0.0.1:80/server-status?auto]) en un objeto JSON.

// Convertir el estado de Apache a JSON

// Dividir el valor en subcadenas y colocar estas subcadenas en un array
var lines = value.split('\n');

// Crear un objeto vacío "output"
var output = {};

// Crear un objeto "workers" con propiedades predefinidas
var workers = {
    '_': 0, 'S': 0, 'R': 0, 'W': 0,
    'K': 0, 'D': 0, 'C': 0, 'L': 0,
    'G': 0, 'I': 0, '.': 0
};

// Añadir las subcadenas del array "lines" al objeto "output" como propiedades (pares clave-valor)
for (var i = 0; i < lines.length; i++) {
    var line = lines[i].match(/([A-z0-9 ]+): (.*)/);

    if (line !== null) {
        output[line[1]] = isNaN(line[2]) ? line[2] : Number(line[2]);
    }
}

// Métricas multiversión
output.ServerUptimeSeconds = output.ServerUptimeSeconds || output.Uptime;
output.ServerVersion = output.ServerVersion || output.Server;

// Analizar la propiedad "Scoreboard" para obtener el recuento de workers
if (typeof output.Scoreboard === 'string') {
    for (var i = 0; i < output.Scoreboard.length; i++) {
        var char = output.Scoreboard[i];

        workers[char]++;
    }
}

// Añadir los datos de workers al objeto "output"
output.Workers = {
    waiting: workers['_'], starting: workers['S'], reading: workers['R'],
    sending: workers['W'], keepalive: workers['K'], dnslookup: workers['D'],
    closing: workers['C'], logging: workers['L'], finishing: workers['G'],
    cleanup: workers['I'], slot: workers['.']
};

// Devolver la cadena JSON
return JSON.stringify(output);

Valor aceptado por la función:

HTTP/1.1 200 OK
Date: Mon, 27 Mar 2023 11:08:39 GMT
Server: Apache/2.4.52 (Ubuntu)
Vary: Accept-Encoding
Content-Encoding: gzip
Content-Length: 405
Content-Type: text/plain; charset=ISO-8859-1

127.0.0.1
ServerVersion: Apache/2.4.52 (Ubuntu)
ServerMPM: prefork
Server Built: 2023-03-08T17:32:01
CurrentTime: Monday, 27-Mar-2023 14:08:39 EEST
RestartTime: Monday, 27-Mar-2023 12:19:59 EEST
ParentServerConfigGeneration: 1
ParentServerMPMGeneration: 0
ServerUptimeSeconds: 6520
ServerUptime: 1 hour 48 minutes 40 seconds
Load1: 0.56
Load5: 0.33
Load15: 0.28
Total Accesses: 2476
Total kBytes: 8370
Total Duration: 52718
CPUUser: 8.16
CPUSystem: 3.44
CPUChildrenUser: 0
CPUChildrenSystem: 0
CPULoad: .177914
Uptime: 6520
ReqPerSec: .379755
BytesPerSec: 3461.58
BytesPerReq: 3461.58
DurationPerReq: 21.2916
BusyWorkers: 2
IdleWorkers: 6
Scoreboard: ____KW__..............................................................................................................................................

Valor devuelto por la función:

{
    "Date": "Mon, 27 Mar 2023 11:08:39 GMT",
    "Server": "Apache/2.4.52 (Ubuntu)",
    "Vary": "Accept-Encoding",
    "Encoding": "gzip",
    "Length": 405,
    "Type": "text/plain; charset=ISO-8859-1",
    "ServerVersion": "Apache/2.4.52 (Ubuntu)",
    "ServerMPM": "prefork",
    "Server Built": "2023-03-08T17:32:01",
    "CurrentTime": "Monday, 27-Mar-2023 14:08:39 EEST",
    "RestartTime": "Monday, 27-Mar-2023 12:19:59 EEST",
    "ParentServerConfigGeneration": 1,
    "ParentServerMPMGeneration": 0,
    "ServerUptimeSeconds": 6520,
    "ServerUptime": "1 hour 48 minutes 40 seconds",
    "Load1": 0.56,
    "Load5": 0.33,
    "Load15": 0.28,
    "Total Accesses": 2476,
    "Total kBytes": 8370,
    "Total Duration": 52718,
    "CPUUser": 8.16,
    "CPUSystem": 3.44,
    "CPUChildrenUser": 0,
    "CPUChildrenSystem": 0,
    "CPULoad": 0.177914,
    "Uptime": 6520,
    "ReqPerSec": 0.379755,
    "BytesPerSec": 1314.55,
    "BytesPerReq": 3461.58,
    "DurationPerReq": 21.2916,
    "BusyWorkers": 2,
    "IdleWorkers": 6,
    "Scoreboard": "____KW__..............................................................................................................................................",
    "Workers": {
        "waiting": 6,
        "starting": 0,
        "reading": 0,
        "sending": 1,
        "keepalive": 1,
        "dnslookup": 0,
        "closing": 0,
        "logging": 0,
        "finishing": 0,
        "cleanup": 0,
        "slot": 142
    }
}