README.md
1# InfluxDB Client Go
2
3[![CircleCI](https://circleci.com/gh/influxdata/influxdb-client-go.svg?style=svg)](https://circleci.com/gh/influxdata/influxdb-client-go)
4[![codecov](https://codecov.io/gh/influxdata/influxdb-client-go/branch/master/graph/badge.svg)](https://codecov.io/gh/influxdata/influxdb-client-go)
5[![License](https://img.shields.io/github/license/influxdata/influxdb-client-go.svg)](https://github.com/influxdata/influxdb-client-go/blob/master/LICENSE)
6[![Slack Status](https://img.shields.io/badge/slack-join_chat-white.svg?logo=slack&style=social)](https://www.influxdata.com/slack)
7
8This repository contains the reference Go client for InfluxDB 2.
9
10#### Note: Use this client library with InfluxDB 2.x and InfluxDB 1.8+ ([see details](#influxdb-18-api-compatibility)). For connecting to InfluxDB 1.7 or earlier instances, use the [influxdb1-go](https://github.com/influxdata/influxdb1-client) client library.
11
12- [Features](#features)
13- [Documentation](#documentation)
14 - [Examples](#examples)
15- [How To Use](#how-to-use)
16 - [Basic Example](#basic-example)
17 - [Writes in Detail](#writes)
18 - [Queries in Detail](#queries)
19 - [Concurrency](#concurrency)
20- [InfluxDB 1.8 API compatibility](#influxdb-18-api-compatibility)
21- [Contributing](#contributing)
22- [License](#license)
23
24## Features
25
26- InfluxDB 2 client
27 - Querying data
28 - using the Flux language
29 - into raw data, flux table representation
30 - [How to queries](#queries)
31 - Writing data using
32 - [Line Protocol](https://docs.influxdata.com/influxdb/v1.6/write_protocols/line_protocol_tutorial/)
33 - [Data Point](https://pkg.go.dev/github.com/influxdata/influxdb-client-go/v2/api/write#Point)
34 - Both [asynchronous](https://pkg.go.dev/github.com/influxdata/influxdb-client-go/v2/api#WriteAPI) or [synchronous](https://pkg.go.dev/github.com/influxdata/influxdb-client-go/v2/api#WriteAPIBlocking) ways
35 - [How to writes](#writes)
36 - InfluxDB 2 API
37 - setup, ready, health
38 - authotizations, users, organizations
39 - buckets, delete
40 - ...
41
42## Documentation
43
44Go API docs is available at: [https://pkg.go.dev/github.com/influxdata/influxdb-client-go/v2](https://pkg.go.dev/github.com/influxdata/influxdb-client-go/v2)
45
46### Examples
47
48Examples for basic writing and querying data are shown below in this document
49
50There are also other examples in the API docs:
51 - [Client usage](https://pkg.go.dev/github.com/influxdata/influxdb-client-go/v2?tab=doc#pkg-examples)
52 - [Management APIs](https://pkg.go.dev/github.com/influxdata/influxdb-client-go/v2/api?tab=doc#pkg-examples)
53
54## How To Use
55
56### Installation
57**Go 1.13** or later is required.
58
591. Add the client package your to your project dependencies (go.mod).
60 ```sh
61 go get github.com/influxdata/influxdb-client-go/v2
62 ```
631. Add import `github.com/influxdata/influxdb-client-go/v2` to your source code.
64
65### Basic Example
66The following example demonstrates how to write data to InfluxDB 2 and read them back using the Flux language:
67```go
68package main
69
70import (
71 "context"
72 "fmt"
73 "time"
74
75 "github.com/influxdata/influxdb-client-go/v2"
76)
77
78func main() {
79 // Create a new client using an InfluxDB server base URL and an authentication token
80 client := influxdb2.NewClient("http://localhost:8086", "my-token")
81 // Use blocking write client for writes to desired bucket
82 writeAPI := client.WriteAPIBlocking("my-org", "my-bucket")
83 // Create point using full params constructor
84 p := influxdb2.NewPoint("stat",
85 map[string]string{"unit": "temperature"},
86 map[string]interface{}{"avg": 24.5, "max": 45.0},
87 time.Now())
88 // write point immediately
89 writeAPI.WritePoint(context.Background(), p)
90 // Create point using fluent style
91 p = influxdb2.NewPointWithMeasurement("stat").
92 AddTag("unit", "temperature").
93 AddField("avg", 23.2).
94 AddField("max", 45.0).
95 SetTime(time.Now())
96 writeAPI.WritePoint(context.Background(), p)
97
98 // Or write directly line protocol
99 line := fmt.Sprintf("stat,unit=temperature avg=%f,max=%f", 23.5, 45.0)
100 writeAPI.WriteRecord(context.Background(), line)
101
102 // Get query client
103 queryAPI := client.QueryAPI("my-org")
104 // Get parser flux query result
105 result, err := queryAPI.Query(context.Background(), `from(bucket:"my-bucket")|> range(start: -1h) |> filter(fn: (r) => r._measurement == "stat")`)
106 if err == nil {
107 // Use Next() to iterate over query result lines
108 for result.Next() {
109 // Observe when there is new grouping key producing new table
110 if result.TableChanged() {
111 fmt.Printf("table: %s\n", result.TableMetadata().String())
112 }
113 // read result
114 fmt.Printf("row: %s\n", result.Record().String())
115 }
116 if result.Err() != nil {
117 fmt.Printf("Query error: %s\n", result.Err().Error())
118 }
119 }
120 // Ensures background processes finishes
121 client.Close()
122}
123```
124### Options
125The InfluxDBClient uses set of options to configure behavior. These are available in the [Options](https://pkg.go.dev/github.com/influxdata/influxdb-client-go/v2#Options) object
126Creating a client instance using
127```go
128client := influxdb2.NewClient("http://localhost:8086", "my-token")
129```
130will use the default options.
131
132To set different configuration values, e.g. to set gzip compression and trust all server certificates, get default options
133and change what is needed:
134```go
135client := influxdb2.NewClientWithOptions("http://localhost:8086", "my-token",
136 influxdb2.DefaultOptions().
137 SetUseGZip(true).
138 SetTLSConfig(&tls.Config{
139 InsecureSkipVerify: true,
140 }))
141```
142### Writes
143
144Client offers two ways of writing, non-blocking and blocking.
145
146### Non-blocking write client
147Non-blocking write client uses implicit batching. Data are asynchronously
148written to the underlying buffer and they are automatically sent to a server when the size of the write buffer reaches the batch size, default 5000, or the flush interval, default 1s, times out.
149Writes are automatically retried on server back pressure.
150
151This write client also offers synchronous blocking method to ensure that write buffer is flushed and all pending writes are finished,
152see [Flush()](https://pkg.go.dev/github.com/influxdata/influxdb-client-go/v2/api#WriteAPI.Flush) method.
153Always use [Close()](https://pkg.go.dev/github.com/influxdata/influxdb-client-go/v2#Client.Close) method of the client to stop all background processes.
154
155Asynchronous write client is recommended for frequent periodic writes.
156
157```go
158package main
159
160import (
161 "fmt"
162 "math/rand"
163 "time"
164
165 "github.com/influxdata/influxdb-client-go/v2"
166)
167
168func main() {
169 // Create a new client using an InfluxDB server base URL and an authentication token
170 // and set batch size to 20
171 client := influxdb2.NewClientWithOptions("http://localhost:8086", "my-token",
172 influxdb2.DefaultOptions().SetBatchSize(20))
173 // Get non-blocking write client
174 writeAPI := client.WriteAPI("my-org","my-bucket")
175 // write some points
176 for i := 0; i <100; i++ {
177 // create point
178 p := influxdb2.NewPoint(
179 "system",
180 map[string]string{
181 "id": fmt.Sprintf("rack_%v", i%10),
182 "vendor": "AWS",
183 "hostname": fmt.Sprintf("host_%v", i%100),
184 },
185 map[string]interface{}{
186 "temperature": rand.Float64() * 80.0,
187 "disk_free": rand.Float64() * 1000.0,
188 "disk_total": (i/10 + 1) * 1000000,
189 "mem_total": (i/100 + 1) * 10000000,
190 "mem_free": rand.Uint64(),
191 },
192 time.Now())
193 // write asynchronously
194 writeAPI.WritePoint(p)
195 }
196 // Force all unwritten data to be sent
197 writeAPI.Flush()
198 // Ensures background processes finishes
199 client.Close()
200}
201```
202
203### Reading async errors
204[Errors()](https://pkg.go.dev/github.com/influxdata/influxdb-client-go/v2/api#WriteAPI.Errors) method returns a channel for reading errors which occurs during async writes. This channel is unbuffered and it
205must be read asynchronously otherwise will block write procedure:
206
207```go
208package main
209
210import (
211 "fmt"
212 "math/rand"
213 "time"
214
215 "github.com/influxdata/influxdb-client-go/v2"
216)
217
218func main() {
219 // Create a new client using an InfluxDB server base URL and an authentication token
220 client := influxdb2.NewClient("http://localhost:8086", "my-token")
221 // Get non-blocking write client
222 writeAPI := client.WriteAPI("my-org", "my-bucket")
223 // Get errors channel
224 errorsCh := writeAPI.Errors()
225 // Create go proc for reading and logging errors
226 go func() {
227 for err := range errorsCh {
228 fmt.Printf("write error: %s\n", err.Error())
229 }
230 }()
231 // write some points
232 for i := 0; i < 100; i++ {
233 // create point
234 p := influxdb2.NewPointWithMeasurement("stat").
235 AddTag("id", fmt.Sprintf("rack_%v", i%10)).
236 AddTag("vendor", "AWS").
237 AddTag("hostname", fmt.Sprintf("host_%v", i%100)).
238 AddField("temperature", rand.Float64()*80.0).
239 AddField("disk_free", rand.Float64()*1000.0).
240 AddField("disk_total", (i/10+1)*1000000).
241 AddField("mem_total", (i/100+1)*10000000).
242 AddField("mem_free", rand.Uint64()).
243 SetTime(time.Now())
244 // write asynchronously
245 writeAPI.WritePoint(p)
246 }
247 // Force all unwritten data to be sent
248 writeAPI.Flush()
249 // Ensures background processes finishes
250 client.Close()
251}
252```
253
254### Blocking write client
255Blocking write client writes given point(s) synchronously. It doesn't have implicit batching. Batch is created from given set of points.
256
257```go
258package main
259
260import (
261 "context"
262 "fmt"
263 "math/rand"
264 "time"
265
266 "github.com/influxdata/influxdb-client-go/v2"
267)
268
269func main() {
270 // Create a new client using an InfluxDB server base URL and an authentication token
271 client := influxdb2.NewClient("http://localhost:8086", "my-token")
272 // Get blocking write client
273 writeAPI := client.WriteAPIBlocking("my-org","my-bucket")
274 // write some points
275 for i := 0; i <100; i++ {
276 // create data point
277 p := influxdb2.NewPoint(
278 "system",
279 map[string]string{
280 "id": fmt.Sprintf("rack_%v", i%10),
281 "vendor": "AWS",
282 "hostname": fmt.Sprintf("host_%v", i%100),
283 },
284 map[string]interface{}{
285 "temperature": rand.Float64() * 80.0,
286 "disk_free": rand.Float64() * 1000.0,
287 "disk_total": (i/10 + 1) * 1000000,
288 "mem_total": (i/100 + 1) * 10000000,
289 "mem_free": rand.Uint64(),
290 },
291 time.Now())
292 // write synchronously
293 err := writeAPI.WritePoint(context.Background(), p)
294 if err != nil {
295 panic(err)
296 }
297 }
298 // Ensures background processes finishes
299 client.Close()
300}
301```
302
303### Queries
304Query client offers retrieving of query results to a parsed representation in a [QueryTableResult](https://pkg.go.dev/github.com/influxdata/influxdb-client-go/v2/api#QueryTableResult) or to a raw string.
305
306### QueryTableResult
307QueryTableResult offers comfortable way how to deal with flux query CSV response. It parses CSV stream into FluxTableMetaData, FluxColumn and FluxRecord objects
308for easy reading the result.
309
310```go
311package main
312
313import (
314 "context"
315 "fmt"
316
317 "github.com/influxdata/influxdb-client-go/v2"
318)
319
320func main() {
321 // Create a new client using an InfluxDB server base URL and an authentication token
322 client := influxdb2.NewClient("http://localhost:8086", "my-token")
323 // Get query client
324 queryAPI := client.QueryAPI("my-org")
325 // get QueryTableResult
326 result, err := queryAPI.Query(context.Background(), `from(bucket:"my-bucket")|> range(start: -1h) |> filter(fn: (r) => r._measurement == "stat")`)
327 if err == nil {
328 // Iterate over query response
329 for result.Next() {
330 // Notice when group key has changed
331 if result.TableChanged() {
332 fmt.Printf("table: %s\n", result.TableMetadata().String())
333 }
334 // Access data
335 fmt.Printf("value: %v\n", result.Record().Value())
336 }
337 // check for an error
338 if result.Err() != nil {
339 fmt.Printf("query parsing error: %s\n", result.Err().Error())
340 }
341 } else {
342 panic(err)
343 }
344 // Ensures background processes finishes
345 client.Close()
346}
347```
348
349### Raw
350[QueryRaw()](https://pkg.go.dev/github.com/influxdata/influxdb-client-go/v2/api#QueryAPI.QueryRaw) returns raw, unparsed, query result string and process it on your own. Returned csv format
351can be controlled by the third parameter, query dialect.
352
353```go
354package main
355
356import (
357 "context"
358 "fmt"
359
360 "github.com/influxdata/influxdb-client-go/v2"
361)
362
363func main() {
364 // Create a new client using an InfluxDB server base URL and an authentication token
365 client := influxdb2.NewClient("http://localhost:8086", "my-token")
366 // Get query client
367 queryAPI := client.QueryAPI("my-org")
368 // Query and get complete result as a string
369 // Use default dialect
370 result, err := queryAPI.QueryRaw(context.Background(), `from(bucket:"my-bucket")|> range(start: -1h) |> filter(fn: (r) => r._measurement == "stat")`, influxdb2.DefaultDialect())
371 if err == nil {
372 fmt.Println("QueryResult:")
373 fmt.Println(result)
374 } else {
375 panic(err)
376 }
377 // Ensures background processes finishes
378 client.Close()
379}
380```
381### Concurrency
382InfluxDB Go Client can be used in a concurrent environment. All its functions are thread-safe.
383
384The best practise is to use a single `Client` instance per server URL. This ensures optimized resources usage,
385most importantly reusing HTTP connections.
386
387For efficient reuse of HTTP resources among multiple clients, create an HTTP client and use `Options.SetHTTPClient()` for setting it to all clients:
388```go
389 // Create HTTP client
390 httpClient := &http.Client{
391 Timeout: time.Second * time.Duration(60),
392 Transport: &http.Transport{
393 DialContext: (&net.Dialer{
394 Timeout: 5 * time.Second,
395 }).DialContext,
396 TLSHandshakeTimeout: 5 * time.Second,
397 TLSClientConfig: &tls.Config{
398 InsecureSkipVerify: true,
399 },
400 MaxIdleConns: 100,
401 MaxIdleConnsPerHost: 100,
402 IdleConnTimeout: 90 * time.Second,
403 },
404 }
405 // Client for server 1
406 client1 := influxdb2.NewClientWithOptions("https://server:8086", "my-token", influxdb2.DefaultOptions().SetHTTPClient(httpClient))
407 // Client for server 2
408 client2 := influxdb2.NewClientWithOptions("https://server:9999", "my-token2", influxdb2.DefaultOptions().SetHTTPClient(httpClient))
409```
410
411Client ensures that there is a single instance of each server API sub-client for the specific area. E.g. a single `WriteAPI` instance for each org/bucket pair,
412a single `QueryAPI` for each org.
413
414Such a single API sub-client instance can be used concurrently:
415```go
416package main
417
418import (
419 "math/rand"
420 "sync"
421 "time"
422
423 influxdb2 "github.com/influxdata/influxdb-client-go"
424 "github.com/influxdata/influxdb-client-go/v2/api/write"
425)
426
427func main() {
428 // Create client
429 client := influxdb2.NewClient("http://localhost:8086", "my-token")
430 // Ensure closing the client
431 defer client.Close()
432
433 // Get write client
434 writeApi := client.WriteAPI("my-org", "my-bucket")
435
436 // Create channel for points feeding
437 pointsCh := make(chan *write.Point, 200)
438
439 threads := 5
440
441 var wg sync.WaitGroup
442 go func(points int) {
443 for i := 0; i < points; i++ {
444 p := influxdb2.NewPoint("meas",
445 map[string]string{"tag": "tagvalue"},
446 map[string]interface{}{"val1": rand.Int63n(1000), "val2": rand.Float64()*100.0 - 50.0},
447 time.Now())
448 pointsCh <- p
449 }
450 close(pointsCh)
451 }(1000000)
452
453 // Launch write routines
454 for t := 0; t < threads; t++ {
455 wg.Add(1)
456 go func() {
457 for p := range pointsCh {
458 writeApi.WritePoint(p)
459 }
460 wg.Done()
461 }()
462 }
463 // Wait for writes complete
464 wg.Wait()
465}
466```
467
468## InfluxDB 1.8 API compatibility
469
470 [InfluxDB 1.8.0 introduced forward compatibility APIs](https://docs.influxdata.com/influxdb/latest/tools/api/#influxdb-2-0-api-compatibility-endpoints) for InfluxDB 2.0. This allow you to easily move from InfluxDB 1.x to InfluxDB 2.0 Cloud or open source.
471
472 Client API usage differences summary:
473 1. Use the form `username:password` for an **authentication token**. Example: `my-user:my-password`. Use an empty string (`""`) if the server doesn't require authentication.
474 1. The organization parameter is not used. Use an empty string (`""`) where necessary.
475 1. Use the form `database/retention-policy` where a **bucket** is required. Skip retention policy if the default retention policy should be used. Examples: `telegraf/autogen`, `telegraf`.
476
477 The following forward compatible APIs are available:
478
479 | API | Endpoint | Description |
480 |:----------|:----------|:----------|
481 | [WriteAPI](https://pkg.go.dev/github.com/influxdata/influxdb-client-go/v2/api#WriteAPI) (also [WriteAPIBlocking](https://pkg.go.dev/github.com/influxdata/influxdb-client-go/v2/api#WriteAPIBlocking))| [/api/v2/write](https://docs.influxdata.com/influxdb/v2.0/write-data/developer-tools/api/) | Write data to InfluxDB 1.8.0+ using the InfluxDB 2.0 API |
482 | [QueryAPI](https://pkg.go.dev/github.com/influxdata/influxdb-client-go/v2/api#QueryAPI) | [/api/v2/query](https://docs.influxdata.com/influxdb/v2.0/query-data/execute-queries/influx-api/) | Query data in InfluxDB 1.8.0+ using the InfluxDB 2.0 API and [Flux](https://docs.influxdata.com/flux/latest/) endpoint should be enabled by the [`flux-enabled` option](https://docs.influxdata.com/influxdb/v1.8/administration/config/#flux-enabled-false)
483 | [Health()](https://pkg.go.dev/github.com/influxdata/influxdb-client-go/v2#Client.Health) | [/health](https://docs.influxdata.com/influxdb/v2.0/api/#tag/Health) | Check the health of your InfluxDB instance |
484
485
486### Example
487```go
488package main
489
490import (
491 "context"
492 "fmt"
493 "time"
494
495 "github.com/influxdata/influxdb-client-go/v2"
496)
497
498func main() {
499 userName := "my-user"
500 password := "my-password"
501 // Create a new client using an InfluxDB server base URL and an authentication token
502 // For authentication token supply a string in the form: "username:password" as a token. Set empty value for an unauthenticated server
503 client := influxdb2.NewClient("http://localhost:8086", fmt.Sprintf("%s:%s",userName, password))
504 // Get the blocking write client
505 // Supply a string in the form database/retention-policy as a bucket. Skip retention policy for the default one, use just a database name (without the slash character)
506 // Org name is not used
507 writeAPI := client.WriteAPIBlocking("", "test/autogen")
508 // create point using full params constructor
509 p := influxdb2.NewPoint("stat",
510 map[string]string{"unit": "temperature"},
511 map[string]interface{}{"avg": 24.5, "max": 45},
512 time.Now())
513 // Write data
514 err := writeAPI.WritePoint(context.Background(), p)
515 if err != nil {
516 fmt.Printf("Write error: %s\n", err.Error())
517 }
518
519 // Get query client. Org name is not used
520 queryAPI := client.QueryAPI("")
521 // Supply string in a form database/retention-policy as a bucket. Skip retention policy for the default one, use just a database name (without the slash character)
522 result, err := queryAPI.Query(context.Background(), `from(bucket:"test")|> range(start: -1h) |> filter(fn: (r) => r._measurement == "stat")`)
523 if err == nil {
524 for result.Next() {
525 if result.TableChanged() {
526 fmt.Printf("table: %s\n", result.TableMetadata().String())
527 }
528 fmt.Printf("row: %s\n", result.Record().String())
529 }
530 if result.Err() != nil {
531 fmt.Printf("Query error: %s\n", result.Err().Error())
532 }
533 } else {
534 fmt.Printf("Query error: %s\n", err.Error())
535 }
536 // Close client
537 client.Close()
538}
539```
540
541## Contributing
542
543If you would like to contribute code you can do through GitHub by forking the repository and sending a pull request into the `master` branch.
544
545## License
546
547The InfluxDB 2 Go Client is released under the [MIT License](https://opensource.org/licenses/MIT).
548