mirror of
https://github.com/ClusterCockpit/cc-metric-collector.git
synced 2024-12-27 07:39:05 +01:00
136 lines
3.5 KiB
Go
136 lines
3.5 KiB
Go
package sinks
|
|
|
|
import (
|
|
"database/sql"
|
|
"fmt"
|
|
_ "github.com/mattn/go-sqlite3"
|
|
"log"
|
|
"sort"
|
|
"strings"
|
|
"time"
|
|
"errors"
|
|
)
|
|
|
|
type SqliteSink struct {
|
|
Sink
|
|
db *sql.DB
|
|
columns map[string][]string
|
|
}
|
|
|
|
type StrList []string
|
|
|
|
func (list StrList) Len() int { return len(list) }
|
|
|
|
func (list StrList) Swap(i, j int) { list[i], list[j] = list[j], list[i] }
|
|
|
|
func (list StrList) Less(i, j int) bool {
|
|
var si string = list[i]
|
|
var sj string = list[j]
|
|
var si_lower = strings.ToLower(si)
|
|
var sj_lower = strings.ToLower(sj)
|
|
if si_lower == sj_lower {
|
|
return si < sj
|
|
}
|
|
return si_lower < sj_lower
|
|
}
|
|
|
|
func (s *SqliteSink) Init(config SinkConfig) error {
|
|
var err error
|
|
if len(config.Database) == 0 {
|
|
return errors.New("Not all configuration variables set required by SqliteSink")
|
|
}
|
|
s.host = config.Host
|
|
s.port = config.Port
|
|
s.database = config.Database
|
|
s.organization = config.Organization
|
|
s.user = config.User
|
|
s.password = config.Password
|
|
log.Print("Opening Sqlite3 database ", s.database)
|
|
s.db, err = sql.Open("sqlite3", fmt.Sprintf("./%s.db", s.database))
|
|
if err != nil {
|
|
log.Fatal(err)
|
|
s.db = nil
|
|
return err
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func (s *SqliteSink) PrepareLists(measurement string, tags map[string]string, fields map[string]interface{}, t time.Time) ([]string, []string, []string) {
|
|
keys := make([]string, 0)
|
|
values := make([]string, 0)
|
|
keytype := make([]string, 0)
|
|
|
|
keys = append(keys, "time")
|
|
values = append(values, fmt.Sprintf("%d", t.Unix()))
|
|
keytype = append(keytype, fmt.Sprintf("time INT8"))
|
|
for k, v := range tags {
|
|
keys = append(keys, k)
|
|
values = append(values, fmt.Sprintf("%q", v))
|
|
keytype = append(keytype, fmt.Sprintf("%s TEXT", k))
|
|
}
|
|
for k, v := range fields {
|
|
keys = append(keys, k)
|
|
switch v.(type) {
|
|
case float32:
|
|
keytype = append(keytype, fmt.Sprintf("%s FLOAT", k))
|
|
values = append(values, fmt.Sprintf("%f", v))
|
|
case float64:
|
|
keytype = append(keytype, fmt.Sprintf("%s DOUBLE", k))
|
|
values = append(values, fmt.Sprintf("%f", v))
|
|
case int64:
|
|
keytype = append(keytype, fmt.Sprintf("%s INT8", k))
|
|
values = append(values, fmt.Sprintf("%d", v))
|
|
case int:
|
|
keytype = append(keytype, fmt.Sprintf("%s INT", k))
|
|
values = append(values, fmt.Sprintf("%d", v))
|
|
case string:
|
|
keytype = append(keytype, fmt.Sprintf("%s TEXT", k))
|
|
values = append(values, fmt.Sprintf("%q", v))
|
|
}
|
|
}
|
|
sort.Sort(StrList(keytype))
|
|
return keytype, keys, values
|
|
}
|
|
|
|
func (s *SqliteSink) Write(measurement string, tags map[string]string, fields map[string]interface{}, t time.Time) error {
|
|
if s.db != nil {
|
|
keytype, keys, values := s.PrepareLists(measurement, tags, fields, t)
|
|
prim_key := []string{"time", "host"}
|
|
if measurement == "cpu" {
|
|
prim_key = append(prim_key, "cpu")
|
|
} else if measurement == "socket" {
|
|
prim_key = append(prim_key, "socket")
|
|
}
|
|
tx, err := s.db.Begin()
|
|
if err == nil {
|
|
c := fmt.Sprintf("create table if not exists %s (%s, PRIMARY KEY (%s));", measurement,
|
|
strings.Join(keytype, ","),
|
|
strings.Join(prim_key, ","))
|
|
i := fmt.Sprintf("insert into %s (%s) values(%s);", measurement, strings.Join(keys, ","), strings.Join(values, ","))
|
|
_, err = tx.Exec(c)
|
|
if err != nil {
|
|
log.Println(err)
|
|
}
|
|
_, err = tx.Exec(i)
|
|
if err != nil {
|
|
log.Println(err)
|
|
}
|
|
err = tx.Commit()
|
|
if err != nil {
|
|
log.Println(err)
|
|
}
|
|
} else {
|
|
log.Println(err)
|
|
}
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (s *SqliteSink) Close() {
|
|
log.Print("Closing Sqlite3 database ", s.database)
|
|
if s.db != nil {
|
|
s.db.Close()
|
|
}
|
|
}
|