增强插件系统:引入插件辅助器和自动方法发现功能
- 在插件系统中添加 PluginHelper 结构体,简化插件方法的自动发现和注册。 - 更新 BasePluginImpl 以支持通过辅助器执行插件方法,增强 Execute 方法的灵活性。 - 统计插件和示例程序中实现新的方法调用方式,展示如何使用自动注册的方法。 - 通过结构体参数传递,简化插件调用过程,提升用户体验。 此更新提升了插件系统的可扩展性和易用性,便于开发者动态管理和执行插件功能。
This commit is contained in:
@@ -12,19 +12,29 @@ import (
|
||||
// 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.BasePluginImpl // 改为使用BasePluginImpl
|
||||
stats map[string]int64
|
||||
startTime time.Time
|
||||
mu sync.RWMutex
|
||||
tickerStop chan bool
|
||||
ticker *time.Ticker
|
||||
config map[string]interface{}
|
||||
}
|
||||
|
||||
// StatsParams 统计请求参数结构体
|
||||
// 允许通过结构体传递参数,简化调用
|
||||
type StatsParams struct {
|
||||
Name string `json:"name"` // 统计项名称
|
||||
Value int64 `json:"value"` // 统计值
|
||||
BytesReceived int64 `json:"bytesReceived"` // 接收字节数
|
||||
BytesSent int64 `json:"bytesSent"` // 发送字节数
|
||||
IsError bool `json:"isError"` // 是否为错误请求
|
||||
}
|
||||
|
||||
// Plugin 导出的插件变量
|
||||
var Plugin = &StatsPlugin{
|
||||
// 使用默认构造函数,不指定插件类型,将默认为通用插件
|
||||
BasePlugin: plugin.NewBasePluginWithDefaultType(
|
||||
BasePluginImpl: plugin.NewPluginWithDefaultType(
|
||||
"StatsPlugin",
|
||||
"1.0.0",
|
||||
"系统运行时统计插件",
|
||||
@@ -109,98 +119,68 @@ func (p *StatsPlugin) Stop(ctx context.Context) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Execute 执行插件功能
|
||||
func (p *StatsPlugin) Execute(ctx context.Context, action string, params map[string]interface{}) (interface{}, error) {
|
||||
switch action {
|
||||
case "incrementStat":
|
||||
// 需要参数: name, value
|
||||
name, ok := params["name"].(string)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("缺少必需参数: name")
|
||||
}
|
||||
// 以下方法将被自动注册为可通过Execute调用的操作
|
||||
|
||||
// 处理整数值参数
|
||||
var value int64
|
||||
if floatValue, ok := params["value"].(float64); ok {
|
||||
value = int64(floatValue)
|
||||
} else if strValue, ok := params["value"].(string); ok {
|
||||
var err error
|
||||
_, err = fmt.Sscanf(strValue, "%d", &value)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("参数value必须是整数: %v", err)
|
||||
}
|
||||
} else {
|
||||
return nil, fmt.Errorf("缺少必需参数: value")
|
||||
}
|
||||
// IncrementStat 增加统计值
|
||||
// 会被自动注册为"incrementstat"操作
|
||||
func (p *StatsPlugin) IncrementStat(name string, value int64) error {
|
||||
p.mu.Lock()
|
||||
defer p.mu.Unlock()
|
||||
|
||||
p.IncrementStat(name, value)
|
||||
return true, nil
|
||||
|
||||
case "getStat":
|
||||
// 需要参数: name
|
||||
name, ok := params["name"].(string)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("缺少必需参数: name")
|
||||
}
|
||||
|
||||
value := p.GetStat(name)
|
||||
return value, nil
|
||||
|
||||
case "getAllStats":
|
||||
// 不需要参数
|
||||
return p.GetAllStats(), nil
|
||||
|
||||
case "recordRequest":
|
||||
// 需要参数: bytesReceived, bytesSent, isError
|
||||
var bytesReceived, bytesSent int64
|
||||
var isError bool
|
||||
|
||||
// 处理bytesReceived参数
|
||||
if floatValue, ok := params["bytesReceived"].(float64); ok {
|
||||
bytesReceived = int64(floatValue)
|
||||
} else {
|
||||
return nil, fmt.Errorf("缺少必需参数: bytesReceived")
|
||||
}
|
||||
|
||||
// 处理bytesSent参数
|
||||
if floatValue, ok := params["bytesSent"].(float64); ok {
|
||||
bytesSent = int64(floatValue)
|
||||
} else {
|
||||
return nil, fmt.Errorf("缺少必需参数: bytesSent")
|
||||
}
|
||||
|
||||
// 处理isError参数
|
||||
if value, ok := params["isError"].(bool); ok {
|
||||
isError = value
|
||||
}
|
||||
|
||||
p.RecordRequest(bytesReceived, bytesSent, isError)
|
||||
return true, nil
|
||||
|
||||
case "resetStats":
|
||||
// 不需要参数
|
||||
p.mu.Lock()
|
||||
p.stats = make(map[string]int64)
|
||||
p.stats["requests"] = 0
|
||||
p.stats["errors"] = 0
|
||||
p.stats["bytes_sent"] = 0
|
||||
p.stats["bytes_received"] = 0
|
||||
p.startTime = time.Now()
|
||||
p.mu.Unlock()
|
||||
return true, nil
|
||||
|
||||
case "getStatsReport":
|
||||
// 生成统计报告
|
||||
report := p.generateStatsReport()
|
||||
return report, nil
|
||||
|
||||
default:
|
||||
return nil, fmt.Errorf("未知的操作: %s", action)
|
||||
if _, exists := p.stats[name]; exists {
|
||||
p.stats[name] += value
|
||||
} else {
|
||||
p.stats[name] = value
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// generateStatsReport 生成统计报告
|
||||
func (p *StatsPlugin) generateStatsReport() map[string]interface{} {
|
||||
// GetStat 获取统计值
|
||||
// 会被自动注册为"getstat"操作
|
||||
func (p *StatsPlugin) GetStat(name string) (int64, error) {
|
||||
p.mu.RLock()
|
||||
defer p.mu.RUnlock()
|
||||
|
||||
if value, exists := p.stats[name]; exists {
|
||||
return value, nil
|
||||
}
|
||||
return 0, fmt.Errorf("统计项 %s 不存在", name)
|
||||
}
|
||||
|
||||
// RecordRequest 记录请求
|
||||
// 会被自动注册为"recordrequest"操作
|
||||
func (p *StatsPlugin) RecordRequest(ctx context.Context, params StatsParams) error {
|
||||
p.IncrementStat("requests", 1)
|
||||
p.IncrementStat("bytes_received", params.BytesReceived)
|
||||
p.IncrementStat("bytes_sent", params.BytesSent)
|
||||
|
||||
if params.IsError {
|
||||
p.IncrementStat("errors", 1)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// ResetStats 重置统计数据
|
||||
// 会被自动注册为"resetstats"操作
|
||||
func (p *StatsPlugin) ResetStats() error {
|
||||
p.mu.Lock()
|
||||
defer p.mu.Unlock()
|
||||
|
||||
p.stats = make(map[string]int64)
|
||||
p.stats["requests"] = 0
|
||||
p.stats["errors"] = 0
|
||||
p.stats["bytes_sent"] = 0
|
||||
p.stats["bytes_received"] = 0
|
||||
p.startTime = time.Now()
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// GenerateStatsReport 生成统计报告
|
||||
// 会被自动注册为"generatestatsreport"操作
|
||||
func (p *StatsPlugin) GenerateStatsReport() (map[string]interface{}, error) {
|
||||
p.mu.RLock()
|
||||
defer p.mu.RUnlock()
|
||||
|
||||
@@ -215,10 +195,29 @@ func (p *StatsPlugin) generateStatsReport() map[string]interface{} {
|
||||
report["error_rate"] = float64(p.stats["errors"]) * 100 / float64(p.stats["requests"])
|
||||
}
|
||||
|
||||
return report
|
||||
return report, nil
|
||||
}
|
||||
|
||||
// GetAllStats 获取所有统计数据
|
||||
// 会被自动注册为"getallstats"操作
|
||||
func (p *StatsPlugin) GetAllStats() (map[string]int64, error) {
|
||||
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, nil
|
||||
}
|
||||
|
||||
// logStats 记录当前统计信息
|
||||
// 不会被注册为操作,因为它是内部方法
|
||||
func (p *StatsPlugin) logStats() {
|
||||
p.mu.RLock()
|
||||
defer p.mu.RUnlock()
|
||||
@@ -240,55 +239,10 @@ func (p *StatsPlugin) logStats() {
|
||||
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
|
||||
// GetAvailableOperations 获取可用操作列表
|
||||
// 这是一个帮助方法,列出所有可通过Execute调用的操作
|
||||
func (p *StatsPlugin) GetAvailableOperations() []string {
|
||||
return p.GetAvailableActions()
|
||||
}
|
||||
|
||||
// main 函数是必须的,但不会被调用
|
||||
|
Reference in New Issue
Block a user