README.md
1# InfluxDB Client
2
3[![GoDoc](https://godoc.org/github.com/influxdata/influxdb?status.svg)](http://godoc.org/github.com/influxdata/influxdb/client/v2)
4
5## Description
6
7**NOTE:** The Go client library now has a "v2" version, with the old version
8being deprecated. The new version can be imported at
9`import "github.com/influxdata/influxdb/client/v2"`. It is not backwards-compatible.
10
11A Go client library written and maintained by the **InfluxDB** team.
12This package provides convenience functions to read and write time series data.
13It uses the HTTP protocol to communicate with your **InfluxDB** cluster.
14
15
16## Getting Started
17
18### Connecting To Your Database
19
20Connecting to an **InfluxDB** database is straightforward. You will need a host
21name, a port and the cluster user credentials if applicable. The default port is
228086. You can customize these settings to your specific installation via the
23**InfluxDB** configuration file.
24
25Though not necessary for experimentation, you may want to create a new user
26and authenticate the connection to your database.
27
28For more information please check out the
29[Admin Docs](https://docs.influxdata.com/influxdb/latest/administration/).
30
31For the impatient, you can create a new admin user _bubba_ by firing off the
32[InfluxDB CLI](https://github.com/influxdata/influxdb/blob/master/cmd/influx/main.go).
33
34```shell
35influx
36> create user bubba with password 'bumblebeetuna'
37> grant all privileges to bubba
38```
39
40And now for good measure set the credentials in you shell environment.
41In the example below we will use $INFLUX_USER and $INFLUX_PWD
42
43Now with the administrivia out of the way, let's connect to our database.
44
45NOTE: If you've opted out of creating a user, you can omit Username and Password in
46the configuration below.
47
48```go
49package main
50
51import (
52 "log"
53 "time"
54
55 "github.com/influxdata/influxdb/client/v2"
56)
57
58const (
59 MyDB = "square_holes"
60 username = "bubba"
61 password = "bumblebeetuna"
62)
63
64
65func main() {
66 // Create a new HTTPClient
67 c, err := client.NewHTTPClient(client.HTTPConfig{
68 Addr: "http://localhost:8086",
69 Username: username,
70 Password: password,
71 })
72 if err != nil {
73 log.Fatal(err)
74 }
75 defer c.Close()
76
77 // Create a new point batch
78 bp, err := client.NewBatchPoints(client.BatchPointsConfig{
79 Database: MyDB,
80 Precision: "s",
81 })
82 if err != nil {
83 log.Fatal(err)
84 }
85
86 // Create a point and add to batch
87 tags := map[string]string{"cpu": "cpu-total"}
88 fields := map[string]interface{}{
89 "idle": 10.1,
90 "system": 53.3,
91 "user": 46.6,
92 }
93
94 pt, err := client.NewPoint("cpu_usage", tags, fields, time.Now())
95 if err != nil {
96 log.Fatal(err)
97 }
98 bp.AddPoint(pt)
99
100 // Write the batch
101 if err := c.Write(bp); err != nil {
102 log.Fatal(err)
103 }
104
105 // Close client resources
106 if err := c.Close(); err != nil {
107 log.Fatal(err)
108 }
109}
110
111```
112
113### Inserting Data
114
115Time series data aka *points* are written to the database using batch inserts.
116The mechanism is to create one or more points and then create a batch aka
117*batch points* and write these to a given database and series. A series is a
118combination of a measurement (time/values) and a set of tags.
119
120In this sample we will create a batch of a 1,000 points. Each point has a time and
121a single value as well as 2 tags indicating a shape and color. We write these points
122to a database called _square_holes_ using a measurement named _shapes_.
123
124NOTE: You can specify a RetentionPolicy as part of the batch points. If not
125provided InfluxDB will use the database _default_ retention policy.
126
127```go
128
129func writePoints(clnt client.Client) {
130 sampleSize := 1000
131
132 bp, err := client.NewBatchPoints(client.BatchPointsConfig{
133 Database: "systemstats",
134 Precision: "us",
135 })
136 if err != nil {
137 log.Fatal(err)
138 }
139
140 rand.Seed(time.Now().UnixNano())
141 for i := 0; i < sampleSize; i++ {
142 regions := []string{"us-west1", "us-west2", "us-west3", "us-east1"}
143 tags := map[string]string{
144 "cpu": "cpu-total",
145 "host": fmt.Sprintf("host%d", rand.Intn(1000)),
146 "region": regions[rand.Intn(len(regions))],
147 }
148
149 idle := rand.Float64() * 100.0
150 fields := map[string]interface{}{
151 "idle": idle,
152 "busy": 100.0 - idle,
153 }
154
155 pt, err := client.NewPoint(
156 "cpu_usage",
157 tags,
158 fields,
159 time.Now(),
160 )
161 if err != nil {
162 log.Fatal(err)
163 }
164 bp.AddPoint(pt)
165 }
166
167 if err := clnt.Write(bp); err != nil {
168 log.Fatal(err)
169 }
170}
171```
172
173#### Uint64 Support
174
175The `uint64` data type is supported if your server is version `1.4.0` or
176greater. To write a data point as an unsigned integer, you must insert
177the point as `uint64`. You cannot use `uint` or any of the other
178derivatives because previous versions of the client have supported
179writing those types as an integer.
180
181### Querying Data
182
183One nice advantage of using **InfluxDB** the ability to query your data using familiar
184SQL constructs. In this example we can create a convenience function to query the database
185as follows:
186
187```go
188// queryDB convenience function to query the database
189func queryDB(clnt client.Client, cmd string) (res []client.Result, err error) {
190 q := client.Query{
191 Command: cmd,
192 Database: MyDB,
193 }
194 if response, err := clnt.Query(q); err == nil {
195 if response.Error() != nil {
196 return res, response.Error()
197 }
198 res = response.Results
199 } else {
200 return res, err
201 }
202 return res, nil
203}
204```
205
206#### Creating a Database
207
208```go
209_, err := queryDB(clnt, fmt.Sprintf("CREATE DATABASE %s", MyDB))
210if err != nil {
211 log.Fatal(err)
212}
213```
214
215#### Count Records
216
217```go
218q := fmt.Sprintf("SELECT count(%s) FROM %s", "value", MyMeasurement)
219res, err := queryDB(clnt, q)
220if err != nil {
221 log.Fatal(err)
222}
223count := res[0].Series[0].Values[0][1]
224log.Printf("Found a total of %v records\n", count)
225```
226
227#### Find the last 10 _shapes_ records
228
229```go
230q := fmt.Sprintf("SELECT * FROM %s LIMIT %d", MyMeasurement, 10)
231res, err = queryDB(clnt, q)
232if err != nil {
233 log.Fatal(err)
234}
235
236for i, row := range res[0].Series[0].Values {
237 t, err := time.Parse(time.RFC3339, row[0].(string))
238 if err != nil {
239 log.Fatal(err)
240 }
241 val := row[1].(string)
242 log.Printf("[%2d] %s: %s\n", i, t.Format(time.Stamp), val)
243}
244```
245
246### Using the UDP Client
247
248The **InfluxDB** client also supports writing over UDP.
249
250```go
251func WriteUDP() {
252 // Make client
253 c, err := client.NewUDPClient("localhost:8089")
254 if err != nil {
255 panic(err.Error())
256 }
257
258 // Create a new point batch
259 bp, _ := client.NewBatchPoints(client.BatchPointsConfig{
260 Precision: "s",
261 })
262
263 // Create a point and add to batch
264 tags := map[string]string{"cpu": "cpu-total"}
265 fields := map[string]interface{}{
266 "idle": 10.1,
267 "system": 53.3,
268 "user": 46.6,
269 }
270 pt, err := client.NewPoint("cpu_usage", tags, fields, time.Now())
271 if err != nil {
272 panic(err.Error())
273 }
274 bp.AddPoint(pt)
275
276 // Write the batch
277 c.Write(bp)
278}
279```
280
281### Point Splitting
282
283The UDP client now supports splitting single points that exceed the configured
284payload size. The logic for processing each point is listed here, starting with
285an empty payload.
286
2871. If adding the point to the current (non-empty) payload would exceed the
288 configured size, send the current payload. Otherwise, add it to the current
289 payload.
2901. If the point is smaller than the configured size, add it to the payload.
2911. If the point has no timestamp, just try to send the entire point as a single
292 UDP payload, and process the next point.
2931. Since the point has a timestamp, re-use the existing measurement name,
294 tagset, and timestamp and create multiple new points by splitting up the
295 fields. The per-point length will be kept close to the configured size,
296 staying under it if possible. This does mean that one large field, maybe a
297 long string, could be sent as a larger-than-configured payload.
298
299The above logic attempts to respect configured payload sizes, but not sacrifice
300any data integrity. Points without a timestamp can't be split, as that may
301cause fields to have differing timestamps when processed by the server.
302
303## Go Docs
304
305Please refer to
306[http://godoc.org/github.com/influxdata/influxdb/client/v2](http://godoc.org/github.com/influxdata/influxdb/client/v2)
307for documentation.
308
309## See Also
310
311You can also examine how the client library is used by the
312[InfluxDB CLI](https://github.com/influxdata/influxdb/blob/master/cmd/influx/main.go).
313