Thursday, 21 September 2017

Monitoring, Alerts, and Google Compute

Have you ever looked for a simple, cheap and efficient solution to get alerts for a system that is not based on emails (as most of us get hundreds of those per day), or where you would need to look at a screen 24x7 to see a label color change from green to red?
I thought of using bots from Telegram to broadcast critical alerts to a Telegram group - and as I wanted to try Google Compute - to deploy the process on Google Compute Engine.
Code has been written in Kotlin

Kotlin/Telegram Code

pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>morse</groupId>
    <artifactId>morse-tg</artifactId>
    <version>1.0</version>

    <properties>
        <kotlin.version>1.1.4-3</kotlin.version>
    </properties>

    <build>
        <sourceDirectory>src/main/kotlin</sourceDirectory>
        <testSourceDirectory>src/test/kotlin</testSourceDirectory>
        <plugins>
            <plugin>
                <groupId>org.jetbrains.kotlin</groupId>
                <artifactId>kotlin-maven-plugin</artifactId>
                <version>${kotlin.version}</version>
                <executions>
                    <execution>
                        <id>compile</id>
                        <phase>compile</phase>
                        <goals>
                            <goal>compile</goal>
                        </goals>
                    </execution>
                    <execution>
                        <id>test-compile</id>
                        <phase>test-compile</phase>
                        <goals>
                            <goal>test-compile</goal>
                        </goals>
                    </execution>
                </executions>
                <configuration>
                    <jvmTarget>1.8</jvmTarget>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.codehaus.mojo</groupId>
                <artifactId>exec-maven-plugin</artifactId>
                <configuration>
                    <mainClass>morse.SupportBot</mainClass>
                </configuration>
            </plugin>
        </plugins>
    </build>

    <dependencies>
        <dependency>
            <groupId>org.jetbrains.kotlin</groupId>
            <artifactId>kotlin-stdlib-jre8</artifactId>
            <version>${kotlin.version}</version>
        </dependency>

        <dependency>
            <groupId>org.jetbrains.kotlin</groupId>
            <artifactId>kotlin-test</artifactId>
            <version>${kotlin.version}</version>
            <scope>test</scope>
        </dependency>

        <dependency>
            <groupId>org.telegram</groupId>
            <artifactId>telegrambots</artifactId>
            <version>3.3</version>
        </dependency>

    </dependencies>

</project>

kt code

package morse

import org.telegram.telegrambots.ApiContextInitializer
import org.telegram.telegrambots.TelegramBotsApi
import org.telegram.telegrambots.logging.BotLogger
import java.util.*
import java.util.logging.Level


class SupportBot : TimerTask() {
    lateinit var longPollHandler:LongPollingHandler

    override fun run() {
        longPollHandler.broadcast()
    }

    fun broadcast() {
        val timer = Timer()
        timer.schedule(this, 10_000, 60_000)
    }

    fun init() {
        BotLogger.info("SupportBot", "init()")
        ApiContextInitializer.init()

        BotLogger.setLevel(Level.ALL)

        val botAPI = TelegramBotsApi()
        BotLogger.info("SupportBot", "registering...()")

        longPollHandler = LongPollingHandler()
        botAPI.registerBot(longPollHandler)
        botAPI.registerBot(WebhookHandler())
        BotLogger.info("SupportBot", "Registered Handler")
    }

    companion object {
        @JvmStatic fun main(args: Array) {
            BotLogger.info("SupportBot", "SupportBot")

            val bot = SupportBot()
            bot.init()
            bot.broadcast()
        }
    }
}

package morse

object Cred {
    val bot = ""
    val token = ""
}

package morse

import org.telegram.telegrambots.api.methods.BotApiMethod
import org.telegram.telegrambots.api.objects.Update
import org.telegram.telegrambots.bots.TelegramWebhookBot
import java.util.*

class WebhookHandler : TelegramWebhookBot() {
    override fun getBotUsername() : String = Cred.bot

    override fun getBotToken(): String = Cred.token

    override fun getBotPath(): String = UUID.randomUUID().toString()

    override fun onWebhookUpdateReceived(update: Update?): BotApiMethod<*>? {
        return null
    }
}

package morse

import org.telegram.telegrambots.api.methods.send.SendMessage
import org.telegram.telegrambots.api.objects.Update
import org.telegram.telegrambots.bots.TelegramLongPollingBot
import org.telegram.telegrambots.logging.BotLogger
import java.util.*


class LongPollingHandler : TelegramLongPollingBot() {
    override fun getBotUsername(): String = Cred.bot

    override fun getBotToken(): String = Cred.token

    override fun onUpdateReceived(update: Update?) {
        BotLogger.info("LongPollingHandler", update.toString())
        try {
            if (update?.hasMessage()!!) {
                val message = update.message
                if (message.hasText()) {
                    val sendMessageReq = SendMessage()
                    sendMessageReq.setChatId(message.chatId)
                    sendMessageReq.text = "You just told me " + message.text
                    sendMessage(sendMessageReq)
                }
            }
        } catch (t: Throwable) {
            BotLogger.error("onUpdateReceived", t)
        }
    }

    fun broadcast() {
        BotLogger.info("LongPollingHandler", "broadcast")

        val sendMessageReq = SendMessage()
        sendMessageReq.chatId = "A negative chat it you get when added to the group"
        sendMessageReq.text = "Random message sent from Google Cloud at " + Date()
        sendMessage(sendMessageReq)
    }
}
maven was used to build, package and run this code.

Google Compute Engine

The easiest part! Nothing much to say. I went for the simple CPU/Mem option available, installed Java 8, Maven, uploaded my code, built entirely locally, and ran it via maven exec:java

Result!

No comments:

Blog Archive