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  }