本文目录导读:

前端统计方案
使用 Axios 拦截器
// 全局错误计数器
const errorCounter = {
total: 0,
byStatus: {},
byUrl: {},
add(url, status) {
this.total++
this.byStatus[status] = (this.byStatus[status] || 0) + 1
this.byUrl[url] = (this.byUrl[url] || 0) + 1
},
report() {
console.table({
total: this.total,
byStatus: this.byStatus,
byUrl: this.byUrl
})
}
}
// Axios 拦截器
axios.interceptors.response.use(
response => response,
error => {
const config = error.config
const status = error.response?.status || 0
errorCounter.add(config.url, status)
// 当错误达到阈值时报告
if (errorCounter.total % 10 === 0) {
errorCounter.report()
// 可以发送到服务器
sendToServer(errorCounter)
}
return Promise.reject(error)
}
)
使用 Fetch API 封装
class ApiMonitor {
constructor() {
this.errors = {
total: 0,
recent: [], // 最近100条错误记录
byEndpoint: {},
byStatusCode: {}
}
}
async fetch(url, options = {}) {
try {
const response = await fetch(url, options)
if (!response.ok) {
this.recordError(url, response.status)
}
return response
} catch (error) {
this.recordError(url, 0, error.message)
throw error
}
}
recordError(url, status, message = '') {
this.errors.total++
this.errors.recent.unshift({
url,
status,
message,
timestamp: Date.now()
})
// 只保留最近100条
if (this.errors.recent.length > 100) {
this.errors.recent.pop()
}
// 按端点统计
this.errors.byEndpoint[url] = (this.errors.byEndpoint[url] || 0) + 1
// 按状态码统计
this.errors.byStatusCode[status] = (this.errors.byStatusCode[status] || 0) + 1
}
getStats() {
return {
...this.errors,
recent: this.errors.recent.slice(0, 10) // 只返回最近10条
}
}
}
// 使用
const api = new ApiMonitor()
const data = await api.fetch('/api/users')
后端统计方案
Node.js + Express 中间件
const errorStats = {
total: 0,
byRoute: {},
byStatusCode: {},
byHour: {},
// 每小时轮转
rotateHourly() {
const hour = new Date().getHours()
if (!this.byHour[hour]) {
this.byHour[hour] = { total: 0, errors: {} }
}
}
}
// 错误统计中间件
const errorMonitor = (err, req, res, next) => {
errorStats.total++
// 按路由统计
const route = req.baseUrl + req.path
if (!errorStats.byRoute[route]) {
errorStats.byRoute[route] = 0
}
errorStats.byRoute[route]++
// 按状态码统计
const status = err.status || 500
if (!errorStats.byStatusCode[status]) {
errorStats.byStatusCode[status] = 0
}
errorStats.byStatusCode[status]++
// 按小时统计
const hour = new Date().getHours()
if (!errorStats.byHour[hour]) {
errorStats.byHour[hour] = 0
}
errorStats.byHour[hour]++
next(err)
}
// 获取统计信息接口
app.get('/api/stats/errors', (req, res) => {
res.json(errorStats)
})
// 重置统计
app.delete('/api/stats/errors', (req, res) => {
Object.assign(errorStats, {
total: 0,
byRoute: {},
byStatusCode: {},
byHour: {}
})
res.sendStatus(200)
})
综合监控方案
使用装饰器模式
class ApiMonitor {
constructor(options = {}) {
this.options = {
reportInterval: 60000, // 1分钟报告一次
maxErrorsBeforeAlert: 10, // 10次错误触发告警
...options
}
this.stats = this.initStats()
this.startReporting()
}
initStats() {
return {
total: 0,
successful: 0,
failed: 0,
lastMinuteErrors: 0,
errorRate: 0,
endpoints: {}
}
}
wrap(endpoint, handler) {
return async (...args) => {
const startTime = Date.now()
try {
const result = await handler(...args)
this.recordSuccess(endpoint, Date.now() - startTime)
return result
} catch (error) {
this.recordError(endpoint, error)
throw error
}
}
}
recordSuccess(endpoint, duration) {
if (!this.stats.endpoints[endpoint]) {
this.stats.endpoints[endpoint] = {
total: 0,
errors: 0,
avgDuration: 0
}
}
const ep = this.stats.endpoints[endpoint]
ep.total++
ep.avgDuration = (ep.avgDuration * (ep.total - 1) + duration) / ep.total
this.stats.total++
this.stats.successful++
}
recordError(endpoint, error) {
if (!this.stats.endpoints[endpoint]) {
this.stats.endpoints[endpoint] = {
total: 0,
errors: 0,
lastError: null
}
}
const ep = this.stats.endpoints[endpoint]
ep.total++
ep.errors++
ep.lastError = {
message: error.message,
timestamp: Date.now()
}
this.stats.total++
this.stats.failed++
this.stats.lastMinuteErrors++
// 检查是否需要告警
if (ep.errors >= this.options.maxErrorsBeforeAlert) {
this.triggerAlert(endpoint, ep)
}
}
triggerAlert(endpoint, stats) {
console.warn(`⚠️ API Alert: ${endpoint} has ${stats.errors} errors`)
// 发送告警通知
this.sendAlert({
endpoint,
errors: stats.errors,
lastError: stats.lastError,
timestamp: new Date()
})
}
startReporting() {
setInterval(() => {
this.stats.errorRate = (this.stats.lastMinuteErrors / (this.stats.total || 1)) * 100
console.table({
'Total Requests': this.stats.total,
'Failed': this.stats.failed,
'Error Rate': `${this.stats.errorRate.toFixed(2)}%`,
'Last Minute Errors': this.stats.lastMinuteErrors
})
// 重置每分钟统计
this.stats.lastMinuteErrors = 0
// 发送到监控系统
this.sendToMonitoring(this.stats)
}, this.options.reportInterval)
}
async sendToMonitoring(stats) {
// 发送到你的监控系统
await fetch('/api/monitoring', {
method: 'POST',
body: JSON.stringify(stats)
})
}
}
// 使用
const monitor = new ApiMonitor({ maxErrorsBeforeAlert: 5 })
const apiHandler = {
getUser: monitor.wrap('/api/users', async (id) => {
const response = await fetch(`/api/users/${id}`)
return response.json()
})
}
实用辅助工具
错误率仪表板
class ErrorDashboard {
constructor() {
this.errors = []
this.MAX_RECORDS = 1000
}
addError(error) {
this.errors.push({
...error,
timestamp: new Date()
})
if (this.errors.length > this.MAX_RECORDS) {
this.errors.shift()
}
}
getErrorRate(timeWindow = 60000) { // 默认最近1分钟
const now = Date.now()
const recent = this.errors.filter(e =>
now - e.timestamp.getTime() < timeWindow
)
return {
count: recent.length,
rate: (recent.length / (timeWindow / 1000)).toFixed(2) + '/s'
}
}
getTopErrors(limit = 5) {
const errorCounts = {}
this.errors.forEach(e => {
const key = `${e.url}:${e.status}`
errorCounts[key] = (errorCounts[key] || 0) + 1
})
return Object.entries(errorCounts)
.sort((a, b) => b[1] - a[1])
.slice(0, limit)
.map(([key, count]) => ({
endpoint: key.split(':')[0],
status: key.split(':')[1],
count
}))
}
}
使用示例
// 全局监控
const monitor = new ApiMonitor()
const dashboard = new ErrorDashboard()
// 在请求封装中使用
async function request(url, options) {
try {
const response = await fetch(url, options)
return response
} catch (error) {
monitor.recordError(url, error)
dashboard.addError({
url,
status: error.status || 500,
message: error.message
})
// 检查错误率
const errorRate = dashboard.getErrorRate()
if (errorRate.count > 10) {
console.warn(`High error rate detected: ${errorRate.rate}`)
}
throw error
}
}
这些方案可以根据你的具体需求进行组合和定制,关键是要:
- 统一拦截所有请求
- 记录详细的错误信息
- 按需生成统计报告
- 设置告警阈值
版权声明:NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播