Giter Club home page Giter Club logo

dogpush's Introduction

Retirement Announcement

At this point in time, we've decided to retire the DogPush project and place it into maintenance mode, and Trueaccord will no longer be managing and maintaining this project.

We'd like to extend a huge thanks and our gratitude to all of the contributors to this project that have helped us to get this project to where it is today and for accompanying us on this journey!

If you run into any issues with this project that you believe require attention or wish to enhance it, feel free to fork this repository however we may decide to delete this repository at a future point in time.

Original README

DogPush

DogPush enables to manage your DataDog monitors in YAML files.

Why would I want to manage my monitors in YAML files?

Excellent question. So many reasons:

  • You can store your monitors in source control so you can track changes (who changed this monitor?), and perform code reviews.
  • Automatically includes the right @-mentions in the message based on team configurations.
  • It is very easy to accidentally make changes to monitors on DataDog's UI. By having your monitors documented in your own source code repository, you can set up a cron job that pushes the monitors to DataDog. This allows you to ensure that accidental changes get automatically corrected.
  • DataDog has a missing feature: it is impossible to set up a monitor that is only active during business hours. With DogPush it is really easy using mute_tags.

Installation

Via PIP

Run pip install dogpush

Via Docker

Run docker pull trueaccord/dogpush

To run, you need ot make your configuration files accessible to the container. Use a command like this:

docker run --rm -v /path/to/config:/config trueaccord/dogpush -c /config/config.yaml diff

Getting Started

Go to DataDog API settings and generate an API key and application key. Create a minimal config.yaml that looks like this:

---
datadog:
  api_key: YOUR_API_KEY
  app_key: YOUR_APP_KEY

Then run dogpush -c ./config.yaml diff and all the alerts you currently have on datadog will appear as untracked.

The next step would be to create your initial alerts file:

dogpush -c ./config.yaml init > ./my_monitors.yaml

Now, add my_monitors.yaml as a rules_file to config.yaml. Edit config.yaml again:

---
datadog:
  api_key: YOUR_API_KEY
  app_key: YOUR_APP_KEY

rule_files:
- my_monitors.yaml

Now, run dogpush diff again, and see that the difference will be empty. Your local rules are in sync with your DataDog rules. If you have a lot of rules, You may split your initial rules file to multiple files (by category, or team), and include all of them in the rule_files section. Paths can be either relative to the config file or absolute. Paths may contain wildcards.

rule_files:
- rds.yaml
- ec2.yaml
- dir1/rules.yaml
- /absolute/path/to/rules.yaml
- path/with/wildcard/*.yaml

Now you can make changes to your rule files. See the changes by running dogpush diff, and push them using dogpush push.

Config file

DogPush config file defines up the DataDog api and app keys. If they are not specified in the file DogPush looks for these in environment variables named DATADOG_API_KEY and DATADOG_APP_KEY.

The file defines the teams and how to alert your team at different severity levels.

Rule Defaults

Your config can optionally define two values to specify defaults. default_rules can be used to specify defaults for the top level values of rules, such as multi and message. default_rule_options can be used to specify default values for the options section of rules, such as locked or notify_audit. All of these values are automatically filled in for every rule you define, but can always be overridden per-rule. For example,

default_rules:
  multi: False
default_rule_options:
  notify_audit: True
  locked: True

The teams section

Teams in DogPush are just a way to append some text to the message body of a monitor so it will grab the attention of the right people. By defining your teams in the global config, it is super easy to add these @-mentions to all your monitors. For example,

teams:
  eng:
    notifications:
      CRITICAL: '@hipchat-Engineering @victorops-eng'
      WARNING: '@[email protected]'
  ops:
    notifications:
      CRITICAL: '@hipchat-Ops'

means that any monitor of severity CRITICAL to the eng team will have the '@hipchat-Engineering @victorops-eng' appending to its message body.

Then, in a rules file, you can have a top level team setting (making all the alerts automatically go to that team), or specify 'team' at the alert level.

The default severity is CRITICAL, and you can override the severity in each monitor by using the severity key.

Muting alerts based on time windows

DogPush supports automatically muting alerts. A common use case is to mute non critical alerts outside business hours. First, define the time window like this:

mute_tags:
  not_business_hours:
    timezone: US/Pacific
    expr: now.hour < 9 or now.hour >= 17 or (now.weekday() in (5, 6))

This defines not_business_hours period. The period is defined using a timezone and a Python expression. The expression provides a now variable of type datetime.datetime and should return True when now falls in a time where the monitor should be muted. In this example, not_business_hours is defined as before 9am or after 5pm or anytime during the weekend. The timezone key specifies in which timezone should the now be localized to. (all the internal time calculations in DogPush are done in UTC regardless of the system's default timezone).

After defining mute_tags, you can apply mute_when: not_business_hours to rules in your rules file. Also read about dogpush mute to learn how to automatically mute these alerts.

See config-sample.yaml for a full example.

DogPush options

There are two optional settings that can be configured in the config file:

dogpush:
  yaml_width: 80
  ignore_prefix: 'string'

The yaml_width option sets the line width of the generated yaml output.

Using ignore_prefix one can define a set of monitor names that are simply ignored by DogPush when fetching the remote monitors.

Rule files

On the top of a rules file you can define team: xyz to define the default team for all the alerts in the file. You can override the team by specifying a different team in an alert.

Tip 1: it is possible to use a list of teams instead of a single team.

Tip 2: if you would like to have a monitor without any team associated with it, you can use team: [] in that monitor. This will override the file's default team settings with an empty list.

The config file references your rule files. See rds.yaml for an example rule file.

Available commands

dogpush init

Prints an initial rules file so you can get started quickly with your existing rules.

dogpush diff

Prints the diff between the monitors in the files and the monitors in datadog. This is useful when just starting out so you can build your initial rule files. Also, use dogpush diff before dogpush push as a dry-run to see what will change.

dogpush diff --no_exitstatus will cause dogpush diff to return exit code 0 regardless of if there is a difference detected. If this flag is not present then dogpush will return 1 if there is a difference between local and remote.

dogpush push

Pushes the local monitors to datadog:

  • will create new monitors
  • will update existing monitors (so it could override what you were doing if you edit an existing monitor in datadog)
  • will not remove or touch untracked monitors (that is, datadog monitors that are not in any of the yaml files) unless the --delete_untracked flag is passed in.

This command can run from a cronjob to ensure the monitors on DataDog are synchronized with the local monitors.

dogpush mute

Use dogpush mute to mute monitors that have a mute_when tag. This command will mute these monitors, and the mute will automatically expires when the period described by mute_when is over. This command can be run from a cron job to ensure monitors are silenced at the right times. As the mute automatically expires, there is no need to run anything to unmute the alerts.

dogpush's People

Contributors

alexef avatar ameng avatar apetrenko-ta avatar b3rnie avatar mjcaddell avatar nandrienko avatar pbhandari356 avatar thesamet avatar willmore avatar zkwong1 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

dogpush's Issues

Composite monitors

hello, this looks like an interesting project, i was wondering if it was possible to create composite monitors with this tool?
I am not sure what would be the best way to represent a dependency graph of monitors something like this:

                                +-----------------+
                           +----+composite monitor+---+
                           |    +-----------------+   |
                           |                          |
                           |                          |
                     +-----v-----------+     +--------v--+
                   +-+composite monitor+--+  |query alert|
                   | +-----------------+  |  +-----------+
                   |                      |
                   |                      |
         +---------v-------+       +------v----+
      +--+composite monitor+--+    |query alert|
      |  +-----------------+  |    +-----------+
      |                       |
      |                       |
+-----v-----+         +-------v---+
|query alert|         |query alert|
+-----------+         +-----------+

Dog Push not working

Hi ,

I'm currently having issues running dogpush diff/push. Im able to download the config and init a new alerts file, however when I add the 'rule_files' file name reference to the config.yaml, i get the following errors:

Traceback (most recent call last):
File "/usr/local/bin/dogpush", line 5, in
dogpush.main()
File "/Library/Python/2.7/site-packages/dogpush/dogpush.py", line 422, in main
args.command(args)
File "/Library/Python/2.7/site-packages/dogpush/dogpush.py", line 316, in command_diff
local_monitors = get_local_monitors()
File "/Library/Python/2.7/site-packages/dogpush/dogpush.py", line 186, in get_local_monitors
r = yaml.safe_load(f)
File "/Library/Python/2.7/site-packages/yaml/init.py", line 93, in safe_load
return load(stream, SafeLoader)
File "/Library/Python/2.7/site-packages/yaml/init.py", line 71, in load
return loader.get_single_data()
File "/Library/Python/2.7/site-packages/yaml/constructor.py", line 39, in get_single_data
return self.construct_document(node)
File "/Library/Python/2.7/site-packages/yaml/constructor.py", line 48, in construct_document
for dummy in generator:
File "/Library/Python/2.7/site-packages/yaml/constructor.py", line 398, in construct_yaml_map
value = self.construct_mapping(node)
File "/Library/Python/2.7/site-packages/yaml/constructor.py", line 208, in construct_mapping
return BaseConstructor.construct_mapping(self, node, deep=deep)
File "/Library/Python/2.7/site-packages/yaml/constructor.py", line 133, in construct_mapping
value = self.construct_object(value_node, deep=deep)
File "/Library/Python/2.7/site-packages/yaml/constructor.py", line 88, in construct_object
data = constructor(self, node)
File "/Library/Python/2.7/site-packages/yaml/constructor.py", line 414, in construct_undefined
node.start_mark)
yaml.constructor.ConstructorError: could not determine a constructor for the tag 'tag:yaml.org,2002:python/unicode'
in "/Users/cgerasimou/dogpush/animus_monitors.yaml", line 15, column 25

Can you please advise if i'm doing something wrong

yaml ScannerError: mapping values are not allowed here

Hi,

having an issue with DogPush:

Just did an initial dump of my monitors followed directly by a diff and get a failing dogpush while reading the YAML just after it was created by himself. No manual changes to the file:

$ rm my_monitors.yaml 
$ dogpush -c ./config.yaml diff > ./my_monitors.yaml
$ dogpush diff 
Traceback (most recent call last):
  File "/home/some/path/virt_envs/dogpush/bin/dogpush", line 5, in <module>
    dogpush.main()
  File "/home/some/path/virt_envs/dogpush/local/lib/python2.7/site-packages/dogpush/dogpush.py", line 422, in main
    args.command(args)
  File "/home/some/path/virt_envs/dogpush/local/lib/python2.7/site-packages/dogpush/dogpush.py", line 316, in command_diff
    local_monitors = get_local_monitors()
  File "/home/some/path/virt_envs/dogpush/local/lib/python2.7/site-packages/dogpush/dogpush.py", line 186, in get_local_monitors
    r = yaml.safe_load(f)
  File "/home/some/path/virt_envs/dogpush/local/lib/python2.7/site-packages/yaml/__init__.py", line 93, in safe_load
    return load(stream, SafeLoader)
  File "/home/some/path/virt_envs/dogpush/local/lib/python2.7/site-packages/yaml/__init__.py", line 71, in load
    return loader.get_single_data()
  File "/home/some/path/virt_envs/dogpush/local/lib/python2.7/site-packages/yaml/constructor.py", line 37, in get_single_data
    node = self.get_single_node()
  File "/home/some/path/virt_envs/dogpush/local/lib/python2.7/site-packages/yaml/composer.py", line 36, in get_single_node
    document = self.compose_document()
  File "/home/some/path/virt_envs/dogpush/local/lib/python2.7/site-packages/yaml/composer.py", line 58, in compose_document
    self.get_event()
  File "/home/some/path/virt_envs/dogpush/local/lib/python2.7/site-packages/yaml/parser.py", line 118, in get_event
    self.current_event = self.state()
  File "/home/some/path/virt_envs/dogpush/local/lib/python2.7/site-packages/yaml/parser.py", line 193, in parse_document_end
    token = self.peek_token()
  File "/home/some/path/virt_envs/dogpush/local/lib/python2.7/site-packages/yaml/scanner.py", line 128, in peek_token
    self.fetch_more_tokens()
  File "/home/some/path/virt_envs/dogpush/local/lib/python2.7/site-packages/yaml/scanner.py", line 220, in fetch_more_tokens
    return self.fetch_value()
  File "/home/some/path/virt_envs/dogpush/local/lib/python2.7/site-packages/yaml/scanner.py", line 576, in fetch_value
    self.get_mark())
yaml.scanner.ScannerError: mapping values are not allowed here
  in "/home/some/path/vcs/git/smt-dogpush/my_monitors.yaml", line 7, column 10

Versions:

$ pip freeze
certifi==2018.1.18
chardet==3.0.4
datadog==0.20.0
decorator==4.2.1
DogPush==0.3.4
idna==2.6
pkg-resources==0.0.0
pytz==2018.4
PyYAML==3.12
requests==2.18.4
simplejson==3.13.2
urllib3==1.22

Release 0.3.4

Hello guys.
There were two important changes since last release. Would it be an option to release new version?

Add Sync/Delete option

I see in the docs that the push command:

will never remove or touch untracked monitors (that is, datadog monitors that are not any of the yaml files).

However, it would be nice to keep monitors completely in sync with my YAML configs, even if that means deleting monitors.

Something like dogpush sync which does push/delete, or a flag on the push command like --delete to enable this option.

I would be glad to work on this if you think its an acceptable feature.

DogPush is silently ignoring errors

Hi all,

Firstly, thanks a lot for DogPush!

I've noticed that it appears to be silently hiding errors returned from DD's API.

To prove it, I have setup an example config and monitor like this:

(dp-test)lex@lex-book2:~/dogpush-test> cat config.yaml

---
datadog:
  api_key: <hidden>
  app_key: <hidden>

rule_files:
  - test.yaml
(dp-test)lex@lex-book2:~/dogpush-test> cat test.yaml
alerts:
- message: "A Test Message"
  name: Test Monitor
  options:
    no_data_timeframe: 480
    renotify_interval: 0
    thresholds: {critical: 20.0, warning: 15.0}
    timeout_h: 0
  query: avg(last_4h):this-isnt-a-query
  tags: ['env:staging']
  type: metric alert

Note how the query is totally invalid?

Then when I run DogPush, it returns a 0 exit code and appears to work successfully, however, the monitor is not updated in Datadog.

(dp-test)lex@lex-book2:~/dogpush-test> dogpush push
Pushing 1 new monitors.
(dp-test)lex@lex-book2:~/dogpush-test> echo $?
0

If I chuck a print statement where DogPush is creating the alert

210         for name in only_local:
211             print datadog.api.Monitor.create(**_prepare_monitor(local_monitors[name]))

I note that DD is returning an error about the monitor that we're ignoring:

{'errors': ["The value provided for parameter 'query' is invalid"]}

Allows name changes for existing monitors

Currently DogPush doesn't support changing the names of existing monitors. This is apparently, because the ids of remote monitors aren't stored locally, so when changing a monitors name DogPush loses the relation to the remote monitor.
Please store the id of remote monitors and use that as criteria for identifying monitors to allow name changes for existing monitors.

Python3 support

When I install under python3 I get the following error:

>>> from dogpush import dogpush
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/local/lib/python3.7/site-packages/dogpush/dogpush.py", line 229
    print '# team: TEAMNAME'
                           ^
SyntaxError: Missing parentheses in call to 'print'. Did you mean print('# team: TEAMNAME')?
>>>

Request for a --ignore_untracked flag on dogpush diff

Perhaps something like this already exists and is not documented, but it would be nice to have a --ignore_untracked flag on the diff command to give a simpler view of what will actually be run with a push. If such a flag already exists could you point me to it? If not can we add that as a feature. My python isn't great, but I could probably take a stab if that would be helpful.

`silenced` map not populating in options list

I have a few monitors muted by scope in datadog and it looks like those fields are not being pulled into the options block of the yaml. According the the datadog documentation

silenced: dictionary of scopes to timestamps or None. Each scope will be muted until the given POSIX timestamp or forever if the value is None.
Default: None

Dogpush init/diff is broken

I started with the config.yaml

---
datadog:
  api_key: ***
  app_key: ***
  
rule_files:
  - monitors.yaml

Where the * is replaced by the actual keys. I tested them with ```dogpush diff````
With the config file

- message: '...'
  multi: true
  name: AWS region is CRITICAL
  options:
    new_host_delay: 300
    no_data_timeframe: 2
    notify_no_data: false
    renotify_interval: 0
    thresholds: {ok: 2}
    timeout_h: 0
  query: '"aws.status".over("*").by("region","service").last(3).count_by_status()'
  type: service check

- message: '...'
  name: CPU Utilization AVG
  options:
    escalation_message: !!python/unicode ''
    include_tags: false
    new_host_delay: 300
    no_data_timeframe: 10
    notify_no_data: false
    renotify_interval: 0
    require_full_window: false
    thresholds: {critical: 90.0, warning: 75.0}
    timeout_h: 0
  query: avg(last_1h):avg:aws.ec2.cpuutilization{*} > 90
  tags: ['*']

I initialized my monitors with

dogpush -c config.yaml init > monitors.yaml

and now I get the error


  File "/usr/local/lib/python2.7/dist-packages/yaml/constructor.py", line 208, in construct_mapping
    return BaseConstructor.construct_mapping(self, node, deep=deep)
  File "/usr/local/lib/python2.7/dist-packages/yaml/constructor.py", line 133, in construct_mapping
    value = self.construct_object(value_node, deep=deep)
  File "/usr/local/lib/python2.7/dist-packages/yaml/constructor.py", line 88, in construct_object
    data = constructor(self, node)
  File "/usr/local/lib/python2.7/dist-packages/yaml/constructor.py", line 414, in construct_undefined
    node.start_mark)
yaml.constructor.ConstructorError: could not determine a constructor for the tag 'tag:yaml.org,2002:python/unicode'
  in "/home/vagrant/monitors.yaml", line 21, column 25

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.