Built a Grafana dashboard to pull data directly from the Snyk API. Tired of their UI for tracking trends. This gives me a single pane for pipeline health alongside build times and deployment status.
Key panels:
* Open issues by severity over time (line chart)
* Current high/critical vulnerabilities by project (bar chart)
* Test pass/fail rate per pipeline run
* License compliance issues count
Uses a simple Python collector script running on a schedule. Fetches data from `/v1/orgs/{orgId}/projects` and the reports API. Pushes to InfluxDB.
Example query for project list:
```python
# Simplified snippet
response = requests.get(
f"{SNYK_API_URL}/v1/org/{ORG_ID}/projects",
headers={"Authorization": f"token {API_TOKEN}"}
)
projects = response.json().get('projects', [])
```
Dashboard is configurable by Snyk organization and project tags. Sits next to my Jenkins and artifact metrics. Now I can correlate vulnerability spikes with dependency updates.
Correlating vulnerability spikes with dependency updates is the right call. We built something similar but added PR age as a metric.
Watch your API rate limits if you scale this across many projects. The /v1/orgs/{orgId}/projects endpoint gets heavy. We had to implement pagination and a longer cache.
Prove it with a benchmark.
Absolutely, pagination is a must. We hit the same wall with about 500 projects. The Snyk API's default page size is 10, so you're looking at dozens of sequential calls. It really adds up.
We ended up using a `while` loop with the `next` link from the `links` field in the response body. It's more reliable than counting offsets. Something like this:
```python
projects = []
url = f"{BASE_URL}/v1/org/{ORG_ID}/projects"
while url:
resp = requests.get(url, headers=headers)
data = resp.json()
projects.extend(data.get('projects', []))
url = data.get('links', {}).get('next')
```
Also, +1 on the longer cache. Our collector runs hourly, but we cache project metadata for 24 hours since it changes so slowly. Saves a ton of calls.
Clean code, happy life
That's the correct way to handle their pagination. The `links.next` approach is the only reliable one because some of their other endpoints, like the reports API, use cursor-based pagination that doesn't follow a simple offset pattern.
One caveat on the 24-hour project cache: it breaks down if you have ephemeral projects from CI pipelines. We've had to implement a two-layer cache - permanent projects cached for a day, but any project with a name matching our CI naming pattern gets a much shorter TTL, like 15 minutes. Otherwise, you miss new scan results for hours.
Also, watch the response size on that loop. With 500 projects, each `projects` array in the response is huge. We started seeing timeouts and had to implement exponential backoff and retry on 502/504 errors, which happen more often than you'd think during their peak times.
Measure twice, migrate once.