Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

APM Server support #49

Open
wants to merge 5 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
88 changes: 88 additions & 0 deletions collector/apm_server.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
package collector

import (
"github.com/prometheus/client_golang/prometheus"
"reflect"
"strings"
)

type apmServerCollector struct {
beatInfo *BeatInfo
stats *Stats
metrics exportedMetrics
}

// NewApmServerCollector constructor
func NewApmServerCollector(beatInfo *BeatInfo, stats *Stats) prometheus.Collector {
return &apmServerCollector{
beatInfo: beatInfo,
stats: stats,
metrics: FlattenMetrics(beatInfo, stats.ApmServer, "", nil),
}
}

// Describe returns all descriptions of the collector.
func (c *apmServerCollector) Describe(ch chan<- *prometheus.Desc) {

for _, metric := range c.metrics {
ch <- metric.desc
}

}

// Collect returns the current state of all metrics of the collector.
func (c *apmServerCollector) Collect(ch chan<- prometheus.Metric) {

for _, i := range c.metrics {
ch <- prometheus.MustNewConstMetric(i.desc, i.valType, i.eval(c.stats))
}

}

// Transform ApmServer struct into flat structure
func FlattenMetrics(beatInfo *BeatInfo, obj interface{}, prefix string, prefixArray []string) []exportedMetric {

var exported []exportedMetric

v := reflect.ValueOf(obj)
currentType := v.Type()

for i := 0; i < v.NumField(); i++ {
if v.Field(i).Kind() == reflect.Struct {
exported = append(exported, FlattenMetrics(beatInfo, v.Field(i).Interface(), prefix+formatMetricName(currentType.Field(i).Name)+"_", append(prefixArray, currentType.Field(i).Name))...)
} else {
var currentMetricName = currentType.Field(i).Name

var metric = exportedMetric{
desc: prometheus.NewDesc(
prometheus.BuildFQName(beatInfo.FormattedBeat(), prefix[:len(prefix)-1], formatMetricName(currentMetricName)),
prefix+currentType.Field(i).Name,
nil, nil,
),
eval: func(stats *Stats) float64 { return resolveStats(stats, append(prefixArray, currentMetricName)) },
valType: prometheus.CounterValue,
}
exported = append(exported, metric)
}

}
return exported
}

// Resolve stats by the array of prefix fields
func resolveStats(stats *Stats, prefixArray []string) float64 {
v := reflect.ValueOf(stats.ApmServer)
for _, prefix := range prefixArray {
if v.Kind() == reflect.Struct {
v = v.FieldByName(prefix)
} else {
return v.Interface().(float64)
}
}
return v.Interface().(float64)
}

// Format the metric name - used to transform Struct names (Capitalized) into lowercase format
func formatMetricName(name string) string {
return strings.ToLower(name)
}
293 changes: 293 additions & 0 deletions collector/apm_server_structs.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,293 @@
package collector

// Generated using https://mholt.github.io/json-to-go/

type ApmServer struct {
Acm struct {
Request struct {
Count float64 `json:"count"`
} `json:"request"`
Response struct {
Count float64 `json:"count"`
Errors struct {
Closed float64 `json:"closed"`
Count float64 `json:"count"`
Decode float64 `json:"decode"`
Forbidden float64 `json:"forbidden"`
Internal float64 `json:"internal"`
Invalidquery float64 `json:"invalidquery"`
Method float64 `json:"method"`
Notfound float64 `json:"notfound"`
Queue float64 `json:"queue"`
Ratelimit float64 `json:"ratelimit"`
Toolarge float64 `json:"toolarge"`
Unauthorized float64 `json:"unauthorized"`
Unavailable float64 `json:"unavailable"`
Validate float64 `json:"validate"`
} `json:"errors"`
Valid struct {
Accepted float64 `json:"accepted"`
Count float64 `json:"count"`
Notmodified float64 `json:"notmodified"`
Ok float64 `json:"ok"`
} `json:"valid"`
} `json:"response"`
Unset float64 `json:"unset"`
} `json:"acm"`
Decoder struct {
Deflate struct {
ContentLength float64 `json:"content-length"`
Count float64 `json:"count"`
} `json:"deflate"`
Gzip struct {
ContentLength float64 `json:"content-length"`
Count float64 `json:"count"`
} `json:"gzip"`
MissingContentLength struct {
Count float64 `json:"count"`
} `json:"missing-content-length"`
Reader struct {
Count float64 `json:"count"`
} `json:"reader"`
Uncompressed struct {
ContentLength float64 `json:"content-length"`
Count float64 `json:"count"`
} `json:"uncompressed"`
} `json:"decoder"`
Jaeger struct {
Grpc struct {
Collect struct {
Event struct {
Dropped struct {
Count float64 `json:"count"`
} `json:"dropped"`
Received struct {
Count float64 `json:"count"`
} `json:"received"`
} `json:"event"`
Request struct {
Count float64 `json:"count"`
} `json:"request"`
Response struct {
Count float64 `json:"count"`
Errors struct {
Count float64 `json:"count"`
} `json:"errors"`
Valid struct {
Count float64 `json:"count"`
} `json:"valid"`
} `json:"response"`
} `json:"collect"`
Sampling struct {
Event struct {
Dropped struct {
Count float64 `json:"count"`
} `json:"dropped"`
Received struct {
Count float64 `json:"count"`
} `json:"received"`
} `json:"event"`
Request struct {
Count float64 `json:"count"`
} `json:"request"`
Response struct {
Count float64 `json:"count"`
Errors struct {
Count float64 `json:"count"`
} `json:"errors"`
Valid struct {
Count float64 `json:"count"`
} `json:"valid"`
} `json:"response"`
} `json:"sampling"`
} `json:"grpc"`
HTTP struct {
Event struct {
Dropped struct {
Count float64 `json:"count"`
} `json:"dropped"`
Received struct {
Count float64 `json:"count"`
} `json:"received"`
} `json:"event"`
Request struct {
Count float64 `json:"count"`
} `json:"request"`
Response struct {
Count float64 `json:"count"`
Errors struct {
Count float64 `json:"count"`
} `json:"errors"`
Valid struct {
Count float64 `json:"count"`
} `json:"valid"`
} `json:"response"`
} `json:"http"`
} `json:"jaeger"`
Processor struct {
Error struct {
Frames float64 `json:"frames"`
Stacktraces float64 `json:"stacktraces"`
Transformations float64 `json:"transformations"`
} `json:"error"`
Metric struct {
Transformations float64 `json:"transformations"`
} `json:"metric"`
Sourcemap struct {
Counter float64 `json:"counter"`
Decoding struct {
Count float64 `json:"count"`
Errors float64 `json:"errors"`
} `json:"decoding"`
Validation struct {
Count float64 `json:"count"`
Errors float64 `json:"errors"`
} `json:"validation"`
} `json:"sourcemap"`
Span struct {
Frames float64 `json:"frames"`
Stacktraces float64 `json:"stacktraces"`
Transformations float64 `json:"transformations"`
} `json:"span"`
Stream struct {
Accepted float64 `json:"accepted"`
Errors struct {
Closed float64 `json:"closed"`
Invalid float64 `json:"invalid"`
Queue float64 `json:"queue"`
Server float64 `json:"server"`
Toolarge float64 `json:"toolarge"`
} `json:"errors"`
} `json:"stream"`
Transaction struct {
Transformations float64 `json:"transformations"`
} `json:"transaction"`
} `json:"processor"`
Profile struct {
Request struct {
Count float64 `json:"count"`
} `json:"request"`
Response struct {
Count float64 `json:"count"`
Errors struct {
Closed float64 `json:"closed"`
Count float64 `json:"count"`
Decode float64 `json:"decode"`
Forbidden float64 `json:"forbidden"`
Internal float64 `json:"internal"`
Invalidquery float64 `json:"invalidquery"`
Method float64 `json:"method"`
Notfound float64 `json:"notfound"`
Queue float64 `json:"queue"`
Ratelimit float64 `json:"ratelimit"`
Toolarge float64 `json:"toolarge"`
Unauthorized float64 `json:"unauthorized"`
Unavailable float64 `json:"unavailable"`
Validate float64 `json:"validate"`
} `json:"errors"`
Valid struct {
Accepted float64 `json:"accepted"`
Count float64 `json:"count"`
Notmodified float64 `json:"notmodified"`
Ok float64 `json:"ok"`
} `json:"valid"`
} `json:"response"`
Unset float64 `json:"unset"`
} `json:"profile"`
Root struct {
Request struct {
Count float64 `json:"count"`
} `json:"request"`
Response struct {
Count float64 `json:"count"`
Errors struct {
Closed float64 `json:"closed"`
Count float64 `json:"count"`
Decode float64 `json:"decode"`
Forbidden float64 `json:"forbidden"`
Internal float64 `json:"internal"`
Invalidquery float64 `json:"invalidquery"`
Method float64 `json:"method"`
Notfound float64 `json:"notfound"`
Queue float64 `json:"queue"`
Ratelimit float64 `json:"ratelimit"`
Toolarge float64 `json:"toolarge"`
Unauthorized float64 `json:"unauthorized"`
Unavailable float64 `json:"unavailable"`
Validate float64 `json:"validate"`
} `json:"errors"`
Valid struct {
Accepted float64 `json:"accepted"`
Count float64 `json:"count"`
Notmodified float64 `json:"notmodified"`
Ok float64 `json:"ok"`
} `json:"valid"`
} `json:"response"`
Unset float64 `json:"unset"`
} `json:"root"`
Sampling struct {
TransactionsDropped float64 `json:"transactions_dropped"`
} `json:"sampling"`
Server struct {
Request struct {
Count float64 `json:"count"`
} `json:"request"`
Response struct {
Count float64 `json:"count"`
Errors struct {
Closed float64 `json:"closed"`
Count float64 `json:"count"`
Decode float64 `json:"decode"`
Forbidden float64 `json:"forbidden"`
Internal float64 `json:"internal"`
Invalidquery float64 `json:"invalidquery"`
Method float64 `json:"method"`
Notfound float64 `json:"notfound"`
Queue float64 `json:"queue"`
Ratelimit float64 `json:"ratelimit"`
Toolarge float64 `json:"toolarge"`
Unauthorized float64 `json:"unauthorized"`
Unavailable float64 `json:"unavailable"`
Validate float64 `json:"validate"`
} `json:"errors"`
Valid struct {
Accepted float64 `json:"accepted"`
Count float64 `json:"count"`
Notmodified float64 `json:"notmodified"`
Ok float64 `json:"ok"`
} `json:"valid"`
} `json:"response"`
Unset float64 `json:"unset"`
} `json:"server"`
Sourcemap struct {
Request struct {
Count float64 `json:"count"`
} `json:"request"`
Response struct {
Count float64 `json:"count"`
Errors struct {
Closed float64 `json:"closed"`
Count float64 `json:"count"`
Decode float64 `json:"decode"`
Forbidden float64 `json:"forbidden"`
Internal float64 `json:"internal"`
Invalidquery float64 `json:"invalidquery"`
Method float64 `json:"method"`
Notfound float64 `json:"notfound"`
Queue float64 `json:"queue"`
Ratelimit float64 `json:"ratelimit"`
Toolarge float64 `json:"toolarge"`
Unauthorized float64 `json:"unauthorized"`
Unavailable float64 `json:"unavailable"`
Validate float64 `json:"validate"`
} `json:"errors"`
Valid struct {
Accepted float64 `json:"accepted"`
Count float64 `json:"count"`
Notmodified float64 `json:"notmodified"`
Ok float64 `json:"ok"`
} `json:"valid"`
} `json:"response"`
Unset float64 `json:"unset"`
} `json:"sourcemap"`
}
Loading