5 Commits
v0.0.5 ... main

Author SHA1 Message Date
67890d936c docs(readme): update help output example 2023-12-21 00:26:43 +00:00
github-actions[bot]
a1d4f70d98 chore(main): release 0.0.6 (#7)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-12-21 00:14:21 +00:00
7b2e98e150 fix(output): write log output to stderr by default instead of stdout
Also refactor flag parsing and main package in general a bit.
2023-12-21 00:11:27 +00:00
3c272d6d3d ci(goreleaser): update homebrew tap repo name 2023-12-20 23:22:11 +00:00
dc62db2ace docs(readme): update homebrew installation instructions 2023-12-20 23:20:55 +00:00
5 changed files with 134 additions and 55 deletions

View File

@@ -1,3 +1,3 @@
{
".": "0.0.5"
".": "0.0.6"
}

View File

@@ -44,6 +44,6 @@ brews:
system "#{bin}/macos-battery-exporter -v"
repository:
owner: jimeh
name: homebrew-macos-battery-exporter
name: homebrew-tap
branch: main
token: "{{ .Env.BREW_TAP_TOKEN }}"

View File

@@ -1,5 +1,12 @@
# Changelog
## [0.0.6](https://github.com/jimeh/macos-battery-exporter/compare/v0.0.5...v0.0.6) (2023-12-21)
### Bug Fixes
* **output:** write log output to stderr by default instead of stdout ([7b2e98e](https://github.com/jimeh/macos-battery-exporter/commit/7b2e98e150f9ee6d630023879395df0912047667))
## [0.0.5](https://github.com/jimeh/macos-battery-exporter/compare/v0.0.4...v0.0.5) (2023-12-16)

View File

@@ -16,9 +16,9 @@
<a href="https://github.com/jimeh/macos-battery-exporter/blob/main/LICENSE"><img src="https://img.shields.io/github/license/jimeh/macos-battery-exporter.svg?style=flat" alt="License Status"></a>
</p>
A Prometheus exporter for macOS which exposes most useful details available from
`ioreg`. Includes a lot more details than what `node_exporter` supports via it's
`node_power_supply_*` metrics.
A Prometheus exporter for macOS battery information, exposing wide range of
details available from `ioreg` about batteries. Includes a lot more details than
what `node_exporter` supports via its `node_power_supply_*` metrics.
## Installation
@@ -29,12 +29,11 @@ Binary releases are available on the
### Homebrew
You can install it from the
[`jimeh/macos-battery-exporter`](https://github.com/jimeh/homebrew-macos-battery-exporter)
You can install it from the [`jimeh/tap`](https://github.com/jimeh/homebrew-tap)
Tap:
```bash
brew install jimeh/macos-battery-exporter/macos-battery-exporter
brew install jimeh/tap/macos-battery-exporter
```
#### Service
@@ -63,19 +62,22 @@ macos-battery-exporter -h
```
```
Usage of macos-battery-exporter:
usage: macos-battery-exporter [<options>]
-b string
Bind address to run server on (default "127.0.0.1")
Bind address to run server on (default "127.0.0.1")
-d string
Log output device (stderr or stdout) (default "stderr")
-l string
Log level (default "info")
Log level (default "info")
-n string
Namespace for metrics (default "macos")
Namespace for metrics (default "macos")
-o string
Output file to write to in Prometheus format
Output file to write to in Prometheus format
-p int
Port to run server on (default 9108)
-s Run as a Prometheus metrics server
-v Print version and exit
Port to run server on (default 9108)
-s Run as a Prometheus metrics server
-v Print version and exit
```
### Print to STDOUT
@@ -159,3 +161,7 @@ macos-battery-exporter -s
```bash
curl http://localhost:9108/metrics
```
## License
[MIT](https://github.com/jimeh/macos-battery-exporter/blob/main/LICENSE)

144
main.go
View File

@@ -5,7 +5,7 @@ package main
import (
"flag"
"fmt"
"log"
"io"
"log/slog"
"os"
"strings"
@@ -16,93 +16,159 @@ import (
)
var (
name = "macos-battery-exporter"
version = "0.0.0-dev"
commit = "unknown"
)
outputFlag = flag.String(
type configuration struct {
Output string
Server bool
Bind string
Port int
Namespace string
LogLevel string
LogDevice string
PrintVersion bool
}
func configure() (*configuration, *flag.FlagSet, error) {
fs := flag.NewFlagSet(name, flag.ExitOnError)
fs.Usage = func() {
fmt.Fprintf(fs.Output(),
"usage: %s [<options>]\n\n", fs.Name(),
)
fs.PrintDefaults()
}
config := &configuration{}
fs.StringVar(&config.Output,
"o", "", "Output file to write to in Prometheus format",
)
serverFlag = flag.Bool("s", false, "Run as a Prometheus metrics server")
bindFlag = flag.String(
fs.BoolVar(&config.Server,
"s", false, "Run as a Prometheus metrics server",
)
fs.StringVar(&config.Bind,
"b", "127.0.0.1", "Bind address to run server on",
)
portFlag = flag.Int("p", 9108, "Port to run server on")
namespaceFlag = flag.String(
fs.IntVar(&config.Port, "p", 9108, "Port to run server on")
fs.StringVar(&config.Namespace,
"n", prombat.DefaultNamespace, "Namespace for metrics",
)
logLevelFlag = flag.String("l", "info", "Log level")
versionFlag = flag.Bool("v", false, "Print version and exit")
)
fs.StringVar(&config.LogLevel,
"l", "info", "Log level",
)
fs.StringVar(&config.LogDevice,
"d", "stderr", "Log output device (stderr or stdout)",
)
fs.BoolVar(&config.PrintVersion,
"v", false, "Print version and exit",
)
err := fs.Parse(os.Args[1:])
if err != nil {
return nil, nil, err
}
return config, fs, nil
}
func main() {
if err := mainE(); err != nil {
log.Fatal(err)
slog.Error(err.Error())
os.Exit(1)
}
}
func mainE() error {
flag.Parse()
err := setupSLog(*logLevelFlag)
config, _, err := configure()
if err != nil {
return err
}
if *versionFlag {
fmt.Printf("macos-battery-exporter %s (%s)\n", version, commit)
err = setupSLog(config.LogDevice, config.LogLevel)
if err != nil {
return err
}
if config.PrintVersion {
fmt.Printf("%s %s (%s)\n", name, version, commit)
return nil
}
if *serverFlag {
opts := prombat.ServerOptions{
Bind: *bindFlag,
Port: *portFlag,
}
return prombat.RunServer(
*namespaceFlag,
prometheus.DefaultRegisterer.(*prometheus.Registry),
opts,
)
if config.Server {
return runServer(config)
}
registry := prometheus.NewRegistry()
err = registry.Register(prombat.NewCollector(*namespaceFlag))
metrics, err := renderMetrics(config)
if err != nil {
return err
}
if config.Output != "" {
return writeToFile(metrics, config.Output)
}
fmt.Print(metrics)
return nil
}
func runServer(config *configuration) error {
opts := prombat.ServerOptions{
Bind: config.Bind,
Port: config.Port,
}
return prombat.RunServer(
config.Namespace,
prometheus.DefaultRegisterer.(*prometheus.Registry),
opts,
)
}
func renderMetrics(config *configuration) (string, error) {
registry := prometheus.NewRegistry()
err := registry.Register(prombat.NewCollector(config.Namespace))
if err != nil {
return "", err
}
gatherers := prometheus.Gatherers{registry}
metricFamilies, err := gatherers.Gather()
if err != nil {
return err
return "", err
}
var sb strings.Builder
for _, mf := range metricFamilies {
_, err := expfmt.MetricFamilyToText(&sb, mf)
if err != nil {
return err
return "", err
}
}
if *outputFlag != "" {
return writeToFile(sb.String(), *outputFlag)
}
fmt.Print(sb.String())
return nil
return sb.String(), nil
}
func setupSLog(levelStr string) error {
func setupSLog(device string, levelStr string) error {
var w io.Writer
switch device {
case "stderr":
w = os.Stderr
case "stdout":
w = os.Stdout
default:
return fmt.Errorf("invalid log device: %s", device)
}
var level slog.Level
err := level.UnmarshalText([]byte(levelStr))
if err != nil {
return err
}
handler := slog.NewTextHandler(os.Stdout, &slog.HandlerOptions{
handler := slog.NewTextHandler(w, &slog.HandlerOptions{
Level: level,
})
logger := slog.New(handler)