Skip to content

Commit

Permalink
[Integrations][NewRelic] Fix not handling a failure of getting relate…
Browse files Browse the repository at this point in the history
…d entity guid for an alert (#152)
  • Loading branch information
Tankilevitch authored Oct 5, 2023
1 parent 6cf8e2d commit 5d949c8
Show file tree
Hide file tree
Showing 7 changed files with 76 additions and 42 deletions.
38 changes: 19 additions & 19 deletions integrations/newrelic/.port/resources/port-app-config.yaml
Original file line number Diff line number Diff line change
@@ -1,24 +1,5 @@
createMissingRelatedEntities: 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"
- kind: newRelicService
selector:
query: 'true'
Expand Down Expand Up @@ -71,3 +52,22 @@ resources:
error_rate: .apmSummary.errorRate
response_time_avg: .apmSummary.responseTimeAverage
instance_count: .apmSummary.instanceCount
- 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"
16 changes: 11 additions & 5 deletions integrations/newrelic/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,32 +7,38 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

<!-- towncrier release notes start -->

# Port_Ocean 0.1.4 (2023-09-27)
# 0.1.5 (2023-10-05)

## Bug Fixes

- Fixed unhandled exception when no entity is returned for a given entity guid found in an newRelic Alert (#1)

# 0.1.4 (2023-09-27)

### Improvements

- Bumped ocean to version 0.3.1 (#1)

# Port_Ocean 0.1.3 (2023-09-13)
# 0.1.3 (2023-09-13)

### Features

- Changed returned entities to ocean with a generator of a list to support ocean 0.3.0

# Port_Ocean 0.1.2 (2023-08-11)
# 0.1.2 (2023-08-11)

### Improvements

- Optimized dockerfile to produce smaller images (PORT-4485)

# 0.1.1 (2023-08-03)
# 0.1.1 (2023-08-03)

### Bug Fixes

- Add README.md (#1)
- Support specifying whether to count open issues per new relic entity (#1)

# 0.1.0 (2023-08-02)
# 0.1.0 (2023-08-02)

### Features

Expand Down
5 changes: 5 additions & 0 deletions integrations/newrelic/newrelic_integration/core/entities.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
get_port_resource_configuration_by_port_kind,
render_query,
)
from newrelic_integration.core.errors import NewRelicNotFoundError


class EntitiesHandler:
Expand All @@ -29,6 +30,10 @@ async def get_entity(self, entity_guid: str) -> dict[Any, Any]:
entity_guid=entity_guid,
)
entity = response.get("data", {}).get("actor", {}).get("entity", {})
if not entity:
raise NewRelicNotFoundError(
f"No entity found in newrelic for guid {entity_guid}",
)
self._format_tags(entity)
return entity

Expand Down
6 changes: 6 additions & 0 deletions integrations/newrelic/newrelic_integration/core/errors.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
class NewRelicError(Exception):
pass


class NewRelicNotFoundError(NewRelicError):
pass
45 changes: 32 additions & 13 deletions integrations/newrelic/newrelic_integration/core/issues.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
from enum import Enum
from typing import Optional, Any, Tuple
from loguru import logger

import httpx

from port_ocean.context.ocean import ocean
from pydantic import BaseModel, Field, Extra

from newrelic_integration.core.errors import NewRelicNotFoundError
from newrelic_integration.core.entities import EntitiesHandler
from newrelic_integration.core.query_templates.issues import (
LIST_ISSUES_BY_ENTITY_GUIDS_MINIMAL_QUERY,
Expand Down Expand Up @@ -56,31 +59,47 @@ async def list_issues(
# key is entity guid and value is the entity type
# used for caching the entity type for each entity guid and avoid querying it multiple times for
# the same entity guid for different issues
queried_issues: dict[str, str] = {}
queried_entities: dict[str, str] = {}
async for issue in send_paginated_graph_api_request(
self.http_client,
LIST_ISSUES_QUERY,
request_type="list_issues",
extract_data=self._extract_issues,
account_id=ocean.integration_config.get("new_relic_account_id"),
):
# clear the cache if it gets too big
if len(queried_entities) > 1000:
logger.debug("Clearing queried entities cache")
queried_entities.clear()

if state is None or issue["state"] == state.value:
# for each related entity we need to get the entity type, so we can add it to the issue
# related entities under the right relation key
for entity_guid in issue["entityGuids"]:
# if we already queried this entity guid before, we can use the cached relation identifier
if entity_guid not in queried_issues.keys():
entity = await EntitiesHandler(self.http_client).get_entity(
entity_guid
)
queried_issues[entity_guid] = entity["type"]
try:
# if we already queried this entity guid before, we can use the cached relation identifier
if entity_guid not in queried_entities.keys():
entity = await EntitiesHandler(self.http_client).get_entity(
entity_guid
)
queried_entities[entity_guid] = entity["type"]

# add the entity guid to the right relation key in the issue
# by the format of .__<type>.entity_guids.[<entity_guid>...]
issue.setdefault(
f"__{queried_issues[entity_guid]}",
{},
).setdefault("entity_guids", []).append(entity_guid)
# add the entity guid to the right relation key in the issue
# by the format of .__<type>.entity_guids.[<entity_guid>...]
issue.setdefault(
f"__{queried_entities[entity_guid]}",
{},
).setdefault("entity_guids", []).append(entity_guid)
except NewRelicNotFoundError:
logger.info(
f"Related entity guid {entity_guid} not found in new relic for issue {issue.get('issueId')}, continuing",
)
except Exception as err:
logger.exception(
f"Failed to get entity {entity_guid} for issue event {issue.get('issueId')}, continuing",
entity_guid=entity_guid,
err=str(err),
)

matching_issues.append(issue)
return matching_issues
Expand Down
6 changes: 2 additions & 4 deletions integrations/newrelic/newrelic_integration/ocean.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,8 @@ async def resync_entities(kind: str) -> ASYNC_GENERATOR_RESYNC_TYPE:
return
# mainly for issues newRelicAlert as it has different resync logic than entities
if not port_resource_configuration.selector.entity_query_filter:
logger.debug(
"Skipping resync for kind without entity_query_filter",
kind=kind,
logger.info(
f"Skipping resync for kind without entity_query_filter, kind: {kind}",
)
return
else:
Expand Down Expand Up @@ -74,7 +73,6 @@ async def handle_issues_events(issue: IssueEvent) -> dict[str, bool]:
async with httpx.AsyncClient() as http_client:
for entity_guid in issue_record["entityGuids"]:
try:
# get the entity from new
entity = await EntitiesHandler(http_client).get_entity(
entity_guid=entity_guid
)
Expand Down
2 changes: 1 addition & 1 deletion integrations/newrelic/pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[tool.poetry]
name = "newrelic"
version = "0.1.4"
version = "0.1.5"
description = "New Relic Integration"
authors = ["Tom Tankilevitch <[email protected]>"]

Expand Down

0 comments on commit 5d949c8

Please sign in to comment.