-
Notifications
You must be signed in to change notification settings - Fork 4.9k
feat(devops): add out-of-the-box prometheus metrics and grafana observability stack #9344
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: preview
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,118 @@ | ||
| { | ||
| "annotations": { | ||
| "list": [ | ||
| { | ||
| "builtIn": 1, | ||
| "datasource": { | ||
| "type": "datasource", | ||
| "uid": "grafana" | ||
| }, | ||
| "enable": true, | ||
| "hide": true, | ||
| "name": "Annotations & Alerts", | ||
| "type": "dashboard" | ||
| } | ||
| ] | ||
| }, | ||
| "editable": true, | ||
| "fiscalYearStartMonth": 0, | ||
| "graphTooltip": 0, | ||
| "id": 1, | ||
| "links": [], | ||
| "liveNow": false, | ||
| "panels": [ | ||
| { | ||
| "collapsed": false, | ||
| "gridPos": { | ||
| "h": 8, | ||
| "w": 12, | ||
| "x": 0, | ||
| "y": 0 | ||
| }, | ||
| "id": 1, | ||
| "title": "API Request Rate (per Second)", | ||
| "type": "timeseries", | ||
| "datasource": { | ||
| "type": "prometheus", | ||
| "uid": "Prometheus" | ||
| }, | ||
| "targets": [ | ||
| { | ||
| "datasource": { | ||
| "type": "prometheus", | ||
| "uid": "Prometheus" | ||
| }, | ||
| "editorMode": "code", | ||
| "expr": "sum(rate(django_http_requests_total_by_view_transport_method_total[5m])) by (view)", | ||
| "legendFormat": "{{view}}", | ||
| "range": true, | ||
| "refId": "A" | ||
| } | ||
| ], | ||
| "fieldConfig": { | ||
| "defaults": { | ||
| "custom": { | ||
| "drawStyle": "line", | ||
| "lineInterpolation": "smooth" | ||
| }, | ||
| "unit": "reqps" | ||
| } | ||
| } | ||
| }, | ||
| { | ||
| "collapsed": false, | ||
| "gridPos": { | ||
| "h": 8, | ||
| "w": 12, | ||
| "x": 12, | ||
| "y": 0 | ||
| }, | ||
| "id": 2, | ||
| "title": "Average API Latency (seconds)", | ||
| "type": "timeseries", | ||
| "datasource": { | ||
| "type": "prometheus", | ||
| "uid": "Prometheus" | ||
| }, | ||
| "targets": [ | ||
| { | ||
| "datasource": { | ||
| "type": "prometheus", | ||
| "uid": "Prometheus" | ||
| }, | ||
| "editorMode": "code", | ||
| "expr": "sum(rate(django_http_requests_latency_seconds_by_view_method_sum[5m])) by (view) / sum(rate(django_http_requests_latency_seconds_by_view_method_count[5m])) by (view)", | ||
| "legendFormat": "{{view}}", | ||
| "range": true, | ||
| "refId": "A" | ||
| } | ||
| ], | ||
| "fieldConfig": { | ||
| "defaults": { | ||
| "custom": { | ||
| "drawStyle": "line", | ||
| "lineInterpolation": "smooth" | ||
| }, | ||
| "unit": "s" | ||
| } | ||
| } | ||
| } | ||
| ], | ||
| "refresh": "5s", | ||
| "schemaVersion": 38, | ||
| "style": "dark", | ||
| "tags": [], | ||
| "templating": { | ||
| "list": [] | ||
| }, | ||
| "time": { | ||
| "from": "now-15m", | ||
| "to": "now" | ||
| }, | ||
| "timepicker": {}, | ||
| "timezone": "", | ||
| "title": "Plane API Analytics", | ||
| "uid": "plane-api-analytics", | ||
| "version": 1, | ||
| "weekStart": "" | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,11 @@ | ||
| apiVersion: 1 | ||
|
|
||
| providers: | ||
| - name: 'Plane Dashboards' | ||
| orgId: 1 | ||
| folder: '' | ||
| type: file | ||
| disableDeletion: false | ||
| editable: true | ||
| options: | ||
| path: /var/lib/grafana/dashboards |
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,8 @@ | ||||||||||||||||||||||||||||
| apiVersion: 1 | ||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
| datasources: | ||||||||||||||||||||||||||||
| - name: Prometheus | ||||||||||||||||||||||||||||
| type: prometheus | ||||||||||||||||||||||||||||
| access: proxy | ||||||||||||||||||||||||||||
| url: http://prometheus:9090 | ||||||||||||||||||||||||||||
| isDefault: true | ||||||||||||||||||||||||||||
|
Comment on lines
+3
to
+8
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win 🧩 Analysis chain🏁 Script executed: #!/bin/bash
set -euo pipefail
printf '\n== datasource.yml ==\n'
cat -n deployments/grafana/provisioning/datasources/datasource.yml
printf '\n== dashboard refs ==\n'
python3 - <<'PY'
import json, re, pathlib
p = pathlib.Path('deployments/grafana/dashboards/plane-dashboard.json')
data = json.loads(p.read_text())
text = p.read_text()
# Find occurrences of datasource references around uid/name keys
for key in ['uid', 'name']:
print(f"\nOccurrences of '{key}':")
for m in re.finditer(rf'"{key}"\s*:\s*"[^"]+"', text):
start = max(0, m.start()-120)
end = min(len(text), m.end()+120)
snippet = text[start:end]
print(snippet.replace('\n', ' '))
PYRepository: makeplane/plane Length of output: 2195 🌐 Web query:
💡 Result: When you omit the Citations:
🌐 Web query:
💡 Result: When provisioning data sources in Grafana, you can explicitly define a unique identifier (UID) in your configuration file to ensure it remains consistent across different environments [1][2][3]. This UID is critical for dashboards, as they must reference this identifier to correctly link to the intended data source [4][5]. To provision a data source with a specific UID, include the uid field in your YAML provisioning file: apiVersion: 1 datasources: - name: My Prometheus type: prometheus uid: my-prometheus-uid # Explicitly defined UID access: proxy url: http://prometheus:9090 In your dashboard JSON files, the datasource field can reference this data source in two primary ways: 1. By Name: You can use the name of the data source as a string (e.g., "datasource": "My Prometheus") [5]. 2. By UID: You can use an object that specifies the type and the UID, or simply the UID string depending on your Grafana version and specific configuration, to ensure the dashboard points to the exact data source regardless of its display name [4][5]. To avoid issues where dashboards fail to find the data source (especially during migrations or when moving between systems), it is best practice to always provide a static, explicit UID in your data source provisioning YAML rather than allowing Grafana to generate a random one [1][5]. If you are exporting dashboards for use across different systems, ensuring the data source UID is identical in both environments prevents broken references [6][2]. Note that in recent versions of Grafana, there has been a move toward enforcing stricter UID formats to improve consistency [7]. Always verify that your defined UID is unique within your Grafana organization [2]. Citations:
Add a stable 🔧 Proposed fix datasources:
- name: Prometheus
type: prometheus
access: proxy
url: http://prometheus:9090
+ uid: Prometheus
isDefault: true📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,9 @@ | ||
| global: | ||
| scrape_interval: 5s | ||
| evaluation_interval: 5s | ||
|
|
||
| scrape_configs: | ||
| - job_name: "plane-api" | ||
| metrics_path: "/metrics" | ||
| static_configs: | ||
| - targets: ["api:8000"] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🔒 Security & Privacy | 🟡 Minor | ⚡ Quick win
🧩 Analysis chain
🏁 Script executed:
Repository: makeplane/plane
Length of output: 153
🏁 Script executed:
Repository: makeplane/plane
Length of output: 21403
🏁 Script executed:
Repository: makeplane/plane
Length of output: 11941
/metricsis exposed without auth inapps/api/plane/urls.py:23.django_prometheus.urlsis mounted at the root, anddocker-compose-local.ymlpublishesapi:8000to the host, so these internal request/DB metrics are reachable by anyone who can hit that port. Lock/metricsto the internal network or add proxy auth if the path is forwarded in production.🤖 Prompt for AI Agents