PDH - PagerDuty CLI for humans
PDH is a new lightweight CLI for pagerduty interaction: uou can handle your incidents triage without leaving your terminal.
It also add some nice tricks to automate the incident triage and easy the on-call burden.
See docs (TBD)
Install
Nix
If you are using cachix you can use the prebuilt packages:
cachix use pdh
nix shell github:mbovo/pdh
Arch linux
yay -S pdh
With docker
docker run -ti -v ~/.config/pdh.yaml:/root/.config/pdh.yaml --rm pdh:0.3.10 inc ls
With pip
pip install pdh>=0.3.10
From source with nix and direnv
git clone https://github.com/mbovo/pdh
direnv allow pdh
cd pdh
pdh inc ls -e
From source with devbox
git clone https://github.com/mbovo/pdh
direnv allow pdh
cd pdh
pdh inc ls -e
From source
git clone https://github.com/mbovo/pdh
cd pdh
task setup
source .venv/bin/activate
pdh inc ls -e
Usage
First of all you need to configure pdh to talk with PagerDuty's APIs:
pdh config
The wizard will prompt you for 3 settings:
apikeyis the API key, you can generate it from the user's profile page on pagerduty websiteemailthe email address of your pagerduty profileuidthe userID of your account (you can read it from the browser address bar when clicking on "My Profile")
Settings are persisted to ~/.config/pdh.yaml in clear.
Listing incidents
Assigned to self:
pdh inc ls
Any other incident currently outstanding:
pdh inc ls -e
Listing incident by team
Listing only outstanding alerts only if they are assigned to a specific team:
pdh inc ls -e --teams mine
Search for a given team id:
pdh teams ls
Use specific id (list):
pdh inc ls -e --team-id "P1LONJG,P4SEF5R"
Sorting incident by field
pdh inc ls --sort assignee --reverse
In case the field is not found the cli will notice you and print the list of available fields
pdh inc ls -e --sort unkn --reverse
Invalid sort field: unkn
Available fields: id, assignee, title, status, created_at, last_status_change_at, url
You can always sort by multiple fields using comma as separator:
pdh inc ls --sort assignee,status
Auto ACK incoming incidents
Watch for new incidents every 10s and automatically set them to Acknowledged
pdh inc ls --watch --new --ack --timeout 10
List all HIGH priority incidents periodically
List incidents assigned to all users every 5s
pdh inc ls --high --everything --watch --timeout 5
Resolve specific incidents
pdh inc resolve INCID0001 INCID0024 INCID0023
Resolve all incidents related to Backups
pdh inc ls --resolve --regexp ".*Backup.*"
Extract custom fields
You can also extract custom fields from the pagerduty json output:
You can nested fields using dot notation (i.e service.summary)
pdh inc ls -e --fields service.summary,status,title,assignee,created_at,url
To understand the available fields you can get the raw json output and inspect it:
pdh inc ls -e -o raw
Rules
PDH support custom scripting applied to your incidents list. These rules are in fact any type of executable you can run on your machine.
pdh inc ls -e --rules-path ./rules/ --rules
The apply subcommand will call the listed executable/script passing along a json to stdin with the incident information. The called script can apply any type of checks/sideffects and output another json to stout to answer the call.
Even though rules can be written in any language it's very straightforward using python:
Rules: an example
An example rule can be written in python with the following lines
#!/usr/bin/env python3
from pdh.rules import rule
@rule
def main(alerts, pagerduty, Filters, Transformations):
# From the given input extract only incidents with the word "EC2" in title
filtered = Filters.apply(alerts, filters=[
Filters.not_regexp("service.summary", ".*My Service.*"),
Filters.regexp("title", ".*EC2.*")
])
# # auto acknowledge all previously filtered incidents
pagerduty.incidents.ack(filtered)
return filtered
if __name__ == "__main__":
main() # type: ignore
pdh inc ls -e --rules-path ./rules/ --rules
┏━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
┃ script ┃ Q1LNI5LNM7RZ2C ┃ Q1C5KG41H0SZAM ┃
┡━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┩
│ ./a.py │ AWS Health Event: us-east-1 EC2 : AWS_EC2_INSTANCE_STOP_SCHEDULED │ AWS Health Event: us-east-1 EC2 : AWS_EC2_INSTANCE_STORE_DRIVE_PERFORMANCE_DEGRADED │
└────────┴────────────────────────────────────────────────────────────────────┴──────────────────────────────────────────────────────────────────────────────────────┘
The default output is table with one line for each script run and with one column per each element in the returned object
Rules: more examples
see rules for more
Requirements
- Taskfile
- Python >=3.10
- Docker
Contributing
First of all you need to setup the dev environment, using Taskfile:
task setup
This will create a python virtualenv and install pre-commit and poetry in your system if you lack them.
License
This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. See for more details.
Metadata
Release files for pdh 0.8.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| pdh-0.8.0.tar.gz | 31.0 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| pdh-0.8.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 66.3 kB
Release files / pdh-0.8.0.tar.gz
| Download URL | pdh-0.8.0.tar.gz |
|---|---|
| Size | 31.0 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
46bceda4d04a789b63a7d94a6af174207081de562a1b7b3652f3380faffb8fa8
|
|
BLAKE2b-256 checksum How to use checksums |
ffdf95230192b14ae594f018a0dd16bdac92977b9f1108f97fa7eeee07dd0671
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.0.1 CPython/3.12.8
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Jan 3, 2025.
Transparency logRelease files / pdh-0.8.0-py3-none-any.whl
| Download URL | pdh-0.8.0-py3-none-any.whl |
|---|---|
| Size | 35.3 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
7a96b28d0e4831b987b4ca0e46267b59e3aac8182ba67b9eb3c101cfcd3508cf
|
|
BLAKE2b-256 checksum How to use checksums |
2b6b6dd0fbd4f5a3758430721b5685e7e6fbefb20ae724e1b65eefed35aa696e
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.0.1 CPython/3.12.8
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Jan 3, 2025.
Transparency log