Files
MyGoNavi/internal/jvm/jmx_provider.go
Syngnat 9d08b185d0 feat(jvm): 新增持续监控与采样链路
- 后端新增监控会话管理,支持启动、停止和历史查询

- JMX、Endpoint、Agent Provider 补齐监控快照采集能力

- JMX helper 增加内存、GC、线程、类加载采样并更新内嵌运行时

- 生成 Wails 监控接口绑定并补充后端回归测试
2026-04-26 14:33:41 +08:00

124 lines
3.8 KiB
Go

package jvm
import (
"context"
"fmt"
"GoNavi-Wails/internal/connection"
)
var jmxHelperRunner = runJMXHelper
type JMXProvider struct{}
func NewJMXProvider() Provider { return &JMXProvider{} }
func (p *JMXProvider) Mode() string { return ModeJMX }
func (p *JMXProvider) TestConnection(ctx context.Context, cfg connection.ConnectionConfig) error {
if err := validateJMXConnection(cfg); err != nil {
return err
}
_, err := jmxHelperRunner(ctx, cfg, jmxHelperCommandPing, nil, nil)
if err != nil {
return fmt.Errorf("jmx test connection failed: %w", err)
}
return nil
}
func (p *JMXProvider) ProbeCapabilities(ctx context.Context, cfg connection.ConnectionConfig) ([]Capability, error) {
if err := validateJMXConnection(cfg); err != nil {
return nil, err
}
readOnly := cfg.JVM.ReadOnly != nil && *cfg.JVM.ReadOnly
return []Capability{{
Mode: ModeJMX,
CanBrowse: true,
CanWrite: !readOnly,
CanPreview: true,
DisplayLabel: "JMX",
Reason: func() string {
if readOnly {
return "当前连接只读"
}
return ""
}(),
}}, nil
}
func (p *JMXProvider) ListResources(ctx context.Context, cfg connection.ConnectionConfig, parentPath string) ([]ResourceSummary, error) {
target, err := parseParentResourcePath(parentPath)
if err != nil {
return nil, err
}
resp, err := jmxHelperRunner(ctx, cfg, jmxHelperCommandList, target, nil)
if err != nil {
return nil, fmt.Errorf("jmx list resources failed: %w", err)
}
items := make([]ResourceSummary, 0, len(resp.Resources))
for _, item := range resp.Resources {
items = append(items, resourceSummaryFromHelper(item))
}
return items, nil
}
func (p *JMXProvider) GetValue(ctx context.Context, cfg connection.ConnectionConfig, resourcePath string) (ValueSnapshot, error) {
target, err := parseRequiredResourcePath(resourcePath)
if err != nil {
return ValueSnapshot{}, err
}
resp, err := jmxHelperRunner(ctx, cfg, jmxHelperCommandGet, &target, nil)
if err != nil {
return ValueSnapshot{}, fmt.Errorf("jmx get value failed: %w", err)
}
return valueSnapshotFromHelper(target, resp.Snapshot)
}
func (p *JMXProvider) GetMonitoringSnapshot(ctx context.Context, cfg connection.ConnectionConfig, previous *JVMMonitoringPoint) (JVMMonitoringSnapshot, error) {
resp, err := jmxHelperRunner(ctx, cfg, jmxHelperCommandMonitor, nil, nil)
if err != nil {
return JVMMonitoringSnapshot{}, fmt.Errorf("jmx get monitoring snapshot failed: %w", err)
}
snapshot, err := monitoringSnapshotFromHelper(resp.MonitoringSnapshot)
if err != nil {
return JVMMonitoringSnapshot{}, err
}
finalizeMonitoringSnapshot(&snapshot, previous)
return snapshot, nil
}
func (p *JMXProvider) PreviewChange(ctx context.Context, cfg connection.ConnectionConfig, req ChangeRequest) (ChangePreview, error) {
target, err := parseRequiredResourcePath(req.ResourceID)
if err != nil {
return ChangePreview{}, err
}
resp, err := jmxHelperRunner(ctx, cfg, jmxHelperCommandPreview, &target, &req)
if err != nil {
return ChangePreview{}, fmt.Errorf("jmx preview change failed: %w", err)
}
return previewFromHelper(target, resp.Preview)
}
func (p *JMXProvider) ApplyChange(ctx context.Context, cfg connection.ConnectionConfig, req ChangeRequest) (ApplyResult, error) {
target, err := parseRequiredResourcePath(req.ResourceID)
if err != nil {
return ApplyResult{}, err
}
if req.ExpectedVersion != "" {
before, getErr := p.GetValue(ctx, cfg, req.ResourceID)
if getErr != nil {
return ApplyResult{}, getErr
}
if before.Version != "" && before.Version != req.ExpectedVersion {
return ApplyResult{}, staleVersionError(req.ResourceID, req.ExpectedVersion, before.Version)
}
}
resp, err := jmxHelperRunner(ctx, cfg, jmxHelperCommandApply, &target, &req)
if err != nil {
return ApplyResult{}, fmt.Errorf("jmx apply change failed: %w", err)
}
return applyResultFromHelper(target, resp.ApplyResult)
}