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!

Monday, 28 November 2016

Ethereum Wallet is amazingly slow to sync

Since the last hard fork, and I must say, even before that, I am struggling with the use of ethereum mist. What a nightmare, does not sync up, very slow, 27,000 blocks behind and no sync end in view...
According to the logs, worst case, it takes 40 secs to get one block, 27,000 blocks, more than 12 days! What!

Sunday, 20 November 2016

BTC to ETH

From my previous post first-experience-with-ethereum, you would have read that I was waiting for my transaction to go through to buy ETH from BTC.
I submitted the transaction on 18/11/2016 at 16:39 - it finally went through more than a day later.....

Saturday, 19 November 2016

First experience with Ethereum

Some Saturday experiment while the kids are having fun... While drinking coffee... a thought, I want to mine!
Obviously long gone are the days where I could earn BTC while mining on a commodity laptop (about 4 millions years on mine according to the latest number of hashes needed 2^68).
So... with the promise of GPU mining (I am using OpenCL) with Ethereum - I decided to give it a try.
Please note that I am using Ubuntu 16.04
  • Installing the Ethereum wallet was a breeze - quite easy to set up - and interestingly - as part of the set up - I was asked if I wanted to buy some ETH from my Bicoin wallet
  • Of course... I did it - and issued a small transaction from my bitcoin client to the given Ethereum address
  • I issued a small payment of 0.005 BTC (3.74 USD) with a transaction fee of 0.00007329 BTC (0.05 USD). I sent my transaction on 18/11/2016 at 16:39 - and at the time of writing this post, i.e., more than 15 hours later, my transaction is still unconfirmed in the memory pool! If you understand the transaction fees concept and how miners can decide to do whatever they want... it is not surprising that my transaction would be at the bottom of stack. This simply proves, if any proof was needed, that Bitcoin is not ready for micro-payments, and probably will never be until this ASIC mining non-sense - must using ASIC (Application-specific integrated circuit) is sorted out
  • While waiting for my transaction from BTC to ETH to go through... if it ever happens.... I decided to run the mining software in GPU mode, Ethermine
  • I recommend to recompile from the source directly - it is the easiest and fastest way to get going

Friday, 18 November 2016

Decoding your FIX messages

Looking for an easy way to decode your FIX messages, entirely local to the browser?
Use http://decodeyourfix.com/

Thursday, 10 November 2016

SCALE 2.12 + JAVA 8

I can confirm I can now use SCALA 2.12 with JAVA 8 libs ... :-) This piece of code, using http://sparkjava.com/ I could not do before, now can:
package demo1

import spark.Spark.get

object MicroService {
  def main(args: Array[String]): Unit = {
    get("/hello", (req, res) => "Hello World")
  }
}
Nice!

Blog Archive