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 Alert Service #1209

Merged
merged 11 commits into from
Mar 27, 2017
Merged

Refactor Alert Service #1209

merged 11 commits into from
Mar 27, 2017

Conversation

nathanielc
Copy link
Contributor

@nathanielc nathanielc commented Feb 17, 2017

This is a refactor of the Alert Service there are a handful of changes:

  • Add the concept of External vs Internal Handlers
  • Create explicit types for each of the different responsibilities of the alert service
  • Remove the concept of Actions, now a handler only ever has a single action.
  • General reorg of the code to make it easy to consume/extend.

TODO

  • Rebased/mergable
  • Tests pass
  • CHANGELOG.md updated
  • Add test for Aggregate and Publish handlers
  • Safely migrate from old handlers to new handlers.

@nathanielc nathanielc changed the title Add no handle collect option to alert topics Add external vs internal handlers Feb 23, 2017
@nathanielc nathanielc force-pushed the nc-alert-nohandle branch 3 times, most recently from 073d874 to 0375e6d Compare March 8, 2017 16:18
@nathanielc nathanielc force-pushed the nc-alert-nohandle branch 3 times, most recently from 0d60091 to f0efb9b Compare March 9, 2017 20:14
@nathanielc nathanielc changed the title Add external vs internal handlers Refactor Alert Service Mar 9, 2017
@nathanielc nathanielc requested a review from desa March 9, 2017 20:17
@nathanielc nathanielc force-pushed the nc-alert-nohandle branch 2 times, most recently from 64cb0c3 to 0085fd9 Compare March 9, 2017 20:50
Copy link
Contributor

@desa desa left a comment

Choose a reason for hiding this comment

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

From what I can tell it seems good. Going to Read over it another time.

This may just be due to my own misunderstanding, but it seems like its not possible to create a topic without using it in a TICKscript. Is this correct?

httpd.HttpError(w, fmt.Sprint("invalid pattern: ", err.Error()), true, http.StatusBadRequest)
return
}
minLevelStr := r.URL.Query().Get("min-level")
Copy link
Contributor

Choose a reason for hiding this comment

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

Not a really an issue since this isn't a hot code path, but URL.Query() generates a new map each time its called.

https://golang.org/src/net/url/url.go?s=27419:27447#L967

h.next = n
}
func (h *stateChangesOnlyHandler) Close() {}
// TODO implement state changes only as a match condition
Copy link
Contributor

Choose a reason for hiding this comment

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

What does this mean?

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, yes so with the change to not have handler actions anymore there is no way to do stateChangesOnly via a handler.

The proposed solution is to use match criteria on handlers. So something like this

id: my_handler
topic: system
kind: slack
   options:
       channel: '#alerts'
match: "changed" == TRUE AND "sometag" == 'bob'

Where the match property is a lambda expression then when it evals to true then the handler handles the alert event. This way we get the same functionality back but in a more consistent manner.

I was thinking we should add the match expression logic in another PR so that its can remain as an independent change. Or should we lump it in here so that we maintain feature parity from the get go? Thoughts?

@nathanielc
Copy link
Contributor Author

it seems like its not possible to create a topic without using it in a TICKscript. Is this correct?

No quite, Topics are created whenever they are referenced so there is no need to explicitly create them. So if they are referenced in a TICKscript they are created as well as if a handler references a topic it will be created.

@desa
Copy link
Contributor

desa commented Mar 14, 2017

No quite, Topics are created whenever they are referenced so there is no need to explicitly create them. So if they are referenced in a TICKscript they are created as well as if a handler references a topic it will be created.

Ah I see. I spent some time confused about this. Here's the process I just went through.

First I created a task with this tickscript

var warn_threshold = 4
var crit_threshold = 10

var period = 1h
var every = 1m

var data = stream
  |from()
    .measurement('system')
  |alert()
   .crit(lambda: TRUE)
   .topic('learning')

Then

$ kapacitor

I noticed the define-handler subcommand and then ran

$ kapacitor define-handler -h

From here I noticed

For example:

	Define a handler using the slack.yaml file:

		$ kapacitor define-handler system slack.yaml

So I make a slack.yaml file

id: example
kind: slack
topic: learning
options:
  username: What

and then I run

$ kapacitor define-handler slack slack.yaml

No errors, so moving on.

$ kapacitor show-topic learning
ID: learning
Level: CRITICAL
Collected: 1340
Handlers: [ ]
Events:
Event      Level    Message                Date
system:nil CRITICAL system:nil is CRITICAL 14 Mar 17 15:27 EDT

Hmm, then I run

$ kapacitor list handlers
ID         Topic    Kind
example   slack slack

Hmm, so I rerun

$ kapacitor define-handler -h

This time I notice

Must provide both a topic ID and a path to a handler file.
Usage: kapacitor define-handler <topic> <path to handler file>

and I notice this time that you specify the topic id as the first positional argument to the command. Then everything was fine.

This confusion was definitely due to me not reading, but the positional arguments vs flags split is different than what I'm used to with kapacitor. The two other define subcommands have

$ kapacitor define <task ID> [options]
$ kapacitor define-template <template ID> [options]

where positional arguments are used for naming things and flags are used to specify details.

@nathanielc
Copy link
Contributor Author

@desa Thanks for the walk through. Agreed lets change it to be more consistent.

Would this be more clear?

kapacitor define-handler slack.yaml -topic system

The difference here is that the ID is in the yaml file. Should we move the ID out of the yaml file so that the ID is specified on the command line?

@desa
Copy link
Contributor

desa commented Mar 14, 2017

@nathanielc
My only issue with pulling it out of the config file is that the define-handler is kind of different than the others.

With define or define-template

kapacitor define example -type stream -dbrp telegraf.autogen -tick example.tick

defines a single task and reissuing that command with different flags redefines the task example. The same thing isn't the case for define-handler though. e.g.

kapacitor define-handler my_hanlder -topic system -file slack.yaml

and

kapacitor define-handler my_hanlder -topic other -file slack.yaml

define two different handlers.

I keep mulling over different ways of going about it and I cant think of one I like.

Syntacticly, I like

kapacitor define-handler my_hanlder -topic system -file slack.yaml

the most. Just because its very similar to how the other define commands work. However, it philosophically bothers me, that changing a flag defines a new thing.

@nathanielc
Copy link
Contributor Author

nathanielc commented Mar 14, 2017

However, it philosophically bothers me, that changing a flag defines a new thing.

This is why I made it an positional argument. In other words the ID for a handler is topicID and handlerID together.

@desa
Copy link
Contributor

desa commented Mar 14, 2017

maybe changing the name of the command?

kapacitor define-topic-handler <topic> <file>

@nathanielc
Copy link
Contributor Author

nathanielc commented Mar 14, 2017

I like that, its a bit verbose but that is what tab completion is for :)

I did a similar thing in the Go client.

@desa
Copy link
Contributor

desa commented Mar 14, 2017

or what about moving the topic into the handler config

id: example
kind: slack
topic: learning
options:
  username: What

and just having

kapacitor define-handler <file>

@nathanielc
Copy link
Contributor Author

I like topic-handler as it also helps with the other commands like list and delete as they become

kapacitor list topic-handlers <topic> <handler>
kapacitor delete topic-handlers <topic> <handler>

And show-handler becomes show-topic-handler <topic> <handler>

It creates a more consistent treatment of handlers, such that they are always referenced in the scope of a topic.

@desa
Copy link
Contributor

desa commented Mar 14, 2017

👍

@desa
Copy link
Contributor

desa commented Mar 14, 2017

Final thought. Maybe this is what you were already thinking, but what about something like

kapacitor define-topic-handler <topic id> <handler id> -config <file>

with

kind: slack
options:
  username: What

@nathanielc
Copy link
Contributor Author

@desa I have pushed an updated CLI, could you look it over and see how UX is?

@desa
Copy link
Contributor

desa commented Mar 15, 2017

For some reason github wont let me directly comment on where some of the issues are.

return fmt.Errorf("cannot list '%s' did you mean 'tasks', 'recordings', 'replays', 'topics', 'handlers' or 'service-tests'?", kind)

Should say topic-handlers

$ kapacitor delete handlers [topic] [ID or pattern]

$ kapacitor delete handlers system slack

Should say topic-handlers

return fmt.Errorf("cannot delete '%s' did you mean 'tasks', 'templates', 'recordings', 'replays', 'topics' or 'handlers'?", kind)

Should say topic-handlers

Just a couple copy issues.

Personally, I think I'd prefer having the handler configuration be specified as a flag, but I don't particularly mind it the way that it currently is.

@nathanielc nathanielc force-pushed the nc-alert-nohandle branch 2 times, most recently from 6e0ce1e to 0553eab Compare March 15, 2017 20:26
@nathanielc
Copy link
Contributor Author

Personally, I think I'd prefer having the handler configuration be specified as a flag, but I don't particularly mind it the way that it currently is.

I started that way and then reversed it because Go is picky about where flags need to be, so it would always have to be the last or first argument which basically turned it into a positional argument. And it is not an optional argument which a flag implies.

I'll fix the other issues.

…m/google/uuid

subrepo:
  subdir:   "vendor/github.com/google/uuid"
  merged:   "6a5e28554"
upstream:
  origin:   "https://github.com/google/uuid.git"
  branch:   "master"
  commit:   "6a5e28554"
git-subrepo:
  version:  "0.3.0"
  origin:   "???"
  commit:   "???"
@nathanielc
Copy link
Contributor Author

@desa The migration path is ready for testing.

You should be able to

  • upgrade with any v1.2 handler and have all functionality continue to work.
  • downgrade back to v1.2 and have everything back to how it was

@desa
Copy link
Contributor

desa commented Mar 21, 2017

@nathanielc Just did a manual test and verified that this process works.

@nathanielc nathanielc merged commit 1521a8c into master Mar 27, 2017
nathanielc added a commit that referenced this pull request Mar 27, 2017
@nathanielc nathanielc deleted the nc-alert-nohandle branch April 26, 2017 16:28
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