Skip to content

Commit 914df2f

Browse files
author
Linus Wallgren
committed
Initial version of code
1 parent 5751570 commit 914df2f

File tree

5 files changed

+175
-0
lines changed

5 files changed

+175
-0
lines changed

go.mod

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
module github.com/AiflooAB/prometheus-mac-proxy

main.go

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
package main
2+
3+
import (
4+
"github.com/AiflooAB/prometheus-mac-proxy/pkg/mac"
5+
"github.com/AiflooAB/prometheus-mac-proxy/pkg/proxy"
6+
)
7+
8+
func main() {
9+
proxy.Start(mac.NewFileTransformer)
10+
}

pkg/mac/mac.go

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
package mac
2+
3+
import (
4+
"bufio"
5+
"fmt"
6+
"log"
7+
"os"
8+
"regexp"
9+
"strings"
10+
11+
"github.com/AiflooAB/prometheus-mac-proxy/pkg/proxy"
12+
)
13+
14+
type macTransformer struct {
15+
ipmac map[string]string
16+
}
17+
18+
func NewFileTransformer() proxy.Transformer {
19+
return &macTransformer{
20+
ipmac: readIPMacMap(),
21+
}
22+
}
23+
24+
func (trans *macTransformer) Transform(line string) string {
25+
mac := getMac(trans.ipmac, line)
26+
27+
return strings.Replace(line, "ip=", fmt.Sprintf("mac=\"%s\",ip=", mac), 1)
28+
}
29+
30+
var ipRegex = regexp.MustCompile(`ip="(.+?)"`)
31+
32+
func getMac(ipmac map[string]string, line string) string {
33+
matches := ipRegex.FindStringSubmatch(line)
34+
if len(matches) >= 1 {
35+
ip := matches[1]
36+
mac, found := ipmac[ip]
37+
if found {
38+
return mac
39+
}
40+
}
41+
return "UNKNOWN"
42+
}
43+
44+
func readIPMacMap() map[string]string {
45+
ipmac := make(map[string]string)
46+
file, err := os.Open("./all") // TODO
47+
if err != nil {
48+
log.Fatal(err)
49+
}
50+
defer file.Close()
51+
52+
scanner := bufio.NewScanner(file)
53+
for scanner.Scan() {
54+
line := scanner.Text()
55+
ip, mac := parsePromscanLine(line)
56+
ipmac[ip] = mac
57+
}
58+
59+
if err := scanner.Err(); err != nil {
60+
fmt.Fprintf(os.Stderr, "Got error while reading file: %v\n", err)
61+
}
62+
63+
return ipmac
64+
}
65+
66+
func parsePromscanLine(line string) (string, string) {
67+
var datetime string
68+
var ip string
69+
var mac string
70+
fmt.Sscanf(line, "%s %s %s", &datetime, &ip, &mac)
71+
return ip, mac
72+
}

pkg/mac/mac_test.go

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
package mac
2+
3+
import (
4+
"reflect"
5+
"testing"
6+
)
7+
8+
func TestTransformPrometheusline(t *testing.T) {
9+
tests := []struct {
10+
name string
11+
ipmac map[string]string
12+
line string
13+
expected string
14+
}{
15+
{
16+
"Missing mac",
17+
map[string]string{},
18+
`fping_response_duration_seconds_bucket{ip="192.168.1.153",le="0.4096"} 7652`,
19+
`fping_response_duration_seconds_bucket{mac="UNKNOWN",ip="192.168.1.153",le="0.4096"} 7652`,
20+
},
21+
{
22+
"Simple mac exists",
23+
map[string]string{"192.168.1.153": "00:11:22:33:44:55:66"},
24+
`fping_response_duration_seconds_bucket{ip="192.168.1.153",le="0.4096"} 7652`,
25+
`fping_response_duration_seconds_bucket{mac="00:11:22:33:44:55:66",ip="192.168.1.153",le="0.4096"} 7652`,
26+
},
27+
{
28+
"Unrelated line",
29+
map[string]string{},
30+
`# TYPE go_memstats_next_gc_bytes gauge`,
31+
`# TYPE go_memstats_next_gc_bytes gauge`,
32+
},
33+
}
34+
35+
for _, test := range tests {
36+
t.Run(test.name, func(t *testing.T) {
37+
transformer := &macTransformer{ipmac: test.ipmac}
38+
parsed := transformer.Transform(test.line)
39+
if !reflect.DeepEqual(test.expected, parsed) {
40+
t.Errorf("\n%+v\n!=\n%+v", test.expected, parsed)
41+
}
42+
})
43+
}
44+
}

pkg/proxy/proxy.go

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
package proxy
2+
3+
import (
4+
"bufio"
5+
"io"
6+
"log"
7+
"net/http"
8+
)
9+
10+
type Transformer interface {
11+
Transform(string) string
12+
}
13+
14+
func Start(transformerConstructor func() Transformer) {
15+
handleHTTP := func(w http.ResponseWriter, req *http.Request) {
16+
resp, err := http.Get("http://localhost:9299/metrics")
17+
18+
if err != nil {
19+
http.Error(w, err.Error(), http.StatusServiceUnavailable)
20+
return
21+
}
22+
defer resp.Body.Close()
23+
24+
copyHeader(w.Header(), resp.Header)
25+
w.WriteHeader(resp.StatusCode)
26+
27+
transformer := transformerConstructor()
28+
29+
scanner := bufio.NewScanner(resp.Body)
30+
for scanner.Scan() {
31+
line := scanner.Text()
32+
33+
io.WriteString(w, transformer.Transform(line))
34+
w.Write([]byte("\n"))
35+
}
36+
}
37+
38+
http.HandleFunc("/metrics", handleHTTP)
39+
log.Fatal(http.ListenAndServe("0.0.0.0:19299", nil))
40+
}
41+
42+
func copyHeader(dst, src http.Header) {
43+
for k, vv := range src {
44+
for _, v := range vv {
45+
dst.Add(k, v)
46+
}
47+
}
48+
}

0 commit comments

Comments
 (0)