<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Prometheus on Yarang's Tech Lair</title><link>https://blog.agentthread.dev/tags/prometheus/</link><description>Recent content in Prometheus on Yarang's Tech Lair</description><generator>Hugo -- gohugo.io</generator><language>en</language><lastBuildDate>Tue, 03 Mar 2026 14:53:47 +0900</lastBuildDate><atom:link href="https://blog.agentthread.dev/tags/prometheus/index.xml" rel="self" type="application/rss+xml"/><item><title>[blog-api-server] Monitoring Dashboard and Alerting System</title><link>https://blog.agentthread.dev/post/2026-03-03-002-blog-api-server-monitoring-alerting/</link><pubDate>Tue, 03 Mar 2026 14:53:47 +0900</pubDate><guid>https://blog.agentthread.dev/post/2026-03-03-002-blog-api-server-monitoring-alerting/</guid><description>&lt;h1 id="blog-api-server-monitoring-dashboard-and-alerting-system"&gt;[blog-api-server] Monitoring Dashboard and Alerting System
&lt;/h1&gt;&lt;h2 id="overview"&gt;Overview
&lt;/h2&gt;&lt;p&gt;A Prometheus-based monitoring system and Slack/Email alerting have been added to blog-api-server, enabling real-time server status tracking and immediate response to issues.&lt;/p&gt;
&lt;h2 id="monitoring-architecture"&gt;Monitoring Architecture
&lt;/h2&gt;&lt;pre class="mermaid" style="visibility:hidden"&gt;flowchart TB
 A[HTTP Request] --&gt; B[MonitoringMiddleware]
 B --&gt; C[Request Logging]
 B --&gt; D[PrometheusMiddleware]
 D --&gt; E[Metrics Collection]
 C --&gt; F[AlertManager]
 E --&gt; F
 F --&gt; G{Threshold Check}
 G --&gt;|Over Threshold| H[Slack Webhook]
 G --&gt;|Critical| I[Email Alert]
 G --&gt;|Normal| J[Log Only]
 K[Prometheus Server] --&gt; L[/metrics/prometheus]
 M[Dashboard] --&gt; N[/dashboard]&lt;/pre&gt;&lt;h2 id="prometheus-metrics"&gt;Prometheus Metrics
&lt;/h2&gt;&lt;h3 id="basic-http-metrics"&gt;Basic HTTP Metrics
&lt;/h3&gt;&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th&gt;Metric&lt;/th&gt;
					&lt;th&gt;Type&lt;/th&gt;
					&lt;th&gt;Labels&lt;/th&gt;
					&lt;th&gt;Description&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;http_requests_total&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;Counter&lt;/td&gt;
					&lt;td&gt;method, endpoint, status&lt;/td&gt;
					&lt;td&gt;Total HTTP requests&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;http_request_duration_seconds&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;Histogram&lt;/td&gt;
					&lt;td&gt;method, endpoint&lt;/td&gt;
					&lt;td&gt;Request latency distribution&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;http_errors_total&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;Counter&lt;/td&gt;
					&lt;td&gt;method, endpoint, status&lt;/td&gt;
					&lt;td&gt;Total error count&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;active_requests&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;Gauge&lt;/td&gt;
					&lt;td&gt;-&lt;/td&gt;
					&lt;td&gt;Current active requests&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3 id="business-metrics"&gt;Business Metrics
&lt;/h3&gt;&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th&gt;Metric&lt;/th&gt;
					&lt;th&gt;Type&lt;/th&gt;
					&lt;th&gt;Labels&lt;/th&gt;
					&lt;th&gt;Description&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;git_operations_total&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;Counter&lt;/td&gt;
					&lt;td&gt;operation, status&lt;/td&gt;
					&lt;td&gt;Git operation count&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;git_operation_duration_seconds&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;Histogram&lt;/td&gt;
					&lt;td&gt;operation&lt;/td&gt;
					&lt;td&gt;Git operation duration&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;translation_requests_total&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;Counter&lt;/td&gt;
					&lt;td&gt;source_lang, target_lang, status&lt;/td&gt;
					&lt;td&gt;Translation request count&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;translation_duration_seconds&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;Histogram&lt;/td&gt;
					&lt;td&gt;-&lt;/td&gt;
					&lt;td&gt;Translation duration&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;post_operations_total&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;Counter&lt;/td&gt;
					&lt;td&gt;operation, language, status&lt;/td&gt;
					&lt;td&gt;Post operation count&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3 id="metrics-collection-code"&gt;Metrics Collection Code
&lt;/h3&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# prometheus_exporter.py&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;from&lt;/span&gt; prometheus_client &lt;span style="color:#f92672"&gt;import&lt;/span&gt; Counter, Histogram, Gauge
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;http_requests_total &lt;span style="color:#f92672"&gt;=&lt;/span&gt; Counter(
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;http_requests_total&amp;#39;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;Total HTTP requests&amp;#39;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; [&lt;span style="color:#e6db74"&gt;&amp;#39;method&amp;#39;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#39;endpoint&amp;#39;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#39;status&amp;#39;&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;http_request_duration_seconds &lt;span style="color:#f92672"&gt;=&lt;/span&gt; Histogram(
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;http_request_duration_seconds&amp;#39;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;HTTP request latency&amp;#39;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; [&lt;span style="color:#e6db74"&gt;&amp;#39;method&amp;#39;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#39;endpoint&amp;#39;&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# Auto-collection in middleware&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;class&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;PrometheusMiddleware&lt;/span&gt;(BaseHTTPMiddleware):
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;async&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;def&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;dispatch&lt;/span&gt;(self, request: Request, call_next):
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; start_time &lt;span style="color:#f92672"&gt;=&lt;/span&gt; time&lt;span style="color:#f92672"&gt;.&lt;/span&gt;time()
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; response &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;await&lt;/span&gt; call_next(request)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; duration &lt;span style="color:#f92672"&gt;=&lt;/span&gt; time&lt;span style="color:#f92672"&gt;.&lt;/span&gt;time() &lt;span style="color:#f92672"&gt;-&lt;/span&gt; start_time
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; http_requests_total&lt;span style="color:#f92672"&gt;.&lt;/span&gt;labels(
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; method&lt;span style="color:#f92672"&gt;=&lt;/span&gt;request&lt;span style="color:#f92672"&gt;.&lt;/span&gt;method,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; endpoint&lt;span style="color:#f92672"&gt;=&lt;/span&gt;request&lt;span style="color:#f92672"&gt;.&lt;/span&gt;url&lt;span style="color:#f92672"&gt;.&lt;/span&gt;path,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; status&lt;span style="color:#f92672"&gt;=&lt;/span&gt;response&lt;span style="color:#f92672"&gt;.&lt;/span&gt;status_code
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; )&lt;span style="color:#f92672"&gt;.&lt;/span&gt;inc()
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; http_request_duration_seconds&lt;span style="color:#f92672"&gt;.&lt;/span&gt;labels(
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; method&lt;span style="color:#f92672"&gt;=&lt;/span&gt;request&lt;span style="color:#f92672"&gt;.&lt;/span&gt;method,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; endpoint&lt;span style="color:#f92672"&gt;=&lt;/span&gt;request&lt;span style="color:#f92672"&gt;.&lt;/span&gt;url&lt;span style="color:#f92672"&gt;.&lt;/span&gt;path
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; )&lt;span style="color:#f92672"&gt;.&lt;/span&gt;observe(duration)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="alerting-system"&gt;Alerting System
&lt;/h2&gt;&lt;h3 id="alert-rules"&gt;Alert Rules
&lt;/h3&gt;&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th&gt;Rule Name&lt;/th&gt;
					&lt;th&gt;Condition&lt;/th&gt;
					&lt;th&gt;Severity&lt;/th&gt;
					&lt;th&gt;Cooldown&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td&gt;High Error Rate&lt;/td&gt;
					&lt;td&gt;error_rate &amp;gt; 5%&lt;/td&gt;
					&lt;td&gt;WARNING&lt;/td&gt;
					&lt;td&gt;5 min&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;Critical Error Rate&lt;/td&gt;
					&lt;td&gt;error_rate &amp;gt; 20%&lt;/td&gt;
					&lt;td&gt;CRITICAL&lt;/td&gt;
					&lt;td&gt;1 min&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;Slow Response Time&lt;/td&gt;
					&lt;td&gt;avg_response_time &amp;gt; 2000ms&lt;/td&gt;
					&lt;td&gt;WARNING&lt;/td&gt;
					&lt;td&gt;10 min&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;High Slow Request Rate&lt;/td&gt;
					&lt;td&gt;slow_request_rate &amp;gt; 10%&lt;/td&gt;
					&lt;td&gt;WARNING&lt;/td&gt;
					&lt;td&gt;5 min&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3 id="alert-channels"&gt;Alert Channels
&lt;/h3&gt;&lt;p&gt;&lt;strong&gt;Slack Webhook&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Supports all severity levels&lt;/li&gt;
&lt;li&gt;Color-coded severity (INFO: green, WARNING: orange, ERROR: red, CRITICAL: dark red)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Email&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;CRITICAL level only&lt;/li&gt;
&lt;li&gt;SMTP-based email delivery&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="alertmanager-code"&gt;AlertManager Code
&lt;/h3&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# alerting.py&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;class&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;AlertManager&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;def&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;check_and_alert&lt;/span&gt;(self, metrics: Dict[str, Any]):
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;for&lt;/span&gt; rule &lt;span style="color:#f92672"&gt;in&lt;/span&gt; self&lt;span style="color:#f92672"&gt;.&lt;/span&gt;rules:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; rule&lt;span style="color:#f92672"&gt;.&lt;/span&gt;should_trigger(metrics):
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; self&lt;span style="color:#f92672"&gt;.&lt;/span&gt;_send_alert(rule, metrics)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;def&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;_send_alert&lt;/span&gt;(self, rule: AlertRule, metrics: Dict[str, Any]):
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; message &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;f&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;&amp;#34;&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt;Alert Rule: &lt;/span&gt;&lt;span style="color:#e6db74"&gt;{&lt;/span&gt;rule&lt;span style="color:#f92672"&gt;.&lt;/span&gt;name&lt;span style="color:#e6db74"&gt;}&lt;/span&gt;&lt;span style="color:#e6db74"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt;Condition: &lt;/span&gt;&lt;span style="color:#e6db74"&gt;{&lt;/span&gt;rule&lt;span style="color:#f92672"&gt;.&lt;/span&gt;condition&lt;span style="color:#e6db74"&gt;}&lt;/span&gt;&lt;span style="color:#e6db74"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt;Current Metrics:
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt;- Total Requests: &lt;/span&gt;&lt;span style="color:#e6db74"&gt;{&lt;/span&gt;metrics&lt;span style="color:#f92672"&gt;.&lt;/span&gt;get(&lt;span style="color:#e6db74"&gt;&amp;#39;total_requests&amp;#39;&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;)&lt;span style="color:#e6db74"&gt;}&lt;/span&gt;&lt;span style="color:#e6db74"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt;- Error Count: &lt;/span&gt;&lt;span style="color:#e6db74"&gt;{&lt;/span&gt;metrics&lt;span style="color:#f92672"&gt;.&lt;/span&gt;get(&lt;span style="color:#e6db74"&gt;&amp;#39;error_count&amp;#39;&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;)&lt;span style="color:#e6db74"&gt;}&lt;/span&gt;&lt;span style="color:#e6db74"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt;- Error Rate: &lt;/span&gt;&lt;span style="color:#e6db74"&gt;{&lt;/span&gt;metrics&lt;span style="color:#f92672"&gt;.&lt;/span&gt;get(&lt;span style="color:#e6db74"&gt;&amp;#39;error_rate_percent&amp;#39;&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;)&lt;span style="color:#e6db74"&gt;}&lt;/span&gt;&lt;span style="color:#e6db74"&gt;%
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt;- Slow Requests: &lt;/span&gt;&lt;span style="color:#e6db74"&gt;{&lt;/span&gt;metrics&lt;span style="color:#f92672"&gt;.&lt;/span&gt;get(&lt;span style="color:#e6db74"&gt;&amp;#39;slow_request_count&amp;#39;&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;)&lt;span style="color:#e6db74"&gt;}&lt;/span&gt;&lt;span style="color:#e6db74"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;&amp;#34;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; self&lt;span style="color:#f92672"&gt;.&lt;/span&gt;slack&lt;span style="color:#f92672"&gt;.&lt;/span&gt;send(
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; title&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;f&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;Alert: &lt;/span&gt;&lt;span style="color:#e6db74"&gt;{&lt;/span&gt;rule&lt;span style="color:#f92672"&gt;.&lt;/span&gt;name&lt;span style="color:#e6db74"&gt;}&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; message&lt;span style="color:#f92672"&gt;=&lt;/span&gt;message&lt;span style="color:#f92672"&gt;.&lt;/span&gt;strip(),
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; severity&lt;span style="color:#f92672"&gt;=&lt;/span&gt;rule&lt;span style="color:#f92672"&gt;.&lt;/span&gt;severity
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; )
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="dashboard-configuration"&gt;Dashboard Configuration
&lt;/h2&gt;&lt;h3 id="monitoring-endpoints"&gt;Monitoring Endpoints
&lt;/h3&gt;&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th&gt;Path&lt;/th&gt;
					&lt;th&gt;Auth&lt;/th&gt;
					&lt;th&gt;Description&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;/health&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;Not Required&lt;/td&gt;
					&lt;td&gt;Server health check&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;/metrics&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;Required&lt;/td&gt;
					&lt;td&gt;JSON format metrics&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;/metrics/prometheus&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;Not Required&lt;/td&gt;
					&lt;td&gt;Prometheus format metrics&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;/metrics/reset&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;Required&lt;/td&gt;
					&lt;td&gt;Reset metrics&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;/dashboard&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;Not Required&lt;/td&gt;
					&lt;td&gt;Web dashboard&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;/alerts/rules&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;Required&lt;/td&gt;
					&lt;td&gt;Alert rules list&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;/alerts/send&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;Required&lt;/td&gt;
					&lt;td&gt;Manual alert send&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3 id="request-tracking-middleware"&gt;Request Tracking Middleware
&lt;/h3&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# middleware.py&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;class&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;MonitoringMiddleware&lt;/span&gt;(BaseHTTPMiddleware):
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;async&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;def&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;dispatch&lt;/span&gt;(self, request: Request, call_next):
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; request_id &lt;span style="color:#f92672"&gt;=&lt;/span&gt; str(uuid&lt;span style="color:#f92672"&gt;.&lt;/span&gt;uuid4())
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; start_time &lt;span style="color:#f92672"&gt;=&lt;/span&gt; time&lt;span style="color:#f92672"&gt;.&lt;/span&gt;time()
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; response &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;await&lt;/span&gt; call_next(request)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; process_time &lt;span style="color:#f92672"&gt;=&lt;/span&gt; (time&lt;span style="color:#f92672"&gt;.&lt;/span&gt;time() &lt;span style="color:#f92672"&gt;-&lt;/span&gt; start_time) &lt;span style="color:#f92672"&gt;*&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;1000&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;# Add tracking info to response headers&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; response&lt;span style="color:#f92672"&gt;.&lt;/span&gt;headers[&lt;span style="color:#e6db74"&gt;&amp;#34;X-Process-Time&amp;#34;&lt;/span&gt;] &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;f&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;&lt;/span&gt;&lt;span style="color:#e6db74"&gt;{&lt;/span&gt;process_time&lt;span style="color:#e6db74"&gt;:&lt;/span&gt;&lt;span style="color:#e6db74"&gt;.2f&lt;/span&gt;&lt;span style="color:#e6db74"&gt;}&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; response&lt;span style="color:#f92672"&gt;.&lt;/span&gt;headers[&lt;span style="color:#e6db74"&gt;&amp;#34;X-Request-ID&amp;#34;&lt;/span&gt;] &lt;span style="color:#f92672"&gt;=&lt;/span&gt; request_id
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; response
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="environment-variables"&gt;Environment Variables
&lt;/h2&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# Slack Alerts&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;SLACK_WEBHOOK_URL&lt;span style="color:#f92672"&gt;=&lt;/span&gt;https://hooks.slack.com/services/...
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# Email Alerts&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;SMTP_SERVER&lt;span style="color:#f92672"&gt;=&lt;/span&gt;smtp.gmail.com
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;SMTP_PORT&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;587&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;SMTP_USERNAME&lt;span style="color:#f92672"&gt;=&lt;/span&gt;your-email@gmail.com
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;SMTP_PASSWORD&lt;span style="color:#f92672"&gt;=&lt;/span&gt;your-app-password
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;ALERT_FROM_EMAIL&lt;span style="color:#f92672"&gt;=&lt;/span&gt;your-email@gmail.com
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;ALERT_TO_EMAILS&lt;span style="color:#f92672"&gt;=&lt;/span&gt;admin@example.com,ops@example.com
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# Threshold Settings&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;SLOW_REQUEST_THRESHOLD&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1000&lt;/span&gt; &lt;span style="color:#75715e"&gt;# 1 second&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;VERY_SLOW_THRESHOLD&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;3000&lt;/span&gt; &lt;span style="color:#75715e"&gt;# 3 seconds&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;MAX_BODY_LOG_LENGTH&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1000&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="future-plans"&gt;Future Plans
&lt;/h2&gt;&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Grafana Integration&lt;/strong&gt;: Visualize Prometheus data in Grafana dashboard&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Dynamic Alert Rules&lt;/strong&gt;: API to add/remove alert rules at runtime&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Metrics Retention&lt;/strong&gt;: Long-term metrics storage and analysis&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Enhanced Health Checks&lt;/strong&gt;: Dependency service (Git, LLM) status checks&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id="conclusion"&gt;Conclusion
&lt;/h2&gt;&lt;p&gt;With Prometheus-based monitoring and Slack/Email alerting, infrastructure is now in place for real-time server monitoring and immediate incident response.&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;&lt;strong&gt;Korean Version:&lt;/strong&gt; &lt;a class="link" href="https://blog.agentthread.dev/ko/post/2026-03-03-002-blog-api-server-monitoring-alerting/" &gt;한국어 버전&lt;/a&gt;&lt;/p&gt;</description></item></channel></rss>