diff --git a/README.md b/README.md index 175b460..0461913 100644 --- a/README.md +++ b/README.md @@ -17,6 +17,8 @@ Help on flags of namenode_exporter: Address on which to expose metrics and web interface. (default ":9070") -web.telemetry-path string Path under which to expose metrics. (default "/metrics") +-const.labels cluster:hd1;idc:idc1 + Const Lables ``` Help on flags of resourcemanager_exporter: @@ -27,6 +29,8 @@ Help on flags of resourcemanager_exporter: Address on which to expose metrics and web interface. (default ":9088") -web.telemetry-path string Path under which to expose metrics. (default "/metrics") +-const.labels cluster:hd1;idc:idc1 + Const Lables ``` -Tested on HDP2.3 +Tested on HDP2.3, CDH5.x diff --git a/go.mod b/go.mod index b011de9..67f08ee 100644 --- a/go.mod +++ b/go.mod @@ -2,14 +2,14 @@ module github.com/wyukawa/hadoop_exporter require ( github.com/Sirupsen/logrus v1.0.6 // indirect - github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973 // indirect - github.com/golang/protobuf v1.2.0 // indirect - github.com/matttproud/golang_protobuf_extensions v1.0.1 // indirect - github.com/prometheus/client_golang v0.8.0 - github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910 // indirect - github.com/prometheus/common v0.0.0-20180801064454-c7de2306084e // indirect + github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect + github.com/modern-go/reflect2 v1.0.1 // indirect + github.com/onsi/ginkgo v1.9.0 // indirect + github.com/onsi/gomega v1.6.0 // indirect + github.com/prometheus/client_golang v1.1.0 github.com/prometheus/log v0.0.0-20151026012452-9a3136781e1f - github.com/prometheus/procfs v0.0.0-20180725123919-05ee40e3a273 // indirect - golang.org/x/crypto v0.0.0-20180910181607-0e37d006457b // indirect - golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e // indirect + github.com/sirupsen/logrus v1.4.2 // indirect + github.com/stretchr/testify v1.4.0 // indirect + gopkg.in/airbrake/gobrake.v2 v2.0.9 // indirect + gopkg.in/gemnasium/logrus-airbrake-hook.v2 v2.1.2 // indirect ) diff --git a/namenode_exporter.go b/namenode_exporter.go index 97114f2..45c9822 100644 --- a/namenode_exporter.go +++ b/namenode_exporter.go @@ -3,8 +3,10 @@ package main import ( "encoding/json" "flag" + "github.com/prometheus/client_golang/prometheus/promhttp" "io/ioutil" "net/http" + "strings" "github.com/prometheus/client_golang/prometheus" "github.com/prometheus/log" @@ -18,6 +20,7 @@ var ( listenAddress = flag.String("web.listen-address", ":9070", "Address on which to expose metrics and web interface.") metricsPath = flag.String("web.telemetry-path", "/metrics", "Path under which to expose metrics.") namenodeJmxUrl = flag.String("namenode.jmx.url", "http://localhost:50070/jmx", "Hadoop JMX URL.") + constLabels = flag.String("const.labels", "", "cluster:dc;idc:dc1") ) type Exporter struct { @@ -43,103 +46,122 @@ type Exporter struct { isActive prometheus.Gauge } -func NewExporter(url string) *Exporter { +func NewExporter(url string, labels map[string]string) *Exporter { return &Exporter{ url: url, MissingBlocks: prometheus.NewGauge(prometheus.GaugeOpts{ Namespace: namespace, Name: "MissingBlocks", Help: "MissingBlocks", + ConstLabels: labels, }), CapacityTotal: prometheus.NewGauge(prometheus.GaugeOpts{ Namespace: namespace, Name: "CapacityTotal", Help: "CapacityTotal", + ConstLabels: labels, }), CapacityUsed: prometheus.NewGauge(prometheus.GaugeOpts{ Namespace: namespace, Name: "CapacityUsed", Help: "CapacityUsed", + ConstLabels: labels, }), CapacityRemaining: prometheus.NewGauge(prometheus.GaugeOpts{ Namespace: namespace, Name: "CapacityRemaining", Help: "CapacityRemaining", + ConstLabels: labels, }), CapacityUsedNonDFS: prometheus.NewGauge(prometheus.GaugeOpts{ Namespace: namespace, Name: "CapacityUsedNonDFS", Help: "CapacityUsedNonDFS", + ConstLabels: labels, }), BlocksTotal: prometheus.NewGauge(prometheus.GaugeOpts{ Namespace: namespace, Name: "BlocksTotal", Help: "BlocksTotal", + ConstLabels: labels, }), FilesTotal: prometheus.NewGauge(prometheus.GaugeOpts{ Namespace: namespace, Name: "FilesTotal", Help: "FilesTotal", + ConstLabels: labels, }), CorruptBlocks: prometheus.NewGauge(prometheus.GaugeOpts{ Namespace: namespace, Name: "CorruptBlocks", Help: "CorruptBlocks", + ConstLabels: labels, }), ExcessBlocks: prometheus.NewGauge(prometheus.GaugeOpts{ Namespace: namespace, Name: "ExcessBlocks", Help: "ExcessBlocks", + ConstLabels: labels, }), StaleDataNodes: prometheus.NewGauge(prometheus.GaugeOpts{ Namespace: namespace, Name: "StaleDataNodes", Help: "StaleDataNodes", + ConstLabels: labels, }), pnGcCount: prometheus.NewGauge(prometheus.GaugeOpts{ Namespace: namespace, Name: "ParNew_CollectionCount", Help: "ParNew GC Count", + ConstLabels: labels, }), pnGcTime: prometheus.NewGauge(prometheus.GaugeOpts{ Namespace: namespace, Name: "ParNew_CollectionTime", Help: "ParNew GC Time", + ConstLabels: labels, }), cmsGcCount: prometheus.NewGauge(prometheus.GaugeOpts{ Namespace: namespace, Name: "ConcurrentMarkSweep_CollectionCount", Help: "ConcurrentMarkSweep GC Count", + ConstLabels: labels, }), cmsGcTime: prometheus.NewGauge(prometheus.GaugeOpts{ Namespace: namespace, Name: "ConcurrentMarkSweep_CollectionTime", Help: "ConcurrentMarkSweep GC Time", + ConstLabels: labels, }), heapMemoryUsageCommitted: prometheus.NewGauge(prometheus.GaugeOpts{ Namespace: namespace, Name: "heapMemoryUsageCommitted", Help: "heapMemoryUsageCommitted", + ConstLabels: labels, }), heapMemoryUsageInit: prometheus.NewGauge(prometheus.GaugeOpts{ Namespace: namespace, Name: "heapMemoryUsageInit", Help: "heapMemoryUsageInit", + ConstLabels: labels, }), heapMemoryUsageMax: prometheus.NewGauge(prometheus.GaugeOpts{ Namespace: namespace, Name: "heapMemoryUsageMax", Help: "heapMemoryUsageMax", + ConstLabels: labels, }), heapMemoryUsageUsed: prometheus.NewGauge(prometheus.GaugeOpts{ Namespace: namespace, Name: "heapMemoryUsageUsed", Help: "heapMemoryUsageUsed", + ConstLabels: labels, }), isActive: prometheus.NewGauge(prometheus.GaugeOpts{ Namespace: namespace, Name: "isActive", Help: "isActive", + ConstLabels: labels, }), } } @@ -305,11 +327,20 @@ func (e *Exporter) Collect(ch chan<- prometheus.Metric) { func main() { flag.Parse() - exporter := NewExporter(*namenodeJmxUrl) + constLabelMap := make(map[string]string) + if len(*constLabels) > 0 { + cLabels := strings.Split(*constLabels, ";") + for _, pair := range cLabels { + kv := strings.Split(pair, ":") + constLabelMap[kv[0]] = kv[1] + } + } + + exporter := NewExporter(*namenodeJmxUrl, constLabelMap) prometheus.MustRegister(exporter) log.Printf("Starting Server: %s", *listenAddress) - http.Handle(*metricsPath, prometheus.Handler()) + http.Handle(*metricsPath, promhttp.Handler()) http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { w.Write([]byte(` NameNode Exporter diff --git a/resourcemanager_exporter.go b/resourcemanager_exporter.go index 0a4e8ff..55f1d4c 100644 --- a/resourcemanager_exporter.go +++ b/resourcemanager_exporter.go @@ -3,8 +3,10 @@ package main import ( "encoding/json" "flag" + "github.com/prometheus/client_golang/prometheus/promhttp" "io/ioutil" "net/http" + "strings" "github.com/prometheus/client_golang/prometheus" "github.com/prometheus/log" @@ -18,6 +20,7 @@ var ( listenAddress = flag.String("web.listen-address", ":9088", "Address on which to expose metrics and web interface.") metricsPath = flag.String("web.telemetry-path", "/metrics", "Path under which to expose metrics.") resourceManagerUrl = flag.String("resourcemanager.url", "http://localhost:8088", "Hadoop ResourceManager URL.") + constLabels = flag.String("const.labels", "", "cluster:dc;idc:dc1") ) type Exporter struct { @@ -47,123 +50,146 @@ type Exporter struct { totalMB prometheus.Gauge } -func NewExporter(url string) *Exporter { +func NewExporter(url string, labels map[string]string) *Exporter { return &Exporter{ url: url, activeNodes: prometheus.NewGauge(prometheus.GaugeOpts{ Namespace: namespace, Name: "activeNodes", Help: "activeNodes", + ConstLabels: labels, }), rebootedNodes: prometheus.NewGauge(prometheus.GaugeOpts{ Namespace: namespace, Name: "rebootedNodes", Help: "rebootedNodes", + ConstLabels: labels, }), decommissionedNodes: prometheus.NewGauge(prometheus.GaugeOpts{ Namespace: namespace, Name: "decommissionedNodes", Help: "decommissionedNodes", + ConstLabels: labels, }), unhealthyNodes: prometheus.NewGauge(prometheus.GaugeOpts{ Namespace: namespace, Name: "unhealthyNodes", Help: "unhealthyNodes", + ConstLabels: labels, }), lostNodes: prometheus.NewGauge(prometheus.GaugeOpts{ Namespace: namespace, Name: "lostNodes", Help: "lostNodes", + ConstLabels: labels, }), totalNodes: prometheus.NewGauge(prometheus.GaugeOpts{ Namespace: namespace, Name: "totalNodes", Help: "totalNodes", + ConstLabels: labels, }), totalVirtualCores: prometheus.NewGauge(prometheus.GaugeOpts{ Namespace: namespace, Name: "totalVirtualCores", Help: "totalVirtualCores", + ConstLabels: labels, }), availableMB: prometheus.NewGauge(prometheus.GaugeOpts{ Namespace: namespace, Name: "availableMB", Help: "availableMB", + ConstLabels: labels, }), reservedMB: prometheus.NewGauge(prometheus.GaugeOpts{ Namespace: namespace, Name: "reservedMB", Help: "reservedMB", + ConstLabels: labels, }), appsKilled: prometheus.NewGauge(prometheus.GaugeOpts{ Namespace: namespace, Name: "appsKilled", Help: "appsKilled", + ConstLabels: labels, }), appsFailed: prometheus.NewGauge(prometheus.GaugeOpts{ Namespace: namespace, Name: "appsFailed", Help: "appsFailed", + ConstLabels: labels, }), appsRunning: prometheus.NewGauge(prometheus.GaugeOpts{ Namespace: namespace, Name: "appsRunning", Help: "appsRunning", + ConstLabels: labels, }), appsPending: prometheus.NewGauge(prometheus.GaugeOpts{ Namespace: namespace, Name: "appsPending", Help: "appsPending", + ConstLabels: labels, }), appsCompleted: prometheus.NewGauge(prometheus.GaugeOpts{ Namespace: namespace, Name: "appsCompleted", Help: "appsCompleted", + ConstLabels: labels, }), appsSubmitted: prometheus.NewGauge(prometheus.GaugeOpts{ Namespace: namespace, Name: "appsSubmitted", Help: "appsSubmitted", + ConstLabels: labels, }), allocatedMB: prometheus.NewGauge(prometheus.GaugeOpts{ Namespace: namespace, Name: "allocatedMB", Help: "allocatedMB", + ConstLabels: labels, }), reservedVirtualCores: prometheus.NewGauge(prometheus.GaugeOpts{ Namespace: namespace, Name: "reservedVirtualCores", Help: "reservedVirtualCores", + ConstLabels: labels, }), availableVirtualCores: prometheus.NewGauge(prometheus.GaugeOpts{ Namespace: namespace, Name: "availableVirtualCores", Help: "availableVirtualCores", + ConstLabels: labels, }), allocatedVirtualCores: prometheus.NewGauge(prometheus.GaugeOpts{ Namespace: namespace, Name: "allocatedVirtualCores", Help: "allocatedVirtualCores", + ConstLabels: labels, }), containersAllocated: prometheus.NewGauge(prometheus.GaugeOpts{ Namespace: namespace, Name: "containersAllocated", Help: "containersAllocated", + ConstLabels: labels, }), containersReserved: prometheus.NewGauge(prometheus.GaugeOpts{ Namespace: namespace, Name: "containersReserved", Help: "containersReserved", + ConstLabels: labels, }), containersPending: prometheus.NewGauge(prometheus.GaugeOpts{ Namespace: namespace, Name: "containersPending", Help: "containersPending", + ConstLabels: labels, }), totalMB: prometheus.NewGauge(prometheus.GaugeOpts{ Namespace: namespace, Name: "totalMB", Help: "totalMB", + ConstLabels: labels, }), } } @@ -293,11 +319,20 @@ func (e *Exporter) Collect(ch chan<- prometheus.Metric) { func main() { flag.Parse() - exporter := NewExporter(*resourceManagerUrl) + constLabelMap := make(map[string]string) + if len(*constLabels) > 0 { + cLabels := strings.Split(*constLabels, ";") + for _, pair := range cLabels { + kv := strings.Split(pair, ":") + constLabelMap[kv[0]] = kv[1] + } + } + + exporter := NewExporter(*resourceManagerUrl, constLabelMap) prometheus.MustRegister(exporter) log.Printf("Starting Server: %s", *listenAddress) - http.Handle(*metricsPath, prometheus.Handler()) + http.Handle(*metricsPath, promhttp.Handler()) http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { w.Write([]byte(` ResourceManager Exporter