Skip to content

Commit

Permalink
Feature: Support different timeframe intervals.
Browse files Browse the repository at this point in the history
The default timeframe interval is the last 30 minutes (default New Relic
behaviour). Now we support custom timeframe intervals, relative
backwards in minutes.

See the readme for more information.

NOTE: This is a breaking change!
  • Loading branch information
kristinn committed Apr 20, 2017
1 parent bfb1b57 commit 4be5f77
Show file tree
Hide file tree
Showing 4 changed files with 88 additions and 51 deletions.
12 changes: 6 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,12 +48,12 @@ deadline: "15s"
workflow:
collect:
metrics:
/inteleon/newrelic/apm/APP_ID/show/summary/application/response_time: {}
/inteleon/newrelic/apm/APP_ID/show/summary/application/throughput: {}
/inteleon/newrelic/apm/APP_ID/show/summary/application/error_rate: {}
"|inteleon|newrelic|apm|APP_ID|metric|External/api.github.com/all|average_response_time|value": {}
"|inteleon|newrelic|apm|APP_ID|metric|External/api.github.com/all|calls_per_minute|value": {}
"|inteleon|newrelic|apm|APP_ID|metric|External/api.github.com/all|standard_deviation|value": {}
/inteleon/newrelic/apm/APP_ID/application/show/summary/application/response_time: {}
/inteleon/newrelic/apm/APP_ID/application/show/summary/application/throughput: {}
/inteleon/newrelic/apm/APP_ID/application/show/summary/application/error_rate: {}
"|inteleon|newrelic|apm|APP_ID|application|metric|*|External/api.github.com/all|average_response_time|value": {} # average value for the last 30 minutes (default New Relic timeframe)
"|inteleon|newrelic|apm|APP_ID|application|metric|1|External/api.github.com/all|calls_per_minute|value": {} # average value for the last minute
"|inteleon|newrelic|apm|APP_ID|application|metric|5|External/api.github.com/all|standard_deviation|value": {} # average value for the last 5 minutes
config:
/inteleon/newrelic:
api_key: "SUPER SECRET NEW RELIC API KEY"
Expand Down
28 changes: 14 additions & 14 deletions newrelic.example.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,20 +7,20 @@ deadline: "15s"
workflow:
collect:
metrics:
/inteleon/newrelic/apm/APP_ID/show/health/status: {}
/inteleon/newrelic/apm/APP_ID/show/reporting: {}
/inteleon/newrelic/apm/APP_ID/show/summary/application/response_time: {}
/inteleon/newrelic/apm/APP_ID/show/summary/application/throughput: {}
/inteleon/newrelic/apm/APP_ID/show/summary/application/error_rate: {}
/inteleon/newrelic/apm/APP_ID/show/summary/application/apdex_target: {}
/inteleon/newrelic/apm/APP_ID/show/summary/application/apdex_score: {}
/inteleon/newrelic/apm/APP_ID/show/summary/application/host_count: {}
/inteleon/newrelic/apm/APP_ID/show/summary/application/instance_count: {}
/inteleon/newrelic/apm/APP_ID/show/summary/user/response_time: {}
/inteleon/newrelic/apm/APP_ID/show/summary/user/throughput: {}
/inteleon/newrelic/apm/APP_ID/show/summary/user/apdex_target: {}
/inteleon/newrelic/apm/APP_ID/show/summary/user/apdex_score: {}
"|inteleon|newrelic|apm|APP_ID|metric|External/all|average_response_time|value": {}
/inteleon/newrelic/apm/APP_ID/application/show/health/status: {}
/inteleon/newrelic/apm/APP_ID/application/show/reporting: {}
/inteleon/newrelic/apm/APP_ID/application/show/summary/application/response_time: {}
/inteleon/newrelic/apm/APP_ID/application/show/summary/application/throughput: {}
/inteleon/newrelic/apm/APP_ID/application/show/summary/application/error_rate: {}
/inteleon/newrelic/apm/APP_ID/application/show/summary/application/apdex_target: {}
/inteleon/newrelic/apm/APP_ID/application/show/summary/application/apdex_score: {}
/inteleon/newrelic/apm/APP_ID/application/show/summary/application/host_count: {}
/inteleon/newrelic/apm/APP_ID/application/show/summary/application/instance_count: {}
/inteleon/newrelic/apm/APP_ID/application/show/summary/user/response_time: {}
/inteleon/newrelic/apm/APP_ID/application/show/summary/user/throughput: {}
/inteleon/newrelic/apm/APP_ID/application/show/summary/user/apdex_target: {}
/inteleon/newrelic/apm/APP_ID/application/show/summary/user/apdex_score: {}
"|inteleon|newrelic|apm|APP_ID|application|metric|1|External/all|average_response_time|value": {}
config:
/inteleon/newrelic:
api_key: "SUPER SECRET API KEY"
55 changes: 40 additions & 15 deletions newrelic/apm.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,86 +13,92 @@ import (
// APMMetrics is a list containing the available APM metrics and their properties.
var APMMetrics = []Metric{
{
Namespace: plugin.NewNamespace("show", "health", "status"),
Namespace: plugin.NewNamespace("application", "show", "health", "status"),
Type: "application",
Path: "HealthStatus",
Unit: "string",
},
{
Namespace: plugin.NewNamespace("show", "reporting"),
Namespace: plugin.NewNamespace("application", "show", "reporting"),
Type: "application",
Path: "Reporting",
Unit: "bool",
},
{
Namespace: plugin.NewNamespace("show", "summary", "application", "response_time"),
Namespace: plugin.NewNamespace("application", "show", "summary", "application", "response_time"),
Type: "application",
Path: "ApplicationSummary/ResponseTime",
Unit: "float",
},
{
Namespace: plugin.NewNamespace("show", "summary", "application", "throughput"),
Namespace: plugin.NewNamespace("application", "show", "summary", "application", "throughput"),
Type: "application",
Path: "ApplicationSummary/Throughput",
Unit: "float",
},
{
Namespace: plugin.NewNamespace("show", "summary", "application", "error_rate"),
Namespace: plugin.NewNamespace("application", "show", "summary", "application", "error_rate"),
Type: "application",
Path: "ApplicationSummary/ErrorRate",
Unit: "float",
},
{
Namespace: plugin.NewNamespace("show", "summary", "application", "apdex_target"),
Namespace: plugin.NewNamespace("application", "show", "summary", "application", "apdex_target"),
Type: "application",
Path: "ApplicationSummary/ApdexTarget",
Unit: "float",
},
{
Namespace: plugin.NewNamespace("show", "summary", "application", "apdex_score"),
Namespace: plugin.NewNamespace("application", "show", "summary", "application", "apdex_score"),
Type: "application",
Path: "ApplicationSummary/ApdexScore",
Unit: "float",
},
{
Namespace: plugin.NewNamespace("show", "summary", "application", "host_count"),
Namespace: plugin.NewNamespace("application", "show", "summary", "application", "host_count"),
Type: "application",
Path: "ApplicationSummary/HostCount",
Unit: "int",
},
{
Namespace: plugin.NewNamespace("show", "summary", "application", "instance_count"),
Namespace: plugin.NewNamespace("application", "show", "summary", "application", "instance_count"),
Type: "application",
Path: "ApplicationSummary/InstanceCount",
Unit: "int",
},
{
Namespace: plugin.NewNamespace("show", "summary", "user", "response_time"),
Namespace: plugin.NewNamespace("application", "show", "summary", "user", "response_time"),
Type: "application",
Path: "EndUserSummary/ResponseTime",
Unit: "float",
},
{
Namespace: plugin.NewNamespace("show", "summary", "user", "throughput"),
Namespace: plugin.NewNamespace("application", "show", "summary", "user", "throughput"),
Type: "application",
Path: "EndUserSummary/Throughput",
Unit: "float",
},
{
Namespace: plugin.NewNamespace("show", "summary", "user", "apdex_target"),
Namespace: plugin.NewNamespace("application", "show", "summary", "user", "apdex_target"),
Type: "application",
Path: "EndUserSummary/ApdexTarget",
Unit: "float",
},
{
Namespace: plugin.NewNamespace("show", "summary", "user", "apdex_score"),
Namespace: plugin.NewNamespace("application", "show", "summary", "user", "apdex_score"),
Type: "application",
Path: "EndUserSummary/ApdexScore",
Unit: "float",
},
{
Namespace: plugin.Namespace{
plugin.NewNamespaceElement("application"),
plugin.NewNamespaceElement("metric"),
plugin.NamespaceElement{
Name: "minutes",
Description: "Number of minutes to construct a relative timeframe from (now - minutes).",
Value: "*",
},
plugin.NamespaceElement{
Name: "metric_name",
Description: "Metric name",
Expand Down Expand Up @@ -300,10 +306,29 @@ func (a *APM) collectApplicationAdditionalMetrics(metrics []plugin.Metric) ([]pl
return appAdditionalMetrics, err
}

metricStringID := m.Namespace.Element(5).Value
relativeMin := m.Namespace.Element(6).Value
metricStringID := m.Namespace.Element(7).Value
metricDataOptions := &nr.MetricDataOptions{
Summarize: true,
}

if relativeMin != "*" {
relativeMinInt, err := strconv.Atoi(relativeMin)
if err != nil {
return appAdditionalMetrics, err
}

metricDataOptions.From = time.Now().UTC().Add(-(time.Duration(relativeMinInt) * time.Minute))
metricDataOptions.To = time.Now().UTC()
}

if _, ok := addMetrics[appIDInt][metricStringID]; !ok {
// Additional application metric missing, fetching...
fetchAppAdditionalMetricData, err := a.APMClient.GetApplicationMetricData(appIDInt, []string{metricStringID}, nil)
fetchAppAdditionalMetricData, err := a.APMClient.GetApplicationMetricData(
appIDInt,
[]string{metricStringID},
metricDataOptions,
)
if err != nil {
return appAdditionalMetrics, err
}
Expand Down
44 changes: 28 additions & 16 deletions newrelic/apm_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ func (a *apmClientTestImpl) GetApplicationMetricData(appID int, names []string,
{
Values: map[string]float64{
"average_response_time": 100.34,
"throughput": 23,
},
},
},
Expand Down Expand Up @@ -85,31 +86,38 @@ func TestCollectMetricsAppIDSuccess(t *testing.T) {

metrics := []plugin.Metric{
{
Namespace: plugin.NewNamespace("inteleon", "newrelic", "apm", "1337", "show", "health", "status"),
Namespace: plugin.NewNamespace("inteleon", "newrelic", "apm", "1337", "application", "show", "health", "status"),
Tags: map[string]string{
"Type": "application",
"Path": "HealthStatus",
"Unit": "string",
},
},
{
Namespace: plugin.NewNamespace("inteleon", "newrelic", "apm", "1234", "show", "health", "status"),
Namespace: plugin.NewNamespace("inteleon", "newrelic", "apm", "1234", "application", "show", "health", "status"),
Tags: map[string]string{
"Type": "application",
"Path": "HealthStatus",
"Unit": "string",
},
},
{
Namespace: plugin.NewNamespace("inteleon", "newrelic", "apm", "1337", "show", "reporting"),
Namespace: plugin.NewNamespace("inteleon", "newrelic", "apm", "1337", "application", "show", "reporting"),
Tags: map[string]string{
"Type": "application",
"Path": "Reporting",
"Unit": "bool",
},
},
{
Namespace: plugin.NewNamespace("inteleon", "newrelic", "apm", "1337", "metric", "hax", "average_response_time", "value"),
Namespace: plugin.NewNamespace("inteleon", "newrelic", "apm", "1337", "application", "metric", "*", "hax", "average_response_time", "value"),
Tags: map[string]string{
"Type": "metric",
"Unit": "float",
},
},
{
Namespace: plugin.NewNamespace("inteleon", "newrelic", "apm", "1337", "application", "metric", "1", "hax", "throughput", "value"),
Tags: map[string]string{
"Type": "metric",
"Unit": "float",
Expand All @@ -130,8 +138,8 @@ func TestCollectMetricsAppIDSuccess(t *testing.T) {
t.Fatal(err)
}

if len(ret) != 4 {
t.Fatal("expected", 4, "got", len(ret))
if len(ret) != 5 {
t.Fatal("expected", 5, "got", len(ret))
}

for _, m := range ret[:2] {
Expand All @@ -148,6 +156,10 @@ func TestCollectMetricsAppIDSuccess(t *testing.T) {
t.Fatal("expected", 100.34, "got", ret[3].Data.(float64))
}

if ret[4].Data.(float64) != 23 {
t.Fatal("expected", 23, "got", ret[4].Data.(float64))
}

if len(apmClient.appIDs) != 2 {
t.Fatal("expected", 2, "got", len(apmClient.appIDs))
}
Expand Down Expand Up @@ -189,38 +201,38 @@ func TestCollectMetricsAppIDMetricNameNotFoundFailure(t *testing.T) {

metrics := []plugin.Metric{
{
Namespace: plugin.NewNamespace("inteleon", "newrelic", "apm", "1337", "show", "health", "status"),
Namespace: plugin.NewNamespace("inteleon", "newrelic", "apm", "1337", "application", "show", "health", "status"),
Tags: map[string]string{
"Type": "application",
"Path": "HealthStatus",
"Unit": "string",
},
},
{
Namespace: plugin.NewNamespace("inteleon", "newrelic", "apm", "1234", "show", "health", "status"),
Namespace: plugin.NewNamespace("inteleon", "newrelic", "apm", "1234", "application", "show", "health", "status"),
Tags: map[string]string{
"Type": "application",
"Path": "HealthStatus",
"Unit": "string",
},
},
{
Namespace: plugin.NewNamespace("inteleon", "newrelic", "apm", "1337", "show", "reporting"),
Namespace: plugin.NewNamespace("inteleon", "newrelic", "apm", "1337", "application", "show", "reporting"),
Tags: map[string]string{
"Type": "application",
"Path": "Reporting",
"Unit": "bool",
},
},
{
Namespace: plugin.NewNamespace("inteleon", "newrelic", "apm", "1337", "metric", "hax", "average_response_time", "value"),
Namespace: plugin.NewNamespace("inteleon", "newrelic", "apm", "1337", "application", "metric", "*", "hax", "average_response_time", "value"),
Tags: map[string]string{
"Type": "metric",
"Unit": "float",
},
},
{
Namespace: plugin.NewNamespace("inteleon", "newrelic", "apm", "1337", "metric", "h4x", "average_response_time", "value"),
Namespace: plugin.NewNamespace("inteleon", "newrelic", "apm", "1337", "application", "metric", "*", "h4x", "average_response_time", "value"),
Tags: map[string]string{
"Type": "metric",
"Unit": "float",
Expand Down Expand Up @@ -256,38 +268,38 @@ func TestCollectMetricsAppIDMetricValueNameNotFoundFailure(t *testing.T) {

metrics := []plugin.Metric{
{
Namespace: plugin.NewNamespace("inteleon", "newrelic", "apm", "1337", "show", "health", "status"),
Namespace: plugin.NewNamespace("inteleon", "newrelic", "apm", "1337", "application", "show", "health", "status"),
Tags: map[string]string{
"Type": "application",
"Path": "HealthStatus",
"Unit": "string",
},
},
{
Namespace: plugin.NewNamespace("inteleon", "newrelic", "apm", "1234", "show", "health", "status"),
Namespace: plugin.NewNamespace("inteleon", "newrelic", "apm", "1234", "application", "show", "health", "status"),
Tags: map[string]string{
"Type": "application",
"Path": "HealthStatus",
"Unit": "string",
},
},
{
Namespace: plugin.NewNamespace("inteleon", "newrelic", "apm", "1337", "show", "reporting"),
Namespace: plugin.NewNamespace("inteleon", "newrelic", "apm", "1337", "application", "show", "reporting"),
Tags: map[string]string{
"Type": "application",
"Path": "Reporting",
"Unit": "bool",
},
},
{
Namespace: plugin.NewNamespace("inteleon", "newrelic", "apm", "1337", "metric", "hax", "average_response_time", "value"),
Namespace: plugin.NewNamespace("inteleon", "newrelic", "apm", "1337", "application", "metric", "*", "hax", "average_response_time", "value"),
Tags: map[string]string{
"Type": "metric",
"Unit": "float",
},
},
{
Namespace: plugin.NewNamespace("inteleon", "newrelic", "apm", "1337", "metric", "hax", "h444x", "value"),
Namespace: plugin.NewNamespace("inteleon", "newrelic", "apm", "1337", "application", "metric", "*", "hax", "h444x", "value"),
Tags: map[string]string{
"Type": "metric",
"Unit": "float",
Expand Down

0 comments on commit 4be5f77

Please sign in to comment.