package main
import (
"bufio"
"bytes"
"encoding/json"
"fmt"
"io/ioutil"
"log"
"net"
"net/http"
"runtime"
"sort"
"strconv"
"strings"
"sync"
"time"
)
const (
Conn_timeout time.Duration = time.Second * 3
Default_timeout time.Duration = time.Second * 3
)
type Connection struct {
conn net.Conn
lock *sync.RWMutex
Reader *bufio.Reader
Writer *bufio.Writer
}
func NewConn(address string) (*Connection, error) {
_, err := net.ResolveTCPAddr("tcp", address)
if err != nil {
return nil, err
}
conn, err := net.DialTimeout("tcp", address, Conn_timeout)
if err != nil {
return nil, err
}
return &Connection{
conn: conn,
lock: new(sync.RWMutex),
Reader: bufio.NewReader(conn),
Writer: bufio.NewWriter(conn),
}, nil
}
func (conn *Connection) Send(data []byte) error {
//conn.lock.Lock()
conn.conn.SetWriteDeadline(time.Now().Add(Default_timeout))
_, err := conn.Writer.Write(data)
if err != nil {
//conn.lock.Unlock()
return err
}
err = conn.Writer.Flush()
//conn.lock.Unlock()
return err
}
func (conn *Connection) Close() error {
//conn.lock.Lock()
//defer conn.lock.Unlock()
return conn.conn.Close()
}
type TsdbItem struct {
Metric string `json:"metric"`
Tags map[string]string `json:"tags"`
Value float64 `json:"value"`
Timestamp int64 `json:"timestamp"`
}
func (this *TsdbItem) String() string {
return fmt.Sprintf(
"<Metric:%s, Tags:%v, Value:%v, TS:%d>",
this.Metric,
this.Tags,
this.Value,
this.Timestamp,
)
}
func (this *TsdbItem) TsdbString() (s string) {
s = fmt.Sprintf("put %s %d %.3f ", this.Metric, this.Timestamp, this.Value)
for k, v := range this.Tags {
key := strings.ToLower(strings.Replace(k, " ", "_", -1))
value := strings.Replace(v, " ", "_", -1)
s += key + "=" + value + " "
}
return s
}
type MetaData struct {
Metric string `json:"metric"`
Endpoint string `json:"endpoint"`
Timestamp int64 `json:"timestamp"`
Step int64 `json:"step"`
Value float64 `json:"value"`
CounterType string `json:"counterType"`
Tags map[string]string `json:"tags"`
}
func convert2TsdbItem(d *MetaData) *TsdbItem {
t := TsdbItem{Tags: make(map[string]string)}
for k, v := range d.Tags {
t.Tags[k] = v
}
t.Tags["endpoint"] = d.Endpoint
t.Metric = d.Metric
t.Timestamp = d.Timestamp
t.Value = d.Value
return &t
}
func NewMetaData() *MetaData {
return &MetaData{
Metric: "tsdb.status",
Endpoint: "opentsdb",
Tags: make(map[string]string),
Step: 60,
Value: 10,
Timestamp: time.Now().Unix(),
CounterType: "GUAGE",
}
}
func init() {
runtime.GOMAXPROCS(runtime.NumCPU())
log.SetFlags(log.Ldate | log.Ltime | log.Lshortfile)
}
//put data to opentsdb
func PutDataToTsdb() {
c, err := NewConn("10.100.101.70:4242")
if err != nil {
log.Println(err)
return
}
var closeCh chan struct{} = make(chan struct{}, 1)
go func(closeCh chan struct{}, c *Connection) {
ticker := time.NewTicker(Default_timeout)
defer ticker.Stop()
for {
select {
case <-ticker.C:
d := convert2TsdbItem(NewMetaData())
var tsdbBuffer bytes.Buffer
tsdbBuffer.WriteString(d.TsdbString())
tsdbBuffer.WriteString("\n")
err := c.Send(tsdbBuffer.Bytes())
if err != nil {
log.Println(err)
}
log.Println("send tsdb message success, msg content:", d.String())
case <-closeCh:
return
}
}
}(closeCh, c)
/*
//windows not support that.
sigs := make(chan os.Signal, 1)
signal.Notify(sigs, syscall.SIGINT, syscall.SIGTERM, syscall.SIGQUIT)
log.Println(os.Getpid(), "register signal notify")
<-sigs
close(closeCh)
time.Sleep(Default_timeout)
*/
select {}
}
type Query struct {
Aggregator string `json:"aggregator"`
Metric string `json:"metric"`
Rate bool `json:"rate,omitempty"`
Tags map[string]string `json:"tags,omitempty"`
}
type QueryParams struct {
Start interface{} `json:"start"`
End interface{} `json:"end,omitempty"`
Queries []Query `json:"queries,omitempty"`
NoAnnotations bool `json:"no_annotations,omitempty"`
GlobalAnnotations bool `json:"global_annotations,omitempty"`
MsResolution bool `json:"ms,omitempty"`
ShowTSUIDs bool `json:"show_tsuids,omitempty"`
ShowSummary bool `json:"show_summary,omitempty"`
ShowQuery bool `json:"show_query,omitempty"`
Delete bool `json:"delete,omitempty"`
}
type QueryResponse struct {
Metric string `json:"metric"`
Tags map[string]string `json:"tags"`
AggregateTags []string `json:"aggregateTags"`
Dps map[string]float64 `json:"dps"`
}
func NewQueryParams() (*QueryParams, error) {
return &QueryParams{}, nil
}
//query data from opentsdb by metric and time
func QueryByMetricAndTimestamp() {
// item := &Query{Tags: make(map[string]string)}
// item.Tags["endpoint"] = "hadoop1"
// item.Aggregator = "none"
// item.Metric = "cpu.idle"
//format time for q.start and q.end
now := time.Now()
m, _ := time.ParseDuration("-1m")
m1 := now.Add(70 * m)
m2 := now.Add(60 * m)
start := m1.Format("2006/01/02-15:04:05")
end := m2.Format("2006/01/02-15:04:05")
fmt.Println(start)
fmt.Println(end)
q, _ := NewQueryParams()
q.Start = start
q.End = end
// q.Start = "2018/11/07-01:30:00"
// q.End = "2018/11/07-01:40:00"
// q.Start = "1h-ago"
// q.Queries = append(q.Queries, *item)
q.Queries = append(q.Queries, Query{Aggregator: "none", Metric: "cpu.idle", Tags: map[string]string{"endpoint": "hadoop1"}})
data, err := json.Marshal(*q)
if err != nil {
fmt.Println(err)
}
req, err := http.NewRequest("POST", "http://10.100.101.70:4242/api/query", bytes.NewBuffer(data))
if err != nil {
fmt.Println(err)
}
req.Header.Set("Content-Type", "application/json")
// fmt.Println("new request :", req)
client := &http.Client{}
resp, err := client.Do(req)
fmt.Println("client do response :", resp)
defer resp.Body.Close()
if err != nil {
panic(err)
}
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
fmt.Println(err)
}
// fmt.Println("tsbody :", string(body))
var tsdb []QueryResponse
err = json.Unmarshal(body, &tsdb)
if err != nil {
log.Fatalln("parse fail:", err)
}
for k, _ := range tsdb {
// fmt.Println("Metric:", tsdb[k].Metric)
// fmt.Println("Tags:", tsdb[k].Tags)
// fmt.Println("AggregateTags:", tsdb[k].AggregateTags)
// fmt.Println("Dps", tsdb[k].Dps)
// fmt.Println("Dps len", len(tsdb[k].Dps))
t := time.Now()
sli := make([]int, 0)
var intstr int
for tk, vv := range tsdb[k].Dps {
fmt.Println(tk, ":", vv)
intstr, _ = strconv.Atoi(tk)
sli = append(sli, intstr)
}
sort.Ints(sli[:])
for _, sv := range sli {
fmt.Println(sv, ":", tsdb[k].Dps[strconv.Itoa(sv)])
}
fmt.Println("slice创建速度:"+time.Now().Sub(t).String(), sli)
}
}
func main() {
QueryByMetricAndTimestamp()
PutDataToTsdb()
}