[comment]: # translation:outdated

[comment]: # ({213e862c-213e862c})
# 4 Javascript предобработка

[comment]: # ({/213e862c-213e862c})

[comment]: # ({1733dde8-57d3be9d})
#### Обзор

В этом разделе приведены сведения о предварительной обработке при помощи JavaScript.

[comment]: # ({/1733dde8-57d3be9d})

[comment]: # ({d59e106c-076d2285})
#### JavaScript предобработка

Предобработка JavaScript выполняется вызовом функции JavaScript с одним параметром 'value' и заданным пользователем телом функции. Результатом шага предобработки является значение, которое возвращается из этой функции, например, для выполнения конвертации градусов с Фаренгейта в Цельсия пользователю необходимо ввести:

    return (value - 32) * 5 / 9

в параметрах JavaScript предобработки, что будет обёрнуто сервером в функцию JavaScript :

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

Входной параметр 'value' всегда передается как строка. Возвращаемое значение автоматически приводится к строке через метод ToString() (если он завершится с ошибкой, тогда эта ошибка возвращается в виде строкового значения), с несколькими исключениями:

-   возврат неопределенного значения приведет к ошибке
-   возврат значения null приведет к тому, что входящее значение будет отброшено, очень похоже на предварительную обработку 'Отбросить значение' на действие 'Другое при ошибке'.

Ошибки можно вернуть при помощи выбрасывания значений / объектов в качестве исключений (обычно это строки или объекты ошибок).

Например:

``` {.java}
if (value == 0)
    throw "Zero input value"
return 1/value
```

У каждого скрипта есть 10-секундный тайм-аут - время ожидания выполнения (в зависимости от скрипта, срабатывания тайм-аута может занять более длительное время); превышение времени ожидания вернет ошибку. Также применяется ограничение heap памяти в 64 мегабайт.

Байтовое представление шага предобработки JavaScript кэшируется и используется повторно, когда шаг применяется в следующий раз. Любые изменения в шагах предварительной обработки элемента данных вызовут сброс закэшированного скрипта и затем повторную компиляцию.

Последовательные ошибки во время выполнения (3 раза подряд) вызовут повторную инициализацию механизма для уменьшения вероятности того, что один скрипт сломает всю среду выполнения для следующих скриптов (это действие заносится в журнал с режимом отладки DebugLevel 4 и выше).

Предобработка JavaScript реализована при помощи механизма JavaScript Duktape (<https://duktape.org/>).

Смотрите также: [Дополнительные объекты JavaScript](/manual/config/items/preprocessing/javascript/javascript_objects)

[comment]: # ({/d59e106c-076d2285})

[comment]: # ({cc2863db-c932b901})
##### Использование макросов в скриптах

Bмеется возможность использования пользовательских макросов в коде JavaScript . Если скрипт содержит макросы, эти макросы раскрываются сервером / прокси до выполнения конкретных шагов предварительной обработки. Обратите внимание, что при тестировании шагов предварительной обработки в веб-интерфейсе, значения макросов не извлекаются автоматически и их нужно указывать вручную.

::: noteclassic
 Когда макрос заменяется своим значением, контекст игнорируется. Значение макроса вставляется в код как есть, невозможно добавить дополнительное экранирование до помещения значения в код JavaScript. Поэтому будьте аккуратны, так как это может вызвать ошибки в JavaScript в некоторых случаях.

:::

В примере ниже, если полученное значение превышает значение макроса {$THRESHOLD}, то вместо самого значения возвращается значение порога (если присутствует):

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

[comment]: # ({/cc2863db-c932b901})

[comment]: # ({new-29d0516e})
### Examples

The following examples illustrate how you can use JavaScript preprocessing.
Each example contains a brief description, a function body for JavaScript preprocessing parameters, and the preprocessing step result (value accepted by the function → value returned by the function).

[comment]: # ({/new-29d0516e})

[comment]: # ({new-85fe10ec})
##### Example 1: Convert number (scientific notation to integer)

Convert a number from scientific notation to an integer.

```javascript
return (Number(value))
```

Result: 2.62128e+07 → 26212800

[comment]: # ({/new-85fe10ec})

[comment]: # ({new-cb346f3f})
##### Example 2: Convert number (binary to decimal)

Convert a binary number to a decimal number.

```javascript
return(parseInt(value,2))
```

Result: 11010010 → 210

[comment]: # ({/new-cb346f3f})

[comment]: # ({new-b90c2a4e})
##### Example 3: Round a number

Round a number to 2 digits.

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

Result: 18.2345 → 18.23

[comment]: # ({/new-b90c2a4e})

[comment]: # ({new-3ccbf334})
##### Example 4: Count letters in a string

Count the number of letters in a string.

```javascript
return (value.length)
```

Result: "zabbix" → 6

[comment]: # ({/new-3ccbf334})

[comment]: # ({new-1a7f5b1b})
##### Example 5: Get time remaining

Get the remaining time (in seconds) until the expiration date of a certificate.

```javascript
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);
```

Result: Feb 12 12:33:56 2022 GMT → 44380233

[comment]: # ({/new-1a7f5b1b})

[comment]: # ({new-04fc1390})
##### Example 6: Modify JSON (remove properties)

Modify a JSON data structure by removing any properties with the key `"data_size"` or `"index_size"`.

```javascript
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)
```

Value accepted by the function:

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

Value returned by the function:

```json
[
    {
        "table_name":"history"
    },
    {
        "table_name":"history_log"
    }
]
```

[comment]: # ({/new-04fc1390})

[comment]: # ({new-7fbf2a11})
##### Example 7: Convert Apache status to JSON

Convert the value received from a [web.page.get](/manual/config/items/itemtypes/zabbix_agent#web.page.gethostpathport) Zabbix agent item (e.g., web.page.get[http://127.0.0.1:80/server-status?auto]) to a JSON object.

```javascript
// Convert Apache status to JSON

// Split the value into substrings and put these substrings into an array
var lines = value.split('\n');

// Create an empty object "output"
var output = {};

// Create an object "workers" with predefined properties
var workers = {
    '_': 0, 'S': 0, 'R': 0, 'W': 0,
    'K': 0, 'D': 0, 'C': 0, 'L': 0,
    'G': 0, 'I': 0, '.': 0
};

// Add the substrings from the "lines" array to the "output" object as properties (key-value pairs)
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]);
    }
}

// Multiversion metrics
output.ServerUptimeSeconds = output.ServerUptimeSeconds || output.Uptime;
output.ServerVersion = output.ServerVersion || output.Server;

// Parse "Scoreboard" property to get the worker count
if (typeof output.Scoreboard === 'string') {
    for (var i = 0; i < output.Scoreboard.length; i++) {
        var char = output.Scoreboard[i];

        workers[char]++;
    }
}

// Add worker data to the "output" object
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['.']
};

// Return JSON string
return JSON.stringify(output);
```

Value accepted by the function:

    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__..............................................................................................................................................

Value returned by the function:

```json
{
    "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
    }
}
```

[comment]: # ({/new-7fbf2a11})
