first commit
This commit is contained in:
commit
fccfe2a4c8
26 files changed
+1819
No files matched your search
@@ -0,0 +1,111 @@
|
||||
package rrd
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
)
|
||||
|
||||
type Manager struct {
|
||||
Tool string
|
||||
Path string
|
||||
GraphDir string
|
||||
mu sync.Mutex
|
||||
}
|
||||
|
||||
type Range struct{ Key, Start, Title string }
|
||||
|
||||
var Ranges = []Range{
|
||||
{"hour", "-12h", "Ostatnie 12 godzin"},
|
||||
{"day", "-24h", "Ostatnie 24 godziny"},
|
||||
{"72h", "-72h", "Ostatnie 72 godziny"},
|
||||
{"week", "-1w", "Ostatni tydzień"},
|
||||
{"month", "-1m", "Ostatni miesiąc"},
|
||||
{"year", "-1y", "Ostatni rok"},
|
||||
}
|
||||
|
||||
func (m *Manager) Validate() error {
|
||||
if _, err := exec.LookPath(m.Tool); err != nil {
|
||||
return fmt.Errorf("rrdtool not found: %w", err)
|
||||
}
|
||||
if st, err := os.Stat(m.Path); err != nil || st.IsDir() {
|
||||
return fmt.Errorf("RRD file unavailable: %s", m.Path)
|
||||
}
|
||||
return os.MkdirAll(m.GraphDir, 0750)
|
||||
}
|
||||
|
||||
func (m *Manager) Update(ctx context.Context, online int) error {
|
||||
if online < 0 {
|
||||
return errors.New("online count cannot be negative")
|
||||
}
|
||||
cmd := exec.CommandContext(ctx, m.Tool, "update", m.Path, "N:"+strconv.Itoa(online))
|
||||
var stderr bytes.Buffer
|
||||
cmd.Stderr = &stderr
|
||||
if err := cmd.Run(); err != nil {
|
||||
return fmt.Errorf("rrd update: %w: %s", err, strings.TrimSpace(stderr.String()))
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *Manager) Last(ctx context.Context) (int, error) {
|
||||
cmd := exec.CommandContext(ctx, m.Tool, "lastupdate", m.Path)
|
||||
out, err := cmd.Output()
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
lines := strings.Split(strings.TrimSpace(string(out)), "\n")
|
||||
if len(lines) < 2 {
|
||||
return 0, errors.New("unexpected rrd lastupdate output")
|
||||
}
|
||||
fields := strings.Fields(lines[len(lines)-1])
|
||||
if len(fields) < 2 {
|
||||
return 0, errors.New("unexpected rrd lastupdate data")
|
||||
}
|
||||
v := fields[len(fields)-1]
|
||||
if v == "U" {
|
||||
return 0, nil
|
||||
}
|
||||
f, err := strconv.ParseFloat(v, 64)
|
||||
return int(f + 0.5), err
|
||||
}
|
||||
|
||||
func (m *Manager) Graph(ctx context.Context, key string) (string, error) {
|
||||
var rg *Range
|
||||
for i := range Ranges {
|
||||
if Ranges[i].Key == key {
|
||||
rg = &Ranges[i]
|
||||
break
|
||||
}
|
||||
}
|
||||
if rg == nil {
|
||||
return "", errors.New("unknown graph range")
|
||||
}
|
||||
if err := os.MkdirAll(m.GraphDir, 0750); err != nil {
|
||||
return "", err
|
||||
}
|
||||
out := filepath.Join(m.GraphDir, key+".png")
|
||||
|
||||
m.mu.Lock()
|
||||
defer m.mu.Unlock()
|
||||
if st, err := os.Stat(out); err == nil && time.Since(st.ModTime()) < 55*time.Second {
|
||||
return out, nil
|
||||
}
|
||||
|
||||
def := "DEF:online=" + m.Path + ":online:LAST"
|
||||
args := []string{"graph", out, "--imgformat", "PNG", "--start", rg.Start, "--end", "now", "--width", "1200", "--height", "320", "--lower-limit", "0", "--alt-autoscale-max", "--title", rg.Title, "--vertical-label", "użytkownicy", "--border", "0", def, "LINE2:online#2F6FED:Online", "GPRINT:online:LAST:Aktualnie\\: %4.0lf", "GPRINT:online:AVERAGE:Średnio\\: %4.0lf", "GPRINT:online:MAX:Maks.\\: %4.0lf\\n"}
|
||||
cmd := exec.CommandContext(ctx, m.Tool, args...)
|
||||
var stderr bytes.Buffer
|
||||
cmd.Stderr = &stderr
|
||||
if err := cmd.Run(); err != nil {
|
||||
return "", fmt.Errorf("rrd graph: %w: %s", err, strings.TrimSpace(stderr.String()))
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
Reference in new issue
Block a user