📋 目錄
服務上線後,用戶回報「頁面打不開」——但你的伺服器 log 裡只有一筆 500 錯誤,沒有任何人知道發生了什麼。SRE(Site Reliability Engineering)的核心思想,是用系統化的方式觀測你的服務,讓問題在用戶察覺之前就被發現。這篇整理前端工程師必懂的監控、日誌、錯誤追蹤概念與實務工具。
前言:為什麼 SRE 對前端工程師重要?
前端工程師習慣了「頁面載入順暢就是正常」的視角。但服務不是只有前端——後端 API、資料庫、第三方服務,任何一個環節出問題,表現出來都是「頁面打不開」。
SRE 的目標:用數據說話,而不是靠用戶回報。當你能觀測整個系統的狀態,問題的定位就從「猜測」變成「確認」。
三個核心工具:日誌(Logs)、指標(Metrics)、錯誤追蹤(Error Tracking)。它們各自解決不同的問題。
監控系統整體架構圖
flowchart TB
subgraph App["🚀 你的應用程式"]
BE[Node.js / Express API]
FE[前端 React / Vue App]
end
subgraph Agents["📡 資料收集層"]
Logs[Winston 日誌]
Metrics[Prometheus Client]
Errors[Sentry SDK]
end
subgraph Storage["💾 儲存層"]
ELK[ELK Stack<br/>Elasticsearch]
Prometheus[(Prometheus)]
SentryDB[Sentry DB]
end
subgraph Visualization["📊 視覺化層"]
Kibana[Kibana Dashboard]
Grafana[Grafana Dashboard]
SentryUI[Sentry UI]
end
subgraph Alerts["🔔 報警層"]
Slack[Slack]
PagerDuty[PagerDuty]
Email[Email]
end
BE --> Logs
FE --> Errors
Logs --> ELK --> Kibana
Metrics --> Prometheus --> Grafana
Errors --> SentryDB --> SentryUI
Grafana --> Alerts
SentryUI --> Alerts
style ELK fill:#3b82f6,color:#fff
style Prometheus fill:#e6522c,color:#fff
style SentryDB fill:#a855f7,color:#fff
style Kibana fill:#f97316,color:#fff
style Grafana fill:#f47825,color:#fff
style SentryUI fill:#a855f7,color:#fff
上圖是典型 SRE 監控架構的全貌:應用程式產生的資料(日誌、指票、錯誤)各自傳送到專屬的儲存系統,最後在各自的 Dashboard 呈現,並透過 Alerting 系統統一通知。
日誌(Logs):系統的日記本
什麼該記錄?
不是所有 log 都有價值。常見的 log 等級:
- ERROR:需要處理的問題(例如資料庫連線失敗)
- WARN:潛在問題,但系統還能運作(例如 API 回應超過 2 秒)
- INFO:正常的業務事件(例如用戶登入、訂單成立)
- DEBUG:開發除錯用,生產環境通常關閉
Node.js + Express 的實際記錄方式
import express from 'express';
import winston from 'winston';
const logger = winston.createLogger({
level: 'info',
format: winston.format.combine(
winston.format.timestamp(),
winston.format.json()
),
transports: [
new winston.transports.File({ filename: 'error.log', level: 'error' }),
new winston.transports.File({ filename: 'combined.log' }),
],
});
const app = express();
app.use((req, res, next) => {
const start = Date.now();
res.on('finish', () => {
const duration = Date.now() - start;
logger.info({
method: req.method,
url: req.url,
status: res.statusCode,
duration: `${duration}ms`,
userAgent: req.get('user-agent'),
});
if (res.statusCode >= 500) {
logger.error({
method: req.method,
url: req.url,
status: res.statusCode,
message: 'Server error occurred',
});
}
});
next();
});
app.post('/api/orders', async (req, res) => {
try {
const order = await createOrder(req.body);
logger.info({ event: 'order_created', orderId: order.id, userId: req.body.userId });
res.status(201).json(order);
} catch (err) {
logger.error({ event: 'order_failed', error: err.message, stack: err.stack });
res.status(500).json({ error: '訂單建立失敗' });
}
});
Log 管理的工具鏈
本機看 log 用 cat error.log 或 tail -f error.log。但在正式環境,通常不用 SSH 進伺服器直接看——而是讓 log 統一收集到一個地方:
- ELK Stack(Elasticsearch + Logstash + Kibana):開源方案,功能完整但維護成本高
- Datadog:SaaS 方案,懶人友善但昂貴
- Grafana Loki:輕量級,搭配 Grafana 使用
指標(Metrics):用數字描述系統健康
Metrics 的核心是數值化的測量。不同於 log 是文字描述,metrics 是數字,可以用圖表呈現趨勢。
四個黃金指標(Golden Signals)
Google SRE 手冊定義的四個最重要的指標:
| 指標 | 意義 | 常見單位 |
|---|---|---|
| Latency(延遲) | 請求處理的時間 | ms(毫秒) |
| Traffic(流量) | 系統承受的負載 | requests/sec |
| Errors(錯誤) | 失敗的請求比例 | %(百分比) |
| Saturation(飽和度) | 系統資源使用率 | % 或 count |
指標資料流動圖
sequenceDiagram
participant App as 應用程式
participant SDK as Prometheus Client
participant Endpoint as /metrics Endpoint
participant Scraper as Prometheus Server
participant DB as Prometheus TSDB
participant Grafana as Grafana
App->>SDK: 計時 HTTP 請求
App->>SDK: 增加 Counter
SDK->>Endpoint: 註冊 metrics
Endpoint-->>Scraper: 拉取 /metrics
Scraper->>DB: 儲存時序資料
DB-->>Grafana: 提供查詢 API
Grafana->>User: 呈現 Dashboard 圖表
Note over App,Grafana: 每 15 秒 Prometheus 抓一次 /metrics,持續收集
Note over Grafana: 圖表查詢使用 PromQL,如 histogram_quantile(0.99, ...)
Node.js + Prometheus Client 實作
import client from 'prom-client';
const register = new client.Registry();
client.collectDefaultMetrics({ register });
const httpRequestDuration = new client.Histogram({
name: 'http_request_duration_seconds',
help: 'Duration of HTTP requests in seconds',
labelNames: ['method', 'route', 'status_code'],
buckets: [0.01, 0.05, 0.1, 0.5, 1, 2, 5],
registers: [register],
});
const httpRequestTotal = new client.Counter({
name: 'http_requests_total',
help: 'Total number of HTTP requests',
labelNames: ['method', 'route', 'status_code'],
registers: [register],
});
app.use((req, res, next) => {
const start = Date.now();
res.on('finish', () => {
const duration = (Date.now() - start) / 1000;
const route = req.route?.path || req.url;
httpRequestDuration
.labels(req.method, route, res.statusCode.toString())
.observe(duration);
httpRequestTotal
.labels(req.method, route, res.statusCode.toString())
.inc();
});
next();
});
app.get('/metrics', async (req, res) => {
res.set('Content-Type', register.contentType);
res.send(await register.metrics());
});
Prometheus 會定期從 /metrics endpoint 抓資料,Grafana 可以拿這些資料畫圖。
常見的監控視覺化圖表
# 錯誤率(Errors)
# 公式:http_requests_total{status_code=~"5.."} / http_requests_total * 100
# 當錯誤率 > 1% 時觸發報警
# P99 延遲(Latency)
# 公式:histogram_quantile(0.99, http_request_duration_seconds)
# 當 P99 > 2s 時代表有 1% 的請求等待超過 2 秒
# 流量(Traffic)
# 觀察是否有異常流量(突然暴增可能是攻擊或快取失效)
錯誤追蹤(Error Tracking):不只是 console.error
錯誤追蹤工具的價值在於自動收集未預期的錯誤、保留上下文、通知相關人員。它補足 log 和 metrics 的盲點——log 通常只寫你主動處理的錯誤,很多意外錯誤不會被捕捉到。
Sentry:最流行的錯誤追蹤工具
import * as Sentry from '@sentry/node';
import express from 'express';
Sentry.init({
dsn: 'https://your-dsn@sentry.io/project-id',
environment: process.env.NODE_ENV,
enabled: process.env.NODE_ENV === 'production',
});
const app = express();
app.use(Sentry.Handlers.errorHandler());
app.post('/api/orders', async (req, res) => {
const order = await createOrder(req.body);
res.status(201).json(order);
});
app.post('/api/users', async (req, res, next) => {
try {
const user = await createUser(req.body);
res.status(201).json(user);
} catch (err) {
Sentry.captureException(err);
next(err);
}
});
Sentry 會自動收集:
- 錯誤訊息與 stack trace
- 發生的路徑(URL、request headers)
- 使用者資訊(如果你有登入機制,可以傳 user ID)
- 發生的地點(哪個函式、哪一行)
- 發生的頻率(同一錯誤影響多少人)
前端錯誤追蹤
錯誤追蹤不只限於後端,前端 JS 的未處理錯誤也要追蹤:
import { ErrorBoundary } from '@sentry/react';
<Sentry.ErrorBoundary fallback={({ error }) => <p>系統發生錯誤,請稍後再試</p>}>
<App />
</Sentry.ErrorBoundary>
後端 Sentry + 前端 Sentry = 完整的錯誤觀測覆蓋。
報警(Alerting):什麼時候該通知你
# Prometheus alert rules 範例
groups:
- name: my-api-alerts
rules:
- alert: HighErrorRate
expr: |
sum(rate(http_requests_total{status_code=~"5.."}[2m]))
/
sum(rate(http_requests_total[2m])) > 0.05
for: 2m
labels:
severity: critical
annotations:
summary: "錯誤率過高"
description: "過去 2 分鐘錯誤率為 {{ $value | humanizePercentage }}"
- alert: HighLatency
expr: |
histogram_quantile(0.99, rate(http_request_duration_seconds_bucket[5m])) > 3
for: 5m
labels:
severity: warning
annotations:
summary: "API 延遲過高"
description: "P99 延遲為 {{ $value }}s"
報警通知的管道:
- Slack:適合非緊急的 warning 等級
- PagerDuty / Opsgenie:適合 critical 等級,會打電話叫醒你
- Email:通常太慢,不適合緊急報警
常見問題
Q:SRE 和 DevOps 的差別是什麼?
A:DevOps 是文化和流程的概念,目標是打破開發和維運之間的壁壘。SRE 是 Google 提出的一套具體實作方法,用軟體工程的思維處理維運問題。可以說 SRE 是 DevOps 的一種實作方式。
Q:我的專案很小,需要監控嗎?
A:如果只是個人專案或流量極低的服務,可以先用最基本的監控。但當開始有真實用戶時,至少要裝一個錯誤追蹤工具(Sentry),它讓你在用戶回報之前就知道出了什麼問題。
Q:報警太多怎麼辦?
A:這叫「alert fatigue」。解決方式是持續檢視和調整報警規則:
- 刪掉從來沒觸發過的報警(假的)
- 合併意義重複的報警
- 確保每個報警都有實際的後續行動,沒行動的報警等於沒有意義
總結:看不見的系統是無法改善的系統
SRE 的核心只有一句話:看不見的系統是無法改善的系統。
這篇文章涵蓋的三個工具:
- 日誌:事後查詢,了解「發生了什麼」
- 指標:趨勢監控,了解「系統健康狀態」
- 錯誤追蹤:主動發現,了解「什麼地方壞了」
一個穩定的服務不是沒有問題,而是能快速發現問題、定位問題、並修復問題。這三個工具串在一起,就構成了一套基本的可觀測性(Observability)系統。
下一步:把 Sentry 接入你目前的 Express API,看看它自動收集到了哪些你從沒注意過的錯誤。
本篇是「前端工程師後端入門」系列第六篇。系列前五篇:《從 Node.js 原生 HTTP 到 Express 框架》、《RESTful API 設計:前端視角的 API 思維》、《Prisma ORM:前端工程師的第一堂資料庫課》、《Docker 部署入門:把你的應用打包上線》、《GitHub Actions CI/CD:自動化你的部署流程》。