Skip to content
This repository has been archived by the owner on May 3, 2022. It is now read-only.

Commit

Permalink
Merge pull request #1 from lovoo/cleanup
Browse files Browse the repository at this point in the history
Cleanup, Vendoring, Makefile
  • Loading branch information
0x46616c6b authored Oct 12, 2016
2 parents 676fcc0 + 718a156 commit 8e3cbb2
Show file tree
Hide file tree
Showing 326 changed files with 144,219 additions and 63 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
ipmitool-*/
build/
23 changes: 23 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
BUILD_DIR = build
PROJECT_NAME = ipmi_exporter

GO = go
GOX = gox
GOX_ARGS = -output="$(BUILD_DIR)/{{.Dir}}_{{.OS}}_{{.Arch}}" -osarch="linux/amd64 linux/386 linux/arm linux/arm64 darwin/amd64 freebsd/amd64 freebsd/386 windows/386 windows/amd64"

.PHONY: build
build:
$(GO) build -o $(BUILD_DIR)/$(PROJECT_NAME) .

.PHONY: clean
clean:
rm -R $(BUILD_DIR)/* || true

.PHONY: test
test:
$(GO) test ./...

.PHONY: release-build
release-build:
@go get -u github.com/mitchellh/gox
@$(GOX) $(GOX_ARGS) github.com/lovoo/$(PROJECT_NAME)
9 changes: 6 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,19 @@

[![GoDoc](https://godoc.org/github.com/lovoo/ipmi_exporter?status.svg)](https://godoc.org/github.com/lovoo/ipmi_exporter)

Ipmi exporter for prometheus.io, written in go.
IPMI Exporter for prometheus.io, written in Go.

## Requirements

* ipmitool

## Docker Usage

docker run --privileged -d --name ipmi_exporter -p 9289:9289 lovoo/ipmi_exporter:latest

## Building

go get -u github.com/lovoo/ipmi_exporter
go install github.com/lovoo/ipmi_exporter
make build

## Contributing

Expand Down
Empty file modified build_ipmitool.sh
100644 → 100755
Empty file.
82 changes: 30 additions & 52 deletions collector.go
Original file line number Diff line number Diff line change
@@ -1,17 +1,13 @@
package main

import (
"log"
"time"

"encoding/csv"
"fmt"
"os/exec"
"strconv"
"strings"
"sync"

"github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/common/log"
)

type metric struct {
Expand All @@ -24,25 +20,17 @@ type metric struct {
// Exporter implements the prometheus.Collector interface. It exposes the metrics
// of a ipmi node.
type Exporter struct {
IpmiBinary string
Waitgroup *sync.WaitGroup
metrics map[string]*prometheus.GaugeVec
duration prometheus.Gauge
totalScrapes prometheus.Counter
namespace string
IpmiBinary string

metrics map[string]*prometheus.GaugeVec
namespace string
}

// NewExporter instantiates a new ipmi Exporter.
func NewExporter(ipmiBinary string, wg *sync.WaitGroup) *Exporter {
func NewExporter(ipmiBinary string) *Exporter {
e := Exporter{
IpmiBinary: ipmiBinary,
Waitgroup: wg,
namespace: "ipmi",
duration: prometheus.NewGauge(prometheus.GaugeOpts{
Namespace: *namespace,
Name: "exporter_last_scrape_duration_seconds",
Help: "The last scrape duration.",
}),
}

e.metrics = map[string]*prometheus.GaugeVec{}
Expand All @@ -55,14 +43,12 @@ type error interface {
Error() string
}

func executeCommand(cmd string, wg *sync.WaitGroup) (string, error) {
func executeCommand(cmd string) (string, error) {
parts := strings.Fields(cmd)
out, err := exec.Command(parts[0], parts[1]).Output()
if err != nil {
fmt.Println("error occured")
fmt.Printf("%s", err)
log.Errorf("error while calling ipmitool: %v", err)
}
wg.Done()
return string(out), err
}

Expand All @@ -72,7 +58,7 @@ func convertValue(strfloat string, strunit string) (value float64, err error) {
strfloat = strings.Replace(strfloat, "0x", "", -1)
parsedValue, err := strconv.ParseUint(strfloat, 16, 32)
if err != nil {
log.Printf("could not translate hex: %v, %v", parsedValue, err)
log.Errorf("could not translate hex: %v, %v", parsedValue, err)
}
value = float64(parsedValue)
} else {
Expand All @@ -83,40 +69,39 @@ func convertValue(strfloat string, strunit string) (value float64, err error) {
}

func convertOutput(result [][]string) (metrics []metric, err error) {
for i := range result {
for _, res := range result {
var value float64
var currentMetric metric

for n := range result[i] {
result[i][n] = strings.TrimSpace(result[i][n])
for n := range res {
res[n] = strings.TrimSpace(res[n])
}
result[i][0] = strings.ToLower(result[i][0])
result[i][0] = strings.Replace(result[i][0], " ", "_", -1)
result[i][0] = strings.Replace(result[i][0], "-", "_", -1)
result[i][0] = strings.Replace(result[i][0], ".", "_", -1)
res[0] = strings.ToLower(res[0])
res[0] = strings.Replace(res[0], " ", "_", -1)
res[0] = strings.Replace(res[0], "-", "_", -1)
res[0] = strings.Replace(res[0], ".", "_", -1)

value, err = convertValue(result[i][1], result[i][2])
value, err = convertValue(res[1], res[2])
if err != nil {
log.Printf("could not parse ipmi output: %s", err)
log.Errorf("could not parse ipmi output: %s", err)
}

currentMetric.value = value
currentMetric.unit = result[i][2]
currentMetric.metricsname = result[i][0]
currentMetric.unit = res[2]
currentMetric.metricsname = res[0]

metrics = append(metrics, currentMetric)
}
return metrics, err
}

func splitAoutput(output string) ([][]string, error) {

r := csv.NewReader(strings.NewReader(output))
r.Comma = '|'
r.Comment = '#'
result, err := r.ReadAll()
if err != nil {
log.Printf("could not parse ipmi output: %v", err)
log.Errorf("could not parse ipmi output: %v", err)
}
return result, err
}
Expand All @@ -139,8 +124,6 @@ func (e *Exporter) Describe(ch chan<- *prometheus.Desc) {
for _, m := range e.metrics {
m.Describe(ch)
}

ch <- e.duration.Desc()
}

// Collect collects all the registered stats metrics from the ipmi node.
Expand All @@ -149,25 +132,20 @@ func (e *Exporter) Collect(metrics chan<- prometheus.Metric) {
for _, m := range e.metrics {
m.Collect(metrics)
}

metrics <- e.duration
}

func (e *Exporter) collect() {
e.Waitgroup.Add(1)

now := time.Now().UnixNano()

output, err := executeCommand(e.IpmiBinary, e.Waitgroup)
output, err := executeCommand(e.IpmiBinary + " sensor")
if err != nil {
log.Errorln(err)
}
splitted, err := splitAoutput(string(output))
if err != nil {
log.Errorln(err)
}
convertedOutput, err := convertOutput(splitted)
createMetrics(e, convertedOutput)

e.duration.Set(float64(time.Now().UnixNano()-now) / 1000000000)

e.Waitgroup.Wait()
if err != nil {
log.Printf("could not retrieve ipmi metrics: %v", err)
return
log.Errorln(err)
}
createMetrics(e, convertedOutput)
}
16 changes: 8 additions & 8 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,27 +2,26 @@ package main

import (
"flag"
"log"
"net/http"
"sync"

"github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/common/log"
)

var (
listenAddress = flag.String("web.listen", ":9289", "Address on which to expose metrics and web interface.")
metricsPath = flag.String("web.path", "/metrics", "Path under which to expose metrics.")
ipmiBinary = flag.String("ipmi.path", "/usr/local/bin/ipmitool sensor", "Path to the ipmi binary")
ipmiBinary = flag.String("ipmi.path", "ipmitool", "Path to the ipmi binary")
namespace = flag.String("namespace", "ipmi", "Namespace for the IPMI metrics.")
)

func main() {
flag.Parse()
var wg sync.WaitGroup

prometheus.MustRegister(NewExporter(*ipmiBinary, &wg))
err := prometheus.Register(NewExporter(*ipmiBinary))
if err != nil {
log.Fatalf("ipmitool didn't return any metrics (%v)", err)
}

log.Printf("Starting Server: %s", *listenAddress)
handler := prometheus.Handler()
if *metricsPath == "" || *metricsPath == "/" {
http.Handle(*metricsPath, handler)
Expand All @@ -39,7 +38,8 @@ func main() {
})
}

err := http.ListenAndServe(*listenAddress, nil)
log.Infof("Starting Server: %s", *listenAddress)
err = http.ListenAndServe(*listenAddress, nil)
if err != nil {
log.Fatal(err)
}
Expand Down
66 changes: 66 additions & 0 deletions vendor/github.com/Sirupsen/logrus/CHANGELOG.md

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

21 changes: 21 additions & 0 deletions vendor/github.com/Sirupsen/logrus/LICENSE

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading

0 comments on commit 8e3cbb2

Please sign in to comment.