Skip to content

Elastic butler were created as a open source alternative to Elastic Stack Alerting tool

Notifications You must be signed in to change notification settings

diogolmenezes/elastic-butler

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

25 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Elastic Butler

Elastic Butler was formed at Oi telecomunication company as an open source alternative to Elastic Stack Alerting tool.

Whereas other services issue notifications based on pre-determined parameters, Elastic Butler allows the user to create their own. Users define the pattern they desire a notification for, known as a recipes, as well as how they are notified, known as notification types.

Such examples include, but are not limited to:

  • Notify me by mail if there are more than 10 fail login attempts in the last 20 minutes
  • Notify me by if we sell more than 1000 iphones in the last day

Get Started

Elastic Butler will store the recipes created, along with the execution result at the Elastic Search Index. Prior to launching Elastic Butler, check the configuration file config/env.json to set up the desired configurations (i.e. - recipes).

Once complete, launch Electric Butler.

NOTE: The user can also use sandbox to perform the first test. Sandbox provides users with an elasticearch and Kibana instances running on the Docker platform.

npm start

Butler uses the @timestamp field to do the "period" filter. Make sure your index has this field.

Execution Email

Configuration

A file config/env.json exists to allow you to provide configuration for this application. This includes many things like sender configuration and data store configuration.

Elastic butler will store the recipes and the execution result at a Elastic Search index this means you can build dashboards and visualizations about your alerts! You could even alert on your alerts if you wanted to.

Recipes

A recipe describe the operation of monitoring. This is how a recipe looks like:

{
    "name": "test-recipe",
    "application": "test",
    "active": true,
    "elasticsearch": "http://localhost:9200",
    "kibana": "http://localhost:5601",
    "interval": 10,
    "search": {
        "index": "shakespeare",
        "query": "\"with love\"",
        "limit": 10,
        "period": "10 m"
    },
    "action": {
        "type": "gmail",
        "to": "[email protected]",
        "subject": "[#hits#] hits at [#application# #recipe#]",
        "body": "<p>Your recipe results:</p> #detail#"
    }
}

To create your first recipe POST it to the store.recipeIndex ( elastic_butler_recipe by default )

POST http://localhost:9200/elastic_butler_recipe/_doc/

{
    "name": "test-recipe",
    "application": "test",
    "active": true,
    "elasticsearch": "http://localhost:9200",
    "kibana": "http://localhost:5601",
    "interval": 1,
    "search": {
        "index": "shakespeare",
        "query": "with love",
        "limit": 10,
        "period": "10 m"
    },
    "action": {
        "type": "gmail",
        "to": "[email protected]",
        "subject": "[#hits#] hits at [#application# #recipe#]",
        "body": "<p>Your recipe results:</p> #detail#"
    }
}

or just execute the setup:

node setup.js

Recipe description:

  • name: Recipe name
  • application: Monitored application name
  • elasticsearch: Elastic-search url with port information (Ex: localhost:9200)
  • search: This is the object to specify the search
  • search.index: Search index name. If you set dateOnIndex at config/env.json, butler will add the current date (-YYYY-MM-DD) at the end of index name.
  • search.query: Elastic search query. (Ex.: code:"500" && "EXTERNAL API ERROR")
  • search.limit: Limit of hits until action be executed
  • search.period: Period in minutes that the occurrence will be searched. (Ex: 20 m) "At last 20 minutes"
  • action: This is the object to specify the action. For default butler has 2 action types (gmail and twiliosms). Butler will search for this type at worker/senders folder. You can create your own sender.

Gmail action type

This action is part of butler default solution, and uses a gmail account to send the notification.

  • action.type: gmail
  • action.to: Recipient's email
  • action.subject: Mail subject. Tags #hits#, #application# and #recipe# will be replaced with recipe data
  • action.body: Mail body. Tag #detail# will be replaced with search result data

Gmail recipe sample

{
    "name" : "test-recipe",
    "application" : "test",
    "active" : false,
    "elasticsearch" : "http://localhost:9200",
    "kibana" : "http://localhost:5601",
    "interval" : 10,
    "action" : {
        "body" : "<p>Your recipe results:</p> #detail#",
        "subject" : "[#hits#] hits at [#application# #recipe#]",
        "to" : "[email protected]",
        "type" : "gmail"
    },
    "search" : {
        "index" : "shakespeare",
        "query" : "\"with love\"",
        "limit" : "10",
        "period" : "60 m"
    }
}

Twiliosms action type

This action is part of butler default solution, and uses a twilio account to send sms.

  • action.type: twiliosms
  • action.to: Recipient's phone number (Ex: +5521999998888)
  • action.body: Sms body. Tags #hits#, #application# and #recipe# will be replaced with recipe data

Twiliosms recipe sample

{
    "name" : "test-recipe-sms",
    "application" : "test",
    "active" : true,
    "elasticsearch" : "http://localhost:9200",
    "kibana" : "http://localhost:5601",
    "interval" : 10,
    "action" : {
        "body" : "#application# #recipe# => #hits# hits",
        "to" : "+5521999998888",
        "type" : "twiliosms"
    },
    "search" : {
        "index" : "shakespeare",
        "query" : "\"with love\"",
        "limit" : "10",
        "period" : "6000 m"
    }
}

Slack action type

This action is part of butler default solution, and uses a slack webhook to send a message.

This action allows you to specify multiple slack webhooks to alert different rooms depending on your recipe.

Setup

  1. Go to https://{yourteam}.slack.com/apps
  2. Install Incoming Webhooks.
  3. Generate a new webhook for your recipe.
  4. Copy the url and include it in the recipe.

Action Attributes

  • action.type: slack
  • action.webhookUrl: https://hooks.slack.com/services/...
  • action.username: Elastic Butler
  • action.iconEmoji: ghost
  • action.detailField: text_entry
  • action.message: Message body. Tags #hits#, #application#, #recipe#, and #detail# will be replaced with recipe/hit data

Slack recipe sample

{
    "name" : "test-recipe",
    "application" : "test",
    "active" : true,
    "elasticsearch" : "http://localhost:9200",
    "kibana" : "http://localhost:5601",
    "interval" : 1,
    "action" : {
        "type" : "slack",
        "message": "[#application#] recieved [#hits#] hits for [#recipe#] \n\n #detail#",
        "webhookUrl": "https://hooks.slack.com/services/...",
        "username": "Elastic Butler",
        "iconEmoji": "ghost",
        "detailField": "text_entry"
    },
    "search" : {
        "index" : "shakespeare",
        "query" : "\"with love\"",
        "limit" : "0",
        "period" : "10 m"
    }
}

Sandbox

For test propouses you can use our sandbox to create an initial test environment:

cd _sandbox

sudo ./sandbox.sh up -d

Our sandbox will use docker-compose to run elastic-search and kibana containers.

After containers are running, you should need import some sample data:

Add sample index mapping at http://localhost:5601/app/kibana#/dev_tools/console

PUT /shakespeare
{
    "mappings": {
        "doc": {
            "properties": {
                "speaker": {
                    "type": "keyword"
                },
                "play_name": {
                    "type": "keyword"
                },
                "line_id": {
                    "type": "integer"
                },
                "speech_number": {
                    "type": "integer"
                }
            }
        }
    }
}

Add the @timestamp ingest to automatic include timestamp information in you data.

PUT _ingest/pipeline/timestamp
{
  "description" : "Adds a timestamp field at the current time",
  "processors" : [ {
    "set" : {
      "field": "@timestamp",
      "value": "{{_ingest.timestamp}}"
    }
  } ]
}

Now you can import some sample data to your index:

cd _sandbox/sample_data

curl -H 'Content-Type: application/x-ndjson' -XPOST 'localhost:9200/shakespeare/doc/_bulk?pretty&pipeline=timestamp' --data-binary @shakespeare_6.0.json

Docker

To run butler on a docker container you need to adjust config/env.json:

  • Edit store configuration url and options
  • Edit senders configurations

Than just run:

cd _docker

sudo ./up.sh

If you want to see container logs:

sudo docker logs butler

To stop butler:

cd _docker

sudo ./down.sh

Creating senders

You can create your own butler sender. To do this you have to create a sender class at worker/senders folder with the name of your type:

// worker/senders/sms.js
class SmsSender {

    constructor() {
        this.config = require('../../config');
    }

    // Send recipe result by sms
    send(recipe, searchResult) {
        let message = this._getInfo(recipe.action.body, recipe, searchResult);
        // send the sms notification here...
    };

    _getInfo(text, recipe, searchResult) {
        return text
                .replace('#application#', recipe.application)
                .replace('#recipe#', recipe.name)
                .replace('#hits#', searchResult.hits.total);
    }
};

module.exports = new SmsSender();

Than you can create a recipe using your new sender:

{
    "name": "Error 500 on process recipe",
    "application": "My Application",
    "active": true,
    "elasticsearch": "http://localhost:9200",
    "kibana": "http://localhost:5601",
    "interval": 10,
    "search": {
        "index": "shakespeare",
        "query": "\"process\" && code: \"500\"",
        "limit": 10,
        "period": "10 m"
    },
    "action": {
        "type": "sms",
        "to": "2199999-8888",
        "body": "#application# #recipe# => #hits# hits"
    }
}

About

Elastic butler were created as a open source alternative to Elastic Stack Alerting tool

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published