refactor: frame converter and mp4 track improvements

- Refactor frame converter implementation
- Update mp4 track to use ICodex
- General refactoring and code improvements

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
langhuihui
2025-08-04 09:17:12 +08:00
parent b6ee2843b0
commit 8a9fffb987
262 changed files with 20831 additions and 12141 deletions

View File

@@ -2,6 +2,7 @@ package plugin_debug
import (
"context"
"encoding/json"
"fmt"
"io"
"net/http"
@@ -20,27 +21,35 @@ import (
"github.com/go-delve/delve/pkg/config"
"github.com/go-delve/delve/service/debugger"
"google.golang.org/protobuf/types/known/emptypb"
"google.golang.org/protobuf/types/known/timestamppb"
"m7s.live/v5"
"m7s.live/v5/pkg/task"
"m7s.live/v5/plugin/debug/pb"
debug "m7s.live/v5/plugin/debug/pkg"
"m7s.live/v5/plugin/debug/pkg/profile"
)
var _ = m7s.InstallPlugin[DebugPlugin](&pb.Api_ServiceDesc, pb.RegisterApiHandler)
var _ = m7s.InstallPlugin[DebugPlugin](m7s.PluginMeta{
ServiceDesc: &pb.Api_ServiceDesc,
RegisterGRPCHandler: pb.RegisterApiHandler,
})
var conf, _ = config.LoadConfig()
type DebugPlugin struct {
pb.UnimplementedApiServer
m7s.Plugin
ProfileDuration time.Duration `default:"10s" desc:"profile持续时间"`
Profile string `desc:"采集profile存储文件"`
Grfout string `default:"grf.out" desc:"grf输出文件"`
EnableChart bool `default:"true" desc:"是否启用图表功能"`
ProfileDuration time.Duration `default:"10s" desc:"profile持续时间"`
Profile string `desc:"采集profile存储文件"`
Grfout string `default:"grf.out" desc:"grf输出文件"`
EnableChart bool `default:"true" desc:"是否启用图表功能"`
EnableTaskHistory bool `default:"false" desc:"是否启用任务历史功能"`
// 添加缓存字段
cpuProfileData *profile.Profile // 缓存 CPU Profile 数据
cpuProfileOnce sync.Once // 确保只采集一次
cpuProfileLock sync.Mutex // 保护缓存数据
chartServer server
// Monitor plugin fields
session *debug.Session
}
type WriteToFile struct {
@@ -54,7 +63,7 @@ func (w *WriteToFile) Header() http.Header {
func (w *WriteToFile) WriteHeader(statusCode int) {}
func (p *DebugPlugin) OnInit() error {
func (p *DebugPlugin) Start() error {
// 启用阻塞分析
runtime.SetBlockProfileRate(1) // 设置采样率为1纳秒
@@ -76,6 +85,32 @@ func (p *DebugPlugin) OnInit() error {
p.AddTask(&p.chartServer)
}
// 初始化 monitor session
if p.DB != nil && p.EnableTaskHistory {
p.session = &debug.Session{
PID: os.Getpid(),
Args: strings.Join(os.Args, " "),
StartTime: time.Now(),
}
err := p.DB.AutoMigrate(p.session)
if err != nil {
return err
}
err = p.DB.Create(p.session).Error
if err != nil {
return err
}
err = p.DB.AutoMigrate(&debug.Task{})
if err != nil {
return err
}
p.Plugin.Server.Using(func() {
p.saveTask(p.Plugin.Server)
})
// 监听任务完成事件
p.Plugin.Server.OnDescendantsDispose(p.saveTask)
}
return nil
}
@@ -84,11 +119,92 @@ func (p *DebugPlugin) Pprof_Trace(w http.ResponseWriter, r *http.Request) {
pprof.Trace(w, r)
}
func (p *DebugPlugin) Dispose() {
// 保存 session 结束时间
if p.DB != nil && p.session != nil {
p.DB.Model(p.session).Update("end_time", time.Now())
}
}
// saveTask 保存任务信息到数据库
func (p *DebugPlugin) saveTask(task task.ITask) {
if p.DB == nil || p.session == nil {
return
}
var th debug.Task
th.SessionID = p.session.ID
th.TaskID = task.GetTaskID()
th.ParentID = task.GetParent().GetTaskID()
th.StartTime = task.GetTask().StartTime
th.EndTime = time.Now()
th.OwnerType = task.GetOwnerType()
th.TaskType = byte(task.GetTaskType())
th.Reason = task.StopReason().Error()
th.Level = task.GetLevel()
b, _ := json.Marshal(task.GetDescriptions())
th.Description = string(b)
p.DB.Create(&th)
}
func (p *DebugPlugin) Pprof_profile(w http.ResponseWriter, r *http.Request) {
r.URL.Path = "/debug" + r.URL.Path
pprof.Profile(w, r)
}
// Monitor plugin API implementations
func (p *DebugPlugin) SearchTask(ctx context.Context, req *pb.SearchTaskRequest) (res *pb.SearchTaskResponse, err error) {
if p.DB == nil {
return nil, fmt.Errorf("database is not initialized")
}
if !p.EnableTaskHistory {
return nil, fmt.Errorf("task history is not enabled")
}
res = &pb.SearchTaskResponse{}
var tasks []*debug.Task
tx := p.DB.Find(&tasks, "session_id = ?", req.SessionId)
if err = tx.Error; err == nil {
for _, t := range tasks {
res.Data = append(res.Data, &pb.Task{
Id: t.TaskID,
StartTime: timestamppb.New(t.StartTime),
EndTime: timestamppb.New(t.EndTime),
Owner: t.OwnerType,
Type: uint32(t.TaskType),
Description: t.Description,
Reason: t.Reason,
SessionId: t.SessionID,
ParentId: t.ParentID,
})
}
}
return
}
func (p *DebugPlugin) SessionList(context.Context, *emptypb.Empty) (res *pb.SessionListResponse, err error) {
if p.DB == nil {
return nil, fmt.Errorf("database is not initialized")
}
if !p.EnableTaskHistory {
return nil, fmt.Errorf("task history is not enabled")
}
res = &pb.SessionListResponse{}
var sessions []*debug.Session
tx := p.DB.Find(&sessions)
err = tx.Error
if err == nil {
for _, s := range sessions {
res.Data = append(res.Data, &pb.Session{
Id: s.ID,
Pid: uint32(s.PID),
Args: s.Args,
StartTime: timestamppb.New(s.StartTime),
EndTime: timestamppb.New(s.EndTime.Time),
})
}
}
return
}
func (p *DebugPlugin) ServeHTTP(w http.ResponseWriter, r *http.Request) {
if r.URL.Path == "/pprof" {
http.Redirect(w, r, "/debug/pprof/", http.StatusFound)
@@ -452,7 +568,7 @@ func (p *DebugPlugin) GetHeapGraph(ctx context.Context, empty *emptypb.Empty) (*
func (p *DebugPlugin) API_TcpDump(rw http.ResponseWriter, r *http.Request) {
query := r.URL.Query()
args := []string{"-W", "1"}
args := []string{"-S", "tcpdump", "-w", "dump.cap"}
if query.Get("interface") != "" {
args = append(args, "-i", query.Get("interface"))
}
@@ -466,25 +582,34 @@ func (p *DebugPlugin) API_TcpDump(rw http.ResponseWriter, r *http.Request) {
http.Error(rw, "duration is required", http.StatusBadRequest)
return
}
rw.Header().Set("Content-Type", "text/plain")
rw.Header().Set("Cache-Control", "no-cache")
rw.Header().Set("Content-Disposition", "attachment; filename=tcpdump.txt")
cmd := exec.CommandContext(p, "tcpdump", args...)
p.Info("starting tcpdump", "args", strings.Join(cmd.Args, " "))
cmd.Stdout = rw
cmd.Stderr = os.Stderr // 将错误输出重定向到标准错误
err := cmd.Start()
if err != nil {
http.Error(rw, fmt.Sprintf("failed to start tcpdump: %v", err), http.StatusInternalServerError)
return
}
// rw.Header().Set("Content-Type", "text/plain")
// rw.Header().Set("Cache-Control", "no-cache")
// rw.Header().Set("Content-Disposition", "attachment; filename=tcpdump.txt")
duration, err := strconv.Atoi(query.Get("duration"))
if err != nil {
http.Error(rw, "invalid duration", http.StatusBadRequest)
return
}
<-time.After(time.Duration(duration) * time.Second)
if err := cmd.Process.Kill(); err != nil {
p.Error("failed to kill tcpdump process", "error", err)
ctx, _ := context.WithTimeout(p, time.Duration(duration)*time.Second)
cmd := exec.CommandContext(ctx, "sudo", args...)
p.Info("starting tcpdump", "args", strings.Join(cmd.Args, " "))
cmd.Stdin = strings.NewReader(query.Get("password"))
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr // 将错误输出重定向到标准错误
err = cmd.Start()
if err != nil {
http.Error(rw, fmt.Sprintf("failed to start tcpdump: %v", err), http.StatusInternalServerError)
return
}
<-ctx.Done()
killcmd := exec.Command("sudo", "-S", "pkill", "-9", "tcpdump")
p.Info("killing tcpdump", "args", strings.Join(killcmd.Args, " "))
killcmd.Stdin = strings.NewReader(query.Get("password"))
killcmd.Stderr = os.Stderr
killcmd.Stdout = os.Stdout
killcmd.Run()
p.Info("kill done")
cmd.Wait()
p.Info("dump done")
http.ServeFile(rw, r, "dump.cap")
}

View File

@@ -11,7 +11,7 @@ import (
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
emptypb "google.golang.org/protobuf/types/known/emptypb"
_ "google.golang.org/protobuf/types/known/timestamppb"
timestamppb "google.golang.org/protobuf/types/known/timestamppb"
reflect "reflect"
sync "sync"
unsafe "unsafe"
@@ -646,6 +646,355 @@ func (x *CpuResponse) GetData() *CpuData {
return nil
}
// Monitor plugin messages
type SearchTaskRequest struct {
state protoimpl.MessageState `protogen:"open.v1"`
SessionId uint32 `protobuf:"varint,1,opt,name=sessionId,proto3" json:"sessionId,omitempty"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *SearchTaskRequest) Reset() {
*x = SearchTaskRequest{}
mi := &file_debug_proto_msgTypes[9]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *SearchTaskRequest) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*SearchTaskRequest) ProtoMessage() {}
func (x *SearchTaskRequest) ProtoReflect() protoreflect.Message {
mi := &file_debug_proto_msgTypes[9]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use SearchTaskRequest.ProtoReflect.Descriptor instead.
func (*SearchTaskRequest) Descriptor() ([]byte, []int) {
return file_debug_proto_rawDescGZIP(), []int{9}
}
func (x *SearchTaskRequest) GetSessionId() uint32 {
if x != nil {
return x.SessionId
}
return 0
}
type Task struct {
state protoimpl.MessageState `protogen:"open.v1"`
Id uint32 `protobuf:"varint,1,opt,name=id,proto3" json:"id,omitempty"`
Owner string `protobuf:"bytes,2,opt,name=owner,proto3" json:"owner,omitempty"`
Type uint32 `protobuf:"varint,3,opt,name=type,proto3" json:"type,omitempty"`
StartTime *timestamppb.Timestamp `protobuf:"bytes,4,opt,name=startTime,proto3" json:"startTime,omitempty"`
EndTime *timestamppb.Timestamp `protobuf:"bytes,5,opt,name=endTime,proto3" json:"endTime,omitempty"`
Description string `protobuf:"bytes,6,opt,name=description,proto3" json:"description,omitempty"`
Reason string `protobuf:"bytes,7,opt,name=reason,proto3" json:"reason,omitempty"`
SessionId uint32 `protobuf:"varint,8,opt,name=sessionId,proto3" json:"sessionId,omitempty"`
ParentId uint32 `protobuf:"varint,9,opt,name=parentId,proto3" json:"parentId,omitempty"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *Task) Reset() {
*x = Task{}
mi := &file_debug_proto_msgTypes[10]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *Task) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*Task) ProtoMessage() {}
func (x *Task) ProtoReflect() protoreflect.Message {
mi := &file_debug_proto_msgTypes[10]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use Task.ProtoReflect.Descriptor instead.
func (*Task) Descriptor() ([]byte, []int) {
return file_debug_proto_rawDescGZIP(), []int{10}
}
func (x *Task) GetId() uint32 {
if x != nil {
return x.Id
}
return 0
}
func (x *Task) GetOwner() string {
if x != nil {
return x.Owner
}
return ""
}
func (x *Task) GetType() uint32 {
if x != nil {
return x.Type
}
return 0
}
func (x *Task) GetStartTime() *timestamppb.Timestamp {
if x != nil {
return x.StartTime
}
return nil
}
func (x *Task) GetEndTime() *timestamppb.Timestamp {
if x != nil {
return x.EndTime
}
return nil
}
func (x *Task) GetDescription() string {
if x != nil {
return x.Description
}
return ""
}
func (x *Task) GetReason() string {
if x != nil {
return x.Reason
}
return ""
}
func (x *Task) GetSessionId() uint32 {
if x != nil {
return x.SessionId
}
return 0
}
func (x *Task) GetParentId() uint32 {
if x != nil {
return x.ParentId
}
return 0
}
type SearchTaskResponse struct {
state protoimpl.MessageState `protogen:"open.v1"`
Code uint32 `protobuf:"varint,1,opt,name=code,proto3" json:"code,omitempty"`
Message string `protobuf:"bytes,2,opt,name=message,proto3" json:"message,omitempty"`
Data []*Task `protobuf:"bytes,3,rep,name=data,proto3" json:"data,omitempty"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *SearchTaskResponse) Reset() {
*x = SearchTaskResponse{}
mi := &file_debug_proto_msgTypes[11]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *SearchTaskResponse) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*SearchTaskResponse) ProtoMessage() {}
func (x *SearchTaskResponse) ProtoReflect() protoreflect.Message {
mi := &file_debug_proto_msgTypes[11]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use SearchTaskResponse.ProtoReflect.Descriptor instead.
func (*SearchTaskResponse) Descriptor() ([]byte, []int) {
return file_debug_proto_rawDescGZIP(), []int{11}
}
func (x *SearchTaskResponse) GetCode() uint32 {
if x != nil {
return x.Code
}
return 0
}
func (x *SearchTaskResponse) GetMessage() string {
if x != nil {
return x.Message
}
return ""
}
func (x *SearchTaskResponse) GetData() []*Task {
if x != nil {
return x.Data
}
return nil
}
type Session struct {
state protoimpl.MessageState `protogen:"open.v1"`
Id uint32 `protobuf:"varint,1,opt,name=id,proto3" json:"id,omitempty"`
Pid uint32 `protobuf:"varint,2,opt,name=pid,proto3" json:"pid,omitempty"`
Args string `protobuf:"bytes,3,opt,name=args,proto3" json:"args,omitempty"`
StartTime *timestamppb.Timestamp `protobuf:"bytes,4,opt,name=startTime,proto3" json:"startTime,omitempty"`
EndTime *timestamppb.Timestamp `protobuf:"bytes,5,opt,name=endTime,proto3" json:"endTime,omitempty"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *Session) Reset() {
*x = Session{}
mi := &file_debug_proto_msgTypes[12]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *Session) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*Session) ProtoMessage() {}
func (x *Session) ProtoReflect() protoreflect.Message {
mi := &file_debug_proto_msgTypes[12]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use Session.ProtoReflect.Descriptor instead.
func (*Session) Descriptor() ([]byte, []int) {
return file_debug_proto_rawDescGZIP(), []int{12}
}
func (x *Session) GetId() uint32 {
if x != nil {
return x.Id
}
return 0
}
func (x *Session) GetPid() uint32 {
if x != nil {
return x.Pid
}
return 0
}
func (x *Session) GetArgs() string {
if x != nil {
return x.Args
}
return ""
}
func (x *Session) GetStartTime() *timestamppb.Timestamp {
if x != nil {
return x.StartTime
}
return nil
}
func (x *Session) GetEndTime() *timestamppb.Timestamp {
if x != nil {
return x.EndTime
}
return nil
}
type SessionListResponse struct {
state protoimpl.MessageState `protogen:"open.v1"`
Code uint32 `protobuf:"varint,1,opt,name=code,proto3" json:"code,omitempty"`
Message string `protobuf:"bytes,2,opt,name=message,proto3" json:"message,omitempty"`
Data []*Session `protobuf:"bytes,3,rep,name=data,proto3" json:"data,omitempty"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *SessionListResponse) Reset() {
*x = SessionListResponse{}
mi := &file_debug_proto_msgTypes[13]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *SessionListResponse) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*SessionListResponse) ProtoMessage() {}
func (x *SessionListResponse) ProtoReflect() protoreflect.Message {
mi := &file_debug_proto_msgTypes[13]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use SessionListResponse.ProtoReflect.Descriptor instead.
func (*SessionListResponse) Descriptor() ([]byte, []int) {
return file_debug_proto_rawDescGZIP(), []int{13}
}
func (x *SessionListResponse) GetCode() uint32 {
if x != nil {
return x.Code
}
return 0
}
func (x *SessionListResponse) GetMessage() string {
if x != nil {
return x.Message
}
return ""
}
func (x *SessionListResponse) GetData() []*Session {
if x != nil {
return x.Data
}
return nil
}
type CpuData struct {
state protoimpl.MessageState `protogen:"open.v1"`
TotalCpuTimeNs uint64 `protobuf:"varint,1,opt,name=total_cpu_time_ns,json=totalCpuTimeNs,proto3" json:"total_cpu_time_ns,omitempty"` // 总 CPU 时间(纳秒)
@@ -660,7 +1009,7 @@ type CpuData struct {
func (x *CpuData) Reset() {
*x = CpuData{}
mi := &file_debug_proto_msgTypes[9]
mi := &file_debug_proto_msgTypes[14]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@@ -672,7 +1021,7 @@ func (x *CpuData) String() string {
func (*CpuData) ProtoMessage() {}
func (x *CpuData) ProtoReflect() protoreflect.Message {
mi := &file_debug_proto_msgTypes[9]
mi := &file_debug_proto_msgTypes[14]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@@ -685,7 +1034,7 @@ func (x *CpuData) ProtoReflect() protoreflect.Message {
// Deprecated: Use CpuData.ProtoReflect.Descriptor instead.
func (*CpuData) Descriptor() ([]byte, []int) {
return file_debug_proto_rawDescGZIP(), []int{9}
return file_debug_proto_rawDescGZIP(), []int{14}
}
func (x *CpuData) GetTotalCpuTimeNs() uint64 {
@@ -744,7 +1093,7 @@ type FunctionProfile struct {
func (x *FunctionProfile) Reset() {
*x = FunctionProfile{}
mi := &file_debug_proto_msgTypes[10]
mi := &file_debug_proto_msgTypes[15]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@@ -756,7 +1105,7 @@ func (x *FunctionProfile) String() string {
func (*FunctionProfile) ProtoMessage() {}
func (x *FunctionProfile) ProtoReflect() protoreflect.Message {
mi := &file_debug_proto_msgTypes[10]
mi := &file_debug_proto_msgTypes[15]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@@ -769,7 +1118,7 @@ func (x *FunctionProfile) ProtoReflect() protoreflect.Message {
// Deprecated: Use FunctionProfile.ProtoReflect.Descriptor instead.
func (*FunctionProfile) Descriptor() ([]byte, []int) {
return file_debug_proto_rawDescGZIP(), []int{10}
return file_debug_proto_rawDescGZIP(), []int{15}
}
func (x *FunctionProfile) GetFunctionName() string {
@@ -820,7 +1169,7 @@ type GoroutineProfile struct {
func (x *GoroutineProfile) Reset() {
*x = GoroutineProfile{}
mi := &file_debug_proto_msgTypes[11]
mi := &file_debug_proto_msgTypes[16]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@@ -832,7 +1181,7 @@ func (x *GoroutineProfile) String() string {
func (*GoroutineProfile) ProtoMessage() {}
func (x *GoroutineProfile) ProtoReflect() protoreflect.Message {
mi := &file_debug_proto_msgTypes[11]
mi := &file_debug_proto_msgTypes[16]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@@ -845,7 +1194,7 @@ func (x *GoroutineProfile) ProtoReflect() protoreflect.Message {
// Deprecated: Use GoroutineProfile.ProtoReflect.Descriptor instead.
func (*GoroutineProfile) Descriptor() ([]byte, []int) {
return file_debug_proto_rawDescGZIP(), []int{11}
return file_debug_proto_rawDescGZIP(), []int{16}
}
func (x *GoroutineProfile) GetId() uint64 {
@@ -888,7 +1237,7 @@ type SystemCall struct {
func (x *SystemCall) Reset() {
*x = SystemCall{}
mi := &file_debug_proto_msgTypes[12]
mi := &file_debug_proto_msgTypes[17]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@@ -900,7 +1249,7 @@ func (x *SystemCall) String() string {
func (*SystemCall) ProtoMessage() {}
func (x *SystemCall) ProtoReflect() protoreflect.Message {
mi := &file_debug_proto_msgTypes[12]
mi := &file_debug_proto_msgTypes[17]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@@ -913,7 +1262,7 @@ func (x *SystemCall) ProtoReflect() protoreflect.Message {
// Deprecated: Use SystemCall.ProtoReflect.Descriptor instead.
func (*SystemCall) Descriptor() ([]byte, []int) {
return file_debug_proto_rawDescGZIP(), []int{12}
return file_debug_proto_rawDescGZIP(), []int{17}
}
func (x *SystemCall) GetName() string {
@@ -950,7 +1299,7 @@ type RuntimeStats struct {
func (x *RuntimeStats) Reset() {
*x = RuntimeStats{}
mi := &file_debug_proto_msgTypes[13]
mi := &file_debug_proto_msgTypes[18]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@@ -962,7 +1311,7 @@ func (x *RuntimeStats) String() string {
func (*RuntimeStats) ProtoMessage() {}
func (x *RuntimeStats) ProtoReflect() protoreflect.Message {
mi := &file_debug_proto_msgTypes[13]
mi := &file_debug_proto_msgTypes[18]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@@ -975,7 +1324,7 @@ func (x *RuntimeStats) ProtoReflect() protoreflect.Message {
// Deprecated: Use RuntimeStats.ProtoReflect.Descriptor instead.
func (*RuntimeStats) Descriptor() ([]byte, []int) {
return file_debug_proto_rawDescGZIP(), []int{13}
return file_debug_proto_rawDescGZIP(), []int{18}
}
func (x *RuntimeStats) GetGcCpuFraction() float64 {
@@ -1061,7 +1410,33 @@ const file_debug_proto_rawDesc = "" +
"\vCpuResponse\x12\x12\n" +
"\x04code\x18\x01 \x01(\rR\x04code\x12\x18\n" +
"\amessage\x18\x02 \x01(\tR\amessage\x12\"\n" +
"\x04data\x18\x03 \x01(\v2\x0e.debug.CpuDataR\x04data\"\xc5\x02\n" +
"\x04data\x18\x03 \x01(\v2\x0e.debug.CpuDataR\x04data\"1\n" +
"\x11SearchTaskRequest\x12\x1c\n" +
"\tsessionId\x18\x01 \x01(\rR\tsessionId\"\xa4\x02\n" +
"\x04Task\x12\x0e\n" +
"\x02id\x18\x01 \x01(\rR\x02id\x12\x14\n" +
"\x05owner\x18\x02 \x01(\tR\x05owner\x12\x12\n" +
"\x04type\x18\x03 \x01(\rR\x04type\x128\n" +
"\tstartTime\x18\x04 \x01(\v2\x1a.google.protobuf.TimestampR\tstartTime\x124\n" +
"\aendTime\x18\x05 \x01(\v2\x1a.google.protobuf.TimestampR\aendTime\x12 \n" +
"\vdescription\x18\x06 \x01(\tR\vdescription\x12\x16\n" +
"\x06reason\x18\a \x01(\tR\x06reason\x12\x1c\n" +
"\tsessionId\x18\b \x01(\rR\tsessionId\x12\x1a\n" +
"\bparentId\x18\t \x01(\rR\bparentId\"c\n" +
"\x12SearchTaskResponse\x12\x12\n" +
"\x04code\x18\x01 \x01(\rR\x04code\x12\x18\n" +
"\amessage\x18\x02 \x01(\tR\amessage\x12\x1f\n" +
"\x04data\x18\x03 \x03(\v2\v.debug.TaskR\x04data\"\xaf\x01\n" +
"\aSession\x12\x0e\n" +
"\x02id\x18\x01 \x01(\rR\x02id\x12\x10\n" +
"\x03pid\x18\x02 \x01(\rR\x03pid\x12\x12\n" +
"\x04args\x18\x03 \x01(\tR\x04args\x128\n" +
"\tstartTime\x18\x04 \x01(\v2\x1a.google.protobuf.TimestampR\tstartTime\x124\n" +
"\aendTime\x18\x05 \x01(\v2\x1a.google.protobuf.TimestampR\aendTime\"g\n" +
"\x13SessionListResponse\x12\x12\n" +
"\x04code\x18\x01 \x01(\rR\x04code\x12\x18\n" +
"\amessage\x18\x02 \x01(\tR\amessage\x12\"\n" +
"\x04data\x18\x03 \x03(\v2\x0e.debug.SessionR\x04data\"\xc5\x02\n" +
"\aCpuData\x12)\n" +
"\x11total_cpu_time_ns\x18\x01 \x01(\x04R\x0etotalCpuTimeNs\x120\n" +
"\x14sampling_interval_ns\x18\x02 \x01(\x04R\x12samplingIntervalNs\x124\n" +
@@ -1094,12 +1469,15 @@ const file_debug_proto_rawDesc = "" +
"\x0fgc_cpu_fraction\x18\x01 \x01(\x01R\rgcCpuFraction\x12\x19\n" +
"\bgc_count\x18\x02 \x01(\x04R\agcCount\x12'\n" +
"\x10gc_pause_time_ns\x18\x03 \x01(\x04R\rgcPauseTimeNs\x12(\n" +
"\x10blocking_time_ns\x18\x04 \x01(\x04R\x0eblockingTimeNs2\xd9\x02\n" +
"\x10blocking_time_ns\x18\x04 \x01(\x04R\x0eblockingTimeNs2\xa5\x04\n" +
"\x03api\x12O\n" +
"\aGetHeap\x12\x16.google.protobuf.Empty\x1a\x13.debug.HeapResponse\"\x17\x82\xd3\xe4\x93\x02\x11\x12\x0f/debug/api/heap\x12_\n" +
"\fGetHeapGraph\x12\x16.google.protobuf.Empty\x1a\x18.debug.HeapGraphResponse\"\x1d\x82\xd3\xe4\x93\x02\x17\x12\x15/debug/api/heap/graph\x12W\n" +
"\vGetCpuGraph\x12\x11.debug.CpuRequest\x1a\x17.debug.CpuGraphResponse\"\x1c\x82\xd3\xe4\x93\x02\x16\x12\x14/debug/api/cpu/graph\x12G\n" +
"\x06GetCpu\x12\x11.debug.CpuRequest\x1a\x12.debug.CpuResponse\"\x16\x82\xd3\xe4\x93\x02\x10\x12\x0e/debug/api/cpuB\x1dZ\x1bm7s.live/v5/plugin/debug/pbb\x06proto3"
"\x06GetCpu\x12\x11.debug.CpuRequest\x1a\x12.debug.CpuResponse\"\x16\x82\xd3\xe4\x93\x02\x10\x12\x0e/debug/api/cpu\x12f\n" +
"\n" +
"SearchTask\x12\x18.debug.SearchTaskRequest\x1a\x19.debug.SearchTaskResponse\"#\x82\xd3\xe4\x93\x02\x1d\x12\x1b/debug/api/task/{sessionId}\x12b\n" +
"\vSessionList\x12\x16.google.protobuf.Empty\x1a\x1a.debug.SessionListResponse\"\x1f\x82\xd3\xe4\x93\x02\x19\x12\x17/debug/api/session/listB\x1dZ\x1bm7s.live/v5/plugin/debug/pbb\x06proto3"
var (
file_debug_proto_rawDescOnce sync.Once
@@ -1113,47 +1491,63 @@ func file_debug_proto_rawDescGZIP() []byte {
return file_debug_proto_rawDescData
}
var file_debug_proto_msgTypes = make([]protoimpl.MessageInfo, 14)
var file_debug_proto_msgTypes = make([]protoimpl.MessageInfo, 19)
var file_debug_proto_goTypes = []any{
(*CpuRequest)(nil), // 0: debug.CpuRequest
(*HeapObject)(nil), // 1: debug.HeapObject
(*HeapStats)(nil), // 2: debug.HeapStats
(*HeapData)(nil), // 3: debug.HeapData
(*HeapEdge)(nil), // 4: debug.HeapEdge
(*HeapResponse)(nil), // 5: debug.HeapResponse
(*HeapGraphResponse)(nil), // 6: debug.HeapGraphResponse
(*CpuGraphResponse)(nil), // 7: debug.CpuGraphResponse
(*CpuResponse)(nil), // 8: debug.CpuResponse
(*CpuData)(nil), // 9: debug.CpuData
(*FunctionProfile)(nil), // 10: debug.FunctionProfile
(*GoroutineProfile)(nil), // 11: debug.GoroutineProfile
(*SystemCall)(nil), // 12: debug.SystemCall
(*RuntimeStats)(nil), // 13: debug.RuntimeStats
(*emptypb.Empty)(nil), // 14: google.protobuf.Empty
(*CpuRequest)(nil), // 0: debug.CpuRequest
(*HeapObject)(nil), // 1: debug.HeapObject
(*HeapStats)(nil), // 2: debug.HeapStats
(*HeapData)(nil), // 3: debug.HeapData
(*HeapEdge)(nil), // 4: debug.HeapEdge
(*HeapResponse)(nil), // 5: debug.HeapResponse
(*HeapGraphResponse)(nil), // 6: debug.HeapGraphResponse
(*CpuGraphResponse)(nil), // 7: debug.CpuGraphResponse
(*CpuResponse)(nil), // 8: debug.CpuResponse
(*SearchTaskRequest)(nil), // 9: debug.SearchTaskRequest
(*Task)(nil), // 10: debug.Task
(*SearchTaskResponse)(nil), // 11: debug.SearchTaskResponse
(*Session)(nil), // 12: debug.Session
(*SessionListResponse)(nil), // 13: debug.SessionListResponse
(*CpuData)(nil), // 14: debug.CpuData
(*FunctionProfile)(nil), // 15: debug.FunctionProfile
(*GoroutineProfile)(nil), // 16: debug.GoroutineProfile
(*SystemCall)(nil), // 17: debug.SystemCall
(*RuntimeStats)(nil), // 18: debug.RuntimeStats
(*timestamppb.Timestamp)(nil), // 19: google.protobuf.Timestamp
(*emptypb.Empty)(nil), // 20: google.protobuf.Empty
}
var file_debug_proto_depIdxs = []int32{
2, // 0: debug.HeapData.stats:type_name -> debug.HeapStats
1, // 1: debug.HeapData.objects:type_name -> debug.HeapObject
4, // 2: debug.HeapData.edges:type_name -> debug.HeapEdge
3, // 3: debug.HeapResponse.data:type_name -> debug.HeapData
9, // 4: debug.CpuResponse.data:type_name -> debug.CpuData
10, // 5: debug.CpuData.functions:type_name -> debug.FunctionProfile
11, // 6: debug.CpuData.goroutines:type_name -> debug.GoroutineProfile
12, // 7: debug.CpuData.system_calls:type_name -> debug.SystemCall
13, // 8: debug.CpuData.runtime_stats:type_name -> debug.RuntimeStats
14, // 9: debug.api.GetHeap:input_type -> google.protobuf.Empty
14, // 10: debug.api.GetHeapGraph:input_type -> google.protobuf.Empty
0, // 11: debug.api.GetCpuGraph:input_type -> debug.CpuRequest
0, // 12: debug.api.GetCpu:input_type -> debug.CpuRequest
5, // 13: debug.api.GetHeap:output_type -> debug.HeapResponse
6, // 14: debug.api.GetHeapGraph:output_type -> debug.HeapGraphResponse
7, // 15: debug.api.GetCpuGraph:output_type -> debug.CpuGraphResponse
8, // 16: debug.api.GetCpu:output_type -> debug.CpuResponse
13, // [13:17] is the sub-list for method output_type
9, // [9:13] is the sub-list for method input_type
9, // [9:9] is the sub-list for extension type_name
9, // [9:9] is the sub-list for extension extendee
0, // [0:9] is the sub-list for field type_name
14, // 4: debug.CpuResponse.data:type_name -> debug.CpuData
19, // 5: debug.Task.startTime:type_name -> google.protobuf.Timestamp
19, // 6: debug.Task.endTime:type_name -> google.protobuf.Timestamp
10, // 7: debug.SearchTaskResponse.data:type_name -> debug.Task
19, // 8: debug.Session.startTime:type_name -> google.protobuf.Timestamp
19, // 9: debug.Session.endTime:type_name -> google.protobuf.Timestamp
12, // 10: debug.SessionListResponse.data:type_name -> debug.Session
15, // 11: debug.CpuData.functions:type_name -> debug.FunctionProfile
16, // 12: debug.CpuData.goroutines:type_name -> debug.GoroutineProfile
17, // 13: debug.CpuData.system_calls:type_name -> debug.SystemCall
18, // 14: debug.CpuData.runtime_stats:type_name -> debug.RuntimeStats
20, // 15: debug.api.GetHeap:input_type -> google.protobuf.Empty
20, // 16: debug.api.GetHeapGraph:input_type -> google.protobuf.Empty
0, // 17: debug.api.GetCpuGraph:input_type -> debug.CpuRequest
0, // 18: debug.api.GetCpu:input_type -> debug.CpuRequest
9, // 19: debug.api.SearchTask:input_type -> debug.SearchTaskRequest
20, // 20: debug.api.SessionList:input_type -> google.protobuf.Empty
5, // 21: debug.api.GetHeap:output_type -> debug.HeapResponse
6, // 22: debug.api.GetHeapGraph:output_type -> debug.HeapGraphResponse
7, // 23: debug.api.GetCpuGraph:output_type -> debug.CpuGraphResponse
8, // 24: debug.api.GetCpu:output_type -> debug.CpuResponse
11, // 25: debug.api.SearchTask:output_type -> debug.SearchTaskResponse
13, // 26: debug.api.SessionList:output_type -> debug.SessionListResponse
21, // [21:27] is the sub-list for method output_type
15, // [15:21] is the sub-list for method input_type
15, // [15:15] is the sub-list for extension type_name
15, // [15:15] is the sub-list for extension extendee
0, // [0:15] is the sub-list for field type_name
}
func init() { file_debug_proto_init() }
@@ -1167,7 +1561,7 @@ func file_debug_proto_init() {
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
RawDescriptor: unsafe.Slice(unsafe.StringData(file_debug_proto_rawDesc), len(file_debug_proto_rawDesc)),
NumEnums: 0,
NumMessages: 14,
NumMessages: 19,
NumExtensions: 0,
NumServices: 1,
},

View File

@@ -140,6 +140,76 @@ func local_request_Api_GetCpu_0(ctx context.Context, marshaler runtime.Marshaler
}
func request_Api_SearchTask_0(ctx context.Context, marshaler runtime.Marshaler, client ApiClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
var protoReq SearchTaskRequest
var metadata runtime.ServerMetadata
var (
val string
ok bool
err error
_ = err
)
val, ok = pathParams["sessionId"]
if !ok {
return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "sessionId")
}
protoReq.SessionId, err = runtime.Uint32(val)
if err != nil {
return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "sessionId", err)
}
msg, err := client.SearchTask(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
return msg, metadata, err
}
func local_request_Api_SearchTask_0(ctx context.Context, marshaler runtime.Marshaler, server ApiServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
var protoReq SearchTaskRequest
var metadata runtime.ServerMetadata
var (
val string
ok bool
err error
_ = err
)
val, ok = pathParams["sessionId"]
if !ok {
return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "sessionId")
}
protoReq.SessionId, err = runtime.Uint32(val)
if err != nil {
return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "sessionId", err)
}
msg, err := server.SearchTask(ctx, &protoReq)
return msg, metadata, err
}
func request_Api_SessionList_0(ctx context.Context, marshaler runtime.Marshaler, client ApiClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
var protoReq emptypb.Empty
var metadata runtime.ServerMetadata
msg, err := client.SessionList(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
return msg, metadata, err
}
func local_request_Api_SessionList_0(ctx context.Context, marshaler runtime.Marshaler, server ApiServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
var protoReq emptypb.Empty
var metadata runtime.ServerMetadata
msg, err := server.SessionList(ctx, &protoReq)
return msg, metadata, err
}
// RegisterApiHandlerServer registers the http handlers for service Api to "mux".
// UnaryRPC :call ApiServer directly.
// StreamingRPC :currently unsupported pending https://github.com/grpc/grpc-go/issues/906.
@@ -246,6 +316,56 @@ func RegisterApiHandlerServer(ctx context.Context, mux *runtime.ServeMux, server
})
mux.Handle("GET", pattern_Api_SearchTask_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
ctx, cancel := context.WithCancel(req.Context())
defer cancel()
var stream runtime.ServerTransportStream
ctx = grpc.NewContextWithServerTransportStream(ctx, &stream)
inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
var err error
var annotatedContext context.Context
annotatedContext, err = runtime.AnnotateIncomingContext(ctx, mux, req, "/debug.Api/SearchTask", runtime.WithHTTPPathPattern("/debug/api/task/{sessionId}"))
if err != nil {
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
return
}
resp, md, err := local_request_Api_SearchTask_0(annotatedContext, inboundMarshaler, server, req, pathParams)
md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer())
annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md)
if err != nil {
runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err)
return
}
forward_Api_SearchTask_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
})
mux.Handle("GET", pattern_Api_SessionList_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
ctx, cancel := context.WithCancel(req.Context())
defer cancel()
var stream runtime.ServerTransportStream
ctx = grpc.NewContextWithServerTransportStream(ctx, &stream)
inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
var err error
var annotatedContext context.Context
annotatedContext, err = runtime.AnnotateIncomingContext(ctx, mux, req, "/debug.Api/SessionList", runtime.WithHTTPPathPattern("/debug/api/session/list"))
if err != nil {
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
return
}
resp, md, err := local_request_Api_SessionList_0(annotatedContext, inboundMarshaler, server, req, pathParams)
md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer())
annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md)
if err != nil {
runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err)
return
}
forward_Api_SessionList_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
})
return nil
}
@@ -375,6 +495,50 @@ func RegisterApiHandlerClient(ctx context.Context, mux *runtime.ServeMux, client
})
mux.Handle("GET", pattern_Api_SearchTask_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
ctx, cancel := context.WithCancel(req.Context())
defer cancel()
inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
var err error
var annotatedContext context.Context
annotatedContext, err = runtime.AnnotateContext(ctx, mux, req, "/debug.Api/SearchTask", runtime.WithHTTPPathPattern("/debug/api/task/{sessionId}"))
if err != nil {
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
return
}
resp, md, err := request_Api_SearchTask_0(annotatedContext, inboundMarshaler, client, req, pathParams)
annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md)
if err != nil {
runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err)
return
}
forward_Api_SearchTask_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
})
mux.Handle("GET", pattern_Api_SessionList_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
ctx, cancel := context.WithCancel(req.Context())
defer cancel()
inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
var err error
var annotatedContext context.Context
annotatedContext, err = runtime.AnnotateContext(ctx, mux, req, "/debug.Api/SessionList", runtime.WithHTTPPathPattern("/debug/api/session/list"))
if err != nil {
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
return
}
resp, md, err := request_Api_SessionList_0(annotatedContext, inboundMarshaler, client, req, pathParams)
annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md)
if err != nil {
runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err)
return
}
forward_Api_SessionList_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
})
return nil
}
@@ -386,6 +550,10 @@ var (
pattern_Api_GetCpuGraph_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"debug", "api", "cpu", "graph"}, ""))
pattern_Api_GetCpu_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2}, []string{"debug", "api", "cpu"}, ""))
pattern_Api_SearchTask_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 1, 0, 4, 1, 5, 3}, []string{"debug", "api", "task", "sessionId"}, ""))
pattern_Api_SessionList_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"debug", "api", "session", "list"}, ""))
)
var (
@@ -396,4 +564,8 @@ var (
forward_Api_GetCpuGraph_0 = runtime.ForwardResponseMessage
forward_Api_GetCpu_0 = runtime.ForwardResponseMessage
forward_Api_SearchTask_0 = runtime.ForwardResponseMessage
forward_Api_SessionList_0 = runtime.ForwardResponseMessage
)

View File

@@ -26,6 +26,17 @@ service api {
get: "/debug/api/cpu"
};
}
rpc SearchTask (SearchTaskRequest) returns (SearchTaskResponse) {
option (google.api.http) = {
get: "/debug/api/task/{sessionId}"
};
}
rpc SessionList (google.protobuf.Empty) returns (SessionListResponse) {
option (google.api.http) = {
get: "/debug/api/session/list"
};
}
}
// CPU分析请求参数
@@ -94,6 +105,43 @@ message CpuResponse {
CpuData data = 3;
}
// Monitor plugin messages
message SearchTaskRequest {
uint32 sessionId = 1;
}
message Task {
uint32 id = 1;
string owner = 2;
uint32 type = 3;
google.protobuf.Timestamp startTime = 4;
google.protobuf.Timestamp endTime = 5;
string description = 6;
string reason = 7;
uint32 sessionId = 8;
uint32 parentId = 9;
}
message SearchTaskResponse {
uint32 code = 1;
string message = 2;
repeated Task data = 3;
}
message Session {
uint32 id = 1;
uint32 pid = 2;
string args = 3;
google.protobuf.Timestamp startTime = 4;
google.protobuf.Timestamp endTime = 5;
}
message SessionListResponse {
uint32 code = 1;
string message = 2;
repeated Session data = 3;
}
message CpuData {
uint64 total_cpu_time_ns = 1; // 总 CPU 时间(纳秒)
uint64 sampling_interval_ns = 2; // 采样间隔(纳秒)

View File

@@ -24,6 +24,8 @@ const (
Api_GetHeapGraph_FullMethodName = "/debug.api/GetHeapGraph"
Api_GetCpuGraph_FullMethodName = "/debug.api/GetCpuGraph"
Api_GetCpu_FullMethodName = "/debug.api/GetCpu"
Api_SearchTask_FullMethodName = "/debug.api/SearchTask"
Api_SessionList_FullMethodName = "/debug.api/SessionList"
)
// ApiClient is the client API for Api service.
@@ -34,6 +36,8 @@ type ApiClient interface {
GetHeapGraph(ctx context.Context, in *emptypb.Empty, opts ...grpc.CallOption) (*HeapGraphResponse, error)
GetCpuGraph(ctx context.Context, in *CpuRequest, opts ...grpc.CallOption) (*CpuGraphResponse, error)
GetCpu(ctx context.Context, in *CpuRequest, opts ...grpc.CallOption) (*CpuResponse, error)
SearchTask(ctx context.Context, in *SearchTaskRequest, opts ...grpc.CallOption) (*SearchTaskResponse, error)
SessionList(ctx context.Context, in *emptypb.Empty, opts ...grpc.CallOption) (*SessionListResponse, error)
}
type apiClient struct {
@@ -84,6 +88,26 @@ func (c *apiClient) GetCpu(ctx context.Context, in *CpuRequest, opts ...grpc.Cal
return out, nil
}
func (c *apiClient) SearchTask(ctx context.Context, in *SearchTaskRequest, opts ...grpc.CallOption) (*SearchTaskResponse, error) {
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
out := new(SearchTaskResponse)
err := c.cc.Invoke(ctx, Api_SearchTask_FullMethodName, in, out, cOpts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *apiClient) SessionList(ctx context.Context, in *emptypb.Empty, opts ...grpc.CallOption) (*SessionListResponse, error) {
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
out := new(SessionListResponse)
err := c.cc.Invoke(ctx, Api_SessionList_FullMethodName, in, out, cOpts...)
if err != nil {
return nil, err
}
return out, nil
}
// ApiServer is the server API for Api service.
// All implementations must embed UnimplementedApiServer
// for forward compatibility.
@@ -92,6 +116,8 @@ type ApiServer interface {
GetHeapGraph(context.Context, *emptypb.Empty) (*HeapGraphResponse, error)
GetCpuGraph(context.Context, *CpuRequest) (*CpuGraphResponse, error)
GetCpu(context.Context, *CpuRequest) (*CpuResponse, error)
SearchTask(context.Context, *SearchTaskRequest) (*SearchTaskResponse, error)
SessionList(context.Context, *emptypb.Empty) (*SessionListResponse, error)
mustEmbedUnimplementedApiServer()
}
@@ -114,6 +140,12 @@ func (UnimplementedApiServer) GetCpuGraph(context.Context, *CpuRequest) (*CpuGra
func (UnimplementedApiServer) GetCpu(context.Context, *CpuRequest) (*CpuResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method GetCpu not implemented")
}
func (UnimplementedApiServer) SearchTask(context.Context, *SearchTaskRequest) (*SearchTaskResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method SearchTask not implemented")
}
func (UnimplementedApiServer) SessionList(context.Context, *emptypb.Empty) (*SessionListResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method SessionList not implemented")
}
func (UnimplementedApiServer) mustEmbedUnimplementedApiServer() {}
func (UnimplementedApiServer) testEmbeddedByValue() {}
@@ -207,6 +239,42 @@ func _Api_GetCpu_Handler(srv interface{}, ctx context.Context, dec func(interfac
return interceptor(ctx, in, info, handler)
}
func _Api_SearchTask_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(SearchTaskRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(ApiServer).SearchTask(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: Api_SearchTask_FullMethodName,
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(ApiServer).SearchTask(ctx, req.(*SearchTaskRequest))
}
return interceptor(ctx, in, info, handler)
}
func _Api_SessionList_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(emptypb.Empty)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(ApiServer).SessionList(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: Api_SessionList_FullMethodName,
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(ApiServer).SessionList(ctx, req.(*emptypb.Empty))
}
return interceptor(ctx, in, info, handler)
}
// Api_ServiceDesc is the grpc.ServiceDesc for Api service.
// It's only intended for direct use with grpc.RegisterService,
// and not to be introspected or modified (even as a copy)
@@ -230,6 +298,14 @@ var Api_ServiceDesc = grpc.ServiceDesc{
MethodName: "GetCpu",
Handler: _Api_GetCpu_Handler,
},
{
MethodName: "SearchTask",
Handler: _Api_SearchTask_Handler,
},
{
MethodName: "SessionList",
Handler: _Api_SessionList_Handler,
},
},
Streams: []grpc.StreamDesc{},
Metadata: "debug.proto",

View File

@@ -0,0 +1,27 @@
package debug
import (
"database/sql"
"time"
)
// Session 表示一个监控会话
type Session struct {
ID uint32 `gorm:"primarykey"`
PID int
Args string
StartTime time.Time
EndTime sql.NullTime
}
// Task 表示一个任务记录
type Task struct {
ID uint `gorm:"primarykey"`
SessionID, TaskID, ParentID uint32
StartTime, EndTime time.Time
OwnerType string
TaskType byte
Description string
Reason string
Level byte
}