mirror of https://github.com/prometheus/prometheus
Browse Source
Because the InfluxDB client library currently pulls in multiple MBs of unnecessary dependencies, I have modified and cut up the vendored version to only pull in the few pieces that are actually needed. On InfluxDB's side, this dependency issue is tracked in: https://github.com/influxdb/influxdb/issues/3447 Hopefully, it will be resolved soon. If a password is needed for InfluxDB, it may be supplied via the INFLUXDB_PW environment variable.pull/1087/head
Julius Volz
9 years ago
7 changed files with 1717 additions and 120 deletions
@ -0,0 +1,180 @@ |
|||||||
|
package client |
||||||
|
|
||||||
|
import ( |
||||||
|
"bytes" |
||||||
|
"fmt" |
||||||
|
"io/ioutil" |
||||||
|
"net/http" |
||||||
|
"net/url" |
||||||
|
"time" |
||||||
|
|
||||||
|
"github.com/influxdb/influxdb/tsdb" |
||||||
|
) |
||||||
|
|
||||||
|
const ( |
||||||
|
// DefaultTimeout is the default connection timeout used to connect to an InfluxDB instance
|
||||||
|
DefaultTimeout = 0 |
||||||
|
) |
||||||
|
|
||||||
|
// 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",
|
||||||
|
// Timeout: If not provided, will default to 0 (no timeout)
|
||||||
|
type Config struct { |
||||||
|
URL url.URL |
||||||
|
Username string |
||||||
|
Password string |
||||||
|
UserAgent string |
||||||
|
Timeout time.Duration |
||||||
|
Precision string |
||||||
|
} |
||||||
|
|
||||||
|
// NewConfig will create a config to be used in connecting to the client
|
||||||
|
func NewConfig() Config { |
||||||
|
return Config{ |
||||||
|
Timeout: DefaultTimeout, |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
// Client is used to make calls to the server.
|
||||||
|
type Client struct { |
||||||
|
url url.URL |
||||||
|
username string |
||||||
|
password string |
||||||
|
httpClient *http.Client |
||||||
|
userAgent string |
||||||
|
precision string |
||||||
|
} |
||||||
|
|
||||||
|
const ( |
||||||
|
ConsistencyOne = "one" |
||||||
|
ConsistencyAll = "all" |
||||||
|
ConsistencyQuorum = "quorum" |
||||||
|
ConsistencyAny = "any" |
||||||
|
) |
||||||
|
|
||||||
|
// 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, |
||||||
|
username: c.Username, |
||||||
|
password: c.Password, |
||||||
|
httpClient: &http.Client{Timeout: c.Timeout}, |
||||||
|
userAgent: c.UserAgent, |
||||||
|
precision: c.Precision, |
||||||
|
} |
||||||
|
if client.userAgent == "" { |
||||||
|
client.userAgent = "InfluxDBClient" |
||||||
|
} |
||||||
|
return &client, nil |
||||||
|
} |
||||||
|
|
||||||
|
// Write takes BatchPoints and allows for writing of multiple points with defaults
|
||||||
|
// If successful, error is nil and Response is nil
|
||||||
|
// If an error occurs, Response may contain additional information if populated.
|
||||||
|
func (c *Client) Write(bp BatchPoints) (*Response, error) { |
||||||
|
u := c.url |
||||||
|
u.Path = "write" |
||||||
|
|
||||||
|
var b bytes.Buffer |
||||||
|
for _, p := range bp.Points { |
||||||
|
if p.Raw != "" { |
||||||
|
if _, err := b.WriteString(p.Raw); err != nil { |
||||||
|
return nil, err |
||||||
|
} |
||||||
|
} else { |
||||||
|
for k, v := range bp.Tags { |
||||||
|
if p.Tags == nil { |
||||||
|
p.Tags = make(map[string]string, len(bp.Tags)) |
||||||
|
} |
||||||
|
p.Tags[k] = v |
||||||
|
} |
||||||
|
|
||||||
|
if _, err := b.WriteString(p.MarshalString()); err != nil { |
||||||
|
return nil, err |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
if err := b.WriteByte('\n'); err != nil { |
||||||
|
return nil, err |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
req, err := http.NewRequest("POST", u.String(), &b) |
||||||
|
if err != nil { |
||||||
|
return nil, err |
||||||
|
} |
||||||
|
req.Header.Set("Content-Type", "") |
||||||
|
req.Header.Set("User-Agent", c.userAgent) |
||||||
|
if c.username != "" { |
||||||
|
req.SetBasicAuth(c.username, c.password) |
||||||
|
} |
||||||
|
params := req.URL.Query() |
||||||
|
params.Set("db", bp.Database) |
||||||
|
params.Set("rp", bp.RetentionPolicy) |
||||||
|
params.Set("precision", bp.Precision) |
||||||
|
params.Set("consistency", bp.WriteConsistency) |
||||||
|
req.URL.RawQuery = params.Encode() |
||||||
|
|
||||||
|
resp, err := c.httpClient.Do(req) |
||||||
|
if err != nil { |
||||||
|
return nil, err |
||||||
|
} |
||||||
|
defer resp.Body.Close() |
||||||
|
|
||||||
|
var response Response |
||||||
|
body, err := ioutil.ReadAll(resp.Body) |
||||||
|
if err != nil { |
||||||
|
return nil, err |
||||||
|
} |
||||||
|
|
||||||
|
if resp.StatusCode != http.StatusNoContent && resp.StatusCode != http.StatusOK { |
||||||
|
var err = fmt.Errorf(string(body)) |
||||||
|
response.Err = err |
||||||
|
return &response, err |
||||||
|
} |
||||||
|
|
||||||
|
return nil, nil |
||||||
|
} |
||||||
|
|
||||||
|
// Structs
|
||||||
|
|
||||||
|
// Response represents a list of statement results.
|
||||||
|
type Response struct { |
||||||
|
Err error |
||||||
|
} |
||||||
|
|
||||||
|
// Point defines the fields that will be written to the database
|
||||||
|
// Measurement, Time, and Fields are required
|
||||||
|
// Precision can be specified if the time is in epoch format (integer).
|
||||||
|
// Valid values for Precision are n, u, ms, s, m, and h
|
||||||
|
type Point struct { |
||||||
|
Measurement string |
||||||
|
Tags map[string]string |
||||||
|
Time time.Time |
||||||
|
Fields map[string]interface{} |
||||||
|
Precision string |
||||||
|
Raw string |
||||||
|
} |
||||||
|
|
||||||
|
func (p *Point) MarshalString() string { |
||||||
|
return tsdb.NewPoint(p.Measurement, p.Tags, p.Fields, p.Time).String() |
||||||
|
} |
||||||
|
|
||||||
|
// 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 time is specified, it will be applied to any point with an empty time.
|
||||||
|
// Precision can be specified if the time 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"` |
||||||
|
RetentionPolicy string `json:"retentionPolicy,omitempty"` |
||||||
|
Tags map[string]string `json:"tags,omitempty"` |
||||||
|
Time time.Time `json:"time,omitempty"` |
||||||
|
Precision string `json:"precision,omitempty"` |
||||||
|
WriteConsistency string `json:"-"` |
||||||
|
} |
File diff suppressed because it is too large
Load Diff
Loading…
Reference in new issue