---
title: "Getting Your Server Notifications Zapierized"
description: "Get Zapping with example code of how to use Zapier to connect services and run actions when events are triggered."
date: 2017-08-25
author: "Teea Alarto"
url: https://www.exoscale.com/blog/server-notifications-zapierized/
---
# Getting Your Server Notifications Zapierized

> Get Zapping with Teea's example code of how to use Zapier to connect services and run actions when events are triggered.

## What is Zapier?

[Zapier](https://zapier.com/) is a web service for connecting different services. It’s free to use in most cases (you pay only for connectivity to services such as Facebook or Salesforce) and offers an easy way to connect your applications or APIs to other systems. In our example we’ll be using a simple program written in Go to be run as a cronjob on your Exoscale instance and send an alert to Slack if disk space or server loads exceed defined values.

## Example App
Our example code can be found in the [examples repository](https://github.com/exoscale/examples/tree/master/server-notifications-zapierized). Use git to clone it and run with `go run yeller.go`. There is a dependency to [jconfig](http://www.stathat.com/c/jconfig) which you can get by executing `go get stathat.com/c/jconfig`. The configuration file `yeller.conf` has values for percentages of disk space and load average as well as a URL for our webhook:

```
{
    "diskfree": 15,
    "load": 2,
    "webhook": "<Your webhook URL here>"
}
```

The contents of the `yeller.go` are as follows:

```
package main

import (
	"bytes"
	"fmt"
	"io/ioutil"
	"log"
	"net/http"
	"os"
	"os/exec"
	"regexp"
	"strconv"
	"strings"
	"syscall"

	"stathat.com/c/jconfig"
)

var conf *jconfig.Config

func main() {
	conf = jconfig.LoadConfig("yeller.conf")

	var errors []string

	error := checkLoad()
	if error != "" {
		errors = append(errors, error)
	}

	error = checkDiskSpace()
	if error != "" {
		errors = append(errors, error)
	}

	if len(errors) > 0 {
		reportErrors(errors)
	}
}

func pushMessage(message string) {
	client := &http.Client{}
	reader := strings.NewReader("{\"message\": \"" + message + "\"}")
	req, err := http.NewRequest("POST", conf.GetString("webhook"), reader)
	if err != nil {
		log.Fatal(err)
	}

	resp, err := client.Do(req)
	if err != nil {
		log.Fatal(err)
	}

	defer resp.Body.Close()
	respBody, err := ioutil.ReadAll(resp.Body)
	body := string(respBody)

	if !strings.Contains(body, "status\": \"success") {
		log.Fatal(body)
	}
}

func reportErrors(errors []string) {
	for i := 0; i < len(errors); i++ {
		pushMessage(errors[i])
	}
}

func checkDiskSpace() string {
	wd, err := os.Getwd()

	if err != nil {
		log.Fatal(err)
	}

	fs := syscall.Statfs_t{}
	err = syscall.Statfs(wd, &fs)

	if err != nil {
		log.Fatal(err)
	}

	var disksize = fs.Blocks * uint64(fs.Bsize)
	var free = fs.Bfree * uint64(fs.Bsize)
	var freepercent = float64(100) / float64(disksize) * float64(free)
	var percentage = conf.GetFloat("diskfree")

	if freepercent <= float64(percentage) {
		return fmt.Sprintf("Diskspace limit reached (free %f%%, limit %f%%)", freepercent, percentage)
	}

	return ""
}

func checkLoad() string {
	var out bytes.Buffer
	cmd := exec.Command("uptime")
	cmd.Stdout = &out
	err := cmd.Run()
	if err != nil {
		log.Fatal(err)
	}

	var load = out.String()
	r := regexp.MustCompile("load averages: (?P<now>[0-9]*.[0-9]*) (?P<5min>[0-9]*.[0-9]*) (?P<15min>[0-9]*.[0-9]*)")

	match := r.FindStringSubmatch(load)

	loadavg, err := strconv.ParseFloat(match[2], 64)
	loadmax := conf.GetFloat("load")

	if err != nil {
		log.Fatal(err)
	}

	if loadavg >= loadmax {
		return fmt.Sprintf("Server load too high (current: %f, max %f)", loadavg, loadmax)
	}

	return ""
}
```

## The Zapier Side
Create an account and start with creating your own Zap by clicking "Make a Zap!". Each Zap has a trigger which initiates it and then one or more actions that run when your Zap is triggered. Our Zap will be triggered when the constraints are exceeded by a webhook, so pick `Webhooks by Zapier` from the list of triggers.

![Zapier webhook interface](https://www.exoscale.com/blog/server-notifications-zapierized/webhook.png)

As type of hook we will use `Catch hook` which will offer us a URL used for triggering the action. Leave the `Child key` part empty and proceed to the next step which offers you the URL. Copy this URL to the `webhook` part in the `yeller.conf` file. After clicking `OK, I did this`, Zapier will wait for the webhook to be triggered. Run the yeller program once (edit the configuration to have values that should be triggered, such as `load` being zero) and Zapier should report a successful test to you:

![test successful](https://www.exoscale.com/blog/server-notifications-zapierized/test.png)

We want our Zap to give us a message in our Slack channel when it is triggered, so choose the `Action App` to be Slack.

![Slack interface](https://www.exoscale.com/blog/server-notifications-zapierized/slack.png)

Set the action to send a channel message and connect Zapier Slack app to your team and Slack account. On the next page define the channel and the message you want to send (click on the file/message icon in the corner) and you’re all set up.

![Slack channel](https://www.exoscale.com/blog/server-notifications-zapierized/channel.png)

Fill the rest of the values as you see fit (or leave them as they are), test it, and you’re done on the Zapier side. Your Slack should get a message about loads being too high.

![server alarm](https://www.exoscale.com/blog/server-notifications-zapierized/alarm.png)

## The Server Side
On the server side of things set `yeller.go` to be run for example every 10 minutes (don’t forget to edit the load and disk space values to your liking!)  and you’re all set! For an execution interval of 10 minutes, add the following line to your [crontab](https://wiki.gentoo.org/wiki/Cron#Editing_crontabs):

```
10 * * * * go run yeller.go >/dev/null 2>&1
```

You can also do the application in your favorite language or just as a shell script, the example Go program doesn’t use any Zapier libraries or such and the code should be fairly self-explanatory even if you have no experience in Go.

Have fun Zapping!

**Want to write on our blog about some specific code or share a tutorial you wrote? Got your own dev or ops story to share? Get in touch with us at hello@exoscale.ch.**

