Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions cmd/burnless/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ func main() {
rootCmd.AddCommand(cli.NewValidateCmd())
rootCmd.AddCommand(cli.NewToilCmd())
rootCmd.AddCommand(cli.NewDiffCmd())
rootCmd.AddCommand(cli.NewStatusCmd())

if err := rootCmd.Execute(); err != nil {
os.Exit(1)
Expand Down
254 changes: 235 additions & 19 deletions docs/getting-started.md
Original file line number Diff line number Diff line change
@@ -1,39 +1,255 @@
# Getting Started with Burnless

## Prerequisites
- Go 1.24+
- A running Prometheus instance
- kubectl (optional, for Kubernetes)
Burnless is an open-source SRE platform that brings reliability engineering under version control. Instead of SLOs living in a Datadog dashboard and runbooks rotting in Confluence, everything lives in a single `sre.yaml` file — reviewed via pull requests, validated in CI, and eventually enforced automatically.

## Install
**Phase 1 (available now):** Track the manual toil your team absorbs every week, convert it to dollar cost, and produce reports that give managers the data to justify automation investment.

**Phase 2 (in development):** A burn rate agent watches Prometheus continuously and triggers remediation runbooks automatically — scaling replicas, rolling back deploys — before a human alert even fires.

---

## 1. Install

**Homebrew (macOS/Linux):**
```bash
brew install --cask Custos-com/tap/burnless
```

**curl one-liner:**
```bash
curl -fsSL https://raw.githubusercontent.com/Custos-com/Burnless/main/install.sh | sh
```

**Go install:**
```bash
go install github.com/Custos-com/Burnless/cmd/burnless@latest
```

Verify your install:
```bash
git clone https://github.com/Custos-com/Burnless.git
cd burnless
make build
burnless version
burnless --help
```

## Create your first sre.yaml
---

## 2. Create your first sre.yaml

Run the interactive wizard:
```bash
burnless init
```

You'll be prompted for six things:
```
Let's create your sre.yaml

? Service name: payments-api
? Team: platform-engineering
? SLO availability target %: 99.9
? SLO window: 30d
? Prometheus metric name: http_requests_total
? Slack channel for alerts: #sre-incidents
? On-call provider: pagerduty
```

This generates a complete `sre.yaml`. Here's what each section means:

```yaml
service: my-api
service: payments-api
team: platform-engineering

# SLOs — what "good" looks like for this service.
# 99.9% availability over 30 days = ~43 minutes of allowed downtime per month.
slos:
- name: availability
target: 99.9%
target: 99.9
window: 30d
indicator:
metric: http_requests_total
good_filter: status!~"5.."

# Error budget alerts — when to fire and what to do.
# 14.4x burn rate = you will exhaust your monthly error budget in 2 days. Critical.
# 6x burn rate = you will exhaust it in 5 days. Warning.
error_budget:
burn_rate_alerts:
- rate: 14.4x
severity: critical
notify:
slack: "#incidents"
- severity: critical
rate: 14.4
window: 1h
remediate: scale-up
- severity: warning
rate: 6
window: 6h
remediate: restart-pods

# Runbooks — what to do when an alert fires.
# auto: agent executes immediately. semi-auto: agent asks for Slack approval first.
runbooks:
scale-up:
mode: auto
steps:
- kubectl scale deploy/payments-api --replicas=+2
restart-pods:
mode: semi-auto
steps:
- kubectl rollout restart deploy/payments-api

oncall:
provider: pagerduty
escalation_minutes: 10
notify_slack: '#sre-incidents'

dashboards:
provider: grafana
auto_generate: true
```

---

## 3. Validate it

```bash
burnless validate
```

Success:
```
✓ sre.yaml is valid
service: payments-api
1 SLO(s) defined
2 burn rate alert(s) configured
2 runbook(s) defined
```

To see what a failure looks like, set `target: 150` in your sre.yaml and run validate again:
```
✗ sre.yaml is invalid
slo[0] target must be between 0 and 100, got 150.00
```

## Run Burnless
Fix it and validate again. **Use this in CI** — `burnless validate` exits 1 on failure, so it blocks merges with broken configs:
```yaml
# .github/workflows/ci.yml
- run: burnless validate
```

---

## 4. Preview what apply will do

```bash
burnless validate # check your sre.yaml is valid
burnless status # see current SLO status
burnless agent # start the agent daemon
burnless diff
```

```
Would create:
SLO: availability target=99.9% window=30d
Alert: critical @ 14.4x burn rate -> scale-up
Alert: warning @ 6.0x burn rate -> restart-pods
Runbook: scale-up (auto, 1 step)
Runbook: restart-pods (semi-auto, 1 step)

Nothing is deployed yet. Run 'burnless apply' to deploy.
```

`burnless diff` with no arguments previews what `apply` would create. Nothing is deployed — it is a dry run.

---

## 5. Check your config summary

```bash
burnless status
```

```
Service: payments-api
Team: platform-engineering

SLOs configured:
-----------------------------------------------------
availability target 99.9% window 30d

Error budget alerts:
-----------------------------------------------------
critical 14.4x burn rate window 1h -> scale-up
warning 6.0x burn rate window 6h -> restart-pods

Runbooks:
-----------------------------------------------------
scale-up mode: auto 1 step(s)
restart-pods mode: semi-auto 1 step(s)

On-call: pagerduty (escalation: 10 min)
Dashboard: grafana (auto-generate: true)

Run 'burnless apply' to deploy this config.
```

---

## 6. Track your first toil event

Toil is manual, repetitive work that interrupts your week and could be automated. Log it as it happens:

```bash
burnless toil log --service payments-api --task manual-rollback --duration 45m --automatable
burnless toil log --service payments-api --task restart-pods --duration 20m --automatable
burnless toil log --service payments-api --task update-config --duration 30m
```

Flags:
- `--service` — which service caused the toil
- `--task` — short name for the task
- `--duration` — how long it took (e.g. `45m`, `2h`)
- `--automatable` — flag if this could be automated (used for priority scoring)

---

## 7. Generate your first report

```bash
burnless toil report --month 2026-06
```

```
Toil Report — June 2026
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Total toil hours: 4h 35m
Estimated cost: $110.58
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Top tasks by automation priority:

HIGH manual-rollback 3x 2h 15m $54.37
HIGH restart-pods 2x 40m $16.10
MED update-config 1x 30m $12.10
```

**What "estimated cost" means:** Burnless uses a $180,000/year fully-loaded SRE salary as the basis. Each hour of toil = ~$90. This gives your manager a concrete number, not just hours.

**What HIGH/MED/LOW means:** Tasks flagged `--automatable` score higher. Tasks that recur frequently score higher. Use this table in your next 1:1 — it makes the case for automation investment without needing to build a spreadsheet.

---

## 8. Export for your manager

```bash
burnless toil export --output june-toil.csv
```

Opens cleanly in Excel or Google Sheets. Share it directly with your manager or attach it to your quarterly review.

---

## What's next

- **Add `sre.yaml` to your Git repo** — treat it like infrastructure code, review changes via PRs
- **Add `burnless validate` to your CI/CD pipeline** — catch broken configs before they merge
- **Coming soon: `burnless apply`** — deploy your SLO config to Prometheus and Grafana automatically
- **Coming soon: burn rate agent** — watches Prometheus every 60 seconds and triggers your runbooks before a human alert fires

**Links:**
- [GitHub](https://github.com/Custos-com/Burnless)
- [Open an issue](https://github.com/Custos-com/Burnless/issues)
- [Contributing guide](../CONTRIBUTING.md)
7 changes: 7 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,16 @@ go 1.24
require gopkg.in/yaml.v3 v3.0.1

require (
github.com/AlecAivazis/survey/v2 v2.3.7 // indirect
github.com/inconshreveable/mousetrap v1.1.0 // indirect
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 // indirect
github.com/mattn/go-colorable v0.1.2 // indirect
github.com/mattn/go-isatty v0.0.8 // indirect
github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b // indirect
github.com/spf13/cobra v1.10.2 // indirect
github.com/spf13/pflag v1.0.9 // indirect
go.etcd.io/bbolt v1.4.3 // indirect
golang.org/x/sys v0.29.0 // indirect
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211 // indirect
golang.org/x/text v0.4.0 // indirect
)
46 changes: 46 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
@@ -1,17 +1,63 @@
github.com/AlecAivazis/survey/v2 v2.3.7 h1:6I/u8FvytdGsgonrYsVn2t8t4QiRnh6QSTqkkhIiSjQ=
github.com/AlecAivazis/survey/v2 v2.3.7/go.mod h1:xUTIdE4KCOIjsBAE1JYsUPoCqYdZ1reCfTwbto0Fduo=
github.com/Netflix/go-expect v0.0.0-20220104043353-73e0943537d2/go.mod h1:HBCaDeC1lPdgDeDbhX8XFpy1jqjK0IBG8W5K+xYqA0w=
github.com/cpuguy83/go-md2man/v2 v2.0.6/go.mod h1:oOW0eioCTA6cOiMLiUPZOpcVxMig6NIQQ7OS05n1F4g=
github.com/creack/pty v1.1.17/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr4O4=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/hinshun/vt10x v0.0.0-20220119200601-820417d04eec/go.mod h1:Q48J4R4DvxnHolD5P8pOtXigYlRuPLGl6moFx3ulM68=
github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8=
github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 h1:Z9n2FFNUXsshfwJMBgNA0RU6/i7WVaAegv3PtuIHPMs=
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51/go.mod h1:CzGEWj7cYgsdH8dAjBGEr58BoE7ScuLd+fwFZ44+/x8=
github.com/mattn/go-colorable v0.1.2 h1:/bC9yWikZXAL9uJdulbSfyVNIR3n3trXl+v8+1sx8mU=
github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE=
github.com/mattn/go-isatty v0.0.8 h1:HLtExJ+uU2HOZ+wI0Tt5DtUDrx8yhUqDcp7fYERX4CE=
github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b h1:j7+1HpAFS1zy5+Q4qx1fWh90gTKwiN4QCGoY9TWyyO4=
github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b/go.mod h1:01TrycV0kFyexm33Z7vhZRXopbI8J3TDReVlkTgMUxE=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/spf13/cobra v1.10.2 h1:DMTTonx5m65Ic0GOoRY2c16WCbHxOOw6xxezuLaBpcU=
github.com/spf13/cobra v1.10.2/go.mod h1:7C1pvHqHw5A4vrJfjNwvOdzYu0Gml16OCs2GRiTUUS4=
github.com/spf13/pflag v1.0.9 h1:9exaQaMOCwffKiiiYk6/BndUBv+iRViNW+4lEMi0PvY=
github.com/spf13/pflag v1.0.9/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
go.etcd.io/bbolt v1.4.3 h1:dEadXpI6G79deX5prL3QRNP6JB8UxVkqo4UPnHaNXJo=
go.etcd.io/bbolt v1.4.3/go.mod h1:tKQlpPaYCVFctUIgFKFnAlvbmB3tpy1vkTnDWohtc0E=
go.yaml.in/yaml/v3 v3.0.4/go.mod h1:DhzuOOF2ATzADvBadXxruRBLzYTpT36CKvDb3+aBEFg=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.29.0 h1:TPYlXGxvx1MGTn2GiZDhnjPA9wZzZeGKHHmKhHYvgaU=
golang.org/x/sys v0.29.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211 h1:JGgROgKl9N8DuW20oFS5gxc+lE67/N3FcwmBPMe7ArY=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
golang.org/x/text v0.4.0 h1:BrVqGRd7+k1DiOgtnFvAkoQEWQvBc25ouMJM6429SFg=
golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
Loading
Loading