-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathggg.go
162 lines (139 loc) · 3.25 KB
/
ggg.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
package main
import (
"os"
"io"
"fmt"
"log"
"xml"
"flag"
"net"
"time"
"strings"
)
type GangliaXml struct {
XMLName xml.Name `xml:"GANGLIA_XML"`
Grid []Grid
Cluster []Cluster
}
type Grid struct {
XMLName xml.Name `xml:"GRID"`
Cluster []Cluster
}
type Cluster struct {
XMLName xml.Name
Host []Host
}
type Host struct {
XMLName xml.Name `xml:"HOST"`
Name string `xml:"attr"`
Ip string `xml:"attr"`
Metric []Metric
}
type Metric struct {
XMLName xml.Name `xml:"METRIC"`
Name string `xml:"attr"`
Val string `xml:"attr"`
Type string `xml:"attr"`
Units string `xml:"attr"`
TN string `xml:"attr"`
TMax string `xml:"attr"`
DMax string `xml:"attr"`
Slope string `xml:"attr"`
ExtraData []ExtraElement `xml:"extra_data>extra_element"`
}
type ExtraElement struct {
XMLName xml.Name `xml:"EXTRA_ELEMENT"`
Name string `xml:"attr"`
Val string `xml:"attr"`
}
var ganglia_addr = flag.String("ganglia_addr", "localhost:8649", "ganglia address")
var carbon_addr = flag.String("carbon_addr", "localhost:2003", "carbon address")
var metric_prefix = flag.String("prefix", "ggg.", "prefix for metric names")
var timestamp = time.Seconds()
var runeMap = map[int]int{
46: 95, // '.' -> '_'
}
func graphiteStringMap(rune int) (ret int) {
ret, ok := runeMap[rune]
if !ok {
ret = rune
}
return
}
func readXmlFromFile(in io.Reader) (gmeta GangliaXml, err os.Error) {
p := xml.NewParser(in)
p.CharsetReader = CharsetReader
gmeta = GangliaXml{}
err = p.Unmarshal(&gmeta, nil)
return
}
func printClusterMetrics(out io.Writer, cl *Cluster, ret chan int) {
ch := make(chan int)
log.Print("Reading hosts")
for _, hst := range cl.Host {
log.Printf("Reading host %s", hst.Name)
go printHostMetrics(out, hst, ch)
}
for _ = range cl.Host {
<-ch
}
ret <- 1
}
func printHostMetrics(out io.Writer, h Host, ret chan int) {
ch := make(chan int)
log.Printf("Reading %s metrics", h.Name)
for _, m := range h.Metric {
go printMetric(out, strings.Map(graphiteStringMap, h.Name), m, ch)
}
// drain the channel
for _ = range h.Metric {
<-ch
}
ret <- 1
}
func printMetric(out io.Writer, host string, m Metric, ret chan int) {
if m.Type != "string" {
fmt.Fprintf(out, "%s%s.%s %s %d\n", *metric_prefix, host, m.Name, m.Val, timestamp)
}
ret <- 1
}
func main() {
flag.Parse()
// open connection to ganglia
ganglia_conn, err := net.Dial("tcp", *ganglia_addr)
if err != nil {
log.Fatal("Dial ganglia: ", err)
}
defer ganglia_conn.Close()
// open connection to carbon-agent
carbon_conn, err := net.Dial("tcp", *carbon_addr)
if err != nil {
log.Fatal("Dial: ", err)
}
defer carbon_conn.Close()
// read xml into memory
gmeta, err := readXmlFromFile(ganglia_conn)
if err != nil {
log.Fatal("xml.unmarshal: ", err)
}
c := make(chan int)
cs := 0
// dispatch goroutines
for _, cl := range gmeta.Cluster {
log.Print("Reading clusters")
/* log.Printf("Cluster %s: %#v\n", cl.Name, cl)*/
go printClusterMetrics(carbon_conn, &cl, c)
cs++
}
for _, gr := range gmeta.Grid {
for _, cl := range gr.Cluster {
go printClusterMetrics(carbon_conn, &cl, c)
cs++
}
}
// drain channel
for cs > 0 {
<-c
cs--
}
}