Skip to content
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

Refactor alerting package #49

Merged
merged 11 commits into from
Feb 2, 2023
Merged

Conversation

yuri-tceretian
Copy link
Contributor

  1. All code moved from alerting sub-package to root. This removes the duplicated path component, e.g "github.com/grafana/alerting/alerting/models" turns to "github.com/grafana/alerting/models"
  2. Refactored channels package.
  • Package renamed to receivers
  • All receivers are moved into their own sub-packages
  • Logging interface is moved to logging package in the root
  • Code for working with images is moved to images package in the root
  • Templates, structs and functions to work with them are moved to templates package in the root
  1. All receivers renamed to Notifier. So reference to receivers will look like email.Notifier and constructor is email.New
  2. Removed a factory function *Factory that wrapped New function with a ReceiverInitError and replaced by a generic function in the Factory.
  3. Copied receivers factory from Grafana.

Fixes #46

Copy link
Collaborator

@gotjosh gotjosh left a comment

Choose a reason for hiding this comment

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

LGTM, but please look at my comments.

I was hoping this was done per package as opposed to in one go so that can we have isolated, bike shedable conversations (as this is a good time to bike shed).

images/images.go Outdated Show resolved Hide resolved
images/testing.go Outdated Show resolved Hide resolved
images/testing.go Outdated Show resolved Hide resolved
images/utils.go Outdated Show resolved Hide resolved
images/utils.go Show resolved Hide resolved
"github.com/grafana/alerting/receivers/wecom"
)

var receiverFactories = map[string]func(receivers.FactoryConfig) (NotificationChannel, error){
Copy link
Collaborator

Choose a reason for hiding this comment

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

NotificationChannel is a legacy Grafana concept, is it possible to get rid of it? I'm fine with this part of the separate PR as this PR is already kind of hard to review as it is right now.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

It's just a composition of two interfaces. I think we can but not in this PR. We need to move code that builds integrations from Grafana first.

notify.ResolvedSender
}

func Factory(receiverType string) (func(receivers.FactoryConfig) (NotificationChannel, error), bool) {
Copy link
Collaborator

Choose a reason for hiding this comment

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

Do these functions warrant tests?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

It probably does but this code is mostly moved as is from Grafana where it did not have the tests either. I am not sure what we can test here. Probably that all receivers are covered. Each receiver is covered by its own tests.

Copy link
Collaborator

Choose a reason for hiding this comment

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

I'd test what happens when a receiver exists and when it does not.

@@ -0,0 +1,98 @@
package notify
Copy link
Collaborator

Choose a reason for hiding this comment

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

I gotta admit, I'm not a fan of this pattern at all. I spent a big portion of my career writing this type of code in ruby and 10 years later I continue to find this hard to read/understand.

The layer of abstraction for the sake of saving an initialisation of an error seems too much.

That being said, I consider this a nit - if you all agree this is OK feel free to ignore my comment.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Not sure to which line of code you refer to. Do you mean wrap function? If yes, I am not a fan of it either, this was made as a workaround for providing a validation of the configuration prior to saving it to the database.
Currently, there is a similar factory method for each receiver and it looks exactly the same. I just made it DRY-er.

Copy link
Collaborator

Choose a reason for hiding this comment

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

Not sure to which line of code you refer to

The whole design within this file. It's called factory so given I cannot comment on files I tend to typically pick the first line of the file when referring to the whole file.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Ah, definitely, I think we should change it to the way it is implemented in Alertmanager!

Description string `json:"description,omitempty" yaml:"description,omitempty"`
}

func BuildConfig(fc receivers.FactoryConfig) (*Config, error) {
Copy link
Collaborator

Choose a reason for hiding this comment

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

nit: This is validating the configuration but it's called BuildConfig in all receivers - this feels misleading, I understand that this "technically" returning a configuration because it's doing the marshalling but the common pattern I see in most cases is to simply execute the unmarshall call inline and call Validate() on top of the built object.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I do not have a strong opinion on this name. BuildConfig and Validate have pros and cons. Ideally, that should be boiled down to custom marshaller implementation for each struct but for now, decryption functionality does not let us do that (I have a ddoc for that).

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I renamed BuildConfig to ValidateConfig.

@yuri-tceretian
Copy link
Contributor Author

I was hoping this was done per package as opposed to in one go so that can we have isolated, bike shedable conversations (as this is a good time to bike shed).

I tried to do so by package but when I touched something it just affected all other files. So, I decided to do it in kinda one change. I did not touch notify package though, as I am not sure what the end structure will be because we still have some code in the Grafana repository.

)

type AlertmanagerConfig struct {
*NotificationChannelConfig
type Config struct {
Copy link
Contributor

Choose a reason for hiding this comment

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

The package-per-receiver is an amazing change 👍

Comment on lines +73 to +74
// Notifier sends alert notifications to the alert manager
type Notifier struct {
Copy link
Contributor

Choose a reason for hiding this comment

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

We called the package receivers but generalized all the notifier types Notifier - WDYT on aligning this? I.e. calling the package two layers up notifiers or calling these structs Receiver?

Do "notifier" and "receiver" always mean the same thing in our context?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

The reason I chose package receivers and struct name Notifier is that:

  • we have notify package, and having notifiers would look awkward. If we want to rename to notifiers then probably we need to rename notify package.
  • Notifier implements upstream's interface Notifier that has method Notify. Receiver in Alertmanager terminology is a set of Integrations, where each Integration wraps a Notifier.

Copy link
Collaborator

@gotjosh gotjosh left a comment

Choose a reason for hiding this comment

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

LGTM

notify/factory.go Outdated Show resolved Hide resolved
Co-authored-by: gotjosh <josue.abreu@gmail.com>
@yuri-tceretian yuri-tceretian merged commit 173c836 into main Feb 2, 2023
@yuri-tceretian yuri-tceretian deleted the yuri-tceretian/notify-refactor branch February 2, 2023 17:29
yuri-tceretian added a commit that referenced this pull request Feb 2, 2023
1. All code moved from alerting sub-package to root. This removes the duplicated path component, e.g "github.com/grafana/alerting/alerting/models" turns to "github.com/grafana/alerting/models"
2. Refactored channels package.
  - Package renamed to `receivers`
  - All receivers are moved into their own sub-packages
  - Logging interface is moved to `logging` package in the root
  - Code for working with images is moved to `images` package in the root
  - Templates, structs and functions to work with them are moved to `templates` package in the root
3. All receivers are renamed to Notifier. So reference to receivers will look like `email.Notifier` and the constructor is `email.New`
4. Removed a factory function *Factory that wrapped New function with a `ReceiverInitError` and replaced by a generic function in the Factory.
5. Copied receivers factory from Grafana.

Co-authored-by: gotjosh <josue.abreu@gmail.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
Archived in project
Development

Successfully merging this pull request may close these issues.

Proposal: Package Structure
3 participants