mirror of
https://github.com/taigrr/wtf
synced 2025-01-18 04:03:14 -08:00
Integrate vendored NewRelic dependency (#767)
The NewRelic module relies on yfronto/newrelic, which no longer exists. yfronto deleted that directory quite awhile ago, and since then it has been vendored. But vendoring a missing repository creates problems when trying to update the vendored code. This PR brings the yfronto/newrelic code into the mainline. Signed-off-by: Chris Cummer <chriscummer@me.com>
This commit is contained in:
75
modules/newrelic/client/README.md
Normal file
75
modules/newrelic/client/README.md
Normal file
@@ -0,0 +1,75 @@
|
||||
[](http://godoc.org/github.com/yfronto/newrelic)
|
||||
[](https://travis-ci.org/yfronto/newrelic)
|
||||
|
||||
# New Relic API library for Go
|
||||
|
||||
This is a Go library that wraps the [New Relic][1] REST
|
||||
API. It provides the needed types to interact with the New Relic REST API.
|
||||
|
||||
It's still in progress and I haven't finished the entirety of the API, yet. I
|
||||
plan to finish all GET (read) operations before any POST (create) operations,
|
||||
and then PUT (update) operations, and, finally, the DELETE operations.
|
||||
|
||||
The API documentation can be found from [New Relic][1],
|
||||
and you'll need an API key (for some operations, an Admin API key is
|
||||
required).
|
||||
|
||||
## USAGE
|
||||
|
||||
This library will provide a client object and any operations can be performed
|
||||
through it. Simply import this library and create a client to get started:
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"github.com/yfronto/newrelic"
|
||||
)
|
||||
|
||||
var api_key = "..." // Required
|
||||
|
||||
func main() {
|
||||
// Create the client object
|
||||
client := newrelic.NewClient(api_key)
|
||||
|
||||
// Get the applciation with ID 12345
|
||||
myApp, err := client.GetApplication(12345)
|
||||
if err != nil {
|
||||
// Handle error
|
||||
}
|
||||
|
||||
// Work with the object
|
||||
fmt.Println(myApp.Name)
|
||||
|
||||
// Some operations accept options
|
||||
opts := &newrelic.AlertEventOptions{
|
||||
// Only events with "MyProduct" as the product name
|
||||
Filter: newRelic.AlertEventFilter{
|
||||
Product: "MyProduct",
|
||||
},
|
||||
}
|
||||
// Get a list of recent events for my product
|
||||
events, err := client.GetAlertEvents(opts)
|
||||
if err != nil {
|
||||
// Handle error
|
||||
}
|
||||
// Display each event with some information
|
||||
for _, e := range events {
|
||||
fmt.Printf("%d -- %d (%s): %s\n", e.Timestamp, e.Id, e.Priority, e.Description)
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Contributing
|
||||
|
||||
As I work to populate all actions, bugs are bound to come up. Feel free to
|
||||
send me a pull request or just file an issue. Staying up to date with an API
|
||||
is hard work and I'm happy to accept contributors.
|
||||
|
||||
**DISCLAIMER:** *I am in no way affiliated with New Relic and this work is
|
||||
merely a convenience project for myself with no guarantees. It should be
|
||||
considered "as-is" with no implication of responsibility. See the included
|
||||
LICENSE for more details.*
|
||||
|
||||
[1]: http://www.newrelic.com
|
||||
59
modules/newrelic/client/alert_conditions.go
Normal file
59
modules/newrelic/client/alert_conditions.go
Normal file
@@ -0,0 +1,59 @@
|
||||
package newrelic
|
||||
|
||||
// AlertCondition describes what triggers an alert for a specific policy.
|
||||
type AlertCondition struct {
|
||||
ID int `json:"id,omitempty"`
|
||||
Type string `json:"type,omitempty"`
|
||||
Name string `json:"name,omitempty"`
|
||||
Enabled bool `json:"name,omitempty"`
|
||||
Entities []string `json:"entities,omitempty"`
|
||||
Metric string `json:"metric,omitempty"`
|
||||
RunbookURL string `json:"runbook_url,omitempty"`
|
||||
Terms []AlertConditionTerm `json:"terms,omitempty"`
|
||||
UserDefined AlertUserDefined `json:"user_defined,omitempty"`
|
||||
}
|
||||
|
||||
// AlertConditionTerm defines thresholds that trigger an AlertCondition.
|
||||
type AlertConditionTerm struct {
|
||||
Duration string `json:"duration,omitempty"`
|
||||
Operator string `json:"operator,omitempty"`
|
||||
Priority string `json:"priority,omitempty"`
|
||||
Threshold string `json:"threshold,omitempty"`
|
||||
TimeFunction string `json:"time_function,omitempty"`
|
||||
}
|
||||
|
||||
// AlertUserDefined describes user-defined behavior for an AlertCondition.
|
||||
type AlertUserDefined struct {
|
||||
Metric string `json:"metric,omitempty"`
|
||||
ValueFunction string `json:"value_function,omitempty"`
|
||||
}
|
||||
|
||||
// AlertConditionOptions define filters for GetAlertConditions.
|
||||
type AlertConditionOptions struct {
|
||||
policyID int
|
||||
Page int
|
||||
}
|
||||
|
||||
func (o *AlertConditionOptions) String() string {
|
||||
if o == nil {
|
||||
return ""
|
||||
}
|
||||
return encodeGetParams(map[string]interface{}{
|
||||
"policy_id": o.policyID,
|
||||
"page": o.Page,
|
||||
})
|
||||
}
|
||||
|
||||
// GetAlertConditions will return any AlertCondition defined for a given
|
||||
// policy, optionally filtered by AlertConditionOptions.
|
||||
func (c *Client) GetAlertConditions(policy int, options *AlertConditionOptions) ([]AlertCondition, error) {
|
||||
resp := &struct {
|
||||
Conditions []AlertCondition `json:"conditions,omitempty"`
|
||||
}{}
|
||||
options.policyID = policy
|
||||
err := c.doGet("alerts_conditions.json", options, resp)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return resp.Conditions, nil
|
||||
}
|
||||
60
modules/newrelic/client/alert_events.go
Normal file
60
modules/newrelic/client/alert_events.go
Normal file
@@ -0,0 +1,60 @@
|
||||
package newrelic
|
||||
|
||||
// AlertEvent describes a triggered event.
|
||||
type AlertEvent struct {
|
||||
ID int `json:"id,omitempty"`
|
||||
EventType string `json:"event_type,omitempty"`
|
||||
Product string `json:"product,omitempty"`
|
||||
EntityType string `json:"entity_type,omitempty"`
|
||||
EntityGroupID int `json:"entity_group_id,omitempty"`
|
||||
EntityID int `json:"entity_id,omitempty"`
|
||||
Priority string `json:"priority,omitempty"`
|
||||
Description string `json:"description,omitempty"`
|
||||
Timestamp int64 `json:"timestamp,omitempty"`
|
||||
IncidentID int `json:"incident_id"`
|
||||
}
|
||||
|
||||
// AlertEventFilter provides filters for AlertEventOptions when calling
|
||||
// GetAlertEvents.
|
||||
type AlertEventFilter struct {
|
||||
// TODO: New relic restricts these options
|
||||
Product string
|
||||
EntityType string
|
||||
EntityGroupID int
|
||||
EntityID int
|
||||
EventType string
|
||||
}
|
||||
|
||||
// AlertEventOptions is an optional means of filtering AlertEvents when
|
||||
// calling GetAlertEvents.
|
||||
type AlertEventOptions struct {
|
||||
Filter AlertEventFilter
|
||||
Page int
|
||||
}
|
||||
|
||||
func (o *AlertEventOptions) String() string {
|
||||
if o == nil {
|
||||
return ""
|
||||
}
|
||||
return encodeGetParams(map[string]interface{}{
|
||||
"filter[product]": o.Filter.Product,
|
||||
"filter[entity_type]": o.Filter.EntityType,
|
||||
"filter[entity_group_id]": o.Filter.EntityGroupID,
|
||||
"filter[entity_id]": o.Filter.EntityID,
|
||||
"filter[event_type]": o.Filter.EventType,
|
||||
"page": o.Page,
|
||||
})
|
||||
}
|
||||
|
||||
// GetAlertEvents will return a slice of recent AlertEvent items triggered,
|
||||
// optionally filtering by AlertEventOptions.
|
||||
func (c *Client) GetAlertEvents(options *AlertEventOptions) ([]AlertEvent, error) {
|
||||
resp := &struct {
|
||||
RecentEvents []AlertEvent `json:"recent_events,omitempty"`
|
||||
}{}
|
||||
err := c.doGet("alerts_events.json", options, resp)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return resp.RecentEvents, nil
|
||||
}
|
||||
91
modules/newrelic/client/alert_events_test_fixtures.go
Normal file
91
modules/newrelic/client/alert_events_test_fixtures.go
Normal file
@@ -0,0 +1,91 @@
|
||||
package newrelic
|
||||
|
||||
type getAlertEventsTestsInput struct {
|
||||
options *AlertEventOptions
|
||||
data string
|
||||
}
|
||||
|
||||
type getAlertEventsTestsOutput struct {
|
||||
data []AlertEvent
|
||||
err error
|
||||
}
|
||||
|
||||
const (
|
||||
testAlertEventJSON = `
|
||||
{
|
||||
"id": 123,
|
||||
"event_type": "VIOLATION_OPEN",
|
||||
"product": "APM",
|
||||
"entity_type": "Application",
|
||||
"entity_group_id": 1234,
|
||||
"entity_id": 12,
|
||||
"priority": "Warning",
|
||||
"description": "Test Alert",
|
||||
"timestamp": 1472355451353,
|
||||
"incident_id": 23
|
||||
}
|
||||
`
|
||||
)
|
||||
|
||||
var (
|
||||
testAlertEvent = AlertEvent{
|
||||
ID: 123,
|
||||
EventType: "VIOLATION_OPEN",
|
||||
Product: "APM",
|
||||
EntityType: "Application",
|
||||
EntityGroupID: 1234,
|
||||
EntityID: 12,
|
||||
Priority: "Warning",
|
||||
Description: "Test Alert",
|
||||
Timestamp: 1472355451353,
|
||||
IncidentID: 23,
|
||||
}
|
||||
getAlertEventsTests = []struct {
|
||||
in getAlertEventsTestsInput
|
||||
out getAlertEventsTestsOutput
|
||||
}{
|
||||
{
|
||||
getAlertEventsTestsInput{
|
||||
options: nil,
|
||||
data: `{"recent_events": [` + testAlertEventJSON + `]}`,
|
||||
},
|
||||
getAlertEventsTestsOutput{
|
||||
data: []AlertEvent{
|
||||
testAlertEvent,
|
||||
},
|
||||
err: nil,
|
||||
},
|
||||
},
|
||||
}
|
||||
alertEventOptionsStringerTests = []struct {
|
||||
in *AlertEventOptions
|
||||
out string
|
||||
}{
|
||||
{
|
||||
&AlertEventOptions{},
|
||||
"",
|
||||
},
|
||||
{
|
||||
nil,
|
||||
"",
|
||||
},
|
||||
{
|
||||
&AlertEventOptions{
|
||||
Filter: AlertEventFilter{
|
||||
Product: "testProduct",
|
||||
EntityType: "testEntityType",
|
||||
EntityGroupID: 123,
|
||||
EntityID: 1234,
|
||||
EventType: "testEventType",
|
||||
},
|
||||
Page: 1,
|
||||
},
|
||||
"filter%5Bentity_group_id%5D=123" +
|
||||
"&filter%5Bentity_id%5D=1234" +
|
||||
"&filter%5Bentity_type%5D=testEntityType" +
|
||||
"&filter%5Bevent_type%5D=testEventType" +
|
||||
"&filter%5Bproduct%5D=testProduct" +
|
||||
"&page=1",
|
||||
},
|
||||
}
|
||||
)
|
||||
53
modules/newrelic/client/application_deployments.go
Normal file
53
modules/newrelic/client/application_deployments.go
Normal file
@@ -0,0 +1,53 @@
|
||||
package newrelic
|
||||
|
||||
import (
|
||||
"strconv"
|
||||
"time"
|
||||
)
|
||||
|
||||
// ApplicationDeploymentLinks represents links that apply to an
|
||||
// ApplicationDeployment.
|
||||
type ApplicationDeploymentLinks struct {
|
||||
Application int `json:"application,omitempty"`
|
||||
}
|
||||
|
||||
// ApplicationDeploymentOptions provide a means to filter when calling
|
||||
// GetApplicationDeployments.
|
||||
type ApplicationDeploymentOptions struct {
|
||||
Page int
|
||||
}
|
||||
|
||||
// ApplicationDeployment contains information about a New Relic Application
|
||||
// Deployment.
|
||||
type ApplicationDeployment struct {
|
||||
ID int `json:"id,omitempty"`
|
||||
Revision string `json:"revision,omitempty"`
|
||||
Changelog string `json:"changelog,omitempty"`
|
||||
Description string `json:"description,omitempty"`
|
||||
User string `json:"user,omitemtpy"`
|
||||
Timestamp time.Time `json:"timestamp,omitempty"`
|
||||
Links ApplicationDeploymentLinks `json:"links,omitempty"`
|
||||
}
|
||||
|
||||
// GetApplicationDeployments returns a slice of New Relic Application
|
||||
// Deployments.
|
||||
func (c *Client) GetApplicationDeployments(id int, opt *ApplicationDeploymentOptions) ([]ApplicationDeployment, error) {
|
||||
resp := &struct {
|
||||
Deployments []ApplicationDeployment `json:"deployments,omitempty"`
|
||||
}{}
|
||||
path := "applications/" + strconv.Itoa(id) + "/deployments.json"
|
||||
err := c.doGet(path, opt, resp)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return resp.Deployments, nil
|
||||
}
|
||||
|
||||
func (o *ApplicationDeploymentOptions) String() string {
|
||||
if o == nil {
|
||||
return ""
|
||||
}
|
||||
return encodeGetParams(map[string]interface{}{
|
||||
"page": o.Page,
|
||||
})
|
||||
}
|
||||
38
modules/newrelic/client/application_host_metrics.go
Normal file
38
modules/newrelic/client/application_host_metrics.go
Normal file
@@ -0,0 +1,38 @@
|
||||
package newrelic
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
)
|
||||
|
||||
// GetApplicationHostMetrics will return a slice of Metric items for a
|
||||
// particular Application ID's Host ID, optionally filtering by
|
||||
// MetricsOptions.
|
||||
func (c *Client) GetApplicationHostMetrics(appID, hostID int, options *MetricsOptions) ([]Metric, error) {
|
||||
mc := NewMetricClient(c)
|
||||
|
||||
return mc.GetMetrics(
|
||||
fmt.Sprintf(
|
||||
"applications/%d/hosts/%d/metrics.json",
|
||||
appID,
|
||||
hostID,
|
||||
),
|
||||
options,
|
||||
)
|
||||
}
|
||||
|
||||
// GetApplicationHostMetricData will return all metric data for a particular
|
||||
// application's host and slice of metric names, optionally filtered by
|
||||
// MetricDataOptions.
|
||||
func (c *Client) GetApplicationHostMetricData(appID, hostID int, names []string, options *MetricDataOptions) (*MetricDataResponse, error) {
|
||||
mc := NewMetricClient(c)
|
||||
|
||||
return mc.GetMetricData(
|
||||
fmt.Sprintf(
|
||||
"applications/%d/hosts/%d/metrics/data.json",
|
||||
appID,
|
||||
hostID,
|
||||
),
|
||||
names,
|
||||
options,
|
||||
)
|
||||
}
|
||||
94
modules/newrelic/client/application_hosts.go
Normal file
94
modules/newrelic/client/application_hosts.go
Normal file
@@ -0,0 +1,94 @@
|
||||
package newrelic
|
||||
|
||||
import (
|
||||
"strconv"
|
||||
)
|
||||
|
||||
// ApplicationHostSummary describes an Application's host.
|
||||
type ApplicationHostSummary struct {
|
||||
ApdexScore float64 `json:"apdex_score,omitempty"`
|
||||
ErrorRate float64 `json:"error_rate,omitempty"`
|
||||
InstanceCount int `json:"instance_count,omitempty"`
|
||||
ResponseTime float64 `json:"response_time,omitempty"`
|
||||
Throughput float64 `json:"throughput,omitempty"`
|
||||
}
|
||||
|
||||
// ApplicationHostEndUserSummary describes the end user summary component of
|
||||
// an ApplicationHost.
|
||||
type ApplicationHostEndUserSummary struct {
|
||||
ResponseTime float64 `json:"response_time,omitempty"`
|
||||
Throughput float64 `json:"throughput,omitempty"`
|
||||
ApdexScore float64 `json:"apdex_score,omitempty"`
|
||||
}
|
||||
|
||||
// ApplicationHostLinks list IDs associated with an ApplicationHost.
|
||||
type ApplicationHostLinks struct {
|
||||
Application int `json:"application,omitempty"`
|
||||
ApplicationInstances []int `json:"application_instances,omitempty"`
|
||||
Server int `json:"server,omitempty"`
|
||||
}
|
||||
|
||||
// ApplicationHost describes a New Relic Application Host.
|
||||
type ApplicationHost struct {
|
||||
ApplicationName string `json:"application_name,omitempty"`
|
||||
ApplicationSummary ApplicationHostSummary `json:"application_summary,omitempty"`
|
||||
HealthStatus string `json:"health_status,omitempty"`
|
||||
Host string `json:"host,omitempty"`
|
||||
ID int `json:"idomitempty"`
|
||||
Language string `json:"language,omitempty"`
|
||||
Links ApplicationHostLinks `json:"links,omitempty"`
|
||||
EndUserSummary ApplicationHostEndUserSummary `json:"end_user_summary,omitempty"`
|
||||
}
|
||||
|
||||
// ApplicationHostsFilter provides a means to filter requests through
|
||||
// ApplicationHostsOptions when calling GetApplicationHosts.
|
||||
type ApplicationHostsFilter struct {
|
||||
Hostname string
|
||||
IDs []int
|
||||
}
|
||||
|
||||
// ApplicationHostsOptions provide a means to filter results when calling
|
||||
// GetApplicationHosts.
|
||||
type ApplicationHostsOptions struct {
|
||||
Filter ApplicationHostsFilter
|
||||
Page int
|
||||
}
|
||||
|
||||
// GetApplicationHosts returns a slice of New Relic Application Hosts,
|
||||
// optionally filtering by ApplicationHostOptions.
|
||||
func (c *Client) GetApplicationHosts(id int, options *ApplicationHostsOptions) ([]ApplicationHost, error) {
|
||||
resp := &struct {
|
||||
ApplicationHosts []ApplicationHost `json:"application_hosts,omitempty"`
|
||||
}{}
|
||||
path := "applications/" + strconv.Itoa(id) + "/hosts.json"
|
||||
err := c.doGet(path, options, resp)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return resp.ApplicationHosts, nil
|
||||
}
|
||||
|
||||
// GetApplicationHost returns a single Application Host associated with the
|
||||
// given application host ID and host ID.
|
||||
func (c *Client) GetApplicationHost(appID, hostID int) (*ApplicationHost, error) {
|
||||
resp := &struct {
|
||||
ApplicationHost ApplicationHost `json:"application_host,omitempty"`
|
||||
}{}
|
||||
path := "applications/" + strconv.Itoa(appID) + "/hosts/" + strconv.Itoa(hostID) + ".json"
|
||||
err := c.doGet(path, nil, resp)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &resp.ApplicationHost, nil
|
||||
}
|
||||
|
||||
func (o *ApplicationHostsOptions) String() string {
|
||||
if o == nil {
|
||||
return ""
|
||||
}
|
||||
return encodeGetParams(map[string]interface{}{
|
||||
"filter[hostname]": o.Filter.Hostname,
|
||||
"filter[ids]": o.Filter.IDs,
|
||||
"page": o.Page,
|
||||
})
|
||||
}
|
||||
38
modules/newrelic/client/application_instance_metrics.go
Normal file
38
modules/newrelic/client/application_instance_metrics.go
Normal file
@@ -0,0 +1,38 @@
|
||||
package newrelic
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
)
|
||||
|
||||
// GetApplicationInstanceMetrics will return a slice of Metric items for a
|
||||
// particular Application ID's instance ID, optionally filtering by
|
||||
// MetricsOptions.
|
||||
func (c *Client) GetApplicationInstanceMetrics(appID, instanceID int, options *MetricsOptions) ([]Metric, error) {
|
||||
mc := NewMetricClient(c)
|
||||
|
||||
return mc.GetMetrics(
|
||||
fmt.Sprintf(
|
||||
"applications/%d/instances/%d/metrics.json",
|
||||
appID,
|
||||
instanceID,
|
||||
),
|
||||
options,
|
||||
)
|
||||
}
|
||||
|
||||
// GetApplicationInstanceMetricData will return all metric data for a
|
||||
// particular application's instance and slice of metric names, optionally
|
||||
// filtered by MetricDataOptions.
|
||||
func (c *Client) GetApplicationInstanceMetricData(appID, instanceID int, names []string, options *MetricDataOptions) (*MetricDataResponse, error) {
|
||||
mc := NewMetricClient(c)
|
||||
|
||||
return mc.GetMetricData(
|
||||
fmt.Sprintf(
|
||||
"applications/%d/instances/%d/metrics/data.json",
|
||||
appID,
|
||||
instanceID,
|
||||
),
|
||||
names,
|
||||
options,
|
||||
)
|
||||
}
|
||||
94
modules/newrelic/client/application_instances.go
Normal file
94
modules/newrelic/client/application_instances.go
Normal file
@@ -0,0 +1,94 @@
|
||||
package newrelic
|
||||
|
||||
import (
|
||||
"strconv"
|
||||
)
|
||||
|
||||
// ApplicationInstanceSummary describes an Application's instance.
|
||||
type ApplicationInstanceSummary struct {
|
||||
ResponseTime float64 `json:"response_time,omitempty"`
|
||||
Throughput float64 `json:"throughput,omitempty"`
|
||||
ErrorRate float64 `json:"error_rate,omitempty"`
|
||||
ApdexScore float64 `json:"apdex_score,omitempty"`
|
||||
InstanceCount int `json:"instance_count,omitempty"`
|
||||
}
|
||||
|
||||
// ApplicationInstanceEndUserSummary describes the end user summary component
|
||||
// of an ApplicationInstance.
|
||||
type ApplicationInstanceEndUserSummary struct {
|
||||
ResponseTime float64 `json:"response_time,omitempty"`
|
||||
Throughput float64 `json:"throughput,omitempty"`
|
||||
ApdexScore float64 `json:"apdex_score,omitempty"`
|
||||
}
|
||||
|
||||
// ApplicationInstanceLinks lists IDs associated with an ApplicationInstances.
|
||||
type ApplicationInstanceLinks struct {
|
||||
Application int `json:"application,omitempty"`
|
||||
ApplicationHost int `json:"application_host,omitempty"`
|
||||
Server int `json:"server,omitempty"`
|
||||
}
|
||||
|
||||
// ApplicationInstance describes a New Relic Application instance.
|
||||
type ApplicationInstance struct {
|
||||
ID int `json:"id,omitempty"`
|
||||
ApplicationName string `json:"application_name,omitempty"`
|
||||
Host string `json:"host,omitempty"`
|
||||
Port int `json:"port,omitempty"`
|
||||
Language string `json:"language,omitempty"`
|
||||
HealthStatus string `json:"health_status,omitempty"`
|
||||
ApplicationSummary ApplicationInstanceSummary `json:"application_summary,omitempty"`
|
||||
EndUserSummary ApplicationInstanceEndUserSummary `json:"end_user_summary,omitempty"`
|
||||
Links ApplicationInstanceLinks `json:"links,omitempty"`
|
||||
}
|
||||
|
||||
// ApplicationInstancesFilter provides a means to filter requests through
|
||||
// ApplicationInstancesOptions when calling GetApplicationInstances.
|
||||
type ApplicationInstancesFilter struct {
|
||||
Hostname string
|
||||
IDs []int
|
||||
}
|
||||
|
||||
// ApplicationInstancesOptions provides a means to filter results when calling
|
||||
// GetApplicationInstances.
|
||||
type ApplicationInstancesOptions struct {
|
||||
Filter ApplicationInstancesFilter
|
||||
Page int
|
||||
}
|
||||
|
||||
// GetApplicationInstances returns a slice of New Relic Application Instances,
|
||||
// optionall filtering by ApplicationInstancesOptions.
|
||||
func (c *Client) GetApplicationInstances(appID int, options *ApplicationInstancesOptions) ([]ApplicationInstance, error) {
|
||||
resp := &struct {
|
||||
ApplicationInstances []ApplicationInstance `json:"application_instances,omitempty"`
|
||||
}{}
|
||||
path := "applications/" + strconv.Itoa(appID) + "/instances.json"
|
||||
err := c.doGet(path, options, resp)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return resp.ApplicationInstances, nil
|
||||
}
|
||||
|
||||
// GetApplicationInstance returns a single Application Instance associated
|
||||
// with the given application ID and instance ID
|
||||
func (c *Client) GetApplicationInstance(appID, instanceID int) (*ApplicationInstance, error) {
|
||||
resp := &struct {
|
||||
ApplicationInstance ApplicationInstance `json:"application_instance,omitempty"`
|
||||
}{}
|
||||
path := "applications/" + strconv.Itoa(appID) + "/instances/" + strconv.Itoa(instanceID) + ".json"
|
||||
err := c.doGet(path, nil, resp)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &resp.ApplicationInstance, nil
|
||||
}
|
||||
func (o *ApplicationInstancesOptions) String() string {
|
||||
if o == nil {
|
||||
return ""
|
||||
}
|
||||
return encodeGetParams(map[string]interface{}{
|
||||
"filter[hostname]": o.Filter.Hostname,
|
||||
"filter[ids]": o.Filter.IDs,
|
||||
"page": o.Page,
|
||||
})
|
||||
}
|
||||
36
modules/newrelic/client/application_metrics.go
Normal file
36
modules/newrelic/client/application_metrics.go
Normal file
@@ -0,0 +1,36 @@
|
||||
package newrelic
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
)
|
||||
|
||||
// GetApplicationMetrics will return a slice of Metric items for a
|
||||
// particular Application ID, optionally filtering by
|
||||
// MetricsOptions.
|
||||
func (c *Client) GetApplicationMetrics(id int, options *MetricsOptions) ([]Metric, error) {
|
||||
mc := NewMetricClient(c)
|
||||
|
||||
return mc.GetMetrics(
|
||||
fmt.Sprintf(
|
||||
"applications/%d/metrics.json",
|
||||
id,
|
||||
),
|
||||
options,
|
||||
)
|
||||
}
|
||||
|
||||
// GetApplicationMetricData will return all metric data for a particular
|
||||
// application and slice of metric names, optionally filtered by
|
||||
// MetricDataOptions.
|
||||
func (c *Client) GetApplicationMetricData(id int, names []string, options *MetricDataOptions) (*MetricDataResponse, error) {
|
||||
mc := NewMetricClient(c)
|
||||
|
||||
return mc.GetMetricData(
|
||||
fmt.Sprintf(
|
||||
"applications/%d/metrics/data.json",
|
||||
id,
|
||||
),
|
||||
names,
|
||||
options,
|
||||
)
|
||||
}
|
||||
175
modules/newrelic/client/application_metrics_test_fixtures.go
Normal file
175
modules/newrelic/client/application_metrics_test_fixtures.go
Normal file
@@ -0,0 +1,175 @@
|
||||
package newrelic
|
||||
|
||||
type getApplicationMetricsTestsInput struct {
|
||||
id int
|
||||
options *MetricsOptions
|
||||
data string
|
||||
}
|
||||
|
||||
type getApplicationMetricsTestsOutput struct {
|
||||
data []Metric
|
||||
err error
|
||||
}
|
||||
|
||||
type getApplicationMetricDataTestsInput struct {
|
||||
id int
|
||||
Names []string
|
||||
options *MetricDataOptions
|
||||
data string
|
||||
}
|
||||
|
||||
type getApplicationMetricDataTestsOutput struct {
|
||||
data *MetricDataResponse
|
||||
err error
|
||||
}
|
||||
|
||||
const (
|
||||
testApplicationMetricJSON = `
|
||||
{
|
||||
"name": "testMetric",
|
||||
"values": [
|
||||
"testValue1",
|
||||
"testValue2"
|
||||
]
|
||||
}
|
||||
`
|
||||
)
|
||||
|
||||
var (
|
||||
testApplicationMetric = Metric{
|
||||
Name: "testMetric",
|
||||
Values: []string{"testValue1", "testValue2"},
|
||||
}
|
||||
getApplicaitonMetricsTests = []struct {
|
||||
in getApplicationMetricsTestsInput
|
||||
out getApplicationMetricsTestsOutput
|
||||
}{
|
||||
{
|
||||
getApplicationMetricsTestsInput{
|
||||
id: 123,
|
||||
options: nil,
|
||||
data: `{"metrics": [` +
|
||||
testApplicationMetricJSON + `,` +
|
||||
testApplicationMetricJSON +
|
||||
`]}`,
|
||||
},
|
||||
getApplicationMetricsTestsOutput{
|
||||
data: []Metric{
|
||||
testApplicationMetric,
|
||||
testApplicationMetric,
|
||||
},
|
||||
err: nil,
|
||||
},
|
||||
},
|
||||
}
|
||||
applicationMetricOptionsStringerTests = []struct {
|
||||
in *MetricsOptions
|
||||
out string
|
||||
}{
|
||||
{
|
||||
&MetricsOptions{},
|
||||
"",
|
||||
},
|
||||
{
|
||||
nil,
|
||||
"",
|
||||
},
|
||||
{
|
||||
&MetricsOptions{
|
||||
Name: "testName",
|
||||
Page: 5,
|
||||
},
|
||||
"name=testName" +
|
||||
"&page=5",
|
||||
},
|
||||
}
|
||||
applicationMetricDataOptionsStringerTests = []struct {
|
||||
in *MetricDataOptions
|
||||
out string
|
||||
}{
|
||||
{
|
||||
&MetricDataOptions{},
|
||||
"",
|
||||
},
|
||||
{
|
||||
nil,
|
||||
"",
|
||||
},
|
||||
{
|
||||
&MetricDataOptions{
|
||||
Names: Array{[]string{"test1", "test2"}},
|
||||
Values: Array{[]string{"value1", "value2"}},
|
||||
From: testTime,
|
||||
To: testTime,
|
||||
Period: 123,
|
||||
Summarize: true,
|
||||
Raw: true,
|
||||
},
|
||||
"from=" + testTimeStringEscaped +
|
||||
"&names%5B%5D=test1" +
|
||||
"&names%5B%5D=test2" +
|
||||
"&period=123" +
|
||||
"&raw=true" +
|
||||
"&summarize=true" +
|
||||
"&to=" + testTimeStringEscaped +
|
||||
"&values%5B%5D=value1&values%5B%5D=value2",
|
||||
},
|
||||
}
|
||||
testApplicationMetricDataJSON = `
|
||||
{
|
||||
"metric_data": {
|
||||
"from": "` + testTimeRawString + `",
|
||||
"to": "` + testTimeRawString + `",
|
||||
"metrics_found": ["name1"],
|
||||
"metrics_not_found": ["name2"],
|
||||
"metrics": [
|
||||
{
|
||||
"name": "testName",
|
||||
"timeslices": [
|
||||
{
|
||||
"from": "` + testTimeRawString + `",
|
||||
"to": "` + testTimeRawString + `",
|
||||
"values": {"testVal": 1.234}
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
`
|
||||
testApplicationMetricData = MetricData{
|
||||
Name: "testName",
|
||||
Timeslices: []MetricTimeslice{
|
||||
MetricTimeslice{
|
||||
From: testTime,
|
||||
To: testTime,
|
||||
Values: map[string]float64{
|
||||
"testVal": 1.234,
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
getApplicaitonMetricDataTests = []struct {
|
||||
in getApplicationMetricDataTestsInput
|
||||
out getApplicationMetricDataTestsOutput
|
||||
}{
|
||||
{
|
||||
getApplicationMetricDataTestsInput{
|
||||
id: 1234,
|
||||
Names: []string{"name1", "name2"},
|
||||
options: &MetricDataOptions{},
|
||||
data: testApplicationMetricDataJSON,
|
||||
},
|
||||
getApplicationMetricDataTestsOutput{
|
||||
data: &MetricDataResponse{
|
||||
From: testTime,
|
||||
To: testTime,
|
||||
MetricsFound: []string{"name1"},
|
||||
MetricsNotFound: []string{"name2"},
|
||||
Metrics: []MetricData{testApplicationMetricData},
|
||||
},
|
||||
err: nil,
|
||||
},
|
||||
},
|
||||
}
|
||||
)
|
||||
111
modules/newrelic/client/applications.go
Normal file
111
modules/newrelic/client/applications.go
Normal file
@@ -0,0 +1,111 @@
|
||||
package newrelic
|
||||
|
||||
import (
|
||||
"strconv"
|
||||
"time"
|
||||
)
|
||||
|
||||
// ApplicationSummary describes the brief summary component of an Application.
|
||||
type ApplicationSummary struct {
|
||||
ResponseTime float64 `json:"response_time,omitempty"`
|
||||
Throughput float64 `json:"throughput,omitempty"`
|
||||
ErrorRate float64 `json:"error_rate,omitempty"`
|
||||
ApdexTarget float64 `json:"apdex_target,omitempty"`
|
||||
ApdexScore float64 `json:"apdex_score,omitempty"`
|
||||
HostCount int `json:"host_count,omitempty"`
|
||||
InstanceCount int `json:"instance_count,omitempty"`
|
||||
ConcurrentInstanceCount int `json:"concurrent_instance_count,omitempty"`
|
||||
}
|
||||
|
||||
// EndUserSummary describes the end user summary component of an Application.
|
||||
type EndUserSummary struct {
|
||||
ResponseTime float64 `json:"response_time,omitempty"`
|
||||
Throughput float64 `json:"throughput,omitempty"`
|
||||
ApdexTarget float64 `json:"apdex_target,omitempty"`
|
||||
ApdexScore float64 `json:"apdex_score,omitempty"`
|
||||
}
|
||||
|
||||
// Settings describe settings for an Application.
|
||||
type Settings struct {
|
||||
AppApdexThreshold float64 `json:"app_apdex_threshold,omitempty"`
|
||||
EndUserApdexThreshold float64 `json:"end_user_apdex_threshold,omitempty"`
|
||||
EnableRealUserMonitoring bool `json:"enable_real_user_monitoring,omitempty"`
|
||||
UseServerSideConfig bool `json:"use_server_side_config,omitempty"`
|
||||
}
|
||||
|
||||
// Links list IDs associated with an Application.
|
||||
type Links struct {
|
||||
Servers []int `json:"servers,omitempty"`
|
||||
ApplicationHosts []int `json:"application_hosts,omitempty"`
|
||||
ApplicationInstances []int `json:"application_instances,omitempty"`
|
||||
AlertPolicy int `json:"alert_policy,omitempty"`
|
||||
}
|
||||
|
||||
// Application describes a New Relic Application.
|
||||
type Application struct {
|
||||
ID int `json:"id,omitempty"`
|
||||
Name string `json:"name,omitempty"`
|
||||
Language string `json:"language,omitempty"`
|
||||
HealthStatus string `json:"health_status,omitempty"`
|
||||
Reporting bool `json:"reporting,omitempty"`
|
||||
LastReportedAt time.Time `json:"last_reported_at,omitempty"`
|
||||
ApplicationSummary ApplicationSummary `json:"application_summary,omitempty"`
|
||||
EndUserSummary EndUserSummary `json:"end_user_summary,omitempty"`
|
||||
Settings Settings `json:"settings,omitempty"`
|
||||
Links Links `json:"links,omitempty"`
|
||||
}
|
||||
|
||||
// ApplicationFilter provides a means to filter requests through
|
||||
// ApplicaitonOptions when calling GetApplications.
|
||||
type ApplicationFilter struct {
|
||||
Name string
|
||||
Host string
|
||||
IDs []int
|
||||
Language string
|
||||
}
|
||||
|
||||
// ApplicationOptions provides a means to filter results when calling
|
||||
// GetApplicaitons.
|
||||
type ApplicationOptions struct {
|
||||
Filter ApplicationFilter
|
||||
Page int
|
||||
}
|
||||
|
||||
func (o *ApplicationOptions) String() string {
|
||||
if o == nil {
|
||||
return ""
|
||||
}
|
||||
return encodeGetParams(map[string]interface{}{
|
||||
"filter[name]": o.Filter.Name,
|
||||
"filter[host]": o.Filter.Host,
|
||||
"filter[ids]": o.Filter.IDs,
|
||||
"filter[language]": o.Filter.Language,
|
||||
"page": o.Page,
|
||||
})
|
||||
}
|
||||
|
||||
// GetApplications returns a slice of New Relic Applications, optionally
|
||||
// filtering by ApplicationOptions.
|
||||
func (c *Client) GetApplications(options *ApplicationOptions) ([]Application, error) {
|
||||
resp := &struct {
|
||||
Applications []Application `json:"applications,omitempty"`
|
||||
}{}
|
||||
err := c.doGet("applications.json", options, resp)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return resp.Applications, nil
|
||||
}
|
||||
|
||||
// GetApplication returns a single Application associated with a given ID.
|
||||
func (c *Client) GetApplication(id int) (*Application, error) {
|
||||
resp := &struct {
|
||||
Application Application `json:"application,omitempty"`
|
||||
}{}
|
||||
path := "applications/" + strconv.Itoa(id) + ".json"
|
||||
err := c.doGet(path, nil, resp)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &resp.Application, nil
|
||||
}
|
||||
165
modules/newrelic/client/applications_test_fixtures.go
Normal file
165
modules/newrelic/client/applications_test_fixtures.go
Normal file
@@ -0,0 +1,165 @@
|
||||
package newrelic
|
||||
|
||||
type getApplicationsTestsInput struct {
|
||||
options *ApplicationOptions
|
||||
data string
|
||||
}
|
||||
|
||||
type getApplicationsTestsOutput struct {
|
||||
data []Application
|
||||
err error
|
||||
}
|
||||
|
||||
type getApplicationTestsInput struct {
|
||||
id int
|
||||
data string
|
||||
}
|
||||
|
||||
type getApplicationTestsOutput struct {
|
||||
data *Application
|
||||
err error
|
||||
}
|
||||
|
||||
var (
|
||||
testApplicationJSON = `
|
||||
{
|
||||
"application_summary": {
|
||||
"apdex_score": 1.0,
|
||||
"apdex_target": 0.5,
|
||||
"error_rate": 0.0,
|
||||
"host_count": 1,
|
||||
"instance_count": 1,
|
||||
"response_time": 0.263,
|
||||
"throughput": 12.3
|
||||
},
|
||||
"end_user_summary": {
|
||||
"response_time": 0.263,
|
||||
"throughput": 12.3,
|
||||
"apdex_target": 0.5,
|
||||
"apdex_score": 1
|
||||
},
|
||||
"health_status": "green",
|
||||
"id": 12345,
|
||||
"language": "java",
|
||||
"last_reported_at": "` + testTimeRawString + `",
|
||||
"links": {
|
||||
"alert_policy": 123,
|
||||
"application_hosts": [
|
||||
1234567
|
||||
],
|
||||
"application_instances": [
|
||||
1234568
|
||||
],
|
||||
"servers": [
|
||||
54321
|
||||
]
|
||||
},
|
||||
"name": "test.example.com",
|
||||
"reporting": true,
|
||||
"settings": {
|
||||
"app_apdex_threshold": 0.5,
|
||||
"enable_real_user_monitoring": true,
|
||||
"end_user_apdex_threshold": 1.0,
|
||||
"use_server_side_config": false
|
||||
}
|
||||
}
|
||||
`
|
||||
testApplication = Application{
|
||||
ID: 12345,
|
||||
Name: "test.example.com",
|
||||
Language: "java",
|
||||
HealthStatus: "green",
|
||||
Reporting: true,
|
||||
LastReportedAt: testTime,
|
||||
ApplicationSummary: ApplicationSummary{
|
||||
ResponseTime: 0.263,
|
||||
Throughput: 12.3,
|
||||
ErrorRate: 0,
|
||||
ApdexTarget: 0.5,
|
||||
ApdexScore: 1,
|
||||
HostCount: 1,
|
||||
InstanceCount: 1,
|
||||
ConcurrentInstanceCount: 0,
|
||||
},
|
||||
EndUserSummary: EndUserSummary{
|
||||
ResponseTime: 0.263,
|
||||
Throughput: 12.3,
|
||||
ApdexTarget: 0.5,
|
||||
ApdexScore: 1,
|
||||
},
|
||||
Settings: Settings{
|
||||
AppApdexThreshold: 0.5,
|
||||
EndUserApdexThreshold: 1,
|
||||
EnableRealUserMonitoring: true,
|
||||
UseServerSideConfig: false,
|
||||
},
|
||||
Links: Links{
|
||||
Servers: []int{54321},
|
||||
ApplicationHosts: []int{1234567},
|
||||
ApplicationInstances: []int{1234568},
|
||||
AlertPolicy: 123,
|
||||
},
|
||||
}
|
||||
testApplications = []Application{
|
||||
testApplication,
|
||||
testApplication,
|
||||
}
|
||||
getApplicationTests = []struct {
|
||||
in getApplicationTestsInput
|
||||
out getApplicationTestsOutput
|
||||
}{
|
||||
{
|
||||
getApplicationTestsInput{
|
||||
id: 12345,
|
||||
data: `{ "application":` + testApplicationJSON + `}`,
|
||||
},
|
||||
getApplicationTestsOutput{
|
||||
data: &testApplication,
|
||||
},
|
||||
},
|
||||
}
|
||||
getApplicationsTests = []struct {
|
||||
in getApplicationsTestsInput
|
||||
out getApplicationsTestsOutput
|
||||
}{
|
||||
{
|
||||
getApplicationsTestsInput{
|
||||
options: nil,
|
||||
data: `{"applications":[` + testApplicationJSON + "," + testApplicationJSON + "]}",
|
||||
},
|
||||
getApplicationsTestsOutput{
|
||||
data: testApplications,
|
||||
err: nil,
|
||||
},
|
||||
},
|
||||
}
|
||||
applicationOptionsStringerTests = []struct {
|
||||
in *ApplicationOptions
|
||||
out string
|
||||
}{
|
||||
{
|
||||
&ApplicationOptions{},
|
||||
"",
|
||||
},
|
||||
{
|
||||
&ApplicationOptions{
|
||||
Filter: ApplicationFilter{
|
||||
Name: "testName",
|
||||
Host: "testHost",
|
||||
IDs: []int{123, 456},
|
||||
Language: "java",
|
||||
},
|
||||
Page: 5,
|
||||
},
|
||||
`filter%5Bhost%5D=testHost` +
|
||||
`&filter%5Bids%5D=123%2C456` +
|
||||
`&filter%5Blanguage%5D=java` +
|
||||
`&filter%5Bname%5D=testName` +
|
||||
`&page=5`,
|
||||
},
|
||||
{
|
||||
nil,
|
||||
"",
|
||||
},
|
||||
}
|
||||
)
|
||||
11
modules/newrelic/client/array.go
Normal file
11
modules/newrelic/client/array.go
Normal file
@@ -0,0 +1,11 @@
|
||||
package newrelic
|
||||
|
||||
// An Array is a type expected by the NewRelic API that differs from a comma-
|
||||
// separated list. When passing GET params that expect an 'Array' type with
|
||||
// one to many values, the expected format is "key=val1&key=val2" but an
|
||||
// argument with zero to many values is of the form "key=val1,val2", and
|
||||
// neither can be used in the other's place, so we have to differentiate
|
||||
// somehow.
|
||||
type Array struct {
|
||||
arr []string
|
||||
}
|
||||
48
modules/newrelic/client/browser_applications.go
Normal file
48
modules/newrelic/client/browser_applications.go
Normal file
@@ -0,0 +1,48 @@
|
||||
package newrelic
|
||||
|
||||
// BrowserApplicationsFilter is the filtering component of
|
||||
// BrowserApplicationsOptions
|
||||
type BrowserApplicationsFilter struct {
|
||||
Name string
|
||||
IDs []int
|
||||
}
|
||||
|
||||
// BrowserApplicationsOptions provides a filtering mechanism for
|
||||
// GetBrowserApplications.
|
||||
type BrowserApplicationsOptions struct {
|
||||
Filter BrowserApplicationsFilter
|
||||
Page int
|
||||
}
|
||||
|
||||
// BrowserApplication describes a New Relic Browser Application.
|
||||
type BrowserApplication struct {
|
||||
ID int `json:"id,omitempty"`
|
||||
Name string `json:"name,omitempty"`
|
||||
BrowserMonitoringKey string `json:"browser_monitoring_key,omitempty"`
|
||||
LoaderScript string `json:"loader_script,omitempty"`
|
||||
}
|
||||
|
||||
// GetBrowserApplications will return a slice of New Relic Browser
|
||||
// Applications, optionally filtered by BrowserApplicationsOptions.
|
||||
func (c *Client) GetBrowserApplications(opt *BrowserApplicationsOptions) ([]BrowserApplication, error) {
|
||||
resp := &struct {
|
||||
BrowserApplications []BrowserApplication `json:"browser_applications,omitempty"`
|
||||
}{}
|
||||
path := "browser_applications.json"
|
||||
err := c.doGet(path, opt, resp)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return resp.BrowserApplications, nil
|
||||
}
|
||||
|
||||
func (o *BrowserApplicationsOptions) String() string {
|
||||
if o == nil {
|
||||
return ""
|
||||
}
|
||||
return encodeGetParams(map[string]interface{}{
|
||||
"filter[name]": o.Filter.Name,
|
||||
"filter[ids]": o.Filter.IDs,
|
||||
"page": o.Page,
|
||||
})
|
||||
}
|
||||
17
modules/newrelic/client/common_test_fixtures.go
Normal file
17
modules/newrelic/client/common_test_fixtures.go
Normal file
@@ -0,0 +1,17 @@
|
||||
package newrelic
|
||||
|
||||
import (
|
||||
"net/url"
|
||||
"time"
|
||||
)
|
||||
|
||||
const (
|
||||
testAPIKey = "test_api_key"
|
||||
testTimeRawString = "2016-01-20T20:29:38Z"
|
||||
)
|
||||
|
||||
var (
|
||||
testTime, _ = time.Parse(time.RFC3339, testTimeRawString)
|
||||
testTimeString = testTime.String()
|
||||
testTimeStringEscaped = url.QueryEscape(testTimeString)
|
||||
)
|
||||
34
modules/newrelic/client/component_metrics.go
Normal file
34
modules/newrelic/client/component_metrics.go
Normal file
@@ -0,0 +1,34 @@
|
||||
package newrelic
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
)
|
||||
|
||||
// GetComponentMetrics will return a slice of Metric items for a
|
||||
// particular Component ID, optionally filtered by MetricsOptions.
|
||||
func (c *Client) GetComponentMetrics(id int, options *MetricsOptions) ([]Metric, error) {
|
||||
mc := NewMetricClient(c)
|
||||
|
||||
return mc.GetMetrics(
|
||||
fmt.Sprintf(
|
||||
"components/%d/metrics.json",
|
||||
id,
|
||||
),
|
||||
options,
|
||||
)
|
||||
}
|
||||
|
||||
// GetComponentMetricData will return all metric data for a particular
|
||||
// component, optionally filtered by MetricDataOptions.
|
||||
func (c *Client) GetComponentMetricData(id int, names []string, options *MetricDataOptions) (*MetricDataResponse, error) {
|
||||
mc := NewMetricClient(c)
|
||||
|
||||
return mc.GetMetricData(
|
||||
fmt.Sprintf(
|
||||
"components/%d/metrics/data.json",
|
||||
id,
|
||||
),
|
||||
names,
|
||||
options,
|
||||
)
|
||||
}
|
||||
100
modules/newrelic/client/http_helper.go
Normal file
100
modules/newrelic/client/http_helper.go
Normal file
@@ -0,0 +1,100 @@
|
||||
package newrelic
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
func (c *Client) doGet(path string, params fmt.Stringer, out interface{}) error {
|
||||
var s string
|
||||
if params != nil {
|
||||
s = params.String()
|
||||
}
|
||||
r := strings.NewReader(s)
|
||||
req, err := http.NewRequest("GET", c.url.String()+path, r)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
req.Header.Add("X-Api-Key", c.apiKey)
|
||||
req.Header.Add("Content-Type", "application/x-www-form-urlencoded")
|
||||
return c.doRequest(req, out)
|
||||
}
|
||||
|
||||
func (c *Client) doRequest(req *http.Request, out interface{}) error {
|
||||
resp, err := c.httpClient.Do(req)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
b, err := ioutil.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if resp.StatusCode != 200 {
|
||||
return fmt.Errorf("newrelic http error (%s): %s", resp.Status, b)
|
||||
}
|
||||
if len(b) == 0 {
|
||||
b = []byte{'{', '}'}
|
||||
}
|
||||
err = json.Unmarshal(b, &out)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func encodeGetParams(params map[string]interface{}) string {
|
||||
s := url.Values{}
|
||||
for k, v := range params {
|
||||
switch v.(type) {
|
||||
case string:
|
||||
val := v.(string)
|
||||
if val != "" {
|
||||
s.Add(k, val)
|
||||
}
|
||||
case int:
|
||||
val := v.(int)
|
||||
// TODO: Zero values versus not defined
|
||||
if val != 0 {
|
||||
s.Add(k, strconv.Itoa(val))
|
||||
}
|
||||
case []string:
|
||||
val := v.([]string)
|
||||
if len(val) != 0 {
|
||||
s.Add(k, strings.Join(val, ","))
|
||||
}
|
||||
case []int:
|
||||
val := v.([]int)
|
||||
arr := []string{}
|
||||
for _, v := range val {
|
||||
arr = append(arr, strconv.Itoa(v))
|
||||
}
|
||||
if len(arr) != 0 {
|
||||
s.Add(k, strings.Join(arr, ","))
|
||||
}
|
||||
case time.Time:
|
||||
val := v.(time.Time)
|
||||
if !val.IsZero() {
|
||||
s.Add(k, val.String())
|
||||
}
|
||||
case Array:
|
||||
val := v.(Array)
|
||||
for _, v := range val.arr {
|
||||
s.Add(k, v)
|
||||
}
|
||||
case bool:
|
||||
if v.(bool) {
|
||||
s.Add(k, "true")
|
||||
}
|
||||
default:
|
||||
s.Add(k, fmt.Sprintf("%v", v))
|
||||
}
|
||||
}
|
||||
return s.Encode()
|
||||
}
|
||||
119
modules/newrelic/client/http_helper_test_fixtures.go
Normal file
119
modules/newrelic/client/http_helper_test_fixtures.go
Normal file
@@ -0,0 +1,119 @@
|
||||
package newrelic
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"net/http"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type testJSONInterface struct {
|
||||
data string `json:"data"id,omitempty"`
|
||||
}
|
||||
|
||||
type testParamsInterface struct {
|
||||
data string
|
||||
}
|
||||
|
||||
type doGetTestsInput struct {
|
||||
path string
|
||||
params *testParamsInterface
|
||||
out testJSONInterface
|
||||
status int
|
||||
data string
|
||||
}
|
||||
|
||||
type doGetTestsOutput struct {
|
||||
data testJSONInterface
|
||||
err error
|
||||
}
|
||||
|
||||
type doRequestTestsInput struct {
|
||||
req *http.Request
|
||||
out testJSONInterface
|
||||
status int
|
||||
data string
|
||||
}
|
||||
|
||||
type doRequestTestOutput struct {
|
||||
data testJSONInterface
|
||||
err error
|
||||
}
|
||||
|
||||
var (
|
||||
doGetTests = []struct {
|
||||
in doGetTestsInput
|
||||
out doGetTestsOutput
|
||||
}{
|
||||
{
|
||||
doGetTestsInput{
|
||||
path: "somePath",
|
||||
params: &testParamsInterface{"testData"},
|
||||
out: testJSONInterface{"testData"},
|
||||
status: 200,
|
||||
data: `{"data": "testStructData"}`,
|
||||
},
|
||||
doGetTestsOutput{
|
||||
data: testJSONInterface{"testData"},
|
||||
err: nil,
|
||||
},
|
||||
},
|
||||
{
|
||||
doGetTestsInput{
|
||||
status: 404,
|
||||
data: "Not Found",
|
||||
},
|
||||
doGetTestsOutput{
|
||||
err: errors.New("newrelic http error (404 Not Found): Not Found"),
|
||||
},
|
||||
},
|
||||
}
|
||||
testRequest, _ = http.NewRequest("GET", "http://testPath",
|
||||
strings.NewReader("testBody"))
|
||||
doRequestTests = []struct {
|
||||
in doRequestTestsInput
|
||||
out doRequestTestOutput
|
||||
}{
|
||||
{
|
||||
doRequestTestsInput{
|
||||
req: testRequest,
|
||||
out: testJSONInterface{"testData"},
|
||||
status: 200,
|
||||
data: `{"data": "testStructData"}`,
|
||||
},
|
||||
doRequestTestOutput{
|
||||
data: testJSONInterface{"testData"},
|
||||
err: nil,
|
||||
},
|
||||
},
|
||||
}
|
||||
encodeGetParamsTests = []struct {
|
||||
in map[string]interface{}
|
||||
out string
|
||||
}{
|
||||
{
|
||||
map[string]interface{}{
|
||||
"testInt": 5,
|
||||
"testString": "test",
|
||||
"testStringSlice": []string{"test1", "test2"},
|
||||
"testArray": Array{[]string{"test1", "test2"}},
|
||||
"testTime": testTime,
|
||||
},
|
||||
"testArray=test1" +
|
||||
"&testArray=test2" +
|
||||
"&testInt=5" +
|
||||
"&testString=test" +
|
||||
"&testStringSlice=test1%2Ctest2" +
|
||||
"&testTime=" + testTimeStringEscaped,
|
||||
},
|
||||
{
|
||||
map[string]interface{}{
|
||||
"unexpectedType": map[string]string{"unexpected": "type"},
|
||||
},
|
||||
"unexpectedType=map%5Bunexpected%3Atype%5D",
|
||||
},
|
||||
}
|
||||
)
|
||||
|
||||
func (m *testParamsInterface) String() string {
|
||||
return "data=testData"
|
||||
}
|
||||
76
modules/newrelic/client/key_transactions.go
Normal file
76
modules/newrelic/client/key_transactions.go
Normal file
@@ -0,0 +1,76 @@
|
||||
package newrelic
|
||||
|
||||
import (
|
||||
"strconv"
|
||||
"time"
|
||||
)
|
||||
|
||||
// KeyTransactionsFilter is the filtering component of KeyTransactionsOptions.
|
||||
type KeyTransactionsFilter struct {
|
||||
Name string
|
||||
IDs []int
|
||||
}
|
||||
|
||||
// KeyTransactionsOptions provides a filtering mechanism for GetKeyTransactions.
|
||||
type KeyTransactionsOptions struct {
|
||||
Filter KeyTransactionsFilter
|
||||
Page int
|
||||
}
|
||||
|
||||
// KeyTransactionLinks link KeyTransactions to the objects to which they
|
||||
// pertain.
|
||||
type KeyTransactionLinks struct {
|
||||
Application int `json:"application,omitempty"`
|
||||
}
|
||||
|
||||
// KeyTransaction represents a New Relic Key Transaction.
|
||||
type KeyTransaction struct {
|
||||
ID int `json:"id,omitempty"`
|
||||
Name string `json:"name,omitempty"`
|
||||
TransactionName string `json:"transaction_name,omitempty"`
|
||||
HealthStatus string `json:"health_status,omitempty"`
|
||||
Reporting bool `json:"reporting,omitempty"`
|
||||
LastReportedAt time.Time `json:"last_reported_at,omitempty"`
|
||||
ApplicationSummary ApplicationSummary `json:"application_summary,omitempty"`
|
||||
EndUserSummary EndUserSummary `json:"end_user_summary,omitempty"`
|
||||
Links KeyTransactionLinks `json:"links,omitempty"`
|
||||
}
|
||||
|
||||
// GetKeyTransactions will return a slice of New Relic Key Transactions,
|
||||
// optionally filtered by KeyTransactionsOptions.
|
||||
func (c *Client) GetKeyTransactions(opt *KeyTransactionsOptions) ([]KeyTransaction, error) {
|
||||
resp := &struct {
|
||||
KeyTransactions []KeyTransaction `json:"key_transactions,omitempty"`
|
||||
}{}
|
||||
path := "key_transactions.json"
|
||||
err := c.doGet(path, opt, resp)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return resp.KeyTransactions, nil
|
||||
}
|
||||
|
||||
// GetKeyTransaction will return a single New Relic Key Transaction for the
|
||||
// given id.
|
||||
func (c *Client) GetKeyTransaction(id int) (*KeyTransaction, error) {
|
||||
resp := &struct {
|
||||
KeyTransaction *KeyTransaction `json:"key_transaction,omitempty"`
|
||||
}{}
|
||||
path := "key_transactions/" + strconv.Itoa(id) + ".json"
|
||||
err := c.doGet(path, nil, resp)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return resp.KeyTransaction, nil
|
||||
}
|
||||
|
||||
func (o *KeyTransactionsOptions) String() string {
|
||||
if o == nil {
|
||||
return ""
|
||||
}
|
||||
return encodeGetParams(map[string]interface{}{
|
||||
"filter[name]": o.Filter.Name,
|
||||
"filter[ids]": o.Filter.IDs,
|
||||
"page": o.Page,
|
||||
})
|
||||
}
|
||||
78
modules/newrelic/client/legacy_alert_policies.go
Normal file
78
modules/newrelic/client/legacy_alert_policies.go
Normal file
@@ -0,0 +1,78 @@
|
||||
package newrelic
|
||||
|
||||
import (
|
||||
"strconv"
|
||||
)
|
||||
|
||||
// LegacyAlertPolicyLinks describes object links for Alert Policies.
|
||||
type LegacyAlertPolicyLinks struct {
|
||||
NotificationChannels []int `json:"notification_channels,omitempty"`
|
||||
Servers []int `json:"servers,omitempty"`
|
||||
}
|
||||
|
||||
// LegacyAlertPolicyCondition describes conditions that trigger an LegacyAlertPolicy.
|
||||
type LegacyAlertPolicyCondition struct {
|
||||
ID int `json:"id,omitempty"`
|
||||
Enabled bool `json:"enabled,omitempty"`
|
||||
Severity string `json:"severity,omitempty"`
|
||||
Threshold float64 `json:"threshold,omitempty"`
|
||||
TriggerMinutes int `json:"trigger_minutes,omitempty"`
|
||||
Type string `json:"type,omitempty"`
|
||||
}
|
||||
|
||||
// LegacyAlertPolicy describes a New Relic alert policy.
|
||||
type LegacyAlertPolicy struct {
|
||||
Conditions []LegacyAlertPolicyCondition `json:"conditions,omitempty"`
|
||||
Enabled bool `json:"enabled,omitempty"`
|
||||
ID int `json:"id,omitempty"`
|
||||
Links LegacyAlertPolicyLinks `json:"links,omitempty"`
|
||||
IncidentPreference string `json:"incident_preference,omitempty"`
|
||||
Name string `json:"name,omitempty"`
|
||||
}
|
||||
|
||||
// LegacyAlertPolicyFilter provides filters for LegacyAlertPolicyOptions.
|
||||
type LegacyAlertPolicyFilter struct {
|
||||
Name string
|
||||
}
|
||||
|
||||
// LegacyAlertPolicyOptions is an optional means of filtering when calling
|
||||
// GetLegacyAlertPolicies.
|
||||
type LegacyAlertPolicyOptions struct {
|
||||
Filter LegacyAlertPolicyFilter
|
||||
Page int
|
||||
}
|
||||
|
||||
func (o *LegacyAlertPolicyOptions) String() string {
|
||||
if o == nil {
|
||||
return ""
|
||||
}
|
||||
return encodeGetParams(map[string]interface{}{
|
||||
"filter[name]": o.Filter.Name,
|
||||
"page": o.Page,
|
||||
})
|
||||
}
|
||||
|
||||
// GetLegacyAlertPolicy will return the LegacyAlertPolicy with particular ID.
|
||||
func (c *Client) GetLegacyAlertPolicy(id int) (*LegacyAlertPolicy, error) {
|
||||
resp := &struct {
|
||||
LegacyAlertPolicy *LegacyAlertPolicy `json:"alert_policy,omitempty"`
|
||||
}{}
|
||||
err := c.doGet("alert_policies/"+strconv.Itoa(id)+".json", nil, resp)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return resp.LegacyAlertPolicy, nil
|
||||
}
|
||||
|
||||
// GetLegacyAlertPolicies will return a slice of LegacyAlertPolicy items,
|
||||
// optionally filtering by LegacyAlertPolicyOptions.
|
||||
func (c *Client) GetLegacyAlertPolicies(options *LegacyAlertPolicyOptions) ([]LegacyAlertPolicy, error) {
|
||||
resp := &struct {
|
||||
LegacyAlertPolicies []LegacyAlertPolicy `json:"alert_policies,omitempty"`
|
||||
}{}
|
||||
err := c.doGet("alert_policies.json", options, resp)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return resp.LegacyAlertPolicies, nil
|
||||
}
|
||||
48
modules/newrelic/client/main.go
Normal file
48
modules/newrelic/client/main.go
Normal file
@@ -0,0 +1,48 @@
|
||||
/*
|
||||
* NewRelic API for Go
|
||||
*
|
||||
* Please see the included LICENSE file for licensing information.
|
||||
*
|
||||
* Copyright 2016 by authors and contributors.
|
||||
*/
|
||||
|
||||
package newrelic
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"net/url"
|
||||
"time"
|
||||
)
|
||||
|
||||
const (
|
||||
// defaultAPIURL is the default base URL for New Relic's latest API.
|
||||
defaultAPIURL = "https://api.newrelic.com/v2/"
|
||||
// defaultTimeout is the default timeout for the http.Client used.
|
||||
defaultTimeout = 5 * time.Second
|
||||
)
|
||||
|
||||
// Client provides a set of methods to interact with the New Relic API.
|
||||
type Client struct {
|
||||
apiKey string
|
||||
httpClient *http.Client
|
||||
url *url.URL
|
||||
}
|
||||
|
||||
// NewWithHTTPClient returns a new Client object for interfacing with the New
|
||||
// Relic API, allowing for override of the http.Client object.
|
||||
func NewWithHTTPClient(apiKey string, client *http.Client) *Client {
|
||||
u, err := url.Parse(defaultAPIURL)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return &Client{
|
||||
apiKey: apiKey,
|
||||
httpClient: client,
|
||||
url: u,
|
||||
}
|
||||
}
|
||||
|
||||
// NewClient returns a new Client object for interfacing with the New Relic API.
|
||||
func NewClient(apiKey string) *Client {
|
||||
return NewWithHTTPClient(apiKey, &http.Client{Timeout: defaultTimeout})
|
||||
}
|
||||
128
modules/newrelic/client/metrics.go
Normal file
128
modules/newrelic/client/metrics.go
Normal file
@@ -0,0 +1,128 @@
|
||||
package newrelic
|
||||
|
||||
import (
|
||||
"time"
|
||||
)
|
||||
|
||||
// Metric describes a New Relic metric.
|
||||
type Metric struct {
|
||||
Name string `json:"name,omitempty"`
|
||||
Values []string `json:"values,omitempty"`
|
||||
}
|
||||
|
||||
// MetricsOptions options allow filtering when getting lists of metric names
|
||||
// associated with an entity.
|
||||
type MetricsOptions struct {
|
||||
Name string
|
||||
Page int
|
||||
}
|
||||
|
||||
// MetricTimeslice describes the period to which a Metric pertains.
|
||||
type MetricTimeslice struct {
|
||||
From time.Time `json:"from,omitempty"`
|
||||
To time.Time `json:"to,omitempty"`
|
||||
Values map[string]float64 `json:"values,omitempty"`
|
||||
}
|
||||
|
||||
// MetricData describes the data for a particular metric.
|
||||
type MetricData struct {
|
||||
Name string `json:"name,omitempty"`
|
||||
Timeslices []MetricTimeslice `json:"timeslices,omitempty"`
|
||||
}
|
||||
|
||||
// MetricDataOptions allow filtering when getting data about a particular set
|
||||
// of New Relic metrics.
|
||||
type MetricDataOptions struct {
|
||||
Names Array
|
||||
Values Array
|
||||
From time.Time
|
||||
To time.Time
|
||||
Period int
|
||||
Summarize bool
|
||||
Raw bool
|
||||
}
|
||||
|
||||
// MetricDataResponse is the response received from New Relic for any request
|
||||
// for metric data.
|
||||
type MetricDataResponse struct {
|
||||
From time.Time `json:"from,omitempty"`
|
||||
To time.Time `json:"to,omitempty"`
|
||||
MetricsNotFound []string `json:"metrics_not_found,omitempty"`
|
||||
MetricsFound []string `json:"metrics_found,omitempty"`
|
||||
Metrics []MetricData `json:"metrics,omitempty"`
|
||||
}
|
||||
|
||||
func (o *MetricsOptions) String() string {
|
||||
if o == nil {
|
||||
return ""
|
||||
}
|
||||
return encodeGetParams(map[string]interface{}{
|
||||
"name": o.Name,
|
||||
"page": o.Page,
|
||||
})
|
||||
}
|
||||
|
||||
func (o *MetricDataOptions) String() string {
|
||||
if o == nil {
|
||||
return ""
|
||||
}
|
||||
return encodeGetParams(map[string]interface{}{
|
||||
"names[]": o.Names,
|
||||
"values[]": o.Values,
|
||||
"from": o.From,
|
||||
"to": o.To,
|
||||
"period": o.Period,
|
||||
"summarize": o.Summarize,
|
||||
"raw": o.Raw,
|
||||
})
|
||||
}
|
||||
|
||||
// MetricClient implements a generic New Relic metrics client.
|
||||
// This is used as a general client for fetching metric names and data.
|
||||
type MetricClient struct {
|
||||
newRelicClient *Client
|
||||
}
|
||||
|
||||
// NewMetricClient creates and returns a new MetricClient.
|
||||
func NewMetricClient(newRelicClient *Client) *MetricClient {
|
||||
return &MetricClient{
|
||||
newRelicClient: newRelicClient,
|
||||
}
|
||||
}
|
||||
|
||||
// GetMetrics is a generic function for fetching a list of available metrics
|
||||
// from different parts of New Relic.
|
||||
// Example: Application metrics, Component metrics, etc.
|
||||
func (mc *MetricClient) GetMetrics(path string, options *MetricsOptions) ([]Metric, error) {
|
||||
resp := &struct {
|
||||
Metrics []Metric `json:"metrics,omitempty"`
|
||||
}{}
|
||||
|
||||
err := mc.newRelicClient.doGet(path, options, resp)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return resp.Metrics, nil
|
||||
}
|
||||
|
||||
// GetMetricData is a generic function for fetching data for a specific metric.
|
||||
// from different parts of New Relic.
|
||||
// Example: Application metric data, Component metric data, etc.
|
||||
func (mc *MetricClient) GetMetricData(path string, names []string, options *MetricDataOptions) (*MetricDataResponse, error) {
|
||||
resp := &struct {
|
||||
MetricData MetricDataResponse `json:"metric_data,omitempty"`
|
||||
}{}
|
||||
|
||||
if options == nil {
|
||||
options = &MetricDataOptions{}
|
||||
}
|
||||
|
||||
options.Names = Array{names}
|
||||
err := mc.newRelicClient.doGet(path, options, resp)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &resp.MetricData, nil
|
||||
}
|
||||
36
modules/newrelic/client/mobile_application_metrics.go
Normal file
36
modules/newrelic/client/mobile_application_metrics.go
Normal file
@@ -0,0 +1,36 @@
|
||||
package newrelic
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
)
|
||||
|
||||
// GetMobileApplicationMetrics will return a slice of Metric items for a
|
||||
// particular MobileAplication ID, optionally filtering by
|
||||
// MetricsOptions.
|
||||
func (c *Client) GetMobileApplicationMetrics(id int, options *MetricsOptions) ([]Metric, error) {
|
||||
mc := NewMetricClient(c)
|
||||
|
||||
return mc.GetMetrics(
|
||||
fmt.Sprintf(
|
||||
"mobile_applications/%d/metrics.json",
|
||||
id,
|
||||
),
|
||||
options,
|
||||
)
|
||||
}
|
||||
|
||||
// GetMobileApplicationMetricData will return all metric data for a particular
|
||||
// MobileAplication and slice of metric names, optionally filtered by
|
||||
// MetricDataOptions.
|
||||
func (c *Client) GetMobileApplicationMetricData(id int, names []string, options *MetricDataOptions) (*MetricDataResponse, error) {
|
||||
mc := NewMetricClient(c)
|
||||
|
||||
return mc.GetMetricData(
|
||||
fmt.Sprintf(
|
||||
"mobile_applications/%d/metrics/data.json",
|
||||
id,
|
||||
),
|
||||
names,
|
||||
options,
|
||||
)
|
||||
}
|
||||
61
modules/newrelic/client/mobile_applications.go
Normal file
61
modules/newrelic/client/mobile_applications.go
Normal file
@@ -0,0 +1,61 @@
|
||||
package newrelic
|
||||
|
||||
import (
|
||||
"strconv"
|
||||
)
|
||||
|
||||
// MobileApplicationSummary describes an Application's host.
|
||||
type MobileApplicationSummary struct {
|
||||
ActiveUsers int `json:"active_users,omitempty"`
|
||||
LaunchCount int `json:"launch_count,omitempty"`
|
||||
Throughput float64 `json:"throughput,omitempty"`
|
||||
ResponseTime float64 `json:"response_time,omitempty"`
|
||||
CallsPerSession float64 `json:"calls_per_session,omitempty"`
|
||||
InteractionTime float64 `json:"interaction_time,omitempty"`
|
||||
FailedCallRate float64 `json:"failed_call_rate,omitempty"`
|
||||
RemoteErrorRate float64 `json:"remote_error_rate"`
|
||||
}
|
||||
|
||||
// MobileApplicationCrashSummary describes a MobileApplication's crash data.
|
||||
type MobileApplicationCrashSummary struct {
|
||||
SupportsCrashData bool `json:"supports_crash_data,omitempty"`
|
||||
UnresolvedCrashCount int `json:"unresolved_crash_count,omitempty"`
|
||||
CrashCount int `json:"crash_count,omitempty"`
|
||||
CrashRate float64 `json:"crash_rate,omitempty"`
|
||||
}
|
||||
|
||||
// MobileApplication describes a New Relic Application Host.
|
||||
type MobileApplication struct {
|
||||
ID int `json:"id,omitempty"`
|
||||
Name string `json:"name,omitempty"`
|
||||
HealthStatus string `json:"health_status,omitempty"`
|
||||
Reporting bool `json:"reporting,omitempty"`
|
||||
MobileSummary MobileApplicationSummary `json:"mobile_summary,omitempty"`
|
||||
CrashSummary MobileApplicationCrashSummary `json:"crash_summary,omitempty"`
|
||||
}
|
||||
|
||||
// GetMobileApplications returns a slice of New Relic Mobile Applications.
|
||||
func (c *Client) GetMobileApplications() ([]MobileApplication, error) {
|
||||
resp := &struct {
|
||||
Applications []MobileApplication `json:"applications,omitempty"`
|
||||
}{}
|
||||
path := "mobile_applications.json"
|
||||
err := c.doGet(path, nil, resp)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return resp.Applications, nil
|
||||
}
|
||||
|
||||
// GetMobileApplication returns a single Mobile Application with the id.
|
||||
func (c *Client) GetMobileApplication(id int) (*MobileApplication, error) {
|
||||
resp := &struct {
|
||||
Application MobileApplication `json:"application,omitempty"`
|
||||
}{}
|
||||
path := "mobile_applications/" + strconv.Itoa(id) + ".json"
|
||||
err := c.doGet(path, nil, resp)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &resp.Application, nil
|
||||
}
|
||||
78
modules/newrelic/client/notification_channels.go
Normal file
78
modules/newrelic/client/notification_channels.go
Normal file
@@ -0,0 +1,78 @@
|
||||
package newrelic
|
||||
|
||||
import (
|
||||
"strconv"
|
||||
)
|
||||
|
||||
// NotificationChannelLinks describes object links for notification channels.
|
||||
type NotificationChannelLinks struct {
|
||||
NotificationChannels []int `json:"notification_channels,omitempty"`
|
||||
User int `json:"user,omitempty"`
|
||||
}
|
||||
|
||||
// NotificationChannel describes a New Relic notification channel.
|
||||
type NotificationChannel struct {
|
||||
ID int `json:"id,omitempty"`
|
||||
Type string `json:"type,omitempty"`
|
||||
DowntimeOnly bool `json:"downtime_only,omitempty"`
|
||||
URL string `json:"url,omitempty"`
|
||||
Name string `json:"name,omitempty"`
|
||||
Description string `json:"description,omitempty"`
|
||||
Email string `json:"email,omitempty"`
|
||||
Subdomain string `json:"subdomain,omitempty"`
|
||||
Service string `json:"service,omitempty"`
|
||||
MobileAlerts bool `json:"mobile_alerts,omitempty"`
|
||||
EmailAlerts bool `json:"email_alerts,omitempty"`
|
||||
Room string `json:"room,omitempty"`
|
||||
Links NotificationChannelLinks `json:"links,omitempty"`
|
||||
}
|
||||
|
||||
// NotificationChannelsFilter provides filters for
|
||||
// NotificationChannelsOptions.
|
||||
type NotificationChannelsFilter struct {
|
||||
Type []string
|
||||
IDs []int
|
||||
}
|
||||
|
||||
// NotificationChannelsOptions is an optional means of filtering when calling
|
||||
// GetNotificationChannels.
|
||||
type NotificationChannelsOptions struct {
|
||||
Filter NotificationChannelsFilter
|
||||
Page int
|
||||
}
|
||||
|
||||
func (o *NotificationChannelsOptions) String() string {
|
||||
if o == nil {
|
||||
return ""
|
||||
}
|
||||
return encodeGetParams(map[string]interface{}{
|
||||
"filter[type]": o.Filter.Type,
|
||||
"filter[ids]": o.Filter.IDs,
|
||||
"page": o.Page,
|
||||
})
|
||||
}
|
||||
|
||||
// GetNotificationChannel will return the NotificationChannel with particular ID.
|
||||
func (c *Client) GetNotificationChannel(id int) (*NotificationChannel, error) {
|
||||
resp := &struct {
|
||||
NotificationChannel *NotificationChannel `json:"notification_channel,omitempty"`
|
||||
}{}
|
||||
err := c.doGet("notification_channels/"+strconv.Itoa(id)+".json", nil, resp)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return resp.NotificationChannel, nil
|
||||
}
|
||||
|
||||
// GetNotificationChannels will return a slice of NotificationChannel items,
|
||||
// optionally filtering by NotificationChannelsOptions.
|
||||
func (c *Client) GetNotificationChannels(options *NotificationChannelsOptions) ([]NotificationChannel, error) {
|
||||
resp := &struct {
|
||||
NotificationChannels []NotificationChannel `json:"notification_channels,omitempty"`
|
||||
}{}
|
||||
err := c.doGet("notification_channels.json", options, resp)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return resp.NotificationChannels, nil
|
||||
}
|
||||
34
modules/newrelic/client/server_metrics.go
Normal file
34
modules/newrelic/client/server_metrics.go
Normal file
@@ -0,0 +1,34 @@
|
||||
package newrelic
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
)
|
||||
|
||||
// GetServerMetrics will return a slice of Metric items for a particular
|
||||
// Server ID, optionally filtering by MetricsOptions.
|
||||
func (c *Client) GetServerMetrics(id int, options *MetricsOptions) ([]Metric, error) {
|
||||
mc := NewMetricClient(c)
|
||||
|
||||
return mc.GetMetrics(
|
||||
fmt.Sprintf(
|
||||
"servers/%d/metrics.json",
|
||||
id,
|
||||
),
|
||||
options,
|
||||
)
|
||||
}
|
||||
|
||||
// GetServerMetricData will return all metric data for a particular Server and
|
||||
// slice of metric names, optionally filtered by MetricDataOptions.
|
||||
func (c *Client) GetServerMetricData(id int, names []string, options *MetricDataOptions) (*MetricDataResponse, error) {
|
||||
mc := NewMetricClient(c)
|
||||
|
||||
return mc.GetMetricData(
|
||||
fmt.Sprintf(
|
||||
"servers/%d/metrics/data.json",
|
||||
id,
|
||||
),
|
||||
names,
|
||||
options,
|
||||
)
|
||||
}
|
||||
92
modules/newrelic/client/servers.go
Normal file
92
modules/newrelic/client/servers.go
Normal file
@@ -0,0 +1,92 @@
|
||||
package newrelic
|
||||
|
||||
import (
|
||||
"strconv"
|
||||
"time"
|
||||
)
|
||||
|
||||
// ServersFilter is the filtering component of ServersOptions.
|
||||
type ServersFilter struct {
|
||||
Name string
|
||||
Host string
|
||||
IDs []int
|
||||
Labels []string
|
||||
Reported bool
|
||||
}
|
||||
|
||||
// ServersOptions provides a filtering mechanism for GetServers.
|
||||
type ServersOptions struct {
|
||||
Filter ServersFilter
|
||||
Page int
|
||||
}
|
||||
|
||||
// ServerSummary describes the summary component of a Server.
|
||||
type ServerSummary struct {
|
||||
CPU float64 `json:"cpu,omitempty"`
|
||||
CPUStolen float64 `json:"cpu_stolen,omitempty"`
|
||||
DiskIO float64 `json:"disk_io,omitempty"`
|
||||
Memory float64 `json:"memory,omitempty"`
|
||||
MemoryUsed int64 `json:"memory_used,omitempty"`
|
||||
MemoryTotal int64 `json:"memory_total,omitempty"`
|
||||
FullestDisk float64 `json:"fullest_disk,omitempty"`
|
||||
FullestDiskFree int64 `json:"fullest_disk_free,omitempty"`
|
||||
}
|
||||
|
||||
// ServerLinks link Servers to the objects to which they pertain.
|
||||
type ServerLinks struct {
|
||||
AlertPolicy int `json:"alert_policy,omitempty"`
|
||||
}
|
||||
|
||||
// Server represents a New Relic Server.
|
||||
type Server struct {
|
||||
ID int `json:"id,omitempty"`
|
||||
AccountID int `json:"account_id,omitempty"`
|
||||
Name string `json:"name,omitempty"`
|
||||
Host string `json:"host,omitempty"`
|
||||
HealthStatus string `json:"health_status,omitempty"`
|
||||
Reporting bool `json:"reporting,omitempty"`
|
||||
LastReportedAt time.Time `json:"last_reported_at,omitempty"`
|
||||
Summary ServerSummary `json:"summary,omitempty"`
|
||||
Links ServerLinks `json:"links,omitempty"`
|
||||
}
|
||||
|
||||
// GetServers will return a slice of New Relic Servers, optionally filtered by
|
||||
// ServerOptions.
|
||||
func (c *Client) GetServers(opt *ServersOptions) ([]Server, error) {
|
||||
resp := &struct {
|
||||
Servers []Server `json:"servers,omitempty"`
|
||||
}{}
|
||||
path := "servers.json"
|
||||
err := c.doGet(path, opt, resp)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return resp.Servers, nil
|
||||
}
|
||||
|
||||
// GetServer will return a single New Relic Server for the given id.
|
||||
func (c *Client) GetServer(id int) (*Server, error) {
|
||||
resp := &struct {
|
||||
Server *Server `json:"server,omitempty"`
|
||||
}{}
|
||||
path := "servers/" + strconv.Itoa(id) + ".json"
|
||||
err := c.doGet(path, nil, resp)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return resp.Server, nil
|
||||
}
|
||||
|
||||
func (o *ServersOptions) String() string {
|
||||
if o == nil {
|
||||
return ""
|
||||
}
|
||||
return encodeGetParams(map[string]interface{}{
|
||||
"filter[name]": o.Filter.Name,
|
||||
"filter[host]": o.Filter.Host,
|
||||
"filter[ids]": o.Filter.IDs,
|
||||
"filter[labels]": o.Filter.Labels,
|
||||
"filter[reported]": o.Filter.Reported,
|
||||
"page": o.Page,
|
||||
})
|
||||
}
|
||||
49
modules/newrelic/client/usages.go
Normal file
49
modules/newrelic/client/usages.go
Normal file
@@ -0,0 +1,49 @@
|
||||
package newrelic
|
||||
|
||||
import (
|
||||
"time"
|
||||
)
|
||||
|
||||
// Usage describes usage over a single time period.
|
||||
type Usage struct {
|
||||
From time.Time `json"from,omitempty"`
|
||||
To time.Time `json:"to,omitempty"`
|
||||
Usage int `json:"usage,omitempty"`
|
||||
}
|
||||
|
||||
// UsageData represents usage data for a product over a time frame, including
|
||||
// a slice of Usages.
|
||||
type UsageData struct {
|
||||
Product string `json:"product,omitempty"`
|
||||
From time.Time `json:"from,omitempty"`
|
||||
To time.Time `json:"to,omitempty"`
|
||||
Unit string `json:"unit,omitempty"`
|
||||
Usages []Usage `json:"usages,omitempty"`
|
||||
}
|
||||
|
||||
type usageParams struct {
|
||||
Start time.Time
|
||||
End time.Time
|
||||
IncludeSubaccount bool
|
||||
}
|
||||
|
||||
func (o *usageParams) String() string {
|
||||
return encodeGetParams(map[string]interface{}{
|
||||
"start_date": o.Start.Format("2006-01-02"),
|
||||
"end_date": o.End.Format("2006-01-02"),
|
||||
"include_subaccounts": o.IncludeSubaccount,
|
||||
})
|
||||
}
|
||||
|
||||
// GetUsages will return usage for a product in a given time frame.
|
||||
func (c *Client) GetUsages(product string, start, end time.Time, includeSubaccounts bool) (*UsageData, error) {
|
||||
resp := &struct {
|
||||
UsageData *UsageData `json:"usage_data,omitempty"`
|
||||
}{}
|
||||
options := &usageParams{start, end, includeSubaccounts}
|
||||
err := c.doGet("usages/"+product+".json", options, resp)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return resp.UsageData, nil
|
||||
}
|
||||
Reference in New Issue
Block a user