New Relic
Port's New Relic integration allows you to model New Relic resources in your software catalog and ingest data into them.
Core support
Setup
Choose one of the following installation methods: Not sure which method is right for your use case? Check the available installation methods.
Configuration
Port integrations use a YAML mapping block to ingest data from the third-party api into Port.
The mapping makes use of the JQ JSON processor to select, modify, concatenate, transform and perform other operations on existing fields and values from the integration API.
Additional Configuration
-
newRelicTypes - An array of Newrelic entity types that will be fetched. The default value is ['SERVICE', 'APPLICATION']. This is related to the type field in the Newrelic entity.
-
calculateOpenIssueCount:
- A boolean value that indicates if the integration should calculate the number of open issues for each entity. The default value is `false``.
- NOTE - This can cause a performance degradation as the integration will have to calculate the number of open issues for each entity, which unfortunately is not supported by the New Relic API.
-
entityQueryFilter:
- A filter that will be applied to the New Relic API query. This will be placed inside the
queryfield of theentitySearchquery in the New Relic GraphQL API. For examples of query filters click here. - Not specifying this field will cause the integration to fetch all the entities and map them to the blueprint defined in the
kind. - Rule of thumb - Most of the time the
EntityQueryFilterwill be the same as theNewRelicTypes. For example, if we want to fetch all the services and applications we will set theEntityQueryFiltertotype in ('SERVICE','APPLICATION')and theNewRelicTypesto['SERVICE', 'APPLICATION'].
- A filter that will be applied to the New Relic API query. This will be placed inside the
-
entityExtraPropertiesQuery:
- An optional property that allows defining extra properties to fetch for each Newrelic entity. This will be concatenated with the default query properties we are requesting under the
entitiessection in theentitySearchquery in the Newrelic GraphQL API. For examples of additional query properties click here.
- An optional property that allows defining extra properties to fetch for each Newrelic entity. This will be concatenated with the default query properties we are requesting under the
-
The
port,entityand themappingskeys are used to map the Newrelic object fields to Port entities. To create multiple mappings of the same kind, you can add another item in theresourcesarray;
Default mapping configuration
This is the default mapping configuration for this integration:
Default mapping configuration (Click to expand)
deleteDependentEntities: true
createMissingRelatedEntities: true
enableMergeEntity: true
resources:
- kind: newRelicService
selector:
query: 'true'
newRelicTypes:
- SERVICE
- APPLICATION
calculateOpenIssueCount: true
entityQueryFilter: type in ('SERVICE','APPLICATION')
entityExtraPropertiesQuery: |-
... on ApmApplicationEntityOutline {
guid
name
apmSummary {
apdexScore
errorRate
hostCount
instanceCount
responseTimeAverage
throughput
}
}
port:
entity:
mappings:
identifier: .guid
title: .name
blueprint: '"newRelicService"'
properties:
has_apm: if .domain | contains("APM") then "true" else "false" end
link: .permalink
open_issues_count: .open_issues_count
reporting: .reporting
tags: .tags
type: .type
throughput: .apmSummary.throughput
error_rate: .apmSummary.errorRate
response_time_avg: .apmSummary.responseTimeAverage
instance_count: .apmSummary.instanceCount
apdex: .apmSummary.apdexScore
- kind: newRelicAlert
selector:
query: .state == "ACTIVATED" or .state == "CREATED"
newRelicTypes:
- ISSUE
port:
entity:
mappings:
identifier: .issueId
title: .title[0]
blueprint: '"newRelicAlert"'
properties:
priority: .priority
state: .state
sources: .sources
conditionName: .conditionName
alertPolicyNames: .policyName
activatedAt: if .activatedAt == null then null else .activatedAt / 1000 | todate end
link: '"https://one.newrelic.com/launcher/nrai.launcher?pane=" + ("{\"isPhoton\": true, \"id\": \"\(.issueId)\", \"nerdletId\": \"nrai.issue-redirect\"}" | @base64)'
description: .description
relations:
alert_to_workload: .__APPLICATION.entity_guids + .__SERVICE.entity_guids
cloud_resource:
combinator: '"and"'
rules:
- property: '"guid"'
operator: '"in"'
value: .entityGuids
- kind: newRelicServiceLevel
selector:
query: 'true'
port:
entity:
mappings:
identifier: .serviceLevel.indicators[0].id
title: .serviceLevel.indicators[0].name
blueprint: '"newRelicServiceLevel"'
properties:
description: .serviceLevel.indicators[0].description
targetThreshold: .serviceLevel.indicators[0].objectives[0].target
createdAt: if .serviceLevel.indicators[0].createdAt != null then (.serviceLevel.indicators[0].createdAt | tonumber / 1000 | todate) else null end
updatedAt: if .serviceLevel.indicators[0].updatedAt != null then (.serviceLevel.indicators[0].updatedAt | tonumber / 1000 | todate) else null end
createdBy: .serviceLevel.indicators[0].createdBy.email
sli: .__SLI.SLI
tags: .tags
slo_compliance: .__SLI.SLI >= .serviceLevel.indicators[0].objectives[0].target
relations:
workload: .tags."nr.associatedEntityGuid"[0]
- kind: entity
selector:
query: 'true'
entityQueryFilter: >-
type IN ( 'AWSEC2INSTANCE', 'AWSS3BUCKET', 'AWSRDSDBINSTANCE', 'AWSLAMBDAFUNCTION', 'AWSELBLOADBALANCER', 'AZUREVIRTUALMACHINE', 'AZURESQLDATABASE', 'GCPCOMPUTEINSTANCE', 'GCPSTORAGEBUCKET', 'GCPSQLDATABASEINSTANCE' )
port:
entity:
mappings:
identifier: .guid
title: .name
blueprint: '"newRelicCloudResource"'
properties:
infrastructureIntegrationType: .type
reporting: .reporting
link: .permalink
tags: .tags
- kind: entities
selector:
query: 'true'
entityQueryFilter: type IN ( 'DASHBOARD' )
port:
entity:
mappings:
identifier: .guid
title: .name
blueprint: '"newRelicDashboards"'
properties:
dashboard_link: .permalink
- kind: newRelicService
selector:
query: 'true'
newRelicTypes:
- SERVICE
- APPLICATION
entityQueryFilter: type in ('SERVICE','APPLICATION')
port:
entity:
mappings:
identifier: .guid
title: .name
blueprint: '"workload"'
relations:
new_relic_workload: .guid
Mapping & selectors per resource
Use the explorer below to view sample payloads and the resulting Port entities for each resource type.
Set up live events
This integration supports live events, allowing real-time updates to your software catalog without waiting for the next scheduled sync.
Note that different events are supported depending on the resource type.
- Hosted by Port
- Self-hosted
Live events base URL
For integrations installed using the Hosted by Port method, you can obtain the live events base URL from the Get an integration API. The response includes liveEventsUuid and liveEventsIngestHostname in the appSpec section.
Call the endpoint with your integration's identifier:
curl -X GET \
'https://api.port.io/v1/integration/<INTEGRATION_IDENTIFIER>' \
-H 'Authorization: Bearer <PORT_ACCESS_TOKEN>'
The port_region, port.baseUrl, portBaseUrl, port_base_url and OCEAN__PORT__BASE_URL parameters select which Port API instance to use:
- EU (app.port.io) →
https://api.port.io - US (app.us.port.io) →
https://api.us.port.io
In the response, look for the following fields under spec.appSpec:
{
"spec": {
"appSpec": {
"liveEventsUuid": "abcdefghijk",
"liveEventsIngestHostname": "ingest.ocean.getport.io"
}
}
}
Combine them to build the live events base URL:
https://<liveEventsIngestHostname>/live-events/<liveEventsUuid>
For example, with the values above, the live events base URL is:
https://ingest.ocean.getport.io/live-events/abcdefghijk
This is the same URL configured for the integration.
BaseUrl & webhook configuration
To enable real-time updates of the data in your software catalog, you need to define the liveEvents.baseUrl parameter.
This parameter should be set to the URL of your New Relic integration instance, which needs to have the option to setup webhooks via HTTP requests/receive HTTP requests, so ensure the network is configured accordingly.
- If New Relic and the integration are in the same cluster/network: Use an internal URL (e.g., a Kubernetes service DNS name).
For Kubernetes deployments, create a service to expose the integration pod and use the service URL asliveEvents.baseUrl. If both the source system and integration are in the same cluster, an internal ClusterIP service is sufficient. - If New Relic is external to the integration's network: The integration must be exposed via an ingress, load balancer, or public URL that New Relic can reach.
If liveEvents.baseUrl is not provided, the integration will continue to function correctly. In such a configuration, to retrieve the latest information from the target system, the scheduledResyncInterval parameter has to be set, or a manual resync will need to be triggered through Port's UI.
To test webhooks or live event delivery to your local environment, expose your local pod or service to the internet using ngrok (e.g. ngrok http http://localhost:8000)
Securing Your Webhooks
The integration.secrets.webhookUsername,integration.secrets.webhookSecret parameters secure your webhooks. If not provided, the integration will process webhooks without validating the source of the events.
Monitoring and sync status
To learn more about how to monitor and check the sync status of your integration, see the relevant documentation.
Capabilities
Tags
Some Newrelic entities have a property named tags which contains potentially useful information such as machine information, hostname, agent name & version, and more. For example:
"tags": [
{
"key": "coreCount",
"values": [
"10"
]
},
{
"key": "hostStatus",
"values": [
"running"
]
},
]
Before mapping, this integration performs a transformation on each tag, after which the example above would look like this:
tags = ["coreCount":"10","hostStatus":"running"]
Examples
Examples of blueprints and the relevant integration configurations:
Service (Entity)
Service blueprint (Click to expand)
{
"identifier": "newRelicService",
"description": "This blueprint represents a New Relic service or application in our software catalog",
"title": "New Relic Service",
"icon": "NewRelic",
"schema": {
"properties": {
"has_apm": {
"title": "Has APM",
"type": "boolean"
},
"open_issues_count": {
"title": "Open Issues Count",
"type": "number",
"default": 0
},
"link": {
"title": "Link",
"type": "string",
"format": "url"
},
"reporting": {
"title": "Reporting",
"type": "boolean"
},
"tags": {
"title": "Tags",
"type": "object"
},
"account_id": {
"title": "Account ID",
"type": "string"
},
"type": {
"title": "Type",
"type": "string"
},
"domain": {
"title": "Domain",
"type": "string"
},
"throughput": {
"title": "Throughput",
"type": "number"
},
"response_time_avg": {
"title": "Response Time AVG",
"type": "number"
},
"error_rate": {
"title": "Error Rate",
"type": "number"
},
"instance_count": {
"title": "Instance Count",
"type": "number"
}
},
"required": []
},
"mirrorProperties": {},
"calculationProperties": {},
"relations": {}
}
Integration configuration (Click to expand)
createMissingRelatedEntities: true
deleteDependentEntities: true
resources:
- kind: newRelicService
selector:
query: "true"
newRelicTypes: ["SERVICE", "APPLICATION"]
calculateOpenIssueCount: true
entityQueryFilter: "type in ('SERVICE','APPLICATION')"
entityExtraPropertiesQuery: |
... on ApmApplicationEntity {
guid
name
alertSeverity
applicationId
apmBrowserSummary {
ajaxRequestThroughput
ajaxResponseTimeAverage
jsErrorRate
pageLoadThroughput
pageLoadTimeAverage
}
apmSummary {
apdexScore
errorRate
hostCount
instanceCount
nonWebResponseTimeAverage
nonWebThroughput
responseTimeAverage
throughput
webResponseTimeAverage
webThroughput
}
}
port:
entity:
mappings:
blueprint: '"newRelicService"'
identifier: .guid
title: .name
properties:
has_apm: 'if .domain | contains("APM") then "true" else "false" end'
link: .permalink
open_issues_count: .__open_issues_count
reporting: .reporting
tags: .tags
domain: .domain
type: .type
Issue
Issue blueprint (Click to expand)
{
"identifier": "newRelicAlert",
"description": "This blueprint represents a New Relic alert in our software catalog",
"title": "New Relic Alert",
"icon": "NewRelic",
"schema": {
"properties": {
"priority": {
"type": "string",
"title": "Priority",
"enum": ["CRITICAL", "HIGH", "MEDIUM", "LOW"],
"enumColors": {
"CRITICAL": "red",
"HIGH": "red",
"MEDIUM": "yellow",
"LOW": "green"
}
},
"state": {
"type": "string",
"title": "State",
"enum": ["ACTIVATED", "CLOSED", "CREATED"],
"enumColors": {
"ACTIVATED": "yellow",
"CLOSED": "green",
"CREATED": "lightGray"
}
},
"trigger": {
"type": "string",
"title": "Trigger"
},
"sources": {
"type": "array",
"title": "Sources"
},
"alertPolicyNames": {
"type": "array",
"title": "Alert Policy Names"
},
"conditionName": {
"type": "array",
"title": "Condition Name"
},
"activatedAt": {
"type": "string",
"title": "Time Issue was activated"
}
},
"required": []
},
"mirrorProperties": {},
"calculationProperties": {},
"relations": {
"newRelicService": {
"title": "New Relic Service",
"target": "newRelicService",
"required": false,
"many": true
}
}
}
Integration configuration (Click to expand)
createMissingRelatedEntities: true
deleteDependentEntities: true
resources:
- kind: newRelicAlert
selector:
query: "true"
newRelicTypes: ["ISSUE"]
port:
entity:
mappings:
blueprint: '"newRelicAlert"'
identifier: .issueId
title: .title[0]
properties:
priority: .priority
state: .state
sources: .sources
conditionName: .conditionName
alertPolicyNames: .policyName
activatedAt: .activatedAt
relations:
newRelicService: .__APPLICATION.entity_guids + .__SERVICE.entity_guids
Service Level
Service Level blueprint (Click to expand)
{
"identifier": "newRelicServiceLevel",
"description": "This blueprint represents a New Relic Service Level",
"title": "New Relic Service Level",
"icon": "NewRelic",
"schema": {
"properties": {
"description": {
"title": "Description",
"type": "string"
},
"targetThreshold": {
"icon": "DefaultProperty",
"title": "Target Threshold",
"type": "number"
},
"createdAt": {
"title": "Created At",
"type": "string",
"format": "date-time"
},
"updatedAt": {
"title": "Updated At",
"type": "string",
"format": "date-time"
},
"createdBy": {
"title": "Creator",
"type": "string",
"format": "user"
},
"sli": {
"type": "number",
"title": "SLI"
},
"tags": {
"type": "object",
"title": "Tags"
}
},
"required": []
},
"mirrorProperties": {},
"calculationProperties": {},
"aggregationProperties": {},
"relations": {
"newRelicService": {
"title": "New Relic service",
"target": "newRelicService",
"required": false,
"many": false
}
}
}
Integration configuration (Click to expand)
createMissingRelatedEntities: true
deleteDependentEntities: true
resources:
- kind: newRelicServiceLevel
selector:
query: 'true'
port:
entity:
mappings:
blueprint: '"newRelicServiceLevel"'
identifier: .serviceLevel.indicators[0].id
title: .serviceLevel.indicators[0].name
properties:
description: .serviceLevel.indicators[0].description
targetThreshold: .serviceLevel.indicators[0].objectives[0].target
createdAt: if .serviceLevel.indicators[0].createdAt != null then (.serviceLevel.indicators[0].createdAt | tonumber / 1000 | todate) else null end
updatedAt: if .serviceLevel.indicators[0].updatedAt != null then (.serviceLevel.indicators[0].updatedAt | tonumber / 1000 | todate) else null end
createdBy: .serviceLevel.indicators[0].createdBy.email
sli: .__SLI.SLI
tags: .tags
relations:
newRelicService: .serviceLevel.indicators[0].guid