@@ -33,14 +33,136 @@ jobs:
3333 mkdir -p /tmp/artifacts/
3434 ARTIFACT_PATH=/tmp/artifacts make test-benchmark
3535
36- - name : Compare with baseline
36+ - name : Convert Benchmark Output to Prometheus Metrics
3737 run : |
38- go install golang.org/x/perf/cmd/benchstat@latest
39- benchstat benchmarks/baseline.txt /tmp/artifacts/new.txt | tee /tmp/artifacts/output
38+ mkdir -p /tmp/artifacts/prometheus/
39+ cat << 'EOF' > benchmark_to_prometheus.py
40+ import sys
41+ import re
4042
41- - name : Upload benchmark results
43+ def parse_benchmark_output(benchmark_output):
44+ metrics = []
45+ for line in benchmark_output.split("\n"):
46+ match = re.match(r"Benchmark([\w\d]+)-\d+\s+\d+\s+([\d]+)\s+ns/op\s+([\d]+)\s+B/op\s+([\d]+)\s+allocs/op", line)
47+ if match:
48+ benchmark_name = match.group(1).lower()
49+ time_ns = match.group(2)
50+ memory_bytes = match.group(3)
51+ allocs = match.group(4)
52+
53+ metrics.append(f"benchmark_{benchmark_name}_ns {time_ns}")
54+ metrics.append(f"benchmark_{benchmark_name}_allocs {allocs}")
55+ metrics.append(f"benchmark_{benchmark_name}_mem_bytes {memory_bytes}")
56+
57+ return "\n".join(metrics)
58+
59+ if __name__ == "__main__":
60+ benchmark_output = sys.stdin.read()
61+ metrics = parse_benchmark_output(benchmark_output)
62+ print(metrics)
63+ EOF
64+
65+ cat /tmp/artifacts/new.txt | python3 benchmark_to_prometheus.py > /tmp/artifacts/prometheus/metrics.txt
66+
67+ # - name: Compare with baseline
68+ # run: |
69+ # go install golang.org/x/perf/cmd/benchstat@latest
70+ # benchstat benchmarks/baseline.txt /tmp/artifacts/new.txt | tee /tmp/artifacts/output
71+
72+ - name : Upload Benchmark Metrics
73+ uses : actions/upload-artifact@v4
74+ with :
75+ name : benchmark-metrics
76+ path : /tmp/artifacts/prometheus/
77+
78+ start-prometheus :
79+ needs : benchmark
80+ runs-on : ubuntu-latest
81+ steps :
82+ - name : Checkout code
83+ uses : actions/checkout@v4
84+ with :
85+ fetch-depth : 0
86+
87+ - name : Download Benchmark Metrics
88+ uses : actions/download-artifact@v4
89+ with :
90+ name : benchmark-metrics
91+ path : ./
92+
93+ - name : List Downloaded Metrics files
94+ run : ls -lh
95+
96+ - name : Set Up Prometheus Config
97+ run : |
98+ cat << 'EOF' > prometheus.yml
99+ global:
100+ scrape_interval: 5s
101+ scrape_configs:
102+ - job_name: 'benchmark_metrics'
103+ static_configs:
104+ - targets: ['localhost:9000']
105+ EOF
106+
107+ - name : Run Prometheus
108+ run : |
109+ docker run -d --name prometheus -p 9090:9090 \
110+ -v ${{ github.workspace }}/prometheus.yml:/etc/prometheus/prometheus.yml \
111+ -v ${{ github.workspace }}/prometheus-data:/prometheus \
112+ prom/prometheus --config.file=/etc/prometheus/prometheus.yml \
113+ --storage.tsdb.path=/prometheus --storage.tsdb.retention.time=1h
114+
115+ - name : Wait for Prometheus to start
116+ run : sleep 10
117+
118+ - name : Check Prometheus is running
119+ run : curl -s http://localhost:9090/-/ready || (docker logs prometheus && exit 1)
120+
121+ - name : Start HTTP Server to Expose Metrics
122+ run : |
123+ cat << 'EOF' > server.py
124+ from http.server import SimpleHTTPRequestHandler, HTTPServer
125+
126+ class MetricsHandler(SimpleHTTPRequestHandler):
127+ def do_GET(self):
128+ if self.path == "/metrics":
129+ self.send_response(200)
130+ self.send_header("Content-type", "text/plain")
131+ self.end_headers()
132+ with open("metrics.txt", "r") as f:
133+ self.wfile.write(f.read().encode())
134+ else:
135+ self.send_response(404)
136+ self.end_headers()
137+
138+ if __name__ == "__main__":
139+ server = HTTPServer(('0.0.0.0', 9000), MetricsHandler)
140+ print("Serving on port 9000...")
141+ server.serve_forever()
142+ EOF
143+
144+ nohup python3 server.py &
145+
146+ - name : Wait for Prometheus to Collect Data
147+ run : sleep 30
148+
149+ - name : Trigger Prometheus Snapshot
150+ run : |
151+ curl -X POST http://localhost:9090/api/v1/admin/tsdb/snapshot
152+
153+ - name : Stop Prometheus
154+ run : docker stop prometheus
155+
156+ - name : Find and Upload Prometheus Snapshot
157+ run : |
158+ SNAPSHOT_PATH=$(ls -td /prometheus/snapshots/* | head -1)
159+ echo "Prometheus snapshot stored in: $SNAPSHOT_PATH"
160+ tar -czf prometheus_snapshot.tar.gz -C "$SNAPSHOT_PATH" .
161+ mv prometheus_snapshot.tar.gz $GITHUB_WORKSPACE/
162+
163+ - name : Upload Prometheus Snapshot
42164 uses : actions/upload-artifact@v4
43165 with :
44- name : benchmark-artifacts
45- path : /tmp/artifacts/
166+ name : prometheus-snapshot
167+ path : prometheus_snapshot.tar.gz
46168
0 commit comments