You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

170 lines
3.6 KiB
Go

package app
import (
"fmt"
"io"
"log"
"net/http"
"net/url"
"os"
"time"
"git.buddy.wtf/buddy/open-hardware-monitor-client/lib/client"
"git.buddy.wtf/buddy/open-hardware-monitor-client/lib/metrics"
"github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/client_golang/prometheus/promhttp"
"github.com/urfave/cli/v2"
)
// App context
type App struct {
cli *cli.App
Client *client.Client
Out io.Writer
}
// FlagHost flag for host
var FlagHost = &cli.StringFlag{
Name: "host",
EnvVars: []string{"OHWM_HOST"},
Value: "127.0.0.1",
Usage: "open hardware monitor host [OSHW_HOST]",
}
// FlagPort flag for host
var FlagPort = &cli.IntFlag{
Name: "port",
EnvVars: []string{"OHWM_PORT"},
Value: 8085,
Usage: "open hardware port [OSHW_PORT]",
}
// FlagScheme flag for host
var FlagScheme = &cli.StringFlag{
Name: "scheme",
EnvVars: []string{"OHWM_SCHEME"},
Value: "http",
Usage: "open hardware monitor scheme (http/https)",
}
// FlagPath flag for path url
var FlagPath = &cli.StringFlag{
Name: "path",
EnvVars: []string{"OHWM_PATH"},
Value: "/data.json",
Usage: "open hardware monitor path (ie /data.json)",
}
// FlagInterface flag for host
var FlagInterface = &cli.StringFlag{
Name: "http",
EnvVars: []string{"OHWM_HTTP"},
Value: ":9200",
Usage: "interface to serve http requests",
}
// New returns instance of an app
func New() *App {
cliapp := cli.NewApp()
app := &App{
Out: os.Stdout,
cli: cliapp,
}
app.cli.Name = "ohwm-client"
app.cli.Description = "Open Hardware Manager Client"
app.cli.UsageText = "ohwm-client [flags] <command> [flags]"
app.cli.HideVersion = true
app.cli.Flags = []cli.Flag{
FlagHost,
FlagPort,
FlagScheme,
FlagPath,
}
app.cli.Commands = []*cli.Command{
&cli.Command{
Name: "print",
Usage: "pretty prints api result",
Action: app.ActionPrint,
},
&cli.Command{
Name: "export",
Usage: "runs http exporter for prometheus",
Action: app.ActionMetrics,
Flags: []cli.Flag{
FlagInterface,
},
},
}
app.cli.Before = app.Before
return app
}
// Run runs cli action
func (a *App) Run(args []string) error {
return a.cli.Run(args)
}
// Before sets up app
func (a *App) Before(ctx *cli.Context) error {
host := fmt.Sprintf("%s:%d", ctx.String("host"), ctx.Int("port"))
a.Client = &client.Client{
Timeout: time.Second,
URL: url.URL{
Scheme: ctx.String("scheme"),
Host: host,
Path: ctx.String("path"),
},
}
return nil
}
// ActionPrint prints api result
func (a *App) ActionPrint(_ *cli.Context) error {
node, err := a.Client.Fetch()
if err != nil {
return err
}
fmt.Fprint(a.Out, node.Stringify())
return nil
}
// ActionMetrics serves http
func (a *App) ActionMetrics(ctx *cli.Context) error {
addr := ctx.String("http")
http.HandleFunc("/metrics", a.HandleMetrics)
log.Println("listen on: " + addr)
return http.ListenAndServe(addr, nil)
}
// HandleMetrics handler
func (a *App) HandleMetrics(resp http.ResponseWriter, req *http.Request) {
root, err := a.Client.Fetch()
if err != nil {
http.Error(resp, err.Error(), http.StatusInternalServerError)
return
}
vals, err := root.Values()
if err != nil {
http.Error(resp, err.Error(), http.StatusInternalServerError)
return
}
collection := metrics.FromVals(vals)
registry := prometheus.NewRegistry()
if err := registry.Register(collection); err != nil {
http.Error(resp, err.Error(), http.StatusInternalServerError)
return
}
handler := promhttp.HandlerFor(registry, promhttp.HandlerOpts{
Registry: registry,
})
handler.ServeHTTP(resp, req)
registry.Unregister(collection)
}