Author: Francis Ndungu
Last Updated: Fri, Jan 7, 2022InfluxDB is an open-source time-series database specifically suitable for IoT projects, cloud-native services, and more. The package is written in the Golang programming language. You can use it for data exploration, data visualization, and to run dashboard applications.
While InfluxDB comes with great tools for storing, querying, and processing data, you can still use its API libraries inside your Golang project. This enhances flexibility when working with the time series data since you can pass it through custom functions that may not be available in the InfluxDB codebase.
In this guide, you'll implement the InfluxDB database functions with Golang on your Ubuntu 20.04 server.
To proceed with this guide, make sure you have the following:
In this tutorial, you'll set up an InfluxDB database and insert some time-series data for testing purposes. Later, you'll query your InfluxDB server via a Golang script to retrieve or insert points to the database.
Connect to your server to complete the following steps:
Log in to the InfluxDB server. Replace admin
with the name of your InfluxDB super-user
account. Pass the -password ''
option to allow the following influx
command to prompt you for a password.
$ influx -username 'admin' -password ''
Key in your password and press ENTER to proceed. Next, execute the following statement to create a sample_db
database.
> CREATE DATABASE sample_db
Switch to the new sample_db
database.
> USE sample_db
Insert the following points into your sample_db
database under the power_usage
measurement. In this application, you're tracking the power loads for users in different homes where a solar system has been installed. In this step, you'll enter the data manually, but this data may originate from IoT devices installed in all homes requiring measurement tracking in a production environment.
> INSERT power_usage,client_id=100731,location=BRANSON current_load_in_amperes=0.2
> INSERT power_usage,client_id=800478,location=MIAMI current_load_in_amperes=0.1
> INSERT power_usage,client_id=907854,location=CHICAGO current_load_in_amperes=0.4
> INSERT power_usage,client_id=532681,location=CHARLESTON current_load_in_amperes=0.1
Query the power_usage
measurement to make sure the data is in place.
> SELECT "client_id", "location", "current_load_in_amperes" FROM power_usage
You should get the following output showing time-stamped data as you entered it in the sample_db
database.
time client_id location current_load_in_amperes
---- --------- -------- -----------------------
1638542140183389389 100731 BRANSON 0.2
1638542147803130270 800478 MIAMI 0.1
1638542155163864457 907854 CHICAGO 0.4
1638542162283179983 532681 CHARLESTON 0.1
Log out from the InfluxDB server.
> QUIT
main.go
FileIn this application, you'll create a main.go
file. This runs the main(...)
function that fires when you start the application.
Separate your source code files from the rest of the Linux files by creating a new project
directory.
$ mkdir project
Next, navigate to the project
directory.
$ cd project
Then, use nano
to open a new main.go
file.
$ nano main.go
Enter the following information into the main.go
file.
package main
import (
"net/http"
"encoding/json"
"fmt"
)
func main() {
http.HandleFunc("/power-consumptions", httpHandler)
http.ListenAndServe(":8080", nil)
}
func httpHandler(w http.ResponseWriter, req *http.Request) {
var err error
resp := map[string]interface{}{}
if req.Method == "POST" {
params := map[string]interface{}{}
err = json.NewDecoder(req.Body).Decode(¶ms)
if err != nil {
fmt.Fprintf(w, err.Error())
}
resp, err = createPoint(params)
}
if req.Method == "GET" {
resp, err = getPoints()
}
enc := json.NewEncoder(w)
enc.SetIndent("", " ")
if err != nil {
fmt.Println(err.Error())
} else {
if err := enc.Encode(resp); err != nil {
fmt.Println(err.Error())
}
}
}
Save and close the main.go
file when you're through with editing.
In the above file, you've created a main()
function to listen for incoming HTTP requests on port 8080
. You've then redirected the request to the httpHandler()
function to determine the HTTP req.Method
. For POST
requests, you're calling a createPoint(params)
function, which you'll create in a new file later. This function accepts the JSON payload as an argument for the point that you want to create to the database.
Next, you're redirecting GET
requests to the getPoints()
function, which retrieves data from the database and returns a map.
influxdb.go
FileYou'll create a file to interact with your InfluxDB server in this step. This file contains two functions. You'll use the createPoint()
function to enter new points into the database and the getPoints()
function to retrieve entries from your power_usage
measurement.
Use nano
to create a new influxdb.go
file.
$ nano influxdb.go
Next, enter the following information into the influxdb.go
file. Replace const USERNAME
and const PASSWORD
with the correct authentication credentials for your InfluxDB server.
package main
import (
"github.com/influxdata/influxdb1-client/v2"
"time"
"errors"
)
const (
USERNAME string = "admin"
PASSWORD string = "EXAMPLE_PASSWORD"
DATABASE string = "sample_db"
)
func createPoint(params map[string]interface{}) (map[string]interface{}, error) {
influxClient, err := client.NewHTTPClient(client.HTTPConfig{
Addr: "http://localhost:8086",
Username: USERNAME,
Password: PASSWORD,
})
if err != nil {
return nil, err
}
bp, err := client.NewBatchPoints(client.BatchPointsConfig{
Database: DATABASE,
})
if err != nil {
return nil, err
}
clientId := params["client_id"].(string)
location := params["location"].(string)
currentLoadInAmperes := params["current_load_in_amperes"]
pt, err := client.NewPoint("power_usage", map[string]string{"client_id": clientId, "location": location},
map[string]interface{}{"current_load_in_amperes": currentLoadInAmperes},
time.Now())
if err != nil {
return nil, err
}
bp.AddPoint(pt)
err = influxClient.Write(bp)
if err != nil {
return nil, err
}
resp := map[string]interface{}{"data" : "Success"}
return resp, nil
}
func getPoints() (map[string]interface{}, error) {
influxClient, err := client.NewHTTPClient(client.HTTPConfig{
Addr: "http://localhost:8086",
Username: USERNAME,
Password: PASSWORD,
})
if err != nil {
return nil, err
}
queryString := "SELECT client_id, location, current_load_in_amperes FROM power_usage"
q := client.NewQuery(queryString, DATABASE, "ns")
response, err := influxClient.Query(q)
if err != nil {
return nil, err
}
err = response.Error()
if err != nil {
return nil, errors.New("Empty record set")
} else {
res := response.Results
if (len(res) == 0) {
return nil, err
}
columns := response.Results[0].Series[0].Columns
points := response.Results[0].Series[0].Values
data := []map[string]interface{}{}
for i := 0; i <= len(points) - 1 ; i++ {
record := map[string]interface{}{}
for j := 0; j <= len(columns) - 1; j++ {
record[string(columns[j])] = points[i][j]
}
data = append(data, record)
}
resp := map[string]interface{}{"data" : data}
return resp, nil
}
}
Save and close the influxdb.go
file when you're through with editing.
In the above file, you have two functions. You're using the createPoint
function to connect and create a point in your InfluxDB database using the payload passed from the main.go
file. Then, you're using the getPoints()
function to connect and retrieve points from the power_usage
measurement. In each case, you're returning a map to the calling function or an error, if any.
You now have a main.go
file that listens for incoming requests and an influxdb.go
that creates and retrieves points from your InfluxDB database. Your application is now ready for testing.
Download the InfluxDB packages that you've used in the project.
$ go get github.com/influxdata/influxdb1-client/v2
Next, run the application. A web server should now listen on port 8080
. Don't enter any other command in this SSH
session.
$ go run ./
SSH to your server on another terminal window and execute the following curl
POST
command to create a new entry into your InfluxDB database.
$ curl -i -X POST localhost:8080/power-consumptions -H "Content-Type: application/json" -d '{"client_id": "656565", "location": "NAIROBI", "current_load_in_amperes": 0.3}'
Confirm the following output. This means you've successfully created a new point into the database.
{
"data": "Success"
}
Then, issue the following GET
command to retrieve points from the database.
$ curl -i -X GET localhost:8080/power-consumptions
You should get the following output with all points, including the latest NAIROBI
entry you've created with the curl
command.
{
"data": [
{
"client_id": "100731",
"current_load_in_amperes": 0.2,
"location": "BRANSON",
"time": 1638542140183389389
},
{
"client_id": "800478",
"current_load_in_amperes": 0.1,
"location": "MIAMI",
"time": 1638542147803130270
},
{
"client_id": "907854",
"current_load_in_amperes": 0.4,
"location": "CHICAGO",
"time": 1638542155163864457
},
{
"client_id": "532681",
"current_load_in_amperes": 0.1,
"location": "CHARLESTON",
"time": 1638542162283179983
},
{
"client_id": "656565",
"current_load_in_amperes": 0.3,
"location": "NAIROBI",
"time": 1638542346252178453
}
]
}
Your application is working as expected.
In this guide, you've implemented InfluxDB database functions with Golang on your Ubuntu 20.04 server to create and retrieve points using a custom JSON API.
Follow the links below to read more Golang tutorials: