1 | # @dollarshaveclub/monitor
|
2 |
|
3 | [![CircleCI](https://circleci.com/gh/dollarshaveclub/monitor/tree/master.svg?style=svg&circle-token=8d27ba25d161dbd81a19eddea92f6e3f69f8c218)](https://circleci.com/gh/dollarshaveclub/monitor/tree/master)
|
4 | [![codecov](https://codecov.io/gh/dollarshaveclub/monitor/branch/master/graph/badge.svg?token=7dgu14EsZp)](https://codecov.io/gh/dollarshaveclub/monitor)
|
5 | [![Greenkeeper badge](https://badges.greenkeeper.io/dollarshaveclub/monitor.svg?token=882bf829fa5624cf562abac32aa14c00e2b636aa738c8bd72593b26740655743&ts=1510381924742)](https://greenkeeper.io/)
|
6 |
|
7 | A remote uptime monitoring framework for running monitors as a CRON job.
|
8 |
|
9 | At Dollar Shave Club, we run our monitors using CircleCI 2 Scheduled Workflows.
|
10 | You can see the test monitors for this repository running every minute here: https://circleci.com/gh/dollarshaveclub/workflows/monitor/tree/master.
|
11 | See our [CircleCI 2 Config](.circleci/config.yml).
|
12 |
|
13 | ## Motivation
|
14 |
|
15 | By switching to this monitoring solution from [New Relic Synthetics](https://newrelic.com/synthetics/pricing), we were able to:
|
16 |
|
17 | - Save hundreds of dollars on New Relic Synthetics costs
|
18 | - Run our monitors every minute instead of every 5 minutes
|
19 | - Test our monitoring scripts, both API and Browser scripts, outside of New Relic's console. We were unable to do this with our Terraform setup.
|
20 | - Use these monitoring scripts as tests for our Dynamic QA environments (our version of [Heroku Review Apps](https://devcenter.heroku.com/articles/github-integration-review-apps))
|
21 | - Additionally, we can develop monitors as the same time as our features, allowing us to merge them at once
|
22 | - Able to easily create and manage hundreds of monitors, which is difficult with Terraform (excessive copy pasta) and any UI-based monitors
|
23 |
|
24 | Because our monitors only use 1 CircleCI container, we essentially pay $50/month for unlimited monitors as long those monitors run in less than 1 minute. Some downsides to this setup is:
|
25 |
|
26 | - Contention with your other tests. If you run out of CircleCI 2 containers, your monitors will queue then run in bursts.
|
27 | - May not be as fast as running monitors as Kubernetes jobs as CircleCI does many commands like `npm install` on every build,
|
28 | which could be slower than just pulling a docker container.
|
29 | However, having a CircleCI UI is a lot better.
|
30 |
|
31 | What about features other monitoring solutions provide?
|
32 |
|
33 | - We pipe all our metrics to Datadog and create all the relevant dashboards
|
34 | - We still use other services like New Relic for features we need, just not for monitoring everything
|
35 | - We don't need to run these monitors from multiple locations.
|
36 | If we do, we'll run them as Kubernetes jobs on different clusters.
|
37 |
|
38 | ## Running Monitors
|
39 |
|
40 | There are two ways to run these monitors.
|
41 |
|
42 | ### Locally
|
43 |
|
44 | To run monitors locally:
|
45 |
|
46 | ```bash
|
47 | ./node_modules/.bin/dsc-monitor 'monitors/**/*.js'
|
48 | ```
|
49 |
|
50 | Run `dsc-monitor --help` for options.
|
51 |
|
52 | NOTE: this assumes you've installed this library as a local dependency, which is installed as `dsc-monitor`.
|
53 | If you're running the monitors from this repository, use `./bin/run.js`.
|
54 | If you've `npm install --global @dollarshaveclub/monitor`, just run `dsc-monitor`.
|
55 |
|
56 | ### Via Docker
|
57 |
|
58 | Copy our [Dockerfile Template](Dockerfile.template) to your repository, then run:
|
59 |
|
60 | ```bash
|
61 | docker build -t dsc-monitor
|
62 | docker run -t dsc-monitor 'monitors/**/*.js'
|
63 | ```
|
64 |
|
65 | ## Creating your Monitoring Repository
|
66 |
|
67 | ```bash
|
68 | mkdir my-monitors # whatever your repo is called
|
69 | cd my-monitors
|
70 | npm init
|
71 | npm i --save @dollarshaveclub/monitors
|
72 | mkdir monitors
|
73 | ```
|
74 |
|
75 | 1. Create a test monitor. You can use one of [our example monitors](monitors/).
|
76 | 1. Add the `npm run monitors` command:
|
77 | 1. Add the following `script` to your `package.json`: `"monitors": "dsc-monitor 'monitors/**/*.js'"`
|
78 | 1. Run your monitors with `npm run monitors`
|
79 | 1. Setting up your monitors in CircleCI as a CRON job:
|
80 | 1. Copy [.circleci/template.config.yml](.circleci/template.config.yml) to `.circleci/config.yml` and push
|
81 |
|
82 | ## Environment Variables
|
83 |
|
84 | Monitor environment variables:
|
85 |
|
86 | - `MONITOR_CONCURRENCY=1` - concurrency of monitors running at the same time
|
87 | - When `concurrency === 1`, results will stream to `stdout`
|
88 | - When `concurrency >= 1`, results will be logged one monitor set at a time
|
89 | - `MONITOR_SHUFFLE` - whether to shuffle monitors and monitor sets
|
90 | - `MONITOR_SHUFFLE_MONITOR_SETS` - whether to shuffle monitor sets
|
91 | - `MONITOR_SHUFFLE_MONITORS` - whether to shuffle monitors within a set
|
92 |
|
93 | ## Defining Monitors
|
94 |
|
95 | All monitoring set is defined in `monitors/`.
|
96 | Each set is a module with:
|
97 |
|
98 | - `exports.id<String> = __filename [optional]` - an ID for your monitor set, defaulting to the filename
|
99 | - `exports.slowThreshold<Number|String> = 30s [optional]` - slow threshold for the entire monitor set
|
100 | - `exports.monitors<Array>` - an array of monitors with the following properties:
|
101 | - `id<String> required` - the ID of the monitor
|
102 | - `parameters<Object> [optional]` - parameters to send to the monitor function and for data purposes
|
103 | - `monitor<Function>(monitorConfig, monitorSetConfig) [required]` - the monitor function, which is passed this monitor object as well as `exports`
|
104 | - `timeout<Number|String> = '5s' [optional]` - timeout for the monitor before it's considered a failure
|
105 | - `slowThreshold<Number|String> = '1s' [optional]` - slow threshold for a monitor
|
106 | - `retries<Number> = 1 [optional]` - number of times to retry a failing monitor
|
107 |
|
108 |
|
109 | - `exports.beforeAll<Function>`
|
110 | - `exports.afterAll<Function>`
|
111 | - `exports.beforeEach<Function>`
|
112 | - `exports.afterEach<Function>` -->
|
113 |
|
114 | What certain fields do:
|
115 |
|
116 | - `slowThreshold` - turns the color of the time from `green` to `yellow` when a monitor or set of monitors take this amount of time
|
117 |
|
118 | ## Notes
|
119 |
|
120 | ### Scheduling Monitors
|
121 |
|
122 | #### CircleCI
|
123 |
|
124 | See CircleCI 2 workflow scheduling: https://circleci.com/docs/2.0/workflows/#scheduling-a-workflow. You can work off our [.circleci/config.yml](.circleci/template.config.yml) template
|
125 |
|
126 | See all builds on master of workflow `monitor` without a commit attached to it: https://circleci.com/gh/dollarshaveclub/monitor/tree/master
|
127 | Or just look at the `monitor` workflow: https://circleci.com/gh/dollarshaveclub/workflows/monitor/tree/master
|