Skip to content

Commit

Permalink
Merge pull request #9 from ContaAzul/add-app-summary
Browse files Browse the repository at this point in the history
Collect application summary data
  • Loading branch information
diogonicoleti authored Jan 19, 2018
2 parents ce0fd4f + 6f23d82 commit 9e312e1
Show file tree
Hide file tree
Showing 4 changed files with 86 additions and 13 deletions.
47 changes: 44 additions & 3 deletions collector/collector.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,10 @@ type newRelicCollector struct {

up *prometheus.Desc
scrapeDuration *prometheus.Desc
appSummaryApdexScore *prometheus.Desc
appSummaryErrorRate *prometheus.Desc
appSummaryResponseTime *prometheus.Desc
appSummaryThroughput *prometheus.Desc
instanceSummaryApdexScore *prometheus.Desc
instanceSummaryErrorRate *prometheus.Desc
instanceSummaryResponseTime *prometheus.Desc
Expand All @@ -44,17 +48,30 @@ func NewNewRelicCollector(apiKey string, config config.Config) prometheus.Collec
nil,
nil,
),
appSummaryApdexScore: newAppSummaryDesc("apdex_score"),
appSummaryErrorRate: newAppSummaryDesc("error_rate"),
appSummaryResponseTime: newAppSummaryDesc("response_time"),
appSummaryThroughput: newAppSummaryDesc("throughput"),
instanceSummaryApdexScore: newInstanceSummaryDesc("apdex_score"),
instanceSummaryErrorRate: newInstanceSummaryDesc("error_rate"),
instanceSummaryResponseTime: newInstanceSummaryDesc("response_time"),
instanceSummaryThroughput: newInstanceSummaryDesc("throughput"),
}
}

func newAppSummaryDesc(name string) *prometheus.Desc {
return prometheus.NewDesc(
prometheus.BuildFQName(namespace, "app_summary", name),
"Application rolling three-to-four-minute average for "+strings.Replace(name, "_", " ", -1),
[]string{"app"},
nil,
)
}

func newInstanceSummaryDesc(name string) *prometheus.Desc {
return prometheus.NewDesc(
prometheus.BuildFQName(namespace, "instance_summary", name),
"Instance rolling three-to-four-minute average for "+strings.Replace(name, "_", " ", -1),
"Application instance rolling three-to-four-minute average for "+strings.Replace(name, "_", " ", -1),
[]string{"app", "instance"},
nil,
)
Expand All @@ -65,6 +82,10 @@ func newInstanceSummaryDesc(name string) *prometheus.Desc {
func (c *newRelicCollector) Describe(ch chan<- *prometheus.Desc) {
ch <- c.up
ch <- c.scrapeDuration
ch <- c.appSummaryApdexScore
ch <- c.appSummaryErrorRate
ch <- c.appSummaryResponseTime
ch <- c.appSummaryThroughput
ch <- c.instanceSummaryApdexScore
ch <- c.instanceSummaryErrorRate
ch <- c.instanceSummaryResponseTime
Expand All @@ -81,20 +102,40 @@ func (c *newRelicCollector) Collect(ch chan<- prometheus.Metric) {
start := time.Now()
for _, app := range c.config.Applications {
log.Infof("Collecting metrics from application: %s", app.Name)
application, err := c.client.ShowApplication(app.ID)
if err != nil {
ch <- prometheus.MustNewConstMetric(c.up, prometheus.GaugeValue, 0)
log.Errorf("Failed to get application: %v", err)
return
}
c.collectApplicationSummary(ch, app.Name, application)

instances, err := c.client.ListInstances(app.ID)
if err != nil {
ch <- prometheus.MustNewConstMetric(c.up, prometheus.GaugeValue, 0)
log.Errorf("Failed to get application instances: %v", err)
return
}

c.collectInstanceSummary(ch, app.Name, instances)
}

ch <- prometheus.MustNewConstMetric(c.up, prometheus.GaugeValue, 1)
ch <- prometheus.MustNewConstMetric(c.scrapeDuration, prometheus.GaugeValue, time.Since(start).Seconds())
}

func (c *newRelicCollector) collectApplicationSummary(ch chan<- prometheus.Metric,
appName string, application newrelic.Application) {
if application.ApplicationSummary.InstanceCount > 0 {
summary := application.ApplicationSummary
ch <- prometheus.MustNewConstMetric(c.appSummaryApdexScore, prometheus.GaugeValue, summary.ApdexScore, appName)
ch <- prometheus.MustNewConstMetric(c.appSummaryErrorRate, prometheus.GaugeValue, summary.ErrorRate, appName)
ch <- prometheus.MustNewConstMetric(c.appSummaryResponseTime, prometheus.GaugeValue, summary.ResponseTime, appName)
ch <- prometheus.MustNewConstMetric(c.appSummaryThroughput, prometheus.GaugeValue, summary.Throughput, appName)
} else {
log.Warnf("Ignoring application %s because its InstanceCount is 0.", appName)
}
}

func (c *newRelicCollector) collectInstanceSummary(ch chan<- prometheus.Metric,
appName string, instances []newrelic.ApplicationInstance) {
for _, instance := range instances {
Expand All @@ -105,7 +146,7 @@ func (c *newRelicCollector) collectInstanceSummary(ch chan<- prometheus.Metric,
ch <- prometheus.MustNewConstMetric(c.instanceSummaryResponseTime, prometheus.GaugeValue, summary.ResponseTime, appName, instance.Host)
ch <- prometheus.MustNewConstMetric(c.instanceSummaryThroughput, prometheus.GaugeValue, summary.Throughput, appName, instance.Host)
} else {
log.Warnf("Ignoring instance %s because its InstanceCount is 0.", instance.Host)
log.Warnf("Ignoring application instance %s because its InstanceCount is 0.", instance.Host)
}
}
}
31 changes: 31 additions & 0 deletions newrelic/application.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package newrelic

import (
"fmt"
)

// Application represents a New Relic application.
type Application struct {
ID int64 `json:"id"`
HealthStatus string `json:"health_status"`
ApplicationSummary ApplicationSummary `json:"application_summary"`
}

type applicationResponse struct {
Application Application `json:"application"`
}

// ShowApplication returns a single Application, identified by ID. The time range for
// summary data is the last 3-4 minutes.
func (c *Client) ShowApplication(applicationID int64) (Application, error) {
var app Application
path := fmt.Sprintf("v2/applications/%d.json", applicationID)
req, err := c.newRequest("GET", path)
if err != nil {
return app, err
}

var response applicationResponse
_, err = c.do(req, &response)
return response.Application, err
}
10 changes: 0 additions & 10 deletions newrelic/application_instances.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,16 +12,6 @@ type ApplicationInstance struct {
ApplicationSummary ApplicationSummary `json:"application_summary"`
}

// ApplicationSummary represents a rolling three-to-four-minute
// average for application key values
type ApplicationSummary struct {
InstanceCount int `json:"instance_count"`
ResponseTime float64 `json:"response_time"`
Throughput float64 `json:"throughput"`
ErrorRate float64 `json:"error_rate"`
ApdexScore float64 `json:"apdex_score"`
}

type listInstancesResponse struct {
Instances []ApplicationInstance `json:"application_instances"`
}
Expand Down
11 changes: 11 additions & 0 deletions newrelic/application_summary.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package newrelic

// ApplicationSummary represents a rolling three-to-four-minute
// average for application key values
type ApplicationSummary struct {
InstanceCount int `json:"instance_count"`
ResponseTime float64 `json:"response_time"`
Throughput float64 `json:"throughput"`
ErrorRate float64 `json:"error_rate"`
ApdexScore float64 `json:"apdex_score"`
}

0 comments on commit 9e312e1

Please sign in to comment.