github.com/sereiner/library@v0.0.0-20200518095232-1fa3e640cc5f/influxdb/client.go (about) 1 package influxdb 2 3 import ( 4 "errors" 5 "fmt" 6 "log" 7 uurl "net/url" 8 "time" 9 //"github.com/sereiner/library/influxdb" 10 //"github.com/sereiner/library/influxdb" 11 ) 12 13 type IInfluxClient interface { 14 QueryResponse(sql string) (response *Response, err error) 15 QueryMaps(sql string) (rx [][]map[string]interface{}, err error) 16 Query(sql string) (result string, err error) 17 SendLineProto(data string) error 18 Send(measurement string, tags map[string]string, fileds map[string]interface{}) error 19 Close() error 20 } 21 22 type InfluxClient struct { 23 interval time.Duration 24 url uurl.URL 25 database string 26 username string 27 password string 28 client *Client 29 closeCh chan struct{} 30 done bool 31 } 32 33 // newInfluxClient starts a InfluxDB reporter which will post the metrics from the given registry at each d interval with the specified tags 34 func NewInfluxClient(url, database, username, password string) (*InfluxClient, error) { 35 u, err := uurl.Parse(url) 36 if err != nil { 37 return nil, fmt.Errorf("unable to parse InfluxDB url %s. err=%v", url, err) 38 } 39 40 rep := &InfluxClient{ 41 url: *u, 42 database: database, 43 username: username, 44 password: password, 45 closeCh: make(chan struct{}), 46 } 47 48 if err := rep.makeClient(); err != nil { 49 return nil, fmt.Errorf("unable to make InfluxDB client. err=%v", err) 50 } 51 go rep.run() 52 return rep, nil 53 } 54 55 func (r *InfluxClient) makeClient() (err error) { 56 r.client, err = NewClient(Config{ 57 URL: r.url, 58 Timeout: time.Second * 3, 59 UserAgent: "hydra", 60 Username: r.username, 61 Password: r.password, 62 }) 63 return 64 } 65 66 func (r *InfluxClient) run() { 67 pingTicker := time.Tick(time.Second * 5) 68 for { 69 select { 70 case <-r.closeCh: 71 r.client = nil 72 return 73 case <-pingTicker: 74 _, _, err := r.client.Ping() 75 if err != nil { 76 log.Printf("got error while sending a ping to InfluxDB, trying to recreate client. err=%v", err) 77 if err = r.makeClient(); err != nil { 78 log.Printf("unable to make InfluxDB client. err=%v", err) 79 } 80 } 81 } 82 } 83 } 84 func (r *InfluxClient) QueryResponse(sql string) (response *Response, err error) { 85 if r.done { 86 return nil, errors.New("连接已关闭") 87 } 88 response, err = r.client.Query(Query{Command: sql, Database: r.database}) 89 if err != nil { 90 err = fmt.Errorf("query.error:%v", err) 91 return 92 } 93 return 94 } 95 func (r *InfluxClient) QueryMaps(sql string) (rx [][]map[string]interface{}, err error) { 96 if r.done { 97 return nil, errors.New("连接已关闭") 98 } 99 response, err := r.client.Query(Query{Command: sql, Database: r.database}) 100 if err != nil { 101 err = fmt.Errorf("query.error:%v", err) 102 return 103 } 104 if err = response.Error(); err != nil { 105 return nil, fmt.Errorf("response.error:%v", err) 106 } 107 rx = make([][]map[string]interface{}, 0, len(response.Results)) 108 for _, v := range response.Results { 109 result := make([]map[string]interface{}, 0, 0) 110 for _, row := range v.Series { 111 for _, value := range row.Values { 112 srow := make(map[string]interface{}) 113 for y, col := range row.Columns { 114 srow[col] = value[y] 115 } 116 result = append(result, srow) 117 } 118 119 } 120 rx = append(rx, result) 121 } 122 return rx, nil 123 } 124 func (r *InfluxClient) Query(sql string) (result string, err error) { 125 if r.done { 126 return "", errors.New("连接已关闭") 127 } 128 response, err := r.client.Query(Query{Command: sql, Database: r.database}) 129 if err != nil { 130 err = fmt.Errorf("query.error:%v", err) 131 return 132 } 133 if err = response.Error(); err != nil { 134 return "", fmt.Errorf("response.error:%v", err) 135 } 136 buf, err := response.MarshalJSON() 137 if err != nil { 138 err = fmt.Errorf("query.result.marshal.error:%v", err) 139 return 140 } 141 result = string(buf) 142 return 143 } 144 func (r *InfluxClient) SendLineProto(data string) error { 145 if r.done { 146 return errors.New("连接已关闭") 147 } 148 _, err := r.client.WriteLineProtocol(data, r.database, "default", "us", "") 149 return err 150 151 } 152 func (r *InfluxClient) Send(measurement string, tags map[string]string, fileds map[string]interface{}) error { 153 if r.done { 154 return errors.New("连接已关闭") 155 } 156 var pts []Point 157 pts = append(pts, Point{ 158 Measurement: measurement, 159 Tags: tags, 160 Fields: fileds, 161 Time: time.Now(), 162 }) 163 164 bps := BatchPoints{ 165 Points: pts, 166 Database: r.database, 167 } 168 169 _, err := r.client.Write(bps) 170 return err 171 } 172 func (r *InfluxClient) Close() error { 173 r.done = true 174 close(r.closeCh) 175 return nil 176 }