From 4ae7fa3d31541c4ac4d126be338d0a42ac630657 Mon Sep 17 00:00:00 2001 From: lyyyuna Date: Thu, 17 Jun 2021 19:53:00 +0800 Subject: [PATCH] adjust cover project structure --- cmd/server.go | 5 ++--- pkg/build/build.go | 6 +++++- pkg/build/goenv.go | 3 ++- pkg/cover/inject.go | 29 +++++++++++++++++++++++++---- pkg/cover/template.go | 6 +++--- pkg/server/api.go | 22 ++++++++++++++++++++++ pkg/server/common.go | 8 ++++++-- pkg/server/rpcstream.go | 4 ++++ pkg/server/server.go | 2 +- 9 files changed, 70 insertions(+), 15 deletions(-) diff --git a/cmd/server.go b/cmd/server.go index c43da80..3866686 100644 --- a/cmd/server.go +++ b/cmd/server.go @@ -1,7 +1,7 @@ package cmd import ( - "github.com/qiniu/goc/v2/pkg/build" + "github.com/qiniu/goc/v2/pkg/server" "github.com/spf13/cobra" ) @@ -22,6 +22,5 @@ func init() { } func serve(cmd *cobra.Command, args []string) { - b := build.NewBuild(cmd, args) - b.Build() + server.RunGocServerUntilExit(8080) } diff --git a/pkg/build/build.go b/pkg/build/build.go index 70058d5..3e35dba 100644 --- a/pkg/build/build.go +++ b/pkg/build/build.go @@ -1,6 +1,7 @@ package build import ( + "github.com/qiniu/goc/v2/pkg/cover" "github.com/qiniu/goc/v2/pkg/flag" "github.com/qiniu/goc/v2/pkg/log" "github.com/spf13/cobra" @@ -31,6 +32,9 @@ func NewBuild(cmd *cobra.Command, args []string) *Build { // 3. build the project in temp. func (b *Build) Build() { b.copyProjectToTmp() - defer b.clean() + // defer b.clean() log.Donef("project copied to temporary directory") + + // inject cover vars + cover.Inject() } diff --git a/pkg/build/goenv.go b/pkg/build/goenv.go index 42d0e76..d6db963 100644 --- a/pkg/build/goenv.go +++ b/pkg/build/goenv.go @@ -6,6 +6,7 @@ import ( "io" "os" "os/exec" + "path" "path/filepath" "strings" @@ -40,7 +41,7 @@ func (b *Build) readProjectMetaInfo() { // get cur pkg dir in the corresponding tmp dir config.GocConfig.TmpPkgDir = filepath.Join(config.GocConfig.TmpModProjectDir, config.GocConfig.CurPkgDir[len(config.GocConfig.CurModProjectDir):]) // get GlobalCoverVarImportPath - config.GocConfig.GlobalCoverVarImportPath = tmpFolderName(config.GocConfig.CurModProjectDir) + config.GocConfig.GlobalCoverVarImportPath = path.Join(config.GocConfig.ImportPath, tmpFolderName(config.GocConfig.CurModProjectDir)) log.Donef("project meta information parsed") } diff --git a/pkg/cover/inject.go b/pkg/cover/inject.go index 793420b..9b5a806 100644 --- a/pkg/cover/inject.go +++ b/pkg/cover/inject.go @@ -2,6 +2,7 @@ package cover import ( "os" + "path" "path/filepath" "github.com/qiniu/goc/v2/pkg/config" @@ -104,15 +105,15 @@ func getPkgTmpDir(pkgDir string) string { // - xxx.go // - yyy_package // - main.go -// - goc_http_cover_apis_auto_generated_11111_22222_bridge.go -// - goc_http_cover_apis_auto_generated_11111_22222_package +// - goc-http-cover-apis-auto-generated-11111-22222-bridge.go +// - goc-http-cover-apis-auto-generated-11111-22222-package // | // -- init.go // // 11111_22222_bridge.go just import 11111_22222_package, where package contains ws handlers. // 使用 bridge.go 文件是为了避免插桩逻辑中的变量名污染 main 包 func injectCoverHandler(where string, covers []*config.PackageCover) { - injectPkgName := "goc_http_cover_apis_auto_generated_11111_22222_package" + injectPkgName := "goc-http-cover-apis-auto-generated-11111-22222-package" wherePkg := filepath.Join(where, injectPkgName) err := os.MkdirAll(wherePkg, os.ModePerm) if err != nil { @@ -120,7 +121,7 @@ func injectCoverHandler(where string, covers []*config.PackageCover) { } // create bridge file - whereBridge := filepath.Join(where, "goc_http_cover_apis_auto_generated_11111_22222_bridge.go") + whereBridge := filepath.Join(where, "goc-http-cover-apis-auto-generated-11111-22222-bridge.go") f, err := os.Create(whereBridge) if err != nil { log.Fatalf("fail to create cover bridge file in temporary project: %v", err) @@ -144,6 +145,7 @@ func injectCoverHandler(where string, covers []*config.PackageCover) { if err != nil { log.Fatalf("fail to create cover handlers in temporary project: %v", err) } + defer f.Close() tmplData := struct { Covers []*config.PackageCover @@ -160,6 +162,25 @@ func injectCoverHandler(where string, covers []*config.PackageCover) { } } +// injectGlobalCoverVarFile 写入所有插桩变量的全局定义至单独一个文件 func injectGlobalCoverVarFile(decl string) { + globalCoverVarPackage := path.Base(config.GocConfig.GlobalCoverVarImportPath) + globalCoverDef := filepath.Join(config.GocConfig.TmpModProjectDir, globalCoverVarPackage) + err := os.MkdirAll(globalCoverDef, os.ModePerm) + if err != nil { + log.Fatalf("fail to create global cover definition package dir: %v", err) + } + coverFile, err := os.Create(filepath.Join(globalCoverDef, "cover.go")) + if err != nil { + log.Fatalf("fail to create global cover definition file: %v", err) + } + defer coverFile.Close() + + packageName := "package coverdef\n\n" + + _, err = coverFile.WriteString(packageName + decl) + if err != nil { + log.Fatalf("fail to write to global cover definition file: %v", err) + } } diff --git a/pkg/cover/template.go b/pkg/cover/template.go index 11be2d5..d1a315b 100644 --- a/pkg/cover/template.go +++ b/pkg/cover/template.go @@ -9,7 +9,7 @@ const coverBridge = ` package main -import _ {{.CoverImportPath | printf "%q"}} +import _ "{{.CoverImportPath}}" ` var coverMainTmpl = template.Must(template.New("coverMain").Parse(coverMain)) @@ -17,12 +17,12 @@ var coverMainTmpl = template.Must(template.New("coverMain").Parse(coverMain)) const coverMain = ` // Code generated by goc system. DO NOT EDIT. -package {{.Package | printf ".%q"}} +package cover import ( "log" - _cover {{.GlobalCoverVarImportPath | printf "%q"}} + _cover "{{.GlobalCoverVarImportPath}}" ) func init() { diff --git a/pkg/server/api.go b/pkg/server/api.go index c0fa3c8..aed6c54 100644 --- a/pkg/server/api.go +++ b/pkg/server/api.go @@ -4,6 +4,7 @@ import ( "net/http" "github.com/gin-gonic/gin" + "github.com/qiniu/goc/v2/pkg/log" ) // listServices return all service informations @@ -23,3 +24,24 @@ func (gs *gocServer) listServices(c *gin.Context) { "items": services, }) } + +// getProfiles get and merge all services' informations +func (gs *gocServer) getProfiles(c *gin.Context) { + gs.rpcClients.Range(func(key, value interface{}) bool { + service, ok := value.(gocCoveredClient) + if !ok { + return false + } + + var req GetProfileReq = "getprofile" + var res GetProfileRes + err := service.rpc.Call("GocAgent.GetProfile", req, &res) + if err != nil { + log.Errorf("fail to get profile from: %v, reasson: %v", service.Id, err) + return true + } + log.Infof("res: %v", res) + + return true + }) +} diff --git a/pkg/server/common.go b/pkg/server/common.go index 90c4e85..2af00a3 100644 --- a/pkg/server/common.go +++ b/pkg/server/common.go @@ -8,10 +8,14 @@ import ( ) const ( - PongWait = 60 * time.Second - PingWait = 30 * time.Second + PongWait = 20 * time.Second + PingWait = 10 * time.Second ) +type GetProfileReq string + +type GetProfileRes string + type ReadWriteCloser struct { ws *websocket.Conn r io.Reader diff --git a/pkg/server/rpcstream.go b/pkg/server/rpcstream.go index afcf195..2fdf04c 100644 --- a/pkg/server/rpcstream.go +++ b/pkg/server/rpcstream.go @@ -88,9 +88,13 @@ func (gs *gocServer) serveRpcStream(c *gin.Context) { break } } + + // 从维护的 websocket 链接中移除 + gs.rpcClients.Delete(clientId) gs.wsclose(ws, 1) }() + log.Infof("one client established, %v, cmdline: %v, pid: %v, hostname: %v", ws.RemoteAddr(), cmdline, pid, hostname) // new rpc client // 在这里 websocket server 作为 rpc 的客户端, // 发送 rpc 请求, diff --git a/pkg/server/server.go b/pkg/server/server.go index 302ad94..0bb6637 100644 --- a/pkg/server/server.go +++ b/pkg/server/server.go @@ -47,7 +47,7 @@ func RunGocServerUntilExit(port int) { r := gin.Default() v2 := r.Group("/v2") { - v2.GET("/cover/profile", nil) + v2.GET("/cover/profile", gs.getProfiles) v2.DELETE("/cover/profile", nil) v2.GET("/services", gs.listServices)