performance

package module
v0.0.0-...-3885b68 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Aug 19, 2023 License: MIT Imports: 7 Imported by: 0

README

a package for recording system metrics on linux.

go get github.com/rexlx/performance

simple example

package main

import (
	"encoding/json"
	"flag"
	"fmt"
	"net/http"
	"strings"
	"sync"
	"time"

	"github.com/go-echarts/go-echarts/v2/charts"
	"github.com/go-echarts/go-echarts/v2/opts"
	"github.com/go-echarts/go-echarts/v2/types"

	"github.com/rexlx/performance"
)

// determines if the app runs as server or client
var (
	server = flag.Bool("server", false, "run as server")
)

// Application struct holds all the data and methods for the app
type Application struct {
	Name      string
	Url       string
	Chart     *charts.Line
	Config    *ChartConfig
	ChartData []opts.LineData
	Interface *http.Client
	Aggs      []Aggregation
	Data      []performance.CpuUsage
	Mu        sync.Mutex
}

// ChartConfig holds the configuration for the chart
type ChartConfig struct {
	Start time.Time
	Times []time.Time
	Step  time.Duration
	Count int
}

type Aggregation struct {
	Value float64
	Time  time.Time
	Name  string
}

func main() {
	flag.Parse()

	// for the API
	client := &http.Client{}
	// for the chart
	items := make([]opts.LineData, 0)

	// init the app
	app := Application{
		Name:      "FoxyBoxy",
		Url:       "http://drfright:8080/",
		Interface: client,
		Aggs:      []Aggregation{},
		Data:      []performance.CpuUsage{},
		Mu:        sync.Mutex{},
		ChartData: items,
		Chart:     charts.NewLine(),
		Config: &ChartConfig{
			Start: time.Now(),
			Times: []time.Time{},
		},
	}

	// if running in client mode
	if !*server {

		for range time.Tick(6 * time.Second) {
			// create the channel for the cpu values
			stream := make(chan []*performance.CpuUsage)
			// get the cpu values
			go performance.GetCpuValues(stream, 3)
			msg := <-stream

			out, err := json.Marshal(msg)
			if err != nil {
				panic(err)
			}
			// send the good news
			app.SendCpuValuesOverHTTP(out)

		}

	} else {
		// we are the server
		fmt.Println("receive cpu values over http")
		// setup our handlers
		http.HandleFunc("/", app.ReceiveCpuValuesOverHTTP)
		http.HandleFunc("/chart", app.ShowLineChart)

		// set up our tasks in the background
		go func() {
			for range time.Tick(30 * time.Second) {
				app.AppendLineChart()
				app.SetLineChart()
			}
		}()
		http.ListenAndServe(":8080", nil)
	}

}

// SendCpuValuesOverHTTP sends the cpu values over http
func (app *Application) SendCpuValuesOverHTTP(vals []byte) {
	req, err := http.NewRequest(http.MethodPost, app.Url, strings.NewReader(string(vals)))
	if err != nil {
		panic(err)
	}

	req.Header.Add("Content-Type", "application/json")

	resp, err := app.Interface.Do(req)
	if err != nil {
		panic(err)
	}

	fmt.Println(resp.Status)
	defer resp.Body.Close()

}

// ReceiveCpuValuesOverHTTP receives the cpu values over http and adds them to the app data / creates an aggregation
func (app *Application) ReceiveCpuValuesOverHTTP(w http.ResponseWriter, r *http.Request) {
	app.Mu.Lock()
	defer app.Mu.Unlock()

	var tmp float64
	var agg Aggregation

	rightNow := time.Now()

	var msg []performance.CpuUsage

	err := json.NewDecoder(r.Body).Decode(&msg)
	if err != nil {
		fmt.Println(err, "continuing")
		return
	}

	app.Data = append(app.Data, msg...)

	for _, v := range msg {
		tmp += v.Usage
	}

	agg.Value = tmp / float64(len(msg))
	agg.Time = rightNow
	app.Aggs = append(app.Aggs, agg)
}

// ShowLineChart renders the line chart
func (app *Application) ShowLineChart(w http.ResponseWriter, r *http.Request) {
	app.Chart.Render(w)
}

// AppendLineChart appends the line chart
func (app *Application) AppendLineChart() {
	app.Mu.Lock()
	defer app.Mu.Unlock()

	var tmp float64

	for _, v := range app.Aggs {
		tmp += v.Value
	}
	app.ChartData = append(app.ChartData, opts.LineData{Value: tmp / float64(len(app.Aggs))})
	app.Config.Times = append(app.Config.Times, time.Now())
	fmt.Println("appending", time.Now())
	app.Aggs = nil
}

// SetLineChart sets the line chart
func (app *Application) SetLineChart() {
	app.Mu.Lock()
	defer app.Mu.Unlock()
	app.Chart.SetGlobalOptions(
		charts.WithInitializationOpts(opts.Initialization{Theme: types.ThemeShine}),
		charts.WithTitleOpts(opts.Title{
			Title:    app.Name,
			Subtitle: "CPU Usage",
		}))
	app.Chart.SetXAxis(app.Config.Times).
		AddSeries("CPU Usage", app.ChartData).
		SetSeriesOptions(charts.WithLineChartOpts(opts.LineChart{Smooth: true}))
}

another example

package main

import (
	"fmt"

	"github.com/rexlx/performance"
)

func main() {
	stream := make(chan []*performance.DiskStat)
	go performance.GetDiskUsage(stream, 1)
	msg := <-stream
	for _, i := range msg {
		fmt.Println(*i)
	}

}

Documentation

Index

Constants

View Source
const (
	KiB
	MiB
	GiB
	TiB
)
View Source
const (
	SwapTotal = iota
	SwapFree
	MemTotal
	MemFree
	Buffers
	Cached
	Slab
)

Variables

This section is empty.

Functions

func ByteConverter

func ByteConverter(n int) string

func Bytes

func Bytes(b int) string

func GetCpuValues

func GetCpuValues(c chan []*CpuUsage, refresh int)

GetCpuValues polls the cpu statistics for a given interval in seconds

func GetDiskUsage

func GetDiskUsage(c chan []*DiskStat, refresh int)

GetDiskUsage polls storage device statistics for a given interval in seconds

func GetKeyOrNone

func GetKeyOrNone(key string, m map[string]int) int

func GetNetValues

func GetNetValues(c chan NetUsage, refresh int)

GetNetValues polls the network statistics for a given interval in seconds

func PollNetworkStatistics

func PollNetworkStatistics() (ifaces map[string]*Iface, err error)

func PrintMemoryUsage

func PrintMemoryUsage()

func ValueToInteger

func ValueToInteger(s string) int

Types

type CpuUsage

type CpuUsage struct {
	Name  string    `json:"name"`
	Time  time.Time `json:"time"`
	Usage float64   `json:"percent_used"`
}

CpuUsage type represents the utilization of a given cpu

type DiskStat

type DiskStat struct {
	Dev            string    `json:"device"`
	Rsuccess       int       `json:"read_success"`
	Rmerged        int       `json:"read_merged"`
	SectorRead     int       `json:"sector_read"`
	Rtime          int       `json:"time_reading"`
	Wcomplete      int       `json:"write_complete"`
	Wmerged        int       `json:"write_merged"`
	SectorWritten  int       `json:"sector_written"`
	Wtime          int       `json:"time_writing"`
	IOinProg       int       `json:"current_io"`
	IOtime         int       `json:"time_io"`
	WeightedTimeIO int       `json:"weighted_time_io"`
	Time           time.Time `json:"time"`
}

DiskStat type represents the utilization of a given partition

type Iface

type Iface struct {
	Name string
	Rx   *RxData
	Tx   *TxData
}

func (*Iface) BytesReceivedToHumanReadable

func (i *Iface) BytesReceivedToHumanReadable() string

func (*Iface) BytesTransmittedToHumanReadable

func (i *Iface) BytesTransmittedToHumanReadable() string

func (*Iface) String

func (i *Iface) String() string

func (*Iface) TotalBytesToHumanReadable

func (i *Iface) TotalBytesToHumanReadable() string

type MemoryStats

type MemoryStats struct {
	SwapTotal,
	SwapFree,
	MemTotal,
	MemFree,
	Buffers,
	Cached,
	Slab int
}

MemoryStats type holds raw data used to calculate usage

type MemoryUsage

type MemoryUsage struct {
	Time   time.Time `json:"time"`
	Swap   int       `json:"swap_used"`
	Used   int       `json:"percent_used"`
	Total  int       `json:"total_memory"`
	Free   int       `json:"free"`
	Buff   int       `json:"buffered"`
	Cached int       `json:"cached"`
	Slab   int       `json:"slab"`
}

MemoryUsage type represents the memory util at a given time

func GetMemoryUsage

func GetMemoryUsage() *MemoryUsage

GetMemoryUsage reads the system memory stats and calculates the usage

func (*MemoryUsage) String

func (m *MemoryUsage) String() string

type NetUsage

type NetUsage struct {
	Name   string    `json:"name"`
	Time   time.Time `json:"time"`
	Ifaces []Iface   `json:"ifaces"`
}

NetUsage type represents the utilization of a given network interface

type RxData

type RxData struct {
	Bytes      int
	Packets    int
	Errs       int
	Drop       int
	Fifo       int
	Frame      int
	Compressed int
	Multicast  int
}

type TxData

type TxData struct {
	Bytes      int
	Packets    int
	Errs       int
	Drop       int
	Fifo       int
	Colls      int
	Carrier    int
	Compressed int
}

type Usage

type Usage struct {
	Total int
	Idle  int
}

Usage type holds the raw data used to calculate the cpu utilization

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL