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