bring back files after directory rename
This commit is contained in:
30
01_standalone_grafana/README.md
Normal file
30
01_standalone_grafana/README.md
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
Example 1 — Grafana by itself
|
||||||
|
===
|
||||||
|
|
||||||
|
No additional resources are needed to run this example.
|
||||||
|
Execute the following command to start Grafana:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
docker run -i -t --rm -p 3000:3000 grafana/grafana:12.0.2
|
||||||
|
```
|
||||||
|
|
||||||
|
You can then access Grafana at `http://localhost:3000` with the default credentials (username: `admin`, password: `admin`).
|
||||||
|
|
||||||
|
##### Custom login credentials
|
||||||
|
|
||||||
|
```bash
|
||||||
|
docker run -i -t --rm -p 3000:3000 \
|
||||||
|
-e GF_SECURITY_ADMIN_USER=a \
|
||||||
|
-e GF_SECURITY_ADMIN_PASSWORD=a \
|
||||||
|
grafana/grafana:12.0.2
|
||||||
|
```
|
||||||
|
|
||||||
|
##### Custom login credentials and preinstalled plugin
|
||||||
|
|
||||||
|
```bash
|
||||||
|
docker run -i -t --rm -p 3000:3000 \
|
||||||
|
-e GF_SECURITY_ADMIN_USER=a \
|
||||||
|
-e GF_SECURITY_ADMIN_PASSWORD=a \
|
||||||
|
-e "GF_INSTALL_PLUGINS=grafana-sentry-datasource" \
|
||||||
|
grafana/grafana:12.0.2
|
||||||
|
```
|
6
02_metrics_with_prometheus/README.md
Normal file
6
02_metrics_with_prometheus/README.md
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
Example 2 — Grafana with Prometheus (metrics data)
|
||||||
|
===
|
||||||
|
|
||||||
|
```bash
|
||||||
|
docker-compose up
|
||||||
|
```
|
56
02_metrics_with_prometheus/docker-compose.yml
Normal file
56
02_metrics_with_prometheus/docker-compose.yml
Normal file
@@ -0,0 +1,56 @@
|
|||||||
|
services:
|
||||||
|
prometheus:
|
||||||
|
image: prom/prometheus:latest
|
||||||
|
container_name: prometheus
|
||||||
|
ports:
|
||||||
|
- "9090:9090"
|
||||||
|
volumes:
|
||||||
|
- ./prometheus/prometheus.yml:/etc/prometheus/prometheus.yml
|
||||||
|
- prometheus_data:/prometheus
|
||||||
|
command:
|
||||||
|
- '--config.file=/etc/prometheus/prometheus.yml'
|
||||||
|
- '--storage.tsdb.path=/prometheus'
|
||||||
|
- '--web.console.libraries=/etc/prometheus/console_libraries'
|
||||||
|
- '--web.console.templates=/etc/prometheus/consoles'
|
||||||
|
- '--storage.tsdb.retention.time=200h'
|
||||||
|
- '--web.enable-lifecycle'
|
||||||
|
networks:
|
||||||
|
- grafana_network
|
||||||
|
|
||||||
|
grafana:
|
||||||
|
image: grafana/grafana:12.0.2
|
||||||
|
container_name: grafana
|
||||||
|
ports:
|
||||||
|
- "3000:3000"
|
||||||
|
environment:
|
||||||
|
- GF_AUTH_ANONYMOUS_ENABLED=true
|
||||||
|
- GF_AUTH_ANONYMOUS_ORG_ROLE=Admin
|
||||||
|
- GF_AUTH_DISABLE_LOGIN_FORM=true
|
||||||
|
- GF_USERS_ALLOW_SIGN_UP=false
|
||||||
|
volumes:
|
||||||
|
- grafana_data:/var/lib/grafana
|
||||||
|
- ./grafana/provisioning:/etc/grafana/provisioning
|
||||||
|
depends_on:
|
||||||
|
- prometheus
|
||||||
|
networks:
|
||||||
|
- grafana_network
|
||||||
|
|
||||||
|
# Example microservice with metrics endpoint
|
||||||
|
metrics_generator:
|
||||||
|
image: prom/node-exporter:latest
|
||||||
|
container_name: example_metrics
|
||||||
|
ports:
|
||||||
|
- "9100:9100"
|
||||||
|
networks:
|
||||||
|
- grafana_network
|
||||||
|
|
||||||
|
volumes:
|
||||||
|
grafana_data:
|
||||||
|
driver: local
|
||||||
|
prometheus_data:
|
||||||
|
driver: local
|
||||||
|
|
||||||
|
networks:
|
||||||
|
grafana_network:
|
||||||
|
driver: bridge
|
||||||
|
|
@@ -0,0 +1,10 @@
|
|||||||
|
apiVersion: 1
|
||||||
|
providers:
|
||||||
|
- name: 'default'
|
||||||
|
orgId: 1
|
||||||
|
folder: ''
|
||||||
|
type: file
|
||||||
|
disableDeletion: false
|
||||||
|
updateIntervalSeconds: 10
|
||||||
|
options:
|
||||||
|
path: /etc/grafana/provisioning/dashboards
|
@@ -0,0 +1,418 @@
|
|||||||
|
{
|
||||||
|
"annotations": {
|
||||||
|
"list": [
|
||||||
|
{
|
||||||
|
"builtIn": 1,
|
||||||
|
"datasource": {
|
||||||
|
"type": "grafana",
|
||||||
|
"uid": "-- Grafana --"
|
||||||
|
},
|
||||||
|
"enable": true,
|
||||||
|
"hide": true,
|
||||||
|
"iconColor": "rgba(0, 211, 255, 1)",
|
||||||
|
"name": "Annotations & Alerts",
|
||||||
|
"type": "dashboard"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"editable": true,
|
||||||
|
"fiscalYearStartMonth": 0,
|
||||||
|
"graphTooltip": 0,
|
||||||
|
"id": 1,
|
||||||
|
"links": [],
|
||||||
|
"panels": [
|
||||||
|
{
|
||||||
|
"datasource": {
|
||||||
|
"type": "prometheus",
|
||||||
|
"uid": "PBFA97CFB590B2093"
|
||||||
|
},
|
||||||
|
"fieldConfig": {
|
||||||
|
"defaults": {
|
||||||
|
"color": {
|
||||||
|
"mode": "palette-classic"
|
||||||
|
},
|
||||||
|
"custom": {
|
||||||
|
"axisBorderShow": false,
|
||||||
|
"axisCenteredZero": false,
|
||||||
|
"axisColorMode": "text",
|
||||||
|
"axisLabel": "",
|
||||||
|
"axisPlacement": "auto",
|
||||||
|
"barAlignment": 0,
|
||||||
|
"barWidthFactor": 0.6,
|
||||||
|
"drawStyle": "line",
|
||||||
|
"fillOpacity": 0,
|
||||||
|
"gradientMode": "none",
|
||||||
|
"hideFrom": {
|
||||||
|
"legend": false,
|
||||||
|
"tooltip": false,
|
||||||
|
"viz": false
|
||||||
|
},
|
||||||
|
"insertNulls": false,
|
||||||
|
"lineInterpolation": "stepBefore",
|
||||||
|
"lineWidth": 4,
|
||||||
|
"pointSize": 5,
|
||||||
|
"scaleDistribution": {
|
||||||
|
"type": "linear"
|
||||||
|
},
|
||||||
|
"showPoints": "auto",
|
||||||
|
"spanNulls": false,
|
||||||
|
"stacking": {
|
||||||
|
"group": "A",
|
||||||
|
"mode": "none"
|
||||||
|
},
|
||||||
|
"thresholdsStyle": {
|
||||||
|
"mode": "off"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"mappings": [],
|
||||||
|
"thresholds": {
|
||||||
|
"mode": "absolute",
|
||||||
|
"steps": [
|
||||||
|
{
|
||||||
|
"color": "green"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"color": "red",
|
||||||
|
"value": 80
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"overrides": []
|
||||||
|
},
|
||||||
|
"gridPos": {
|
||||||
|
"h": 8,
|
||||||
|
"w": 12,
|
||||||
|
"x": 0,
|
||||||
|
"y": 0
|
||||||
|
},
|
||||||
|
"id": 2,
|
||||||
|
"options": {
|
||||||
|
"legend": {
|
||||||
|
"calcs": [],
|
||||||
|
"displayMode": "list",
|
||||||
|
"placement": "bottom",
|
||||||
|
"showLegend": true
|
||||||
|
},
|
||||||
|
"tooltip": {
|
||||||
|
"hideZeros": false,
|
||||||
|
"mode": "single",
|
||||||
|
"sort": "none"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"pluginVersion": "12.0.2",
|
||||||
|
"targets": [
|
||||||
|
{
|
||||||
|
"disableTextWrap": false,
|
||||||
|
"editorMode": "builder",
|
||||||
|
"expr": "go_memstats_heap_objects",
|
||||||
|
"fullMetaSearch": false,
|
||||||
|
"includeNullMetadata": true,
|
||||||
|
"legendFormat": "__auto",
|
||||||
|
"range": true,
|
||||||
|
"refId": "A",
|
||||||
|
"useBackend": false
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"title": "Heap objects",
|
||||||
|
"type": "timeseries"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"datasource": {
|
||||||
|
"type": "prometheus",
|
||||||
|
"uid": "PBFA97CFB590B2093"
|
||||||
|
},
|
||||||
|
"fieldConfig": {
|
||||||
|
"defaults": {
|
||||||
|
"color": {
|
||||||
|
"mode": "palette-classic"
|
||||||
|
},
|
||||||
|
"custom": {
|
||||||
|
"axisBorderShow": false,
|
||||||
|
"axisCenteredZero": false,
|
||||||
|
"axisColorMode": "text",
|
||||||
|
"axisLabel": "",
|
||||||
|
"axisPlacement": "auto",
|
||||||
|
"barAlignment": 0,
|
||||||
|
"barWidthFactor": 0.6,
|
||||||
|
"drawStyle": "line",
|
||||||
|
"fillOpacity": 0,
|
||||||
|
"gradientMode": "none",
|
||||||
|
"hideFrom": {
|
||||||
|
"legend": false,
|
||||||
|
"tooltip": false,
|
||||||
|
"viz": false
|
||||||
|
},
|
||||||
|
"insertNulls": false,
|
||||||
|
"lineInterpolation": "linear",
|
||||||
|
"lineWidth": 1,
|
||||||
|
"pointSize": 5,
|
||||||
|
"scaleDistribution": {
|
||||||
|
"type": "linear"
|
||||||
|
},
|
||||||
|
"showPoints": "auto",
|
||||||
|
"spanNulls": false,
|
||||||
|
"stacking": {
|
||||||
|
"group": "A",
|
||||||
|
"mode": "none"
|
||||||
|
},
|
||||||
|
"thresholdsStyle": {
|
||||||
|
"mode": "off"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"mappings": [],
|
||||||
|
"thresholds": {
|
||||||
|
"mode": "absolute",
|
||||||
|
"steps": [
|
||||||
|
{
|
||||||
|
"color": "green"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"color": "red",
|
||||||
|
"value": 80
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"overrides": []
|
||||||
|
},
|
||||||
|
"gridPos": {
|
||||||
|
"h": 17,
|
||||||
|
"w": 12,
|
||||||
|
"x": 12,
|
||||||
|
"y": 0
|
||||||
|
},
|
||||||
|
"id": 4,
|
||||||
|
"options": {
|
||||||
|
"legend": {
|
||||||
|
"calcs": [],
|
||||||
|
"displayMode": "list",
|
||||||
|
"placement": "bottom",
|
||||||
|
"showLegend": true
|
||||||
|
},
|
||||||
|
"tooltip": {
|
||||||
|
"hideZeros": false,
|
||||||
|
"mode": "single",
|
||||||
|
"sort": "none"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"pluginVersion": "12.0.2",
|
||||||
|
"targets": [
|
||||||
|
{
|
||||||
|
"disableTextWrap": false,
|
||||||
|
"editorMode": "builder",
|
||||||
|
"expr": "node_load1",
|
||||||
|
"fullMetaSearch": false,
|
||||||
|
"includeNullMetadata": true,
|
||||||
|
"legendFormat": "__auto",
|
||||||
|
"range": true,
|
||||||
|
"refId": "A",
|
||||||
|
"useBackend": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"datasource": {
|
||||||
|
"type": "prometheus",
|
||||||
|
"uid": "PBFA97CFB590B2093"
|
||||||
|
},
|
||||||
|
"disableTextWrap": false,
|
||||||
|
"editorMode": "builder",
|
||||||
|
"expr": "node_load5",
|
||||||
|
"fullMetaSearch": false,
|
||||||
|
"hide": false,
|
||||||
|
"includeNullMetadata": true,
|
||||||
|
"instant": false,
|
||||||
|
"legendFormat": "__auto",
|
||||||
|
"range": true,
|
||||||
|
"refId": "B",
|
||||||
|
"useBackend": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"datasource": {
|
||||||
|
"type": "prometheus",
|
||||||
|
"uid": "PBFA97CFB590B2093"
|
||||||
|
},
|
||||||
|
"disableTextWrap": false,
|
||||||
|
"editorMode": "builder",
|
||||||
|
"expr": "node_load15",
|
||||||
|
"fullMetaSearch": false,
|
||||||
|
"hide": false,
|
||||||
|
"includeNullMetadata": true,
|
||||||
|
"instant": false,
|
||||||
|
"legendFormat": "__auto",
|
||||||
|
"range": true,
|
||||||
|
"refId": "C",
|
||||||
|
"useBackend": false
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"title": "Load avg",
|
||||||
|
"type": "timeseries"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"datasource": {
|
||||||
|
"type": "prometheus",
|
||||||
|
"uid": "PBFA97CFB590B2093"
|
||||||
|
},
|
||||||
|
"fieldConfig": {
|
||||||
|
"defaults": {
|
||||||
|
"color": {
|
||||||
|
"mode": "thresholds"
|
||||||
|
},
|
||||||
|
"mappings": [],
|
||||||
|
"thresholds": {
|
||||||
|
"mode": "absolute",
|
||||||
|
"steps": [
|
||||||
|
{
|
||||||
|
"color": "green"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"color": "red",
|
||||||
|
"value": 80
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"overrides": []
|
||||||
|
},
|
||||||
|
"gridPos": {
|
||||||
|
"h": 9,
|
||||||
|
"w": 8,
|
||||||
|
"x": 0,
|
||||||
|
"y": 8
|
||||||
|
},
|
||||||
|
"id": 1,
|
||||||
|
"options": {
|
||||||
|
"minVizHeight": 75,
|
||||||
|
"minVizWidth": 75,
|
||||||
|
"orientation": "auto",
|
||||||
|
"reduceOptions": {
|
||||||
|
"calcs": [
|
||||||
|
"lastNotNull"
|
||||||
|
],
|
||||||
|
"fields": "",
|
||||||
|
"values": false
|
||||||
|
},
|
||||||
|
"showThresholdLabels": false,
|
||||||
|
"showThresholdMarkers": true,
|
||||||
|
"sizing": "auto"
|
||||||
|
},
|
||||||
|
"pluginVersion": "12.0.2",
|
||||||
|
"targets": [
|
||||||
|
{
|
||||||
|
"datasource": {
|
||||||
|
"type": "prometheus",
|
||||||
|
"uid": "PBFA97CFB590B2093"
|
||||||
|
},
|
||||||
|
"disableTextWrap": false,
|
||||||
|
"editorMode": "builder",
|
||||||
|
"expr": "go_goroutines",
|
||||||
|
"fullMetaSearch": false,
|
||||||
|
"includeNullMetadata": true,
|
||||||
|
"legendFormat": "__auto",
|
||||||
|
"range": true,
|
||||||
|
"refId": "A",
|
||||||
|
"useBackend": false
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"title": "Go routines",
|
||||||
|
"type": "gauge"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"datasource": {
|
||||||
|
"type": "prometheus",
|
||||||
|
"uid": "PBFA97CFB590B2093"
|
||||||
|
},
|
||||||
|
"fieldConfig": {
|
||||||
|
"defaults": {
|
||||||
|
"color": {
|
||||||
|
"mode": "thresholds"
|
||||||
|
},
|
||||||
|
"mappings": [],
|
||||||
|
"thresholds": {
|
||||||
|
"mode": "absolute",
|
||||||
|
"steps": [
|
||||||
|
{
|
||||||
|
"color": "green"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"color": "red",
|
||||||
|
"value": 80
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"overrides": [
|
||||||
|
{
|
||||||
|
"__systemRef": "hideSeriesFrom",
|
||||||
|
"matcher": {
|
||||||
|
"id": "byNames",
|
||||||
|
"options": {
|
||||||
|
"mode": "exclude",
|
||||||
|
"names": [
|
||||||
|
"{__name__=\"node_nfs_packets_total\", instance=\"metrics_generator:9100\", job=\"metrics_generator\", protocol=\"tcp\"}"
|
||||||
|
],
|
||||||
|
"prefix": "All except:",
|
||||||
|
"readOnly": true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"properties": []
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"gridPos": {
|
||||||
|
"h": 9,
|
||||||
|
"w": 4,
|
||||||
|
"x": 8,
|
||||||
|
"y": 8
|
||||||
|
},
|
||||||
|
"id": 3,
|
||||||
|
"options": {
|
||||||
|
"colorMode": "value",
|
||||||
|
"graphMode": "area",
|
||||||
|
"justifyMode": "auto",
|
||||||
|
"orientation": "auto",
|
||||||
|
"percentChangeColorMode": "standard",
|
||||||
|
"reduceOptions": {
|
||||||
|
"calcs": [
|
||||||
|
"lastNotNull"
|
||||||
|
],
|
||||||
|
"fields": "",
|
||||||
|
"values": false
|
||||||
|
},
|
||||||
|
"showPercentChange": false,
|
||||||
|
"textMode": "auto",
|
||||||
|
"wideLayout": true
|
||||||
|
},
|
||||||
|
"pluginVersion": "12.0.2",
|
||||||
|
"targets": [
|
||||||
|
{
|
||||||
|
"disableTextWrap": false,
|
||||||
|
"editorMode": "builder",
|
||||||
|
"expr": "process_open_fds",
|
||||||
|
"fullMetaSearch": false,
|
||||||
|
"includeNullMetadata": true,
|
||||||
|
"legendFormat": "__auto",
|
||||||
|
"range": true,
|
||||||
|
"refId": "A",
|
||||||
|
"useBackend": false
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"title": "Open file descriptors",
|
||||||
|
"type": "stat"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"preload": false,
|
||||||
|
"schemaVersion": 41,
|
||||||
|
"tags": [],
|
||||||
|
"templating": {
|
||||||
|
"list": []
|
||||||
|
},
|
||||||
|
"time": {
|
||||||
|
"from": "now-5m",
|
||||||
|
"to": "now"
|
||||||
|
},
|
||||||
|
"timepicker": {},
|
||||||
|
"timezone": "browser",
|
||||||
|
"title": "Example dashboard with system metrics",
|
||||||
|
"uid": "2e48b630-2206-4876-b606-2132a21d1934",
|
||||||
|
"version": 5
|
||||||
|
}
|
@@ -0,0 +1,8 @@
|
|||||||
|
apiVersion: 1
|
||||||
|
|
||||||
|
datasources:
|
||||||
|
- name: Prometheus
|
||||||
|
type: prometheus
|
||||||
|
access: proxy
|
||||||
|
url: http://prometheus:9090
|
||||||
|
isDefault: true
|
14
02_metrics_with_prometheus/prometheus/prometheus.yml
Normal file
14
02_metrics_with_prometheus/prometheus/prometheus.yml
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
global:
|
||||||
|
scrape_interval: 15s
|
||||||
|
evaluation_interval: 15s
|
||||||
|
|
||||||
|
scrape_configs:
|
||||||
|
# - job_name: 'prometheus'
|
||||||
|
# static_configs:
|
||||||
|
# - targets: ['localhost:9090']
|
||||||
|
|
||||||
|
- job_name: 'metrics_generator'
|
||||||
|
static_configs:
|
||||||
|
- targets: ['metrics_generator:9100']
|
||||||
|
scrape_interval: 2s
|
||||||
|
scrape_timeout: 1s
|
6
03_logs_with_loki/README.md
Normal file
6
03_logs_with_loki/README.md
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
Example 3 — Grafana with Loki (logs data)
|
||||||
|
===
|
||||||
|
|
||||||
|
```bash
|
||||||
|
docker-compose up
|
||||||
|
```
|
55
03_logs_with_loki/docker-compose.yml
Normal file
55
03_logs_with_loki/docker-compose.yml
Normal file
@@ -0,0 +1,55 @@
|
|||||||
|
services:
|
||||||
|
|
||||||
|
grafana:
|
||||||
|
image: grafana/grafana:12.0.2
|
||||||
|
container_name: grafana
|
||||||
|
ports:
|
||||||
|
- "3000:3000"
|
||||||
|
environment:
|
||||||
|
- GF_AUTH_ANONYMOUS_ENABLED=true
|
||||||
|
- GF_AUTH_ANONYMOUS_ORG_ROLE=Admin
|
||||||
|
- GF_AUTH_DISABLE_LOGIN_FORM=true
|
||||||
|
- GF_USERS_ALLOW_SIGN_UP=false
|
||||||
|
volumes:
|
||||||
|
- grafana_data:/var/lib/grafana
|
||||||
|
- ./grafana/provisioning:/etc/grafana/provisioning
|
||||||
|
depends_on:
|
||||||
|
- loki
|
||||||
|
networks:
|
||||||
|
- grafana_network
|
||||||
|
|
||||||
|
loki:
|
||||||
|
image: grafana/loki:latest
|
||||||
|
container_name: loki
|
||||||
|
ports:
|
||||||
|
- "3100:3100"
|
||||||
|
volumes:
|
||||||
|
- ./loki:/etc/loki
|
||||||
|
- loki_data:/loki
|
||||||
|
command: -config.file=/etc/loki/loki.yml
|
||||||
|
networks:
|
||||||
|
- grafana_network
|
||||||
|
|
||||||
|
|
||||||
|
log-generator:
|
||||||
|
build:
|
||||||
|
context: ./log-generator
|
||||||
|
dockerfile: Dockerfile
|
||||||
|
container_name: log-generator
|
||||||
|
networks:
|
||||||
|
- grafana_network
|
||||||
|
depends_on:
|
||||||
|
- loki
|
||||||
|
|
||||||
|
volumes:
|
||||||
|
grafana_data:
|
||||||
|
driver: local
|
||||||
|
prometheus_data:
|
||||||
|
driver: local
|
||||||
|
loki_data:
|
||||||
|
driver: local
|
||||||
|
|
||||||
|
networks:
|
||||||
|
grafana_network:
|
||||||
|
driver: bridge
|
||||||
|
|
@@ -0,0 +1,10 @@
|
|||||||
|
apiVersion: 1
|
||||||
|
providers:
|
||||||
|
- name: 'default'
|
||||||
|
orgId: 1
|
||||||
|
folder: ''
|
||||||
|
type: file
|
||||||
|
disableDeletion: false
|
||||||
|
updateIntervalSeconds: 10
|
||||||
|
options:
|
||||||
|
path: /etc/grafana/provisioning/dashboards
|
@@ -0,0 +1,274 @@
|
|||||||
|
{
|
||||||
|
"annotations": {
|
||||||
|
"list": [
|
||||||
|
{
|
||||||
|
"builtIn": 1,
|
||||||
|
"datasource": {
|
||||||
|
"type": "grafana",
|
||||||
|
"uid": "-- Grafana --"
|
||||||
|
},
|
||||||
|
"enable": true,
|
||||||
|
"hide": true,
|
||||||
|
"iconColor": "rgba(0, 211, 255, 1)",
|
||||||
|
"name": "Annotations & Alerts",
|
||||||
|
"type": "dashboard"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"editable": true,
|
||||||
|
"fiscalYearStartMonth": 0,
|
||||||
|
"graphTooltip": 0,
|
||||||
|
"id": 1,
|
||||||
|
"links": [],
|
||||||
|
"panels": [
|
||||||
|
{
|
||||||
|
"datasource": {
|
||||||
|
"type": "loki",
|
||||||
|
"uid": "P8E80F9AEF21F6940"
|
||||||
|
},
|
||||||
|
"fieldConfig": {
|
||||||
|
"defaults": {
|
||||||
|
"color": {
|
||||||
|
"mode": "palette-classic"
|
||||||
|
},
|
||||||
|
"custom": {
|
||||||
|
"hideFrom": {
|
||||||
|
"legend": false,
|
||||||
|
"tooltip": false,
|
||||||
|
"viz": false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"mappings": []
|
||||||
|
},
|
||||||
|
"overrides": []
|
||||||
|
},
|
||||||
|
"gridPos": {
|
||||||
|
"h": 29,
|
||||||
|
"w": 4,
|
||||||
|
"x": 0,
|
||||||
|
"y": 0
|
||||||
|
},
|
||||||
|
"id": 3,
|
||||||
|
"options": {
|
||||||
|
"legend": {
|
||||||
|
"displayMode": "list",
|
||||||
|
"placement": "bottom",
|
||||||
|
"showLegend": true
|
||||||
|
},
|
||||||
|
"pieType": "pie",
|
||||||
|
"reduceOptions": {
|
||||||
|
"calcs": [
|
||||||
|
"lastNotNull"
|
||||||
|
],
|
||||||
|
"fields": "",
|
||||||
|
"values": false
|
||||||
|
},
|
||||||
|
"tooltip": {
|
||||||
|
"hideZeros": false,
|
||||||
|
"mode": "single",
|
||||||
|
"sort": "none"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"pluginVersion": "12.0.2",
|
||||||
|
"targets": [
|
||||||
|
{
|
||||||
|
"direction": "backward",
|
||||||
|
"editorMode": "code",
|
||||||
|
"expr": "sum by(service_name) (rate({job=\"log-generator\"} [$__auto]))",
|
||||||
|
"queryType": "range",
|
||||||
|
"refId": "A"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"title": "Logs per service",
|
||||||
|
"type": "piechart"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"datasource": {
|
||||||
|
"type": "loki",
|
||||||
|
"uid": "P8E80F9AEF21F6940"
|
||||||
|
},
|
||||||
|
"fieldConfig": {
|
||||||
|
"defaults": {
|
||||||
|
"color": {
|
||||||
|
"mode": "thresholds"
|
||||||
|
},
|
||||||
|
"custom": {
|
||||||
|
"align": "auto",
|
||||||
|
"cellOptions": {
|
||||||
|
"type": "auto"
|
||||||
|
},
|
||||||
|
"filterable": true,
|
||||||
|
"inspect": false
|
||||||
|
},
|
||||||
|
"mappings": [],
|
||||||
|
"thresholds": {
|
||||||
|
"mode": "absolute",
|
||||||
|
"steps": [
|
||||||
|
{
|
||||||
|
"color": "green"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"color": "red",
|
||||||
|
"value": 80
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"overrides": []
|
||||||
|
},
|
||||||
|
"gridPos": {
|
||||||
|
"h": 13,
|
||||||
|
"w": 20,
|
||||||
|
"x": 4,
|
||||||
|
"y": 0
|
||||||
|
},
|
||||||
|
"id": 1,
|
||||||
|
"options": {
|
||||||
|
"cellHeight": "md",
|
||||||
|
"footer": {
|
||||||
|
"countRows": false,
|
||||||
|
"enablePagination": true,
|
||||||
|
"fields": "",
|
||||||
|
"reducer": [
|
||||||
|
"sum"
|
||||||
|
],
|
||||||
|
"show": false
|
||||||
|
},
|
||||||
|
"showHeader": true
|
||||||
|
},
|
||||||
|
"pluginVersion": "12.0.2",
|
||||||
|
"targets": [
|
||||||
|
{
|
||||||
|
"datasource": {
|
||||||
|
"type": "loki",
|
||||||
|
"uid": "P8E80F9AEF21F6940"
|
||||||
|
},
|
||||||
|
"direction": "backward",
|
||||||
|
"editorMode": "builder",
|
||||||
|
"expr": "{severity=\"error\"}",
|
||||||
|
"queryType": "range",
|
||||||
|
"refId": "A"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"title": "Errors",
|
||||||
|
"type": "table"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"datasource": {
|
||||||
|
"type": "loki",
|
||||||
|
"uid": "P8E80F9AEF21F6940"
|
||||||
|
},
|
||||||
|
"fieldConfig": {
|
||||||
|
"defaults": {
|
||||||
|
"color": {
|
||||||
|
"mode": "thresholds"
|
||||||
|
},
|
||||||
|
"mappings": [],
|
||||||
|
"thresholds": {
|
||||||
|
"mode": "absolute",
|
||||||
|
"steps": [
|
||||||
|
{
|
||||||
|
"color": "green"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"color": "red",
|
||||||
|
"value": 80
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"overrides": []
|
||||||
|
},
|
||||||
|
"gridPos": {
|
||||||
|
"h": 7,
|
||||||
|
"w": 4,
|
||||||
|
"x": 4,
|
||||||
|
"y": 13
|
||||||
|
},
|
||||||
|
"id": 2,
|
||||||
|
"options": {
|
||||||
|
"minVizHeight": 75,
|
||||||
|
"minVizWidth": 75,
|
||||||
|
"orientation": "auto",
|
||||||
|
"reduceOptions": {
|
||||||
|
"calcs": [
|
||||||
|
"lastNotNull"
|
||||||
|
],
|
||||||
|
"fields": "",
|
||||||
|
"values": false
|
||||||
|
},
|
||||||
|
"showThresholdLabels": false,
|
||||||
|
"showThresholdMarkers": true,
|
||||||
|
"sizing": "auto"
|
||||||
|
},
|
||||||
|
"pluginVersion": "12.0.2",
|
||||||
|
"targets": [
|
||||||
|
{
|
||||||
|
"direction": "backward",
|
||||||
|
"editorMode": "builder",
|
||||||
|
"expr": "sum by(severity) (rate({severity=\"critical\"} [$__auto]))",
|
||||||
|
"queryType": "range",
|
||||||
|
"refId": "A"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"title": "Error log rate",
|
||||||
|
"type": "gauge"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"datasource": {
|
||||||
|
"type": "loki",
|
||||||
|
"uid": "P8E80F9AEF21F6940"
|
||||||
|
},
|
||||||
|
"fieldConfig": {
|
||||||
|
"defaults": {},
|
||||||
|
"overrides": []
|
||||||
|
},
|
||||||
|
"gridPos": {
|
||||||
|
"h": 16,
|
||||||
|
"w": 16,
|
||||||
|
"x": 8,
|
||||||
|
"y": 13
|
||||||
|
},
|
||||||
|
"id": 4,
|
||||||
|
"options": {
|
||||||
|
"dedupStrategy": "none",
|
||||||
|
"enableInfiniteScrolling": false,
|
||||||
|
"enableLogDetails": true,
|
||||||
|
"prettifyLogMessage": false,
|
||||||
|
"showCommonLabels": false,
|
||||||
|
"showLabels": false,
|
||||||
|
"showTime": true,
|
||||||
|
"sortOrder": "Descending",
|
||||||
|
"wrapLogMessage": false
|
||||||
|
},
|
||||||
|
"pluginVersion": "12.0.2",
|
||||||
|
"targets": [
|
||||||
|
{
|
||||||
|
"direction": "backward",
|
||||||
|
"editorMode": "builder",
|
||||||
|
"expr": "{job=\"log-generator\"}",
|
||||||
|
"queryType": "range",
|
||||||
|
"refId": "A"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"title": "Log tail",
|
||||||
|
"transparent": true,
|
||||||
|
"type": "logs"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"preload": false,
|
||||||
|
"schemaVersion": 41,
|
||||||
|
"tags": [],
|
||||||
|
"templating": {
|
||||||
|
"list": []
|
||||||
|
},
|
||||||
|
"time": {
|
||||||
|
"from": "now-6h",
|
||||||
|
"to": "now"
|
||||||
|
},
|
||||||
|
"timepicker": {},
|
||||||
|
"timezone": "browser",
|
||||||
|
"title": "Simple logs dashboard",
|
||||||
|
"uid": "a86bbd08-0669-4d22-9c03-f9eacfa00788",
|
||||||
|
"version": 6
|
||||||
|
}
|
@@ -0,0 +1,8 @@
|
|||||||
|
apiVersion: 1
|
||||||
|
|
||||||
|
datasources:
|
||||||
|
- name: Loki
|
||||||
|
type: loki
|
||||||
|
access: proxy
|
||||||
|
url: http://loki:3100
|
||||||
|
isDefault: false
|
11
03_logs_with_loki/log-generator/Dockerfile
Normal file
11
03_logs_with_loki/log-generator/Dockerfile
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
FROM golang:alpine AS builder
|
||||||
|
|
||||||
|
ADD logger.go /logger.go
|
||||||
|
|
||||||
|
RUN go build -o /service /logger.go
|
||||||
|
|
||||||
|
FROM scratch
|
||||||
|
|
||||||
|
COPY --from=builder /service .
|
||||||
|
|
||||||
|
ENTRYPOINT [ "/service" ]
|
76
03_logs_with_loki/log-generator/logger.go
Normal file
76
03_logs_with_loki/log-generator/logger.go
Normal file
@@ -0,0 +1,76 @@
|
|||||||
|
// Copyright Quesma, licensed under the Elastic License 2.0.
|
||||||
|
// SPDX-License-Identifier: Elastic-2.0
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
"log"
|
||||||
|
"math/rand"
|
||||||
|
"net/http"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
const url = "http://loki:3100/loki/api/v1/push"
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
hostNames := []string{"zeus", "cassandra", "hercules",
|
||||||
|
"oracle", "athena", "jupiter", "poseidon", "hades", "artemis", "apollo", "demeter",
|
||||||
|
"dionysus", "hephaestus", "hermes", "hestia", "iris", "nemesis", "pan", "persephone", "prometheus", "selen"}
|
||||||
|
|
||||||
|
serviceNames := []string{"frontend", "backend", "database", "cache", "queue", "monitoring", "loadbalancer", "proxy",
|
||||||
|
"storage", "auth", "api", "web", "worker", "scheduler", "cron", "admin", "service", "gateway", "service", "service", "service"}
|
||||||
|
|
||||||
|
sourceNames := []string{"kubernetes", "ubuntu", "debian", "centos", "redhat", "fedora", "arch", "gentoo", "alpine", "suse",
|
||||||
|
"rhel", "coreos", "docker", "rancher", "vmware", "xen", "hyperv", "openstack", "aws", "gcp", "azure", "digitalocean"}
|
||||||
|
|
||||||
|
severityNames := []string{"info", "info", "info", "info", "info", "info", "warning", "error", "critical", "debug", "debug", "debug"}
|
||||||
|
|
||||||
|
messageNames := []string{"User logged in", "User logged out", "User created", "User deleted", "User updated",
|
||||||
|
"User password changed", "User password reset", "User password reset requested", "User password reset failed"}
|
||||||
|
|
||||||
|
for {
|
||||||
|
time.Sleep(time.Duration(1000+rand.Intn(2000)) * time.Millisecond)
|
||||||
|
|
||||||
|
timestamp := time.Now()
|
||||||
|
severity := severityNames[rand.Intn(len(severityNames))]
|
||||||
|
source := sourceNames[rand.Intn(len(sourceNames))]
|
||||||
|
serviceName := serviceNames[rand.Intn(len(serviceNames))]
|
||||||
|
hostName := hostNames[rand.Intn(len(hostNames))]
|
||||||
|
message := messageNames[rand.Intn(len(messageNames))]
|
||||||
|
|
||||||
|
// Create Loki push request format
|
||||||
|
logEntry := map[string]interface{}{
|
||||||
|
"streams": []map[string]interface{}{
|
||||||
|
{
|
||||||
|
"stream": map[string]string{
|
||||||
|
"severity": severity,
|
||||||
|
"source": source,
|
||||||
|
"service_name": serviceName,
|
||||||
|
"host_name": hostName,
|
||||||
|
"job": "log-generator",
|
||||||
|
},
|
||||||
|
"values": [][]string{
|
||||||
|
{
|
||||||
|
fmt.Sprintf("%d", timestamp.UnixNano()),
|
||||||
|
message,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
body, err := json.Marshal(logEntry)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
resp, err := http.Post(url, "application/json", bytes.NewBuffer(body))
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
resp.Body.Close()
|
||||||
|
}
|
||||||
|
}
|
42
03_logs_with_loki/loki/loki.yml
Normal file
42
03_logs_with_loki/loki/loki.yml
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
auth_enabled: false
|
||||||
|
|
||||||
|
server:
|
||||||
|
http_listen_port: 3100
|
||||||
|
|
||||||
|
ingester:
|
||||||
|
lifecycler:
|
||||||
|
address: 127.0.0.1
|
||||||
|
ring:
|
||||||
|
kvstore:
|
||||||
|
store: inmemory
|
||||||
|
replication_factor: 1
|
||||||
|
final_sleep: 0s
|
||||||
|
chunk_idle_period: 5m
|
||||||
|
chunk_retain_period: 30s
|
||||||
|
wal:
|
||||||
|
dir: /loki/wal
|
||||||
|
|
||||||
|
schema_config:
|
||||||
|
configs:
|
||||||
|
- from: 2020-10-24
|
||||||
|
store: tsdb
|
||||||
|
object_store: filesystem
|
||||||
|
schema: v13
|
||||||
|
index:
|
||||||
|
prefix: index_
|
||||||
|
period: 24h
|
||||||
|
|
||||||
|
storage_config:
|
||||||
|
tsdb_shipper:
|
||||||
|
active_index_directory: /loki/tsdb-shipper-active
|
||||||
|
cache_location: /loki/tsdb-shipper-cache
|
||||||
|
filesystem:
|
||||||
|
directory: /loki/chunks
|
||||||
|
|
||||||
|
limits_config:
|
||||||
|
reject_old_samples: true
|
||||||
|
reject_old_samples_max_age: 168h
|
||||||
|
|
||||||
|
compactor:
|
||||||
|
working_directory: /loki/tsdb-shipper-compactor
|
||||||
|
|
6
04_traces_with_tempo/README.md
Normal file
6
04_traces_with_tempo/README.md
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
Example 4 — Grafana with Tempo (distributed tracing data)
|
||||||
|
===
|
||||||
|
|
||||||
|
```bash
|
||||||
|
docker-compose up
|
||||||
|
```
|
56
04_traces_with_tempo/docker-compose.yml
Normal file
56
04_traces_with_tempo/docker-compose.yml
Normal file
@@ -0,0 +1,56 @@
|
|||||||
|
services:
|
||||||
|
|
||||||
|
grafana:
|
||||||
|
image: grafana/grafana:12.0.2
|
||||||
|
ports:
|
||||||
|
- "3000:3000"
|
||||||
|
environment:
|
||||||
|
- GF_AUTH_ANONYMOUS_ENABLED=true
|
||||||
|
- GF_AUTH_ANONYMOUS_ORG_ROLE=Admin
|
||||||
|
- GF_AUTH_DISABLE_LOGIN_FORM=true
|
||||||
|
- GF_USERS_ALLOW_SIGN_UP=false
|
||||||
|
volumes:
|
||||||
|
- grafana_data:/var/lib/grafana
|
||||||
|
- ./grafana/provisioning:/etc/grafana/provisioning
|
||||||
|
depends_on:
|
||||||
|
- tempo
|
||||||
|
networks:
|
||||||
|
- grafana_network
|
||||||
|
|
||||||
|
tempo:
|
||||||
|
image: grafana/tempo:latest
|
||||||
|
command: ["-config.file=/etc/tempo.yaml"]
|
||||||
|
volumes:
|
||||||
|
- ./tempo/tempo.yml:/etc/tempo.yaml
|
||||||
|
- ./tempo/data:/var/tempo
|
||||||
|
ports:
|
||||||
|
- "14268:14268" # jaeger ingest
|
||||||
|
- "3200:3200" # tempo
|
||||||
|
- "9095:9095" # tempo grpc
|
||||||
|
- "4317:4317" # otlp grpc
|
||||||
|
- "4318:4318" # otlp http
|
||||||
|
- "9411:9411" # zipkin
|
||||||
|
networks:
|
||||||
|
- grafana_network
|
||||||
|
|
||||||
|
|
||||||
|
k6-tracing:
|
||||||
|
image: ghcr.io/grafana/xk6-client-tracing:v0.0.7
|
||||||
|
environment:
|
||||||
|
- ENDPOINT=tempo:4317
|
||||||
|
restart: always
|
||||||
|
depends_on:
|
||||||
|
- tempo
|
||||||
|
networks:
|
||||||
|
- grafana_network
|
||||||
|
|
||||||
|
volumes:
|
||||||
|
grafana_data:
|
||||||
|
driver: local
|
||||||
|
prometheus_data:
|
||||||
|
driver: local
|
||||||
|
|
||||||
|
networks:
|
||||||
|
grafana_network:
|
||||||
|
driver: bridge
|
||||||
|
|
@@ -0,0 +1,10 @@
|
|||||||
|
apiVersion: 1
|
||||||
|
providers:
|
||||||
|
- name: 'default'
|
||||||
|
orgId: 1
|
||||||
|
folder: ''
|
||||||
|
type: file
|
||||||
|
disableDeletion: false
|
||||||
|
updateIntervalSeconds: 10
|
||||||
|
options:
|
||||||
|
path: /etc/grafana/provisioning/dashboards
|
@@ -0,0 +1,8 @@
|
|||||||
|
apiVersion: 1
|
||||||
|
|
||||||
|
datasources:
|
||||||
|
- name: Tempo
|
||||||
|
type: tempo
|
||||||
|
access: proxy
|
||||||
|
url: http://tempo:3200
|
||||||
|
isDefault: false
|
91
04_traces_with_tempo/tempo/tempo.yml
Normal file
91
04_traces_with_tempo/tempo/tempo.yml
Normal file
@@ -0,0 +1,91 @@
|
|||||||
|
stream_over_http_enabled: true
|
||||||
|
server:
|
||||||
|
http_listen_port: 3200
|
||||||
|
log_level: info
|
||||||
|
|
||||||
|
cache:
|
||||||
|
background:
|
||||||
|
writeback_goroutines: 5
|
||||||
|
|
||||||
|
query_frontend:
|
||||||
|
search:
|
||||||
|
duration_slo: 5s
|
||||||
|
throughput_bytes_slo: 1.073741824e+09
|
||||||
|
metadata_slo:
|
||||||
|
duration_slo: 5s
|
||||||
|
throughput_bytes_slo: 1.073741824e+09
|
||||||
|
trace_by_id:
|
||||||
|
duration_slo: 100ms
|
||||||
|
metrics:
|
||||||
|
max_duration: 200h # maximum duration of a metrics query, increase for local setups
|
||||||
|
query_backend_after: 5m
|
||||||
|
duration_slo: 5s
|
||||||
|
throughput_bytes_slo: 1.073741824e+09
|
||||||
|
|
||||||
|
distributor:
|
||||||
|
usage:
|
||||||
|
cost_attribution:
|
||||||
|
enabled: true
|
||||||
|
receivers: # this configuration will listen on all ports and protocols that tempo is capable of.
|
||||||
|
jaeger: # the receives all come from the OpenTelemetry collector. more configuration information can
|
||||||
|
protocols: # be found there: https://github.com/open-telemetry/opentelemetry-collector/tree/main/receiver
|
||||||
|
thrift_http: #
|
||||||
|
endpoint: "tempo:14268" # for a production deployment you should only enable the receivers you need!
|
||||||
|
grpc:
|
||||||
|
endpoint: "tempo:14250"
|
||||||
|
thrift_binary:
|
||||||
|
endpoint: "tempo:6832"
|
||||||
|
thrift_compact:
|
||||||
|
endpoint: "tempo:6831"
|
||||||
|
zipkin:
|
||||||
|
endpoint: "tempo:9411"
|
||||||
|
otlp:
|
||||||
|
protocols:
|
||||||
|
grpc:
|
||||||
|
endpoint: "tempo:4317"
|
||||||
|
http:
|
||||||
|
endpoint: "tempo:4318"
|
||||||
|
opencensus:
|
||||||
|
endpoint: "tempo:55678"
|
||||||
|
|
||||||
|
ingester:
|
||||||
|
max_block_duration: 5m # cut the headblock when this much time passes. this is being set for demo purposes and should probably be left alone normally
|
||||||
|
|
||||||
|
compactor:
|
||||||
|
compaction:
|
||||||
|
block_retention: 720h # overall Tempo trace retention. set for demo purposes
|
||||||
|
|
||||||
|
metrics_generator:
|
||||||
|
registry:
|
||||||
|
external_labels:
|
||||||
|
source: tempo
|
||||||
|
cluster: docker-compose
|
||||||
|
storage:
|
||||||
|
path: /var/tempo/generator/wal
|
||||||
|
remote_write:
|
||||||
|
- url: http://prometheus:9090/api/v1/write
|
||||||
|
send_exemplars: true
|
||||||
|
traces_storage:
|
||||||
|
path: /var/tempo/generator/traces
|
||||||
|
processor:
|
||||||
|
local_blocks:
|
||||||
|
filter_server_spans: false
|
||||||
|
flush_to_storage: true
|
||||||
|
|
||||||
|
storage:
|
||||||
|
trace:
|
||||||
|
cache: ""
|
||||||
|
backend: local # backend configuration to use
|
||||||
|
wal:
|
||||||
|
path: /var/tempo/wal # where to store the wal locally
|
||||||
|
local:
|
||||||
|
path: /var/tempo/blocks
|
||||||
|
|
||||||
|
overrides:
|
||||||
|
defaults:
|
||||||
|
cost_attribution:
|
||||||
|
dimensions:
|
||||||
|
service.name: ""
|
||||||
|
metrics_generator:
|
||||||
|
processors: [service-graphs, span-metrics, local-blocks] # enables metrics generator
|
||||||
|
generate_native_histograms: both
|
6
05_profiling_with_pyroscope/README.md
Normal file
6
05_profiling_with_pyroscope/README.md
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
Example 5 — Grafana with Pyroscope (profiling data)
|
||||||
|
===
|
||||||
|
|
||||||
|
```bash
|
||||||
|
docker-compose up
|
||||||
|
```
|
44
05_profiling_with_pyroscope/docker-compose.yml
Normal file
44
05_profiling_with_pyroscope/docker-compose.yml
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
services:
|
||||||
|
|
||||||
|
grafana:
|
||||||
|
image: grafana/grafana:12.0.2
|
||||||
|
ports:
|
||||||
|
- "3000:3000"
|
||||||
|
environment:
|
||||||
|
- GF_INSTALL_PLUGINS=grafana-pyroscope-app
|
||||||
|
- GF_AUTH_ANONYMOUS_ENABLED=true
|
||||||
|
- GF_AUTH_ANONYMOUS_ORG_ROLE=Admin
|
||||||
|
- GF_AUTH_DISABLE_LOGIN_FORM=true
|
||||||
|
- GF_USERS_ALLOW_SIGN_UP=false
|
||||||
|
volumes:
|
||||||
|
- grafana_data:/var/lib/grafana
|
||||||
|
- ./grafana/provisioning:/etc/grafana/provisioning
|
||||||
|
depends_on:
|
||||||
|
- pyroscope
|
||||||
|
networks:
|
||||||
|
- grafana_network
|
||||||
|
|
||||||
|
pyroscope:
|
||||||
|
image: grafana/pyroscope:latest
|
||||||
|
ports:
|
||||||
|
- 4040:4040
|
||||||
|
networks:
|
||||||
|
- grafana_network
|
||||||
|
|
||||||
|
sample_app:
|
||||||
|
build:
|
||||||
|
context: ./sample_app
|
||||||
|
dockerfile: Dockerfile
|
||||||
|
environment:
|
||||||
|
- PYROSCOPE_SERVER_ADDRESS=http://pyroscope:4040
|
||||||
|
networks:
|
||||||
|
- grafana_network
|
||||||
|
|
||||||
|
volumes:
|
||||||
|
grafana_data:
|
||||||
|
driver: local
|
||||||
|
|
||||||
|
networks:
|
||||||
|
grafana_network:
|
||||||
|
driver: bridge
|
||||||
|
|
@@ -0,0 +1,10 @@
|
|||||||
|
apiVersion: 1
|
||||||
|
providers:
|
||||||
|
- name: 'default'
|
||||||
|
orgId: 1
|
||||||
|
folder: ''
|
||||||
|
type: file
|
||||||
|
disableDeletion: false
|
||||||
|
updateIntervalSeconds: 10
|
||||||
|
options:
|
||||||
|
path: /etc/grafana/provisioning/dashboards
|
13
05_profiling_with_pyroscope/sample_app/Dockerfile
Normal file
13
05_profiling_with_pyroscope/sample_app/Dockerfile
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
FROM golang:1.23.11
|
||||||
|
|
||||||
|
WORKDIR /go/src/app
|
||||||
|
|
||||||
|
COPY main.go go.mod go.sum ./
|
||||||
|
|
||||||
|
RUN go get -d ./
|
||||||
|
RUN go build -o main .
|
||||||
|
|
||||||
|
RUN adduser --disabled-password --gecos --quiet pyroscope
|
||||||
|
USER pyroscope
|
||||||
|
|
||||||
|
CMD ["./main"]
|
10
05_profiling_with_pyroscope/sample_app/go.mod
Normal file
10
05_profiling_with_pyroscope/sample_app/go.mod
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
module sample_app
|
||||||
|
|
||||||
|
go 1.23.0
|
||||||
|
|
||||||
|
require github.com/grafana/pyroscope-go v1.2.4
|
||||||
|
|
||||||
|
require (
|
||||||
|
github.com/grafana/pyroscope-go/godeltaprof v0.1.8 // indirect
|
||||||
|
github.com/klauspost/compress v1.17.11 // indirect
|
||||||
|
)
|
6
05_profiling_with_pyroscope/sample_app/go.sum
Normal file
6
05_profiling_with_pyroscope/sample_app/go.sum
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
github.com/grafana/pyroscope-go v1.2.4 h1:B22GMXz+O0nWLatxLuaP7o7L9dvP0clLvIpmeEQQM0Q=
|
||||||
|
github.com/grafana/pyroscope-go v1.2.4/go.mod h1:zzT9QXQAp2Iz2ZdS216UiV8y9uXJYQiGE1q8v1FyhqU=
|
||||||
|
github.com/grafana/pyroscope-go/godeltaprof v0.1.8 h1:iwOtYXeeVSAeYefJNaxDytgjKtUuKQbJqgAIjlnicKg=
|
||||||
|
github.com/grafana/pyroscope-go/godeltaprof v0.1.8/go.mod h1:2+l7K7twW49Ct4wFluZD3tZ6e0SjanjcUUBPVD/UuGU=
|
||||||
|
github.com/klauspost/compress v1.17.11 h1:In6xLpyWOi1+C7tXUUWv2ot1QvBjxevKAaI6IXrJmUc=
|
||||||
|
github.com/klauspost/compress v1.17.11/go.mod h1:pMDklpSncoRMuLFrf1W9Ss9KT+0rH90U12bZKk7uwG0=
|
288
05_profiling_with_pyroscope/sample_app/main.go
Normal file
288
05_profiling_with_pyroscope/sample_app/main.go
Normal file
@@ -0,0 +1,288 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"crypto/rand"
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
"log"
|
||||||
|
"math"
|
||||||
|
"os"
|
||||||
|
"runtime/pprof"
|
||||||
|
"sort"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
"sync"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/grafana/pyroscope-go"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Simulate different types of workloads
|
||||||
|
|
||||||
|
//go:noinline
|
||||||
|
func cpuIntensiveWork(n int) {
|
||||||
|
// CPU-bound work with actual computation
|
||||||
|
sum := 0.0
|
||||||
|
for i := 0; i < n; i++ {
|
||||||
|
sum += math.Sqrt(float64(i)) * math.Sin(float64(i))
|
||||||
|
}
|
||||||
|
_ = sum // prevent optimization
|
||||||
|
}
|
||||||
|
|
||||||
|
//go:noinline
|
||||||
|
func memoryIntensiveWork(size int) {
|
||||||
|
// Memory allocation and manipulation
|
||||||
|
data := make([][]byte, size)
|
||||||
|
for i := range data {
|
||||||
|
data[i] = make([]byte, 1024)
|
||||||
|
rand.Read(data[i])
|
||||||
|
}
|
||||||
|
|
||||||
|
// Some processing to prevent optimization
|
||||||
|
for i := range data {
|
||||||
|
for j := range data[i] {
|
||||||
|
data[i][j] = byte((int(data[i][j]) + i + j) % 256)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//go:noinline
|
||||||
|
func recursiveFibonacci(n int) int {
|
||||||
|
if n <= 1 {
|
||||||
|
return n
|
||||||
|
}
|
||||||
|
return recursiveFibonacci(n-1) + recursiveFibonacci(n-2)
|
||||||
|
}
|
||||||
|
|
||||||
|
//go:noinline
|
||||||
|
func recursiveFactorial(n int) int {
|
||||||
|
if n <= 1 {
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
return n * recursiveFactorial(n-1)
|
||||||
|
}
|
||||||
|
|
||||||
|
//go:noinline
|
||||||
|
func stringProcessing(iterations int) {
|
||||||
|
var builder strings.Builder
|
||||||
|
for i := 0; i < iterations; i++ {
|
||||||
|
builder.WriteString(fmt.Sprintf("iteration-%d-", i))
|
||||||
|
}
|
||||||
|
|
||||||
|
// JSON marshaling/unmarshaling
|
||||||
|
data := map[string]interface{}{
|
||||||
|
"message": builder.String(),
|
||||||
|
"count": iterations,
|
||||||
|
"nested": map[string]int{
|
||||||
|
"a": 1, "b": 2, "c": 3,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
jsonData, _ := json.Marshal(data)
|
||||||
|
var result map[string]interface{}
|
||||||
|
json.Unmarshal(jsonData, &result)
|
||||||
|
}
|
||||||
|
|
||||||
|
//go:noinline
|
||||||
|
func sortingWork(size int) {
|
||||||
|
// Create random data
|
||||||
|
data := make([]int, size)
|
||||||
|
for i := range data {
|
||||||
|
data[i] = int(time.Now().UnixNano()) % 10000
|
||||||
|
}
|
||||||
|
|
||||||
|
// Multiple sorting algorithms
|
||||||
|
data1 := make([]int, len(data))
|
||||||
|
copy(data1, data)
|
||||||
|
sort.Ints(data1)
|
||||||
|
|
||||||
|
// Bubble sort for smaller datasets (inefficient by design)
|
||||||
|
if size <= 1000 {
|
||||||
|
data2 := make([]int, len(data))
|
||||||
|
copy(data2, data)
|
||||||
|
bubbleSort(data2)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//go:noinline
|
||||||
|
func bubbleSort(arr []int) {
|
||||||
|
n := len(arr)
|
||||||
|
for i := 0; i < n-1; i++ {
|
||||||
|
for j := 0; j < n-i-1; j++ {
|
||||||
|
if arr[j] > arr[j+1] {
|
||||||
|
arr[j], arr[j+1] = arr[j+1], arr[j]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//go:noinline
|
||||||
|
func networkSimulation(requests int) {
|
||||||
|
// Simulate network-like delays and processing
|
||||||
|
for i := 0; i < requests; i++ {
|
||||||
|
// Simulate variable latency
|
||||||
|
latency := time.Duration(10+i%50) * time.Microsecond
|
||||||
|
time.Sleep(latency)
|
||||||
|
|
||||||
|
// Simulate request processing
|
||||||
|
processRequest(i)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//go:noinline
|
||||||
|
func processRequest(id int) {
|
||||||
|
// Simulate request processing with string operations
|
||||||
|
request := fmt.Sprintf("request-%d", id)
|
||||||
|
parts := strings.Split(request, "-")
|
||||||
|
if len(parts) > 1 {
|
||||||
|
num, _ := strconv.Atoi(parts[1])
|
||||||
|
_ = num * 2
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//go:noinline
|
||||||
|
func concurrentWork(ctx context.Context, workers int) {
|
||||||
|
var wg sync.WaitGroup
|
||||||
|
|
||||||
|
for i := 0; i < workers; i++ {
|
||||||
|
wg.Add(1)
|
||||||
|
go func(workerID int) {
|
||||||
|
defer wg.Done()
|
||||||
|
pyroscope.TagWrapper(ctx, pyroscope.Labels("worker", fmt.Sprintf("worker-%d", workerID)), func(c context.Context) {
|
||||||
|
// Each worker does different types of work
|
||||||
|
switch workerID % 3 {
|
||||||
|
case 0:
|
||||||
|
cpuIntensiveWork(1000000)
|
||||||
|
case 1:
|
||||||
|
memoryIntensiveWork(500)
|
||||||
|
case 2:
|
||||||
|
stringProcessing(10000)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}(i)
|
||||||
|
}
|
||||||
|
|
||||||
|
wg.Wait()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Different function types for varied flame graph patterns
|
||||||
|
|
||||||
|
func fastFunction(c context.Context) {
|
||||||
|
pyroscope.TagWrapper(c, pyroscope.Labels("function", "fast", "type", "cpu"), func(c context.Context) {
|
||||||
|
cpuIntensiveWork(1000000)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func slowFunction(c context.Context) {
|
||||||
|
pprof.Do(c, pprof.Labels("function", "slow", "type", "mixed"), func(c context.Context) {
|
||||||
|
cpuIntensiveWork(5000000)
|
||||||
|
memoryIntensiveWork(200)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func recursiveFunction(c context.Context) {
|
||||||
|
pyroscope.TagWrapper(c, pyroscope.Labels("function", "recursive", "type", "fibonacci"), func(c context.Context) {
|
||||||
|
// Fibonacci creates deep call stacks
|
||||||
|
result := recursiveFibonacci(35)
|
||||||
|
_ = result
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func memoryFunction(c context.Context) {
|
||||||
|
pyroscope.TagWrapper(c, pyroscope.Labels("function", "memory", "type", "allocation"), func(c context.Context) {
|
||||||
|
memoryIntensiveWork(1000)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func stringFunction(c context.Context) {
|
||||||
|
pyroscope.TagWrapper(c, pyroscope.Labels("function", "string", "type", "processing"), func(c context.Context) {
|
||||||
|
stringProcessing(50000)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func sortingFunction(c context.Context) {
|
||||||
|
pyroscope.TagWrapper(c, pyroscope.Labels("function", "sorting", "type", "algorithms"), func(c context.Context) {
|
||||||
|
sortingWork(5000)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func networkFunction(c context.Context) {
|
||||||
|
pyroscope.TagWrapper(c, pyroscope.Labels("function", "network", "type", "simulation"), func(c context.Context) {
|
||||||
|
networkSimulation(100)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func mathFunction(c context.Context) {
|
||||||
|
pyroscope.TagWrapper(c, pyroscope.Labels("function", "math", "type", "factorial"), func(c context.Context) {
|
||||||
|
result := recursiveFactorial(15)
|
||||||
|
_ = result
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func concurrentFunction(c context.Context) {
|
||||||
|
pyroscope.TagWrapper(c, pyroscope.Labels("function", "concurrent", "type", "goroutines"), func(c context.Context) {
|
||||||
|
concurrentWork(c, 10)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
serverAddress := os.Getenv("PYROSCOPE_SERVER_ADDRESS")
|
||||||
|
if serverAddress == "" {
|
||||||
|
serverAddress = "http://localhost:4040"
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err := pyroscope.Start(pyroscope.Config{
|
||||||
|
ApplicationName: "sample_app",
|
||||||
|
ServerAddress: serverAddress,
|
||||||
|
Logger: pyroscope.StandardLogger,
|
||||||
|
Tags: map[string]string{
|
||||||
|
"version": "2.0",
|
||||||
|
"env": "demo",
|
||||||
|
},
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalf("error starting pyroscope profiler: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Main execution loop with varied workloads
|
||||||
|
pyroscope.TagWrapper(context.Background(), pyroscope.Labels("phase", "main"), func(c context.Context) {
|
||||||
|
iteration := 0
|
||||||
|
for {
|
||||||
|
iteration++
|
||||||
|
|
||||||
|
// Create varied execution patterns
|
||||||
|
switch iteration % 9 {
|
||||||
|
case 0:
|
||||||
|
fastFunction(c)
|
||||||
|
case 1:
|
||||||
|
slowFunction(c)
|
||||||
|
case 2:
|
||||||
|
recursiveFunction(c)
|
||||||
|
case 3:
|
||||||
|
memoryFunction(c)
|
||||||
|
case 4:
|
||||||
|
stringFunction(c)
|
||||||
|
case 5:
|
||||||
|
sortingFunction(c)
|
||||||
|
case 6:
|
||||||
|
networkFunction(c)
|
||||||
|
case 7:
|
||||||
|
mathFunction(c)
|
||||||
|
case 8:
|
||||||
|
concurrentFunction(c)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Occasional heavy computation phase
|
||||||
|
if iteration%20 == 0 {
|
||||||
|
pyroscope.TagWrapper(c, pyroscope.Labels("phase", "heavy"), func(c context.Context) {
|
||||||
|
cpuIntensiveWork(10000000)
|
||||||
|
memoryIntensiveWork(2000)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// Short pause to make the profiling more readable
|
||||||
|
time.Sleep(10 * time.Millisecond)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
Reference in New Issue
Block a user