Files
goproxy/examples/plugin/plugins/stats/stats_plugin.go
DarkiT 098c721ee9 增强插件系统:添加插件类型支持
- 在插件接口和基本插件结构中引入插件类型(PluginType),并定义了多种预定义的插件类型。
- 更新插件管理器以支持按类型管理插件,新增按类型获取、初始化和启动插件的方法。
- 修改现有插件(如日志插件和统计插件)以实现插件类型接口,确保兼容性。
- 优化插件信息输出,包含插件类型信息。

此更新提升了插件系统的灵活性和可扩展性,便于未来添加更多插件类型。
2025-03-14 11:07:53 +08:00

176 lines
3.7 KiB
Go

package main
import (
"context"
"fmt"
"sync"
"time"
"github.com/darkit/goproxy/examples/plugin"
)
// StatsPlugin 统计插件
// 用于收集和记录系统运行时统计数据
type StatsPlugin struct {
*plugin.BasePlugin
stats map[string]int64
startTime time.Time
mu sync.RWMutex
tickerStop chan bool
ticker *time.Ticker
config map[string]interface{}
}
// Plugin 导出的插件变量
var Plugin = &StatsPlugin{
BasePlugin: plugin.NewBasePlugin(
"StatsPlugin",
"1.0.0",
"系统运行时统计插件",
"开发者",
plugin.PluginTypeUtils, // 设置为工具类插件
),
stats: make(map[string]int64),
tickerStop: make(chan bool),
}
// Init 初始化插件
func (p *StatsPlugin) Init(ctx context.Context, config map[string]interface{}) error {
p.config = config
// 初始化统计指标
p.mu.Lock()
p.stats["requests"] = 0
p.stats["errors"] = 0
p.stats["bytes_sent"] = 0
p.stats["bytes_received"] = 0
p.mu.Unlock()
fmt.Println("统计插件初始化完成")
return nil
}
// Start 启动插件
func (p *StatsPlugin) Start(ctx context.Context) error {
p.startTime = time.Now()
// 启动定时统计任务
interval := 60 * time.Second // 默认60秒
// 从配置中获取统计间隔
if intervalSec, ok := p.config["interval_seconds"].(float64); ok {
interval = time.Duration(intervalSec) * time.Second
}
p.ticker = time.NewTicker(interval)
go func() {
for {
select {
case <-p.ticker.C:
p.logStats()
case <-p.tickerStop:
p.ticker.Stop()
return
case <-ctx.Done():
p.ticker.Stop()
return
}
}
}()
fmt.Println("统计插件已启动")
return nil
}
// Stop 停止插件
func (p *StatsPlugin) Stop(ctx context.Context) error {
if p.ticker != nil {
p.tickerStop <- true
}
// 输出最终统计信息
p.logStats()
fmt.Println("统计插件已停止")
return nil
}
// logStats 记录当前统计信息
func (p *StatsPlugin) logStats() {
p.mu.RLock()
defer p.mu.RUnlock()
uptime := time.Since(p.startTime).Seconds()
fmt.Printf("===== 系统统计信息 =====\n")
fmt.Printf("运行时间: %.2f 秒\n", uptime)
fmt.Printf("总请求数: %d\n", p.stats["requests"])
fmt.Printf("错误数: %d\n", p.stats["errors"])
fmt.Printf("发送字节: %d\n", p.stats["bytes_sent"])
fmt.Printf("接收字节: %d\n", p.stats["bytes_received"])
if uptime > 0 && p.stats["requests"] > 0 {
fmt.Printf("平均请求/秒: %.2f\n", float64(p.stats["requests"])/uptime)
fmt.Printf("错误率: %.2f%%\n", float64(p.stats["errors"])*100/float64(p.stats["requests"]))
}
fmt.Printf("=======================\n")
}
// IncrementStat 增加统计值
func (p *StatsPlugin) IncrementStat(name string, value int64) {
p.mu.Lock()
defer p.mu.Unlock()
if _, exists := p.stats[name]; exists {
p.stats[name] += value
} else {
p.stats[name] = value
}
}
// GetStat 获取统计值
func (p *StatsPlugin) GetStat(name string) int64 {
p.mu.RLock()
defer p.mu.RUnlock()
if value, exists := p.stats[name]; exists {
return value
}
return 0
}
// RecordRequest 记录请求
func (p *StatsPlugin) RecordRequest(bytesReceived, bytesSent int64, isError bool) {
p.IncrementStat("requests", 1)
p.IncrementStat("bytes_received", bytesReceived)
p.IncrementStat("bytes_sent", bytesSent)
if isError {
p.IncrementStat("errors", 1)
}
}
// GetAllStats 获取所有统计数据
func (p *StatsPlugin) GetAllStats() map[string]int64 {
p.mu.RLock()
defer p.mu.RUnlock()
// 创建一个副本
statsCopy := make(map[string]int64, len(p.stats))
for k, v := range p.stats {
statsCopy[k] = v
}
// 添加运行时间
statsCopy["uptime_seconds"] = int64(time.Since(p.startTime).Seconds())
return statsCopy
}
// main 函数是必须的,但不会被调用
func main() {
// 不会被执行,仅用于编译插件
}