3
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

Zabbix 5.0 で Slack に通知するメッセージ内容を編集する

Last updated at Posted at 2021-09-04

Zabbix5.0はwebhookを利用することでSlack連携出来ますが、今回はその内容をデフォルトから編集して通知内容を好きなようにしてみます。
今回は①webhook-javascriptを編集する方法と、②旧来のアクション設定のメッセージを活用する方法の2点を記載します。

image.png

Slack-botを作成してデフォルト内容を通知できるようになるまでは以下から。

1. webhook-javascriptを編集する

メディアタイプのスクリプトの内容を修正することで対応する方法です。

image.png

基本的には、スクリプトのjavascriptを修正しますが、その際にはzabbixのマクロを多用して修正します。

1.1 通知タイトルの修正

slackメッセージ最上部の通知タイトルを修正します。
image.png

通知タイトルはマクロalert.subjectを利用しています。
こちらの内容はアクション設定の件名を利用していますので、こちらを編集しておきます。

[設定] - [アクション] - [対象のアクション]を開き、[実行内容]タブから[実行内容]の[実行内容の詳細]を開きます。
image.png

ここで、メッセージのカスタマイズにチェックを入れ、件名欄にslackで表示したい内容を入力します。
こちらにもマクロを利用可能ですが、今回は特に入れていません。

メッセージ欄は入力不要です。入力しても今回はslackメッセージに反映されません。

image.png

同様に復旧時の通知内容についても変更しておくと、障害発生時と復旧時のslackメッセージ内容が変更されます。

通知タイトルも下記のマクロのように修正してもよいのですが、既存のwebhook-javascriptは通知タイトルがzabbixへのハイパーリンクとなるようになっていますので、そのまま便利に使わせてもらうため上記のようにしています。

1.2 項目名修正

デフォルトは項目名が英語となっているため、日本語に変更します。
image.png

以後はメディアタイプのスクリプトを修正していきます。
メディアタイプのスクリプトを展開します。
image.png

デフォルト内容の210行目~288行目あたりがslack通知内容を記載しているところになります。
例として、Hostと表示されていたホスト名をホスト名と日本語表示する際の記載変更が以下となります。
image.png

このように、基本的には以下のコードブロックで通知内容を表現できるので、適宜、小タイトルとマクロにて内容を修正することが出来ます。

fields
        fields: [
            {
                title: '小タイトル',
                value: 'Zabbixマクロ',
                short: true
            }
        ]

1.3 絵文字利用

slack絵文字を利用することもできます。
image.png

slack絵文字をコードとして埋め込むことが可能なので、そちらを適宜内容に追加しています。
image.png

例として、1.2 項目名修正の小タイトル修正時にも、日本語タイトルの横に:computer:と記載することで絵文字をslackメッセージ内に入れ込んでいます。

image.png

1.4 深刻度の日本語化

深刻度についてはデフォルトで英語表記となっているので日本語化してみます。
image.png

event.severityの内容

マクロの記載 日本語転換
Disaster 致命的な障害
High 重度の障害
Average 軽度の障害
Warning 警告
Information 情報
Not classified 未分類

以下のコード部分について、適当にswitch文で置換して表現しています。

serverity_before
        message.fields.push(
            {
                title: 'Severity',
                value: params.event_severity,
                short: true
            }

 ↓↓↓

serverity_after
        var SEVERITY_JP = '';
        switch (params.event_severity){
            case 'Disaster': SEVERITY_JP = '致命的な障害'; break;
            case 'High': SEVERITY_JP = '重度の障害'; break;
            case 'Average': SEVERITY_JP = '軽度の障害'; break;
            case 'Warning': SEVERITY_JP = '警告'; break;
            case 'Information': SEVERITY_JP = '情報'; break;
            case 'Not classified': SEVERITY_JP = '未分類'; break;
            default: SEVERITY_JP = 'その他';
            }

        message.fields.push(
            {
                title: '深刻度:boom:',
                value: SEVERITY_JP,
                short: true
            }

1.5 回復時の内容

回復時間や障害継続時間については障害回復時のみ表示可能となるため、回復時のみ通知するような部分を作成してみます。
image.png

まず、障害/回復/更新のステータス変更については、zabbixマクロで以下のフラグ判別が可能です。
よって、event.value0の場合のみ、内容が出力されるようブロックを作成します。

ステータス event.value event.update.status
障害発生 1 0
回復 0 -
更新 1 1
only_repair_message
    if (params.event_value === '0') {
        message.fields.push(
            {
                title: '回復時間:clock10:',
                value: params.event_recovery_date + ' ' + params.event_recovery_time,
                short: true
            },
            {
                title: '継続時間:clock10:',
                value: params.event_duration,
                short: true
            }
        );

    }

既存コードの Event time のように value: '{0} {1}'.format(event_recovery_date, event_recovery_time) と記載すると、以下のように undefined undefined となってしまいますので、上記のように結合をしています。

image.png

#変数内容が障害発生時に固定されてしまうからでしょうか…

1.6 その他(トリガーの説明)

slackのメディアタイプに限らないですが、トリガー名だけでは障害がわかりにくいこともあるので、トリガーの説明を記載して通知に含めます。
image.png

こちらはトリガーの設定に内容を記載し、メディアタイプとしてはtrigger.descriptionを利用します。

image.png

trigger_description
            {
                title: 'トリガーの説明:notebook_with_decorative_cover:',
                value: params.trigger_description,
                short: true
            }

1.7 今回利用したコード

なお、下記を利用するほか、メディアタイプにevent_durationを追加しています(下記の真ん中)。
image.png

こちら
webhook_edit
var SEVERITY_COLORS = [
    '#97AAB3', '#7499FF', '#FFC859',
    '#FFA059', '#E97659', '#E45959'
];

var RESOLVE_COLOR = '#009900';

var SLACK_MODE_HANDLERS = {
    alarm: handlerAlarm,
    event: handlerEvent
};


if (!String.prototype.format) {
    String.prototype.format = function() {
        var args = arguments;

        return this.replace(/{(\d+)}/g, function(match, number) {
            return number in args
                ? args[number]
                : match
            ;
        });
    };
}

function isEventProblem(params) {
    return params.event_value == 1
        && params.event_update_status == 0
    ;
}

function isEventUpdate(params) {
    return params.event_value == 1
        && params.event_update_status == 1
    ;
}

function isEventResolve(params) {
    return params.event_value == 0;
}

function getPermalink(channelId, messageTimestamp) {
    var req = new CurlHttpRequest();

    if (typeof params.HTTPProxy === 'string' && params.HTTPProxy.trim() !== '') {
        req.SetProxy(params.HTTPProxy);
    }

    req.AddHeader('Content-Type: application/x-www-form-urlencoded; charset=utf-8');
    req.AddHeader('Authorization: Bearer ' + params.bot_token);

    var query = '{0}?channel={1}&message_ts={2}'.format(
            Slack.getPermalink,
            encodeURIComponent(channelId),
            encodeURIComponent(messageTimestamp)),
        resp = JSON.parse(req.Get(query));

    if (req.Status() != 200 || !resp.ok || resp.ok === 'false') {
        throw 'message was created, but getting message link was failed with reason "' + resp.error + '"';
    }

    return resp.permalink;
}

function createProblemURL(zabbix_url, triggerid, eventid, event_source) {
    var problem_url = '';
    if (event_source === '0') {
        problem_url = '{0}/tr_events.php?triggerid={1}&eventid={2}'
            .format(
                zabbix_url,
                triggerid,
                eventid
            );
    }
    else {
        problem_url = zabbix_url;
    }

    return problem_url;
}

function handlerAlarm(params) {
    var fields = {
        channel: params.channel,
        as_user: params.slack_as_user,
    };

    if (isEventProblem(params)) {
        fields.attachments = [
            createMessage(
                SEVERITY_COLORS[params.event_nseverity] || 0,
                params.event_date,
                params.event_time,
                createProblemURL(params.zabbix_url, params.trigger_id, params.event_id, params.event_source)
            )
        ];

        var resp = JSON.parse(req.Post(Slack.postMessage, JSON.stringify(fields)));

        if (req.Status() != 200 || !resp.ok || resp.ok === 'false') {
            throw resp.error;
        }

        result.tags.__message_ts = resp.ts;
        result.tags.__channel_id = resp.channel;
        result.tags.__channel_name = params.channel;
        result.tags.__message_link = getPermalink(resp.channel, resp.ts);
    }
    else if (isEventUpdate(params)) {
        fields.thread_ts = params.message_ts;
        fields.attachments = [
            createMessage(
                SEVERITY_COLORS[params.event_nseverity] || 0,
                params.event_update_date,
                params.event_update_time,
                createProblemURL(params.zabbix_url, params.trigger_id, params.event_id, params.event_source),
                true
            )
        ];

        resp = JSON.parse(req.Post(Slack.postMessage, JSON.stringify(fields)));
        if (req.Status() != 200 || !resp.ok || resp.ok === 'false') {
            throw resp.error;
        }

    }
    else if (isEventResolve(params)) {
        fields.channel = params.channel_id;
        fields.text = '';
        fields.ts = params.message_ts;
        fields.attachments = [
            createMessage(
                RESOLVE_COLOR,
                params.event_date,
                params.event_time,
                createProblemURL(params.zabbix_url, params.trigger_id, params.event_id, params.event_source)
            )
        ];

        resp = JSON.parse(req.Post(Slack.chatUpdate, JSON.stringify(fields)));
        if (req.Status() != 200 || !resp.ok || resp.ok === 'false') {
            throw resp.error;
        }
    }
}

function handlerEvent(params) {
    var fields = {
        channel: params.channel,
        as_user: params.slack_as_user
    };

    if (isEventProblem(params)) {
        fields.attachments = [
            createMessage(
                SEVERITY_COLORS[params.event_nseverity] || 0,
                params.event_date,
                params.event_time,
                createProblemURL(params.zabbix_url, params.trigger_id, params.event_id, params.event_source)
            )
        ];

        var resp = JSON.parse(req.Post(Slack.postMessage, JSON.stringify(fields)));

        if (req.Status() != 200 || !resp.ok || resp.ok === 'false') {
            throw resp.error;
        }

        result.tags.__channel_name = params.channel;
        result.tags.__message_link = getPermalink(resp.channel, resp.ts);

    }
    else if (isEventUpdate(params)) {
        fields.attachments = [
            createMessage(
                SEVERITY_COLORS[params.event_nseverity] || 0,
                params.event_update_date,
                params.event_update_time,
                createProblemURL(params.zabbix_url, params.trigger_id, params.event_id, params.event_source),
                false
            )
        ];

        resp = JSON.parse(req.Post(Slack.postMessage, JSON.stringify(fields)));

        if (req.Status() != 200 || !resp.ok || resp.ok === 'false') {
            throw resp.error;
        }

    }
    else if (isEventResolve(params)) {
        fields.attachments = [
            createMessage(
                RESOLVE_COLOR,
                params.event_recovery_date,
                params.event_recovery_time,
                createProblemURL(params.zabbix_url, params.trigger_id, params.event_id, params.event_source)
            )
        ];

        resp = JSON.parse(req.Post(Slack.postMessage, JSON.stringify(fields)));

        if (req.Status() != 200 || !resp.ok || resp.ok === 'false') {
            throw resp.error;
        }
    }
}

function createMessage(
    event_severity_color,
    event_date,
    event_time,
    problem_url,
    isShort,
    messageText,
    event_recovery_date, 
    event_recovery_time
) {
    var message = {
        fallback: params.alert_subject,
        title: params.alert_subject,
        color: event_severity_color,
        title_link: problem_url,
        pretext: messageText || '',

        fields: [
            {
                title: 'ホスト名:computer:',
                value: '{0} [{1}]'.format(params.host_name, params.host_conn),
                short: true
            },
            {
                title: 'トリガー名:gun:',
                value: params.event_name,
                short: true

            }
        ],
    };

    if (params.event_source === '0') {
     var SEVERITY_JP = '';
        switch (params.event_severity){
            case 'Disaster': SEVERITY_JP = '致命的な障害'; break;
            case 'High': SEVERITY_JP = '重度の障害'; break;
            case 'Average': SEVERITY_JP = '軽度の障害'; break;
            case 'Warning': SEVERITY_JP = '警告'; break;
            case 'Information': SEVERITY_JP = '情報'; break;
            case 'Not classified': SEVERITY_JP = '未分類'; break;
            default: SEVERITY_JP = 'その他';
            }

        message.fields.push(
            {
                title: '深刻度:boom:',
                value: SEVERITY_JP,
                short: true
            },
            {
                title: '最新の値:new:',
                value: params.event_opdata,
                short: true
            }
        );
    }

    if (!isShort  && params.event_source === '0') {
        message['actions'] = [
            {
                type: 'button',
                text: 'Zabbixを開く:mag_right:',
                url: problem_url
            }
        ];

        message.fields.push(
            {
                title: '発生時間:clock10:',
                value: '{0} {1}'.format(event_date, event_time),
                short: true
            },
            {
                title: 'トリガーの説明:notebook_with_decorative_cover:',
                value: params.trigger_description,
                short: true
            }
        );

    }

    if (params.event_source !== '0' || params.event_update_status === '1') {
        message.fields.push(
            {
                title: 'Details',
                value: params.alert_message,
                short: false
            }
        );
    }

    if (params.event_value === '0') {
        message.fields.push(
            {
                title: '回復時間:clock10:',
                value: params.event_recovery_date + ' ' + params.event_recovery_time,
                short: true
            },
            {
                title: '継続時間:clock10:',
                value: params.event_duration,
                short: true
            }
        );

    }


    return message;
}

function validateParams(params) {
    if (typeof params.bot_token !== 'string' || params.bot_token.trim() === '') {
        throw 'Field "bot_token" cannot be empty';
    }

    if (typeof params.channel !== 'string' || params.channel.trim() === '') {
        throw 'Field "channel" cannot be empty';
    }

    if (isNaN(params.event_id)) {
        throw 'Field "event_id" is not a number';
    }

    if ([0, 1, 2, 3].indexOf(parseInt(params.event_source)) === -1) {
        throw 'Incorrect "event_source" parameter given: "' + params.event_source + '".\nMust be 0-3.';
    }

    if (params.event_source !== '0') {
        params.event_nseverity = '0';
        params.event_severity = 'Not classified';
        params.event_update_status = '0';
        params.slack_mode = 'event';
    }

    if (params.event_source === '1' || params.event_source === '2') {
        params.event_value = '1';
    }

    if (params.event_source === '1') {
        params.host_name = params.discovery_host_dns;
        params.host_ip = params.discovery_host_ip;
    }

    if (!~[0, 1, 2, 3, 4, 5].indexOf(parseInt(params.event_nseverity))) {
        throw 'Incorrect "event_nseverity" parameter given: ' + params.event_nseverity + '\nMust be 0-5.';
    }

    if (typeof params.event_severity !== 'string' || params.event_severity.trim() === '') {
        throw 'Field "event_severity" cannot be empty';
    }

    if (params.event_update_status !== '0' && params.event_update_status !== '1') {
        throw 'Incorrect "event_update_status" parameter given: ' + params.event_update_status + '\nMust be 0 or 1.';
    }

    if (params.event_value !== '0' && params.event_value !== '1') {
        throw 'Incorrect "event_value" parameter given: ' + params.event_value + '\nMust be 0 or 1.';
    }

    if (typeof params.host_conn !== 'string' || params.host_conn.trim() === '') {
        throw 'Field "host_conn" cannot be empty';
    }

    if (typeof params.host_name !== 'string' || params.host_name.trim() === '') {
        throw 'Field "host_name" cannot be empty';
    }

    if (!~['true', 'false'].indexOf(params.slack_as_user.toLowerCase())) {
        throw 'Incorrect "slack_as_user" parameter given: ' + params.slack_as_user + '\nMust be "true" or "false".';
    }

    if (!~['alarm', 'event'].indexOf(params.slack_mode)) {
        throw 'Incorrect "slack_mode" parameter given: ' + params.slack_mode + '\nMust be "alarm" or "event".';
    }

    if (isNaN(params.trigger_id) && params.event_source === '0') {
        throw 'field "trigger_id" is not a number';
    }

    if (typeof params.zabbix_url !== 'string' || params.zabbix_url.trim() === '') {
        throw 'Field "zabbix_url" cannot be empty';
    }

    if (!/^(http|https):\/\/.+/.test(params.zabbix_url)) {
        throw 'Field "zabbix_url" must contain a schema';
    }
}

try {
    var params = JSON.parse(value);

    validateParams(params);

    var req = new CurlHttpRequest(),
        result = {tags: {}};

    if (typeof params.HTTPProxy === 'string' && params.HTTPProxy.trim() !== '') {
        req.SetProxy(params.HTTPProxy);
    }

    req.AddHeader('Content-Type: application/json; charset=utf-8');
    req.AddHeader('Authorization: Bearer ' + params.bot_token);

    var slack_endpoint = 'https://slack.com/api/';

    var Slack = {
        postMessage: slack_endpoint + 'chat.postMessage',
        getPermalink: slack_endpoint + 'chat.getPermalink',
        chatUpdate: slack_endpoint + 'chat.update'
    };

    params.slack_mode = params.slack_mode.toLowerCase();
    params.slack_mode = params.slack_mode in SLACK_MODE_HANDLERS
        ? params.slack_mode
        : 'alarm';

    SLACK_MODE_HANDLERS[params.slack_mode](params);

    if (params.event_source === '0') {
        return JSON.stringify(result);
    }
    else {
        return 'OK';
    }
}
catch (error) {
    Zabbix.Log(4, '[ Slack Webhook ] Slack notification failed : ' + error);
    throw 'Slack notification failed : ' + error;
}

2. アクション設定のメッセージを活用

zabbixメール通知などで利用していた、アクション内のメッセージを利用してslack連携する方法となります。

image.png

zabbix 4.0などで以下の画面で設定していた内容となります。

image.png

2.1 アクション設定

アクション設定にて、メッセージのカスタマイズにチェックを入れ、件名およびメッセージ欄にslackで表示したい内容を入力します。
image.png

メッセージ
以下の障害が発生しました。

発生時刻  {EVENT.DATE} {EVENT.TIME} 
発生ホスト {HOST.NAME}
深刻度   {EVENT.SEVERITY}
発生障害  {EVENT.NAME}

障害の説明
------------------------------------
{TRIGGER.DESCRIPTION}

2.2 メディアタイプ設定

続いて、メディアタイプのスクリプト設定を変更します。

先ほど設定した件名およびメッセージ欄は以下のマクロとなりますので、それ以外の内容を全面的に除外しています。
デフォルト内容の210行目~288行目あたりがslack通知内容を記載しているところになります。
下記変更で対応は完了となります。

アクション マクロ
件名 alert.subject
メッセージ alert_message

image.png

2.3 今回利用したコード

スクリプト内容は以下となります。

こちら
webhook+action
var SEVERITY_COLORS = [
    '#97AAB3', '#7499FF', '#FFC859',
    '#FFA059', '#E97659', '#E45959'
];

var RESOLVE_COLOR = '#009900';

var SLACK_MODE_HANDLERS = {
    alarm: handlerAlarm,
    event: handlerEvent
};


if (!String.prototype.format) {
    String.prototype.format = function() {
        var args = arguments;

        return this.replace(/{(\d+)}/g, function(match, number) {
            return number in args
                ? args[number]
                : match
            ;
        });
    };
}

function isEventProblem(params) {
    return params.event_value == 1
        && params.event_update_status == 0
    ;
}

function isEventUpdate(params) {
    return params.event_value == 1
        && params.event_update_status == 1
    ;
}

function isEventResolve(params) {
    return params.event_value == 0;
}

function getPermalink(channelId, messageTimestamp) {
    var req = new CurlHttpRequest();

    if (typeof params.HTTPProxy === 'string' && params.HTTPProxy.trim() !== '') {
        req.SetProxy(params.HTTPProxy);
    }

    req.AddHeader('Content-Type: application/x-www-form-urlencoded; charset=utf-8');
    req.AddHeader('Authorization: Bearer ' + params.bot_token);

    var query = '{0}?channel={1}&message_ts={2}'.format(
            Slack.getPermalink,
            encodeURIComponent(channelId),
            encodeURIComponent(messageTimestamp)),
        resp = JSON.parse(req.Get(query));

    if (req.Status() != 200 || !resp.ok || resp.ok === 'false') {
        throw 'message was created, but getting message link was failed with reason "' + resp.error + '"';
    }

    return resp.permalink;
}

function createProblemURL(zabbix_url, triggerid, eventid, event_source) {
    var problem_url = '';
    if (event_source === '0') {
        problem_url = '{0}/tr_events.php?triggerid={1}&eventid={2}'
            .format(
                zabbix_url,
                triggerid,
                eventid
            );
    }
    else {
        problem_url = zabbix_url;
    }

    return problem_url;
}

function handlerAlarm(params) {
    var fields = {
        channel: params.channel,
        as_user: params.slack_as_user,
    };

    if (isEventProblem(params)) {
        fields.attachments = [
            createMessage(
                SEVERITY_COLORS[params.event_nseverity] || 0,
                params.event_date,
                params.event_time,
                createProblemURL(params.zabbix_url, params.trigger_id, params.event_id, params.event_source)
            )
        ];

        var resp = JSON.parse(req.Post(Slack.postMessage, JSON.stringify(fields)));

        if (req.Status() != 200 || !resp.ok || resp.ok === 'false') {
            throw resp.error;
        }

        result.tags.__message_ts = resp.ts;
        result.tags.__channel_id = resp.channel;
        result.tags.__channel_name = params.channel;
        result.tags.__message_link = getPermalink(resp.channel, resp.ts);
    }
    else if (isEventUpdate(params)) {
        fields.thread_ts = params.message_ts;
        fields.attachments = [
            createMessage(
                SEVERITY_COLORS[params.event_nseverity] || 0,
                params.event_update_date,
                params.event_update_time,
                createProblemURL(params.zabbix_url, params.trigger_id, params.event_id, params.event_source),
                true
            )
        ];

        resp = JSON.parse(req.Post(Slack.postMessage, JSON.stringify(fields)));
        if (req.Status() != 200 || !resp.ok || resp.ok === 'false') {
            throw resp.error;
        }

    }
    else if (isEventResolve(params)) {
        fields.channel = params.channel_id;
        fields.text = '';
        fields.ts = params.message_ts;
        fields.attachments = [
            createMessage(
                RESOLVE_COLOR,
                params.event_date,
                params.event_time,
                createProblemURL(params.zabbix_url, params.trigger_id, params.event_id, params.event_source)
            )
        ];

        resp = JSON.parse(req.Post(Slack.chatUpdate, JSON.stringify(fields)));
        if (req.Status() != 200 || !resp.ok || resp.ok === 'false') {
            throw resp.error;
        }
    }
}

function handlerEvent(params) {
    var fields = {
        channel: params.channel,
        as_user: params.slack_as_user
    };

    if (isEventProblem(params)) {
        fields.attachments = [
            createMessage(
                SEVERITY_COLORS[params.event_nseverity] || 0,
                params.event_date,
                params.event_time,
                createProblemURL(params.zabbix_url, params.trigger_id, params.event_id, params.event_source)
            )
        ];

        var resp = JSON.parse(req.Post(Slack.postMessage, JSON.stringify(fields)));

        if (req.Status() != 200 || !resp.ok || resp.ok === 'false') {
            throw resp.error;
        }

        result.tags.__channel_name = params.channel;
        result.tags.__message_link = getPermalink(resp.channel, resp.ts);

    }
    else if (isEventUpdate(params)) {
        fields.attachments = [
            createMessage(
                SEVERITY_COLORS[params.event_nseverity] || 0,
                params.event_update_date,
                params.event_update_time,
                createProblemURL(params.zabbix_url, params.trigger_id, params.event_id, params.event_source),
                false
            )
        ];

        resp = JSON.parse(req.Post(Slack.postMessage, JSON.stringify(fields)));

        if (req.Status() != 200 || !resp.ok || resp.ok === 'false') {
            throw resp.error;
        }

    }
    else if (isEventResolve(params)) {
        fields.attachments = [
            createMessage(
                RESOLVE_COLOR,
                params.event_recovery_date,
                params.event_recovery_time,
                createProblemURL(params.zabbix_url, params.trigger_id, params.event_id, params.event_source)
            )
        ];

        resp = JSON.parse(req.Post(Slack.postMessage, JSON.stringify(fields)));

        if (req.Status() != 200 || !resp.ok || resp.ok === 'false') {
            throw resp.error;
        }
    }
}

function createMessage(
    event_severity_color,
    event_date,
    event_time,
    problem_url,
    isShort,
    messageText
) {
    var message = {
        fallback: params.alert_subject,
        title: params.alert_subject,
        color: event_severity_color,
        title_link: problem_url,
        pretext: messageText || '',

        fields: [
            {
                value: params.alert_message,
                short: true

            }
        ],
    };

    return message;
}

function validateParams(params) {
    if (typeof params.bot_token !== 'string' || params.bot_token.trim() === '') {
        throw 'Field "bot_token" cannot be empty';
    }

    if (typeof params.channel !== 'string' || params.channel.trim() === '') {
        throw 'Field "channel" cannot be empty';
    }

    if (isNaN(params.event_id)) {
        throw 'Field "event_id" is not a number';
    }

    if ([0, 1, 2, 3].indexOf(parseInt(params.event_source)) === -1) {
        throw 'Incorrect "event_source" parameter given: "' + params.event_source + '".\nMust be 0-3.';
    }

    if (params.event_source !== '0') {
        params.event_nseverity = '0';
        params.event_severity = 'Not classified';
        params.event_update_status = '0';
        params.slack_mode = 'event';
    }

    if (params.event_source === '1' || params.event_source === '2') {
        params.event_value = '1';
    }

    if (params.event_source === '1') {
        params.host_name = params.discovery_host_dns;
        params.host_ip = params.discovery_host_ip;
    }

    if (!~[0, 1, 2, 3, 4, 5].indexOf(parseInt(params.event_nseverity))) {
        throw 'Incorrect "event_nseverity" parameter given: ' + params.event_nseverity + '\nMust be 0-5.';
    }

    if (typeof params.event_severity !== 'string' || params.event_severity.trim() === '') {
        throw 'Field "event_severity" cannot be empty';
    }

    if (params.event_update_status !== '0' && params.event_update_status !== '1') {
        throw 'Incorrect "event_update_status" parameter given: ' + params.event_update_status + '\nMust be 0 or 1.';
    }

    if (params.event_value !== '0' && params.event_value !== '1') {
        throw 'Incorrect "event_value" parameter given: ' + params.event_value + '\nMust be 0 or 1.';
    }

    if (typeof params.host_conn !== 'string' || params.host_conn.trim() === '') {
        throw 'Field "host_conn" cannot be empty';
    }

    if (typeof params.host_name !== 'string' || params.host_name.trim() === '') {
        throw 'Field "host_name" cannot be empty';
    }

    if (!~['true', 'false'].indexOf(params.slack_as_user.toLowerCase())) {
        throw 'Incorrect "slack_as_user" parameter given: ' + params.slack_as_user + '\nMust be "true" or "false".';
    }

    if (!~['alarm', 'event'].indexOf(params.slack_mode)) {
        throw 'Incorrect "slack_mode" parameter given: ' + params.slack_mode + '\nMust be "alarm" or "event".';
    }

    if (isNaN(params.trigger_id) && params.event_source === '0') {
        throw 'field "trigger_id" is not a number';
    }

    if (typeof params.zabbix_url !== 'string' || params.zabbix_url.trim() === '') {
        throw 'Field "zabbix_url" cannot be empty';
    }

    if (!/^(http|https):\/\/.+/.test(params.zabbix_url)) {
        throw 'Field "zabbix_url" must contain a schema';
    }
}

try {
    var params = JSON.parse(value);

    validateParams(params);

    var req = new CurlHttpRequest(),
        result = {tags: {}};

    if (typeof params.HTTPProxy === 'string' && params.HTTPProxy.trim() !== '') {
        req.SetProxy(params.HTTPProxy);
    }

    req.AddHeader('Content-Type: application/json; charset=utf-8');
    req.AddHeader('Authorization: Bearer ' + params.bot_token);

    var slack_endpoint = 'https://slack.com/api/';

    var Slack = {
        postMessage: slack_endpoint + 'chat.postMessage',
        getPermalink: slack_endpoint + 'chat.getPermalink',
        chatUpdate: slack_endpoint + 'chat.update'
    };

    params.slack_mode = params.slack_mode.toLowerCase();
    params.slack_mode = params.slack_mode in SLACK_MODE_HANDLERS
        ? params.slack_mode
        : 'alarm';

    SLACK_MODE_HANDLERS[params.slack_mode](params);

    if (params.event_source === '0') {
        return JSON.stringify(result);
    }
    else {
        return 'OK';
    }
}
catch (error) {
    Zabbix.Log(4, '[ Slack Webhook ] Slack notification failed : ' + error);
    throw 'Slack notification failed : ' + error;
}

参考

3
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?