commit
e11262c398
|
@ -7,6 +7,7 @@
|
|||
- [#1877](https://github.com/influxdb/influxdb/pull/1877): Broker clients track broker leader
|
||||
- [#1862](https://github.com/influxdb/influxdb/pull/1862): Fix memory leak in `httpd.serveWait`. Thanks @mountkin
|
||||
- [#1868](https://github.com/influxdb/influxdb/pull/1868): Use `BatchPoints` for `client.Write` method. Thanks @vladlopes, @georgmu, @d2g, @evanphx, @akolosov.
|
||||
- [#1881](https://github.com/influxdb/influxdb/pull/1881): Update documentation for `client` package. Misc library tweaks.
|
||||
|
||||
## v0.9.0-rc9 [2015-03-06]
|
||||
|
||||
|
|
|
@ -1,4 +1,9 @@
|
|||
InfluxDB Go Client Library
|
||||
============
|
||||
|
||||
# TODO Add links to the godoc and examples when they are written
|
||||
Please refer to [http://godoc.org/github.com/influxdb/influxdb/client](http://godoc.org/github.com/influxdb/influxdb/client)
|
||||
for documentation.
|
||||
|
||||
# Currently Used:
|
||||
|
||||
You can see a use of the client libray in the [InfluxDB CLI](https://github.com/influxdb/influxdb/blob/master/cmd/influx/main.go).
|
||||
|
|
|
@ -12,11 +12,16 @@ import (
|
|||
"github.com/influxdb/influxdb/influxql"
|
||||
)
|
||||
|
||||
// Query is used to send a command to the server. Both Command and Database are required.
|
||||
type Query struct {
|
||||
Command string
|
||||
Database string
|
||||
}
|
||||
|
||||
// Config is used to specify what server to connect to.
|
||||
// URL: The URL of the server connecting to.
|
||||
// Username/Password are optional. They will be passed via basic auth if provided.
|
||||
// UserAgent: If not provided, will default "InfluxDBClient",
|
||||
type Config struct {
|
||||
URL url.URL
|
||||
Username string
|
||||
|
@ -24,6 +29,7 @@ type Config struct {
|
|||
UserAgent string
|
||||
}
|
||||
|
||||
// Client is used to make calls to the server.
|
||||
type Client struct {
|
||||
url url.URL
|
||||
username string
|
||||
|
@ -32,6 +38,7 @@ type Client struct {
|
|||
userAgent string
|
||||
}
|
||||
|
||||
// NewClient will instantiate and return a connected client to issue commands to the server.
|
||||
func NewClient(c Config) (*Client, error) {
|
||||
client := Client{
|
||||
url: c.URL,
|
||||
|
@ -40,13 +47,20 @@ func NewClient(c Config) (*Client, error) {
|
|||
httpClient: &http.Client{},
|
||||
userAgent: c.UserAgent,
|
||||
}
|
||||
if client.userAgent == "" {
|
||||
client.userAgent = "InfluxDBClient"
|
||||
}
|
||||
return &client, nil
|
||||
}
|
||||
|
||||
// Query sends a command to the server and returns the Results
|
||||
func (c *Client) Query(q Query) (*Results, error) {
|
||||
u := c.url
|
||||
|
||||
u.Path = "query"
|
||||
if c.username != "" {
|
||||
u.User = url.UserPassword(c.username, c.password)
|
||||
}
|
||||
values := u.Query()
|
||||
values.Set("q", q.Command)
|
||||
values.Set("db", q.Database)
|
||||
|
@ -56,9 +70,7 @@ func (c *Client) Query(q Query) (*Results, error) {
|
|||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if c.userAgent != "" {
|
||||
req.Header.Set("User-Agent", c.userAgent)
|
||||
}
|
||||
req.Header.Set("User-Agent", c.userAgent)
|
||||
resp, err := c.httpClient.Do(req)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
@ -75,6 +87,9 @@ func (c *Client) Query(q Query) (*Results, error) {
|
|||
return &results, nil
|
||||
}
|
||||
|
||||
// Write takes BatchPoints and allows for writing of multiple points with defaults
|
||||
// If successful, error is nil and Results is nil
|
||||
// If an error occurs, Results may contain additional information if populated.
|
||||
func (c *Client) Write(bp BatchPoints) (*Results, error) {
|
||||
c.url.Path = "write"
|
||||
|
||||
|
@ -88,9 +103,7 @@ func (c *Client) Write(bp BatchPoints) (*Results, error) {
|
|||
return nil, err
|
||||
}
|
||||
req.Header.Set("Content-Type", "application/json")
|
||||
if c.userAgent != "" {
|
||||
req.Header.Set("User-Agent", c.userAgent)
|
||||
}
|
||||
req.Header.Set("User-Agent", c.userAgent)
|
||||
resp, err := c.httpClient.Do(req)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
@ -109,9 +122,11 @@ func (c *Client) Write(bp BatchPoints) (*Results, error) {
|
|||
return &results, results.Error()
|
||||
}
|
||||
|
||||
return &results, nil
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
// Ping will check to see if the server is up
|
||||
// Ping returns how long the requeset took, the version of the server it connected to, and an error if one occured.
|
||||
func (c *Client) Ping() (time.Duration, string, error) {
|
||||
now := time.Now()
|
||||
u := c.url
|
||||
|
@ -121,9 +136,7 @@ func (c *Client) Ping() (time.Duration, string, error) {
|
|||
if err != nil {
|
||||
return 0, "", err
|
||||
}
|
||||
if c.userAgent != "" {
|
||||
req.Header.Set("User-Agent", c.userAgent)
|
||||
}
|
||||
req.Header.Set("User-Agent", c.userAgent)
|
||||
resp, err := c.httpClient.Do(req)
|
||||
if err != nil {
|
||||
return 0, "", err
|
||||
|
@ -183,7 +196,8 @@ type Results struct {
|
|||
Err error
|
||||
}
|
||||
|
||||
func (r Results) MarshalJSON() ([]byte, error) {
|
||||
// MarshalJSON encodes the result into JSON.
|
||||
func (r *Results) MarshalJSON() ([]byte, error) {
|
||||
// Define a struct that outputs "error" as a string.
|
||||
var o struct {
|
||||
Results []Result `json:"results,omitempty"`
|
||||
|
@ -234,6 +248,9 @@ func (a Results) Error() error {
|
|||
}
|
||||
|
||||
// Point defines the fields that will be written to the database
|
||||
// Name, Timestamp, and Fields are required
|
||||
// Precision can be specified if the timestamp is in epoch format (integer).
|
||||
// Valid values for Precision are n, u, ms, s, m, and h
|
||||
type Point struct {
|
||||
Name string
|
||||
Tags map[string]string
|
||||
|
@ -341,6 +358,12 @@ func normalizeFields(fields map[string]interface{}) map[string]interface{} {
|
|||
}
|
||||
|
||||
// BatchPoints is used to send batched data in a single write.
|
||||
// Database and Points are required
|
||||
// If no retention policy is specified, it will use the databases default retention policy.
|
||||
// If tags are specified, they will be "merged" with all points. If a point already has that tag, it is ignored.
|
||||
// If timestamp is specified, it will be applied to any point with an empty timestamp.
|
||||
// Precision can be specified if the timestamp is in epoch format (integer).
|
||||
// Valid values for Precision are n, u, ms, s, m, and h
|
||||
type BatchPoints struct {
|
||||
Points []Point `json:"points,omitempty"`
|
||||
Database string `json:"database,omitempty"`
|
||||
|
@ -409,6 +432,7 @@ func (bp *BatchPoints) UnmarshalJSON(b []byte) error {
|
|||
|
||||
// utility functions
|
||||
|
||||
// Addr provides the current url as a string of the server the client is connected to.
|
||||
func (c *Client) Addr() string {
|
||||
return c.url.String()
|
||||
}
|
||||
|
|
|
@ -6,6 +6,7 @@ import (
|
|||
"net/http"
|
||||
"net/http/httptest"
|
||||
"net/url"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
|
@ -134,8 +135,6 @@ func TestClient_UserAgent(t *testing.T) {
|
|||
t.Fatalf("unexpected error. expected %v, actual %v", nil, err)
|
||||
}
|
||||
|
||||
defaultUserAgent := receivedUserAgent
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
userAgent string
|
||||
|
@ -144,7 +143,7 @@ func TestClient_UserAgent(t *testing.T) {
|
|||
{
|
||||
name: "Empty user agent",
|
||||
userAgent: "",
|
||||
expected: defaultUserAgent,
|
||||
expected: "InfluxDBClient",
|
||||
},
|
||||
{
|
||||
name: "Custom user agent",
|
||||
|
@ -167,7 +166,7 @@ func TestClient_UserAgent(t *testing.T) {
|
|||
if err != nil {
|
||||
t.Fatalf("unexpected error. expected %v, actual %v", nil, err)
|
||||
}
|
||||
if receivedUserAgent != test.expected {
|
||||
if !strings.HasPrefix(receivedUserAgent, test.expected) {
|
||||
t.Fatalf("Unexpected user agent. expected %v, actual %v", test.expected, receivedUserAgent)
|
||||
}
|
||||
|
||||
|
@ -177,7 +176,7 @@ func TestClient_UserAgent(t *testing.T) {
|
|||
if err != nil {
|
||||
t.Fatalf("unexpected error. expected %v, actual %v", nil, err)
|
||||
}
|
||||
if receivedUserAgent != test.expected {
|
||||
if !strings.HasPrefix(receivedUserAgent, test.expected) {
|
||||
t.Fatalf("Unexpected user agent. expected %v, actual %v", test.expected, receivedUserAgent)
|
||||
}
|
||||
|
||||
|
|
|
@ -690,7 +690,7 @@ func TestClientLibrary(t *testing.T) {
|
|||
},
|
||||
{
|
||||
name: "no points",
|
||||
writeExpected: `{}`,
|
||||
writeExpected: `null`,
|
||||
bp: client.BatchPoints{Database: "mydb"},
|
||||
},
|
||||
{
|
||||
|
@ -701,7 +701,7 @@ func TestClientLibrary(t *testing.T) {
|
|||
{Name: "cpu", Fields: map[string]interface{}{"value": 1.1}, Timestamp: now},
|
||||
},
|
||||
},
|
||||
writeExpected: `{}`,
|
||||
writeExpected: `null`,
|
||||
query: client.Query{Command: `select * from "mydb"."myrp".cpu`},
|
||||
queryExpected: fmt.Sprintf(`{"results":[{"series":[{"name":"cpu","columns":["time","value"],"values":[["%s",1.1]]}]}]}`, now.Format(time.RFC3339Nano)),
|
||||
},
|
||||
|
@ -726,7 +726,7 @@ func TestClientLibrary(t *testing.T) {
|
|||
}
|
||||
|
||||
if test.query.Command != "" {
|
||||
time.Sleep(50 * time.Millisecond)
|
||||
time.Sleep(100 * time.Millisecond)
|
||||
queryResult, err := c.Query(test.query)
|
||||
if test.queryErr != errToString(err) {
|
||||
t.Errorf("unexpected error. expected: %s, got %v", test.queryErr, err)
|
||||
|
|
Loading…
Reference in New Issue