Using InfluxDB with Dart

InfluxDB is the hot new time-series database everyone is talking about. You can use it to collect IOT sensor data, build a custom devops monitoring solution or just send your own time-series data that you want analyzed.

The cool thing about Influx is that you write data to it through HTTP, this makes it super simple to write from any language, including Dart!

In this tutorial, we'll go over some quick tips that can help writing to InfluxDB even easier by using the versatile http package.

If you don't have Influx setup, do so now by either installing it on your own server or getting a free 14 day trial from Influx themselves at https://customers.influxdb.com/.

I recommend just getting the 14 day free trial. It comes with Grafana a great dashboard and charting solution for time series data, and it's managed by Influx so you don't have to worry about scaling. After the 14 day trial it's $49/month. Not bad!

Let's get started!

In your project's pubspec.yaml add the http package and the cryptoutils: "^0.1.10" package as a dependency. We will use cryptoutils to base64 our username/password for Basic HTTP Auth.

Why not just use Darts built in http solution?

The http package provides a nice high level abstraction, which lets you do cool stuff like: await http.get("url") or await http.post("url",body:data)

Next create a class called InfluxDB. Below is the entire class we will be writing, feel free to copy and paste and follow along below as we go through each section and why it's required!

library db.influx;

import 'dart:async';
import 'dart:io';
import 'package:http/http.dart' as http;
import 'package:http/src/response.dart';
import 'package:http/src/base_client.dart';
import 'package:http/src/client.dart';
import 'package:http/src/streamed_response.dart';
import 'package:http/src/base_request.dart';
import 'dart:convert';
import 'package:cryptoutils/cryptoutils.dart';

    class InfluxDB {
      static String _connectionString = "URL";
      static String _db = "databaseName";
      InfluxDBClient client = new InfluxDBClient(new Client());

      write(String data) async {
  client.postSilentMicrotask("$_connectionString/write?db=$_db", body: data);
      }
    }

    class InfluxDBClient extends BaseClient {
      String userAgent;
      Client _inner;
      String _username = "";
      String _password = "";

      InfluxDBClient(this._inner);

      Future<StreamedResponse> send(BaseRequest request) {
        request.headers["Authorization"] = "Basic ${CryptoUtils.bytesToBase64(UTF8.encode("$_username:$_password"))}";
        request.headers["Content-Type"] = "application/x-www-form-urlencoded";
        return _inner.send(request);
      }

      postSilentMicrotask(url, {Map<String, String> headers, body, Encoding encoding}) async {
        scheduleMicrotask(() async {
          Response resp = await this.post(url, headers: headers, body: body, encoding: encoding);
          // You can log resp.body here 
        });
      }
    }

The first thing you'll notice is we are instantiating a class called InfluxDBClient and passing it a reference to new Client(). Client is from the http library and it's basically the HTTP client that makes the network calls. But what is InfluxDBClient?

If you scroll down a bit, you'll notice the bulk of the code is actually for InfluxDBClient extends BaseClient. By extending http's BaseClient class, we can add custom headers to every request and do some cool stuff when we want to POST. BaseClient needs a reference to Client and thats why we pass it in when created InfluxDBClient.

Now whenever you POST or GET (or any other HTTP method) using the http package , http creates the request internally into a BaseRequest class and calls send while passing in BaseRequest. BaseRequest pretty much holds all the information for the GET or POST request.

The cool thing here is you can intercept the send method and add custom logic here, in our case we add the required Authorization and Content-Type headers required by InfluxDB. Finally we call the instance of Client we passed in earlier and send the BaseRequest off.

You'll notice that instead of doing a simple POST we wrap it up in a Microtask. I like doing this because it lets the event loop do all the critical tasks first and just before it deals with the next event loop cycle it deals with the microtask.

Microtask Flow

And voila! Now you can write data to Influx easily!

InfluxDB Reference:
https://docs.influxdata.com/influxdb/v0.10/guides/writing_data/