😼 KittenRouter: Opensource 🔍 Elasticsearch Monitoring, Logging & 🚦 Failover of webtraffic (with ☁️ Cloudflare Workers)
Tags: showdev, serverless, cloudflare, webdev
Published: 2019-05-14 14:11:24

---
title: 😼 KittenRouter: Opensource 🔍 Elasticsearch Monitoring, Logging & 🚦 Failover of webtraffic (with ☁️ Cloudflare Workers)
published: true
description: Get HA server request, and elastic logs, Nyow
tags: #showdev #serverless #cloudflare #webdev
series: The InboxKitten journey 🐈
cover_image: https://thepracticaldev.s3.amazonaws.com/i/61o55beleb2jlxx1eczj.jpg
canonical_url: https://uilicious.com/blog/kittenrouter-opensource-elasticsearch-monitoring-logging-failover-of-webtraffic-with-cloudflare-workers/
---

![KittenRouter logo](https://thepracticaldev.s3.amazonaws.com/i/1j3qpkan01o7c2n9ugg1.png)
<figcaption>Special thanks to Nai Jie for the logo (he also did InboxKitten logo)</figcaption>

# Introducing KittenRouter - Serverless cousins to InboxKitten

Since we were using Cloudflare serverless kittens for our API. Why not expand this for the UI assets as well?

- Log every web request on cloudflare (This is an [enterprise only feature](https://support.cloudflare.com/hc/en-us/articles/216672448-Cloudflare-Logs-formerly-ELS-)), helping us to track server failures.
- Automated failover on server errors, to maintain overall site availability (High Availability!).
- All as a reusable class module

Keeping the project small along the ["do one thing and do it well"](https://en.wikipedia.org/wiki/Unix_philosophy) concept, the pseudo code could be summarized as below.

```bash
when receiving a request {
   for( each backend configuration ) {
      if (invalid backend configuration - wrong domain, etc) {
         continue - to next backend configuration iteration
      }
      perform cachable request to the backend
      log request to ElasticSearch backend - or alternative log provider
      if( 
         request result is valid || 
         is last configuration || 
         default backend configuration
      ) {
         return result - Ends request processing
      }
      continue - to next backend configuration iteration
   }      
}

# PS: The above is conceptually the synchronous flow. In the actual
# implementation, logging should occur asynchronously without blocking
```

This allows us to configure redundancies within the backend, with commons.host servers coming in first, followed by firebase as "backup".

---

# Background context (why we made this?)

{% link https://dev.to/uilicious/why-we-migrated-serverless-inboxkitten-from-firebase-to-cloudflare-workers-and-commonshost-gd3 %}

When we migrated our UI frontend from Firebase to [Commons.Host (an opensource and public CDN/Static hosting providers)](https://commons.host/), one of the issues we faced was random 404's in random remote locations. Like Russia - possibly due to the lack of servers there.

![Commonshost Global Map](https://thepracticaldev.s3.amazonaws.com/i/mpy4xba5ennrfjt3phh9.png) 
<figcaption>Commons.host, server locations at point of writing</figcaption>

And because we are supporters of the growing 🇸🇬 Commons Host project, we decided to stand by them together, instead of ditching them for alternatives.

We wanted a better way to debug such issues while improving the overall reliability of our service.

> Side note to any big-brother authorities, we only track static assets loading with IP address masking on inboxkitten.com. No logging is done on the API. So yea, do not bother asking me for such data.

---

# Elasticsearch Monitoring: Commons Host

What's awesome, is using the logging done by KittenRouter, of our commons host deployment, we can start having hard data on its status.

![HTTP code logging](https://thepracticaldev.s3.amazonaws.com/i/ui2rilz7vuv581xg1qm8.png)
<figcaption>78 errors out of 12,069 requests ~ 0.65% failure rate</figcaption>

Is that currently in such a setup, we have 99.35% of our traffic routed through the free public servers of commons.host. 

And for the remaining 0.65% of request which fails, They automatically fall back onto firebase infrastructure, under its free tier.

While it's not yet 9 nines, considering that these commons.host servers and cloudflare servers are scattered around the world. [It's well within the 98% of real world user metrics of most CDNs](https://www.cdnperf.com/#!rum)

![Commons host dashboard](https://thepracticaldev.s3.amazonaws.com/i/4f3n8js8c6mzd2vlhwgb.png)

Furthermore, with the header information provided, we can keep track of the error rate on a per server basis. And with the KittenRouter setup on Cloudflare, you can configure such monitoring for any existing site without application code change.

We have since provided the commons.host team access to the above elasticsearch cluster for extracting useful data on their infrastructure under real user load.

> Clarification notes, for privacy reasons, commons.host do not perform such level of logging on their systems for sites hosted on their platform. 
> 
> The intention here for us at Uilicious, is to provide them with useful real-world usage metrics of their servers, and effectively exempting our website, inboxkitten.com, from such privacy protection, to help them improve their service.

---

# Elasticsearch Monitoring: InboxKitten

![KittenRouter world map](https://thepracticaldev.s3.amazonaws.com/i/x54ehgmxsfkkicfke089.png)

Finally, we are able to easily use cloudflare country codes to help us keep track of our Kitten world domination map - live!. Meow-hahaha!

> Greenland, and Madagascar - I got my ~~plague inc~~ InboxKitten eyes set on you!

---

# Cool! Where can I get the code


For deployment and configuration details...

{% github https://github.com/uilicious/KittenRouter %}

[or alternatively NPM](https://www.npmjs.com/package/kittenrouter)

---

# That's cool, but Why do I even need Inboxkitten disposable email for again?

One of the key use cases currently, and why we built this project, is to perform email validations as part of our automated test scripts. Such as the following...

```js

// Lets goto inbox kitten
I.goTo("https://inboxkitten.com");
I.see("Open-Source Disposable Email");

// Go to a random inbox inbox 
I.fill("email", SAMPLE.id(22));
I.click("Get Mail Nyow!");

// Check that its empty
I.see("There for no messages for this kitten :(");

// Testing for regular email
// (sent using a jenkins perodic build)
I.goTo("https://inboxkitten.com");
I.see("Open-Source Disposable Email");
I.fill("email", "ik-reciever-f7s1g28");
I.click("Get Mail Nyow!");

// See an email we expect, nyow
I.see("Testing inboxkitten subject");

```

With sharable test results such as 

[![uilicious demo](https://thepracticaldev.s3.amazonaws.com/i/c2kos152a1tkkdsfewkc.gif)<figcaption>Catfeeding: Uilicious testing inboxkittens XD</figcaption>](https://snippet.uilicious.com/test/public/7t74nVS828weKMtzGgJppF)

Plus it's simple, cool, and fun to tinker around with.

---

# What's next for KittenRouter?

{% github https://github.com/uilicious/KittenRouter/issues/3 %}

Let's see where this InboxKitten journey goes next... Till then we will be taking a cat nap!

![Cat sleeping](https://thepracticaldev.s3.amazonaws.com/i/8fmx06l7bnvogfxptd1f.jpg)

--- 

# Happy Shipping 🖖🏼🚀