Skip to content

Commit

Permalink
Merged in phstsai/node-exporter-dockerfile (pull request #2)
Browse files Browse the repository at this point in the history
add the dockerfile for node-exporter

Approved-by: Hung-Wei Chiu <[email protected]>
  • Loading branch information
WakeupTsai authored and hwchiu committed May 28, 2018
2 parents b14f66f + 931a490 commit 6df9b9f
Show file tree
Hide file tree
Showing 5 changed files with 216 additions and 0 deletions.
13 changes: 13 additions & 0 deletions dockerfiles/node-exporter/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# Build stage
FROM golang:1.7.3 AS builder
RUN go get github.com/prometheus/node_exporter
COPY ./src/node-exporter/ /go/src/github.com/prometheus/node_exporter/collector
WORKDIR /go/src/github.com/prometheus/node_exporter
RUN make build test

# the final image
FROM alpine:3.7
COPY --from=builder /go/src/github.com/prometheus/node_exporter/node_exporter /bin/node_exporter
EXPOSE 9100
ENTRYPOINT [ "/bin/node_exporter" ]

66 changes: 66 additions & 0 deletions src/node-exporter/netdev_iface_common.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
//phstsai
package collector

import (
"fmt"
"net"

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

type netIfaceCollector struct {
subsystem string
metricDescs map[string]*prometheus.Desc
}

func init() {
registerCollector("iface", defaultEnabled, NewNetIfaceCollector)
}

// NewNetIfaceCollector returns a new Collector exposing network device stats.
func NewNetIfaceCollector() (Collector, error) {
return &netIfaceCollector{
subsystem: "network",
metricDescs: map[string]*prometheus.Desc{},
}, nil
}

func (c *netIfaceCollector) Update(ch chan<- prometheus.Metric) error {
netDevDefault, err := getDefaultDev()
if err != nil {
return fmt.Errorf("couldn't get default network devices: %s", err)
}

for key, value := range netDevDefault {
desc, ok := c.metricDescs[key]

if !ok {
desc = prometheus.NewDesc(
prometheus.BuildFQName(namespace, c.subsystem, "interface"),
fmt.Sprintf("List network devices and label the default one."),
[]string{"device"},
nil,
)
c.metricDescs[key] = desc
}

ch <- prometheus.MustNewConstMetric(desc, prometheus.GaugeValue, float64(value), key)
}
return nil
}

func Split(r rune) bool {
return r == ' ' || r == '\t'
}

func getNetDev() (map[string]int, error) {
netDev := map[string]int{}

ifaces, _ := net.Interfaces()

for _, iface := range ifaces {
netDev[iface.Name] = 0
}

return netDev, nil
}
45 changes: 45 additions & 0 deletions src/node-exporter/netdev_iface_common_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
package collector

import (
"fmt"
"os/exec"
"runtime"
"strings"
"testing"
)

func TestGetDefaultDev(t *testing.T) {
iface := ""
defaultInterface := ""

switch runtime.GOOS {
case "linux":
out, err := exec.Command("bash", "-c", "ip route get 8.8.8.8 | awk 'NR==1 {print $5}'").Output()
if err != nil {
t.Error("Can't get the interface for default route, maybe the system does not have the network connectivity", err)
}
//the output should look like eth0
fmt.Sscanf(string(out), "%s", &defaultInterface)
if defaultInterface == "" {
t.Error("Parse the interface fail")
}
case "darwin":
// skip the test for osx
t.Skip("Skip the test when os is drawin.")
}

netDevDefault, err := getDefaultDev()
if err != nil {
t.Error("couldn't get default network devices", err)
}

for key, value := range netDevDefault {
if value == 1 {
iface = key
}
}

if strings.Compare(defaultInterface, iface) != 0 {
t.Error("Default interface didn't match the result from getDefaultDev().")
}
}
48 changes: 48 additions & 0 deletions src/node-exporter/netdev_iface_darwin.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
package collector

import (
"errors"
"fmt"
"os/exec"
)

/*
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <ifaddrs.h>
#include <net/if.h>
*/
import "C"

func getDefaultDev() (map[string]int, error) {
iface := ""
netDev := map[string]int{}

var ifap, ifa *C.struct_ifaddrs
if C.getifaddrs(&ifap) == -1 {
return nil, errors.New("getifaddrs() failed")
}
defer C.freeifaddrs(ifap)

for ifa = ifap; ifa != nil; ifa = ifa.ifa_next {
if ifa.ifa_addr.sa_family == C.AF_LINK {
dev := C.GoString(ifa.ifa_name)
netDev[dev] = 0
}
}

out, err := exec.Command("bash", "-c", "route -n get default | grep interface").Output()
if err != nil {
return nil, fmt.Errorf("Couldn't get network devices: %s", err)
}

fmt.Sscanf(string(out), " interface:%s", &iface)
if iface == "" {
return nil, fmt.Errorf("Parse the interface fail")
}

netDev[iface] = 1

return netDev, nil
}
44 changes: 44 additions & 0 deletions src/node-exporter/netdev_iface_linux.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
package collector

import (
"bufio"
"fmt"
"log"
"os"
"strings"
)

func getDefaultDev() (map[string]int, error) {
// /proc/net/route stores the kernel's routing table
// The interface whose destination is 00000000 is the interface of the default gateway
file, err := os.Open("/proc/net/route")
if err != nil {
log.Fatal(err)
}
defer file.Close()

netDev, err := getNetDev()
if err != nil {
return nil, fmt.Errorf("couldn't get network devices: %s", err)
}

scanner := bufio.NewScanner(file)
scanner.Scan()
for scanner.Scan() {
if scanner.Text() == "" {
break
}
s := strings.FieldsFunc(scanner.Text(), Split)
if s[1] == "00000000" {
netDev[s[0]] = 1
}
}

if err := scanner.Err(); err != nil {
log.Fatal(err)
return nil, err
}

return netDev, nil

}

0 comments on commit 6df9b9f

Please sign in to comment.