Skip to content

feat(newrelic): APM application id can be looked up by name #361

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 2 commits into
base: master
Choose a base branch
from

Conversation

3bbbeau
Copy link

@3bbbeau 3bbbeau commented Mar 5, 2025

Summary

This is intended to be a quality of life feature to allow ArgoCD ApplicationSet resources to minimize boilerplate when dealing with NewRelic APM resources across multiple environments.

Currently

  • An application programmatically uses the NR SDK to report to NewRelic
  • NewRelic APM Application ID has to then be retrieved following the first run of an application from the NR Dashboard and added to an ArgoCD Application via the annotation, across multiple environments.
---
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  annotations:
    notifications.argoproj.io/subscribe.<trigger-name>.newrelic: 123456789

Desired

Using ArgoCD ApplicationSet resources, the annotation can be either provided via the application id as the above example, or instead by name, e.g. MyApp-{{ .values.env }}:

---
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  annotations:
    notifications.argoproj.io/subscribe.<trigger-name>.newrelic: MyApp-Dev

Logic

If dest.Recipient can be parsed to an int, then the application id was directly provided and logic remains as before.

If dest.Recipient cannot be parsed to an integer, then it was passed by name (since all NewRelic APM IDs are defined as integers within the schema) and we call /v2/applications.json to query using filter[name]

If /v2/applications.json returns multiple application IDs then an error is returned, as we can't determine which application id to use to place the deployment marker.

@3bbbeau 3bbbeau force-pushed the feat/newrelic-appid-by-name branch 8 times, most recently from a89ba06 to 063b8d4 Compare March 5, 2025 12:18
3bbbeau added 2 commits March 5, 2025 12:53
This is intended to be a quality of life addition to allow
`ApplicationSet` resources to minimize boilerplate when dealing with
NewRelic APM resources across multiple environments.
- An application programmatically [uses the NR SDK to report to
  NewRelic](https://github.com/newrelic/go-agent/blob/master/v3/examples/server/main.go#L267-L274)
- NewRelic APM Application ID has to then be retrieved following the
  first run of an application from the NR Dashboard and added to an
  ArgoCD `Application` via the annotation, across multiple environments.
Using ArgoCD `ApplicationSet` resources, the annotation can be either
provided via app_id, or by name, e.g. `MyApp-{{ .values.env }}`
If `dest.Recipient` can be parsed to an int, then app_id is provided
and logic remains as before.
If `dest.Recipient` cannot be parsed to an integer, then it was passed
by name and we call `/v2/applications.json` to query using
`filter[name]`
If `/v2/applications.json` returns multiple application IDs then an
error is returned, as we can't determine which app_id to use to place
the deployment marker.

Signed-off-by: 3bbbeau <0x3bb@3bb.io>
Signed-off-by: 3bbbeau <0x3bb@3bb.io>
@3bbbeau 3bbbeau force-pushed the feat/newrelic-appid-by-name branch from 063b8d4 to 2d77a47 Compare March 5, 2025 12:53
}

func (s newrelicService) getApplicationId(client *http.Client, appName string) (string, error) {
applicationsApi := fmt.Sprintf("%s/v2/applications.json?filter[name]=%s", s.opts.ApiURL, appName)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd use the url library to construct this, to avoid appName potentially injecting arbitrary stuff

}
}
}
markerApi := fmt.Sprintf(s.opts.ApiURL+"/v2/applications/%s/deployments.json", appId)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

+1, use url package to construct URLs

Comment on lines +185 to +187
var appId = dest.Recipient
if dest.Recipient != "" {
_, err := strconv.Atoi(dest.Recipient)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Instead of reusing Recipient, could you use a new RecipientName field? Clarifies the UX and avoids any weirdness around, for example, a name that happens to also be a number.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for taking a look at this. I first interpreted your comment as changing the Destination struct but I'm not actually sure where you mean without making this change of wider significance.

I had a look at the other services to see how they had handled service-specific changes in recipient fields:

// It's a channel
if strings.HasPrefix(dest.Recipient, "#") || strings.HasPrefix(dest.Recipient, "@") {
message.Channel = dest.Recipient
} else {
message.RoomID = dest.Recipient

if strings.HasPrefix(dest.Recipient, "-") {
chatID, err := strconv.ParseInt(dest.Recipient, 10, 64)
if err != nil {
return err
}
// Init message with ParseMode is 'Markdown'
msg := tgbotapi.NewMessage(chatID, notification.Message)
msg.ParseMode = "Markdown"
_, err = bot.Send(msg)
if err != nil {
return err
}
} else {
// Init message with ParseMode is 'Markdown'
msg := tgbotapi.NewMessageToChannel("@"+dest.Recipient, notification.Message)
msg.ParseMode = "Markdown"


Could we do something similar with name: 12345678 and id: 12345678 and default to the latter given no prefix for backwards compatibility? That would leave the Destination struct alone and address the issue of New Relic APM names that happen to be numbers.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants