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