See original article on Medium
This article shows how you can easily inject a generic key/value into Google Cloud Monitoring and set up alerts on it. I use it to alert on disk space, and now also low battery!
This morning I was in London, and I forgot my charger at home. With plenty of time but 🪫 little battery, I thought: hey! I need to have a way to predict when my battery is low! And I need to do it in a totally overkill way!
My battery was at 42%, which seemed a subtle indication my idea was worth blogging. Googling around, I found an article which gave me the tip on how to script my Mac’s battery (note this only works for a Macbook).
Ugly code here (hey! I’m in an airport with no charger, do you want Unit tests too?!?)
|
|
I know, I call the same command 10 times and I could cache it. This is for the next iteration!
The best part of this is, not only I get my battery life, it also gives me my battery durability — so when I need to change battery. Woohoo!
There you go, let’s try it out, let me just remove the cable so you dont get a boring 100%.
Battery level is 98%. Unfortunately 14% of my battery potential seems gone 😢
Battery is 98%, yay! Unfortunately seems like ~14% of my battery is gone. Luckily I don’t pay for its repair :)
Step 2: push this metric to the ☁ ️(GCP)
Now, I want a script which emits my metric from CLI. So I can say something like push-to-gcp <METRIC_NAME> <METRIC_VALUE>
.
I’ve coded my disk space a month ago, let me abstract it into some more reusable code (always Ruby): palladius/sakura :: bin/gcp-write-metric .
|
|
Ok! Now let’s try it out.
Caption: Created the timeseries ‘prova’ (test in italian) with meaningful number 123! Wow!
Created the timeseries ‘prova’ (test in italian) with meaningful number 123! Wow!
Note you need to specify the project_id via ENV var (coming soon, the — project
option, or better the project_id auto
inferral from gcloud
config).
Let’s now glue the two scripts and upload the two Macbook info and see on the DevConsole:
|
|
This script requires a project_id in ARGV, then it does the work for you, knowing the fields which are useful from macbook-battery are coming from values 3 and 5 (yes, a JSON encoding/parsing would be less error prone!). Let’s call it:
Caption: Meanwhile I went home, and launched this on my other M1 Mac. Always, boringly, attached to the current. Destined to an infinite life between 99 and 100%. Wait — this Mac, although charged, is on hold until 80%. Maybe cells optimization? I’m impressed.
Once everything works, you need to “productionize it”, which means setting up a Cron job (actually, launchd).
I use bash -lc
to leverage PATH and other goodies from my .bashrc
but I hope you’re a better scripter and can make it work without that
cumbersome import. Also make sure to add PATH correctly (I usually fail a few times before I get it right).
$ crontab -e
[…]
PATH=/sbin:/bin:/usr/sbin:/usr/bin:~/git/sakura/bin/
3/5 * * * * bash -lc '/Users/ricc/path-to/sakura/bin/gcp-write-mac-battery-values-on-project your-project-id'
[…]
Step3: View metric and Create dashboard
Let’s now head to the Metrics Explorer here and check a fake GCE metric:
- Go to https://console.cloud.google.com/monitoring/metrics-explorer
- In “Select a metric” > Type “Battery” and see the options fall from many to two:
Caption: Here are my two metrics, CamelCased too!
Select BatteryLife. This should take you to a nice dashboard (possibly empty if you just created this — be patient). Use the time control to go back in time or zoom until you get the desired view.
Since this signal comes from (possibly) multiple Macs, select “group by” -> hostname. You could see something like this:
Caption: See battery for last day. My Mac (3) at home is always plugged in, the one at work (42) goes to meeting rooms from time to time. To be honest i unplugged it twice just to get a nice screenshot — cheater!
- Now click “Save Chart” and enjoy.
Bingo! You can have a dashboard where you see side by side both BatteryLife and BatteryHealth.
Step4. Set alerting when battery is low
Now let’s get an alert when the battery is below 14% (42 divided by π).
- Open https://console.cloud.google.com/monitoring/alerting
- Click “+ Create Policy” (see sample JSON output)
- “Select Metric” as above (type BatteryLife)
- [optional] You may add a filter on the computer you care about: hostname = “my-favorite-mac”
- Adjust TransformData parameters if you wish.
- Click “Create Policy” -> Configure Alert trigger
- ConditionType: Threshold
- Position: Below threshold
- Threshold value: 14 (or value of your choice, like 20).
- click Create Policy
- Finally, configure your Notification Channels (documentation), where I’ve set up previously my email and swiss phone:
Caption: What life would be without emojis?
- [optional] You can add some Policy User Labels. I enjoy using labels at all time (eg env=prod, scope=personal, ..).
- [optional] You can fill in the Documentation like a Playbook. I always try to write something meaningful as part of SRE methodology (“no alert is good if it’s not actionable”). The action here is to attach your Mac to a power source.
- Finally review the values and click Review Alert:
Conclusions
In this brief article, we’ve seen how you can script a meaningful metric from your machine, and inject it to Cloud Monitoring from command line.
It’s very easy to slice and dice these values (in this case aggregate by hostname), then dashboard and alert on them.
Caption: plug it to have battery or unplug it to see a nice graph?
The sky is just the limit now. You can do something silly like counting your Chrome Tabs and alert when they’re more than 42 with some silly messages like “A message from the Galaxy: restart Chrome!”
brew install chrome-cli # only-once install
PROJECT_ID=my-project-123 gcp-write-metric mac-chrome-cli-ntabs $(chrome-cli list tabs | wc -l)
Note: in the code I use “gce_instance” when I should be really using “global” metric (docs). I loved GCE Instance as it already has hostname and GCP zone baked in, but it’s incorrect (I tell GCP that’s a VM in the cloud, which is not). New code to support this is being developed in this amazing script: 🌸 gcp-write-metric-done-well