From 1e8cea497181b38cff659ad9e15281d53bbe988b Mon Sep 17 00:00:00 2001 From: LiHui Date: Wed, 1 Jun 2022 15:00:33 +0800 Subject: [PATCH 1/2] add gops --- go.mod | 3 + go.sum | 12 + vendor/github.com/google/gops/LICENSE | 27 ++ vendor/github.com/google/gops/agent/agent.go | 285 ++++++++++++++++++ .../google/gops/agent/sockopt_reuseport.go | 37 +++ .../google/gops/agent/sockopt_unsupported.go | 14 + .../google/gops/internal/internal.go | 71 +++++ .../google/gops/internal/internal_go1_13.go | 20 ++ .../gops/internal/internal_lt_go1_13.go | 12 + .../github.com/google/gops/signal/signal.go | 38 +++ vendor/modules.txt | 13 +- 11 files changed, 530 insertions(+), 2 deletions(-) create mode 100644 vendor/github.com/google/gops/LICENSE create mode 100644 vendor/github.com/google/gops/agent/agent.go create mode 100644 vendor/github.com/google/gops/agent/sockopt_reuseport.go create mode 100644 vendor/github.com/google/gops/agent/sockopt_unsupported.go create mode 100644 vendor/github.com/google/gops/internal/internal.go create mode 100644 vendor/github.com/google/gops/internal/internal_go1_13.go create mode 100644 vendor/github.com/google/gops/internal/internal_lt_go1_13.go create mode 100644 vendor/github.com/google/gops/signal/signal.go diff --git a/go.mod b/go.mod index f8566d559..731089df5 100644 --- a/go.mod +++ b/go.mod @@ -50,6 +50,7 @@ require ( github.com/golang/example v0.0.0-20170904185048-46695d81d1fa github.com/google/go-cmp v0.5.6 github.com/google/go-containerregistry v0.6.0 + github.com/google/gops v0.3.23 github.com/google/uuid v1.1.2 github.com/gorilla/handlers v1.4.0 // indirect github.com/gorilla/websocket v1.4.2 @@ -81,6 +82,8 @@ require ( github.com/prometheus/client_golang v1.11.0 github.com/prometheus/common v0.26.0 github.com/prometheus/prometheus v1.8.2-0.20200907175821-8219b442c864 + github.com/shirou/gopsutil v0.0.0-20180427012116-c95755e4bcd7 // indirect + github.com/shirou/w32 v0.0.0-20160930032740-bb4de0191aa4 // indirect github.com/sony/sonyflake v0.0.0-20181109022403-6d5bd6181009 github.com/speps/go-hashids v2.0.0+incompatible github.com/spf13/cobra v1.2.1 diff --git a/go.sum b/go.sum index 8ec224b98..332a8e5e7 100644 --- a/go.sum +++ b/go.sum @@ -59,6 +59,7 @@ github.com/Shopify/logrus-bugsnag v0.0.0-20171204204709-577dee27f20d h1:UrqY+r/O github.com/Shopify/logrus-bugsnag v0.0.0-20171204204709-577dee27f20d/go.mod h1:HI8ITrYtUY+O+ZhtlqUnD8+KwNPOyugEhfP9fdUIaEQ= github.com/Shopify/sarama v1.19.0/go.mod h1:FVkBWblsNy7DGZRfXLU0O9RCGt5g3g3yEuWXgklEdEo= github.com/Shopify/toxiproxy v2.1.4+incompatible/go.mod h1:OXgGpZ6Cli1/URJOF1DMxUHB2q5Ap20/P/eIdh4G0pI= +github.com/StackExchange/wmi v1.2.1/go.mod h1:rcmrprowKIVzvc+NUiLncP2uuArMWLCbu9SBzvHz7e8= github.com/VividCortex/gohistogram v1.0.0/go.mod h1:Pf5mBqqDxYaXu3hDrrU+w6nw50o/4+TcAqDqk/vUH7g= github.com/afex/hystrix-go v0.0.0-20180502004556-fa1af6a1f4f5/go.mod h1:SkGFH1ia65gfNATL8TAiHDNxPzPdmEL5uirI2Uyuz6c= github.com/agnivade/levenshtein v1.0.1/go.mod h1:CURSv5d9Uaml+FovSIICkLbAUZ9S4RqaHDIsdSBg7lM= @@ -287,6 +288,8 @@ github.com/go-logr/logr v0.4.0 h1:K7/B1jt6fIBQVd4Owv2MqGQClcgf0R266+7C/QjRcLc= github.com/go-logr/logr v0.4.0/go.mod h1:z6/tIYblkpsD+a4lm/fGIIU9mZ+XfAiaFtq7xTgseGU= github.com/go-logr/zapr v0.4.0 h1:uc1uML3hRYL9/ZZPdgHS/n8Nzo+eaYL/Efxkkamf7OM= github.com/go-logr/zapr v0.4.0/go.mod h1:tabnROwaDl0UNxkVeFRbY8bwB37GwRv0P8lg6aAiEnk= +github.com/go-ole/go-ole v1.2.5/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0= +github.com/go-ole/go-ole v1.2.6-0.20210915003542-8b1f7f90f6b1/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0= github.com/go-openapi/analysis v0.19.10 h1:5BHISBAXOc/aJK25irLZnx2D3s6WyYaY9D4gmuz9fdE= github.com/go-openapi/analysis v0.19.10/go.mod h1:qmhS3VNFxBlquFJ0RGoDtylO9y4pgTAUNE9AEEMdlJQ= github.com/go-openapi/errors v0.19.4 h1:fSGwO1tSYHFu70NKaWJt5Qh0qoBRtCm/mXS1yhf+0W0= @@ -388,6 +391,8 @@ github.com/google/go-querystring v1.0.0 h1:Xkwi/a1rcvNg1PPYe5vI8GbeBY/jrVuDX5ASu github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck= github.com/google/gofuzz v1.1.0 h1:Hsa8mG0dQ46ij8Sl2AYJDUv1oA9/d6Vk+3LG99Oe02g= github.com/google/gofuzz v1.1.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= +github.com/google/gops v0.3.23 h1:OjsHRINl5FiIyTc8jivIg4UN0GY6Nh32SL8KRbl8GQo= +github.com/google/gops v0.3.23/go.mod h1:7diIdLsqpCihPSX3fQagksT/Ku/y4RL9LHTlKyEUDl8= github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= github.com/google/pprof v0.0.0-20200417002340-c6e0a841f49a/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= @@ -501,6 +506,7 @@ github.com/kelseyhightower/envconfig v1.4.0 h1:Im6hONhd3pLkfDFsbRgu68RDNkGF1r3dv github.com/kelseyhightower/envconfig v1.4.0/go.mod h1:cccZRl6mQpaq41TPp5QxidR+Sa3axMbJDNb//FQX6Gg= github.com/kevinburke/ssh_config v0.0.0-20180830205328-81db2a75821e h1:RgQk53JHp/Cjunrr1WlsXSZpqXn+uREuHvUVcK82CV8= github.com/kevinburke/ssh_config v0.0.0-20180830205328-81db2a75821e/go.mod h1:CT57kijsi8u/K/BOFA39wgDQJ9CxiF4nAY/ojJ6r6mM= +github.com/keybase/go-ps v0.0.0-20190827175125-91aafc93ba19/go.mod h1:hY+WOq6m2FpbvyrI93sMaypsttvaIL5nhVR92dTMUcQ= github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/kisielk/sqlstruct v0.0.0-20150923205031-648daed35d49/go.mod h1:yyMNCyc/Ib3bDTKd379tNMpB/7/H5TjM2Y9QJ5THLbE= @@ -741,6 +747,9 @@ github.com/segmentio/kafka-go v0.2.0/go.mod h1:X6itGqS9L4jDletMsxZ7Dz+JFWxM6JHfP github.com/sercand/kuberesolver v2.4.0+incompatible/go.mod h1:lWF3GL0xptCB/vCiJPl/ZshwPsX/n4Y7u0CW9E7aQIQ= github.com/sergi/go-diff v1.0.0 h1:Kpca3qRNrduNnOQeazBd0ysaKrUJiIuISHxogkT9RPQ= github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo= +github.com/shirou/gopsutil v0.0.0-20180427012116-c95755e4bcd7/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA= +github.com/shirou/gopsutil/v3 v3.21.9/go.mod h1:YWp/H8Qs5fVmf17v7JNZzA0mPJ+mS2e9JdiUF9LlKzQ= +github.com/shirou/w32 v0.0.0-20160930032740-bb4de0191aa4/go.mod h1:qsXQc7+bwAM3Q1u/4XEfrquwF8Lw7D7y5cD8CuHnfIc= github.com/shopspring/decimal v0.0.0-20180709203117-cd690d0c9e24/go.mod h1:M+9NzErvs504Cn4c5DxATwIqPbtswREoFCre64PpcG4= github.com/shurcooL/httpfs v0.0.0-20190707220628-8d4bc4ba7749/go.mod h1:ZY1cvUeJuFPAdZ/B6v7RHavJWZn2YPVFQ1OSXhCGOkg= github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= @@ -784,6 +793,8 @@ github.com/thanos-io/thanos v0.13.1-0.20200910143741-e0b7f7b32e9c/go.mod h1:1Ize github.com/tidwall/pretty v1.0.0 h1:HsD+QiTn7sK6flMKIvNmpqz1qrpP3Ps6jOKIKMooyg4= github.com/tidwall/pretty v1.0.0/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk= github.com/tinylib/msgp v1.1.0/go.mod h1:+d+yLhGm8mzTaHzB+wgMYrodPfmZrzkirds8fDWklFE= +github.com/tklauser/go-sysconf v0.3.9/go.mod h1:11DU/5sG7UexIrp/O6g35hrWzu0JxlwQ3LSFUzyeuhs= +github.com/tklauser/numcpus v0.3.0/go.mod h1:yFGUr7TUHQRAhyqBcEg0Ge34zDBAsIvJJcyE6boqnA8= github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5 h1:LnC5Kc/wtumK+WB441p7ynQJzVuNRJiqddSIE3IlSEQ= github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= github.com/tv42/httpunix v0.0.0-20150427012821-b75d8614f926/go.mod h1:9ESjWnEqriFuLhtthL60Sar/7RFoluCcXsuvEwTV5KM= @@ -991,6 +1002,7 @@ k8s.io/utils v0.0.0-20200603063816-c1c6865ac451/go.mod h1:jPW/WVKK9YHAvNhRxK0md/ kubesphere.io/monitoring-dashboard v0.2.2 h1:aniATtXLgRAAvKOjd2UxWWHMh4/T7a0HoQ9bd+/bGcA= kubesphere.io/monitoring-dashboard v0.2.2/go.mod h1:ksDjmOuoN0C0GuYp0s5X3186cPgk2asLUaO1WlEKISY= rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= +rsc.io/goversion v1.2.0/go.mod h1:Eih9y/uIBS3ulggl7KNJ09xGSLcuNaLgmvvqa07sgfo= rsc.io/letsencrypt v0.0.1 h1:DV0d09Ne9E7UUa9ZqWktZ9L2VmybgTgfq7xlfFR/bbU= rsc.io/letsencrypt v0.0.1/go.mod h1:buyQKZ6IXrRnB7TdkHP0RyEybLx18HHyOSoTyoOLqNY= rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4= diff --git a/vendor/github.com/google/gops/LICENSE b/vendor/github.com/google/gops/LICENSE new file mode 100644 index 000000000..55e52a010 --- /dev/null +++ b/vendor/github.com/google/gops/LICENSE @@ -0,0 +1,27 @@ +Copyright (c) 2016 The Go Authors. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the following disclaimer +in the documentation and/or other materials provided with the +distribution. + * Neither the name of Google Inc. nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/vendor/github.com/google/gops/agent/agent.go b/vendor/github.com/google/gops/agent/agent.go new file mode 100644 index 000000000..2af03e5a5 --- /dev/null +++ b/vendor/github.com/google/gops/agent/agent.go @@ -0,0 +1,285 @@ +// Copyright 2016 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Package agent provides hooks programs can register to retrieve +// diagnostics data by using gops. +package agent + +import ( + "bufio" + "context" + "encoding/binary" + "fmt" + "io" + "io/ioutil" + "net" + "os" + gosignal "os/signal" + "path/filepath" + "runtime" + "runtime/debug" + "runtime/pprof" + "runtime/trace" + "strconv" + "strings" + "sync" + "syscall" + "time" + + "github.com/google/gops/internal" + "github.com/google/gops/signal" +) + +const defaultAddr = "127.0.0.1:0" + +var ( + mu sync.Mutex + portfile string + listener net.Listener + + units = []string{" bytes", "KB", "MB", "GB", "TB", "PB"} +) + +// Options allows configuring the started agent. +type Options struct { + // Addr is the host:port the agent will be listening at. + // Optional. + Addr string + + // ConfigDir is the directory to store the configuration file, + // PID of the gops process, filename, port as well as content. + // Optional. + ConfigDir string + + // ShutdownCleanup automatically cleans up resources if the + // running process receives an interrupt. Otherwise, users + // can call Close before shutting down. + // Optional. + ShutdownCleanup bool + + // ReuseSocketAddrAndPort determines whether the SO_REUSEADDR and + // SO_REUSEPORT socket options should be set on the listening socket of + // the agent. This option is only effective on unix-like OSes and if + // Addr is set to a fixed host:port. + // Optional. + ReuseSocketAddrAndPort bool +} + +// Listen starts the gops agent on a host process. Once agent started, users +// can use the advanced gops features. The agent will listen to Interrupt +// signals and exit the process, if you need to perform further work on the +// Interrupt signal use the options parameter to configure the agent +// accordingly. +// +// Note: The agent exposes an endpoint via a TCP connection that can be used by +// any program on the system. Review your security requirements before starting +// the agent. +func Listen(opts Options) error { + mu.Lock() + defer mu.Unlock() + + if portfile != "" { + return fmt.Errorf("gops: agent already listening at: %v", listener.Addr()) + } + + // new + gopsdir := opts.ConfigDir + if gopsdir == "" { + cfgDir, err := internal.ConfigDir() + if err != nil { + return err + } + gopsdir = cfgDir + } + + err := os.MkdirAll(gopsdir, os.ModePerm) + if err != nil { + return err + } + if opts.ShutdownCleanup { + gracefulShutdown() + } + + addr := opts.Addr + if addr == "" { + addr = defaultAddr + } + var lc net.ListenConfig + if opts.ReuseSocketAddrAndPort { + lc.Control = setReuseAddrAndPortSockopts + } + listener, err = lc.Listen(context.Background(), "tcp", addr) + if err != nil { + return err + } + port := listener.Addr().(*net.TCPAddr).Port + portfile = filepath.Join(gopsdir, strconv.Itoa(os.Getpid())) + err = ioutil.WriteFile(portfile, []byte(strconv.Itoa(port)), os.ModePerm) + if err != nil { + return err + } + + go listen() + return nil +} + +func listen() { + buf := make([]byte, 1) + for { + fd, err := listener.Accept() + if err != nil { + // No great way to check for this, see https://golang.org/issues/4373. + if !strings.Contains(err.Error(), "use of closed network connection") { + fmt.Fprintf(os.Stderr, "gops: %v\n", err) + } + if netErr, ok := err.(net.Error); ok && !netErr.Temporary() { + break + } + continue + } + if _, err := fd.Read(buf); err != nil { + fmt.Fprintf(os.Stderr, "gops: %v\n", err) + continue + } + if err := handle(fd, buf); err != nil { + fmt.Fprintf(os.Stderr, "gops: %v\n", err) + continue + } + fd.Close() + } +} + +func gracefulShutdown() { + c := make(chan os.Signal, 1) + gosignal.Notify(c, syscall.SIGINT, syscall.SIGTERM, syscall.SIGQUIT) + go func() { + // cleanup the socket on shutdown. + sig := <-c + Close() + ret := 1 + if sig == syscall.SIGTERM { + ret = 0 + } + os.Exit(ret) + }() +} + +// Close closes the agent, removing temporary files and closing the TCP listener. +// If no agent is listening, Close does nothing. +func Close() { + mu.Lock() + defer mu.Unlock() + + if portfile != "" { + os.Remove(portfile) + portfile = "" + } + if listener != nil { + listener.Close() + } +} + +func formatBytes(val uint64) string { + var i int + var target uint64 + for i = range units { + target = 1 << uint(10*(i+1)) + if val < target { + break + } + } + if i > 0 { + return fmt.Sprintf("%0.2f%s (%d bytes)", float64(val)/(float64(target)/1024), units[i], val) + } + return fmt.Sprintf("%d bytes", val) +} + +func handle(conn io.ReadWriter, msg []byte) error { + switch msg[0] { + case signal.StackTrace: + return pprof.Lookup("goroutine").WriteTo(conn, 2) + case signal.GC: + runtime.GC() + _, err := conn.Write([]byte("ok")) + return err + case signal.MemStats: + var s runtime.MemStats + runtime.ReadMemStats(&s) + fmt.Fprintf(conn, "alloc: %v\n", formatBytes(s.Alloc)) + fmt.Fprintf(conn, "total-alloc: %v\n", formatBytes(s.TotalAlloc)) + fmt.Fprintf(conn, "sys: %v\n", formatBytes(s.Sys)) + fmt.Fprintf(conn, "lookups: %v\n", s.Lookups) + fmt.Fprintf(conn, "mallocs: %v\n", s.Mallocs) + fmt.Fprintf(conn, "frees: %v\n", s.Frees) + fmt.Fprintf(conn, "heap-alloc: %v\n", formatBytes(s.HeapAlloc)) + fmt.Fprintf(conn, "heap-sys: %v\n", formatBytes(s.HeapSys)) + fmt.Fprintf(conn, "heap-idle: %v\n", formatBytes(s.HeapIdle)) + fmt.Fprintf(conn, "heap-in-use: %v\n", formatBytes(s.HeapInuse)) + fmt.Fprintf(conn, "heap-released: %v\n", formatBytes(s.HeapReleased)) + fmt.Fprintf(conn, "heap-objects: %v\n", s.HeapObjects) + fmt.Fprintf(conn, "stack-in-use: %v\n", formatBytes(s.StackInuse)) + fmt.Fprintf(conn, "stack-sys: %v\n", formatBytes(s.StackSys)) + fmt.Fprintf(conn, "stack-mspan-inuse: %v\n", formatBytes(s.MSpanInuse)) + fmt.Fprintf(conn, "stack-mspan-sys: %v\n", formatBytes(s.MSpanSys)) + fmt.Fprintf(conn, "stack-mcache-inuse: %v\n", formatBytes(s.MCacheInuse)) + fmt.Fprintf(conn, "stack-mcache-sys: %v\n", formatBytes(s.MCacheSys)) + fmt.Fprintf(conn, "other-sys: %v\n", formatBytes(s.OtherSys)) + fmt.Fprintf(conn, "gc-sys: %v\n", formatBytes(s.GCSys)) + fmt.Fprintf(conn, "next-gc: when heap-alloc >= %v\n", formatBytes(s.NextGC)) + lastGC := "-" + if s.LastGC != 0 { + lastGC = fmt.Sprint(time.Unix(0, int64(s.LastGC))) + } + fmt.Fprintf(conn, "last-gc: %v\n", lastGC) + fmt.Fprintf(conn, "gc-pause-total: %v\n", time.Duration(s.PauseTotalNs)) + fmt.Fprintf(conn, "gc-pause: %v\n", s.PauseNs[(s.NumGC+255)%256]) + fmt.Fprintf(conn, "gc-pause-end: %v\n", s.PauseEnd[(s.NumGC+255)%256]) + fmt.Fprintf(conn, "num-gc: %v\n", s.NumGC) + fmt.Fprintf(conn, "num-forced-gc: %v\n", s.NumForcedGC) + fmt.Fprintf(conn, "gc-cpu-fraction: %v\n", s.GCCPUFraction) + fmt.Fprintf(conn, "enable-gc: %v\n", s.EnableGC) + fmt.Fprintf(conn, "debug-gc: %v\n", s.DebugGC) + case signal.Version: + fmt.Fprintf(conn, "%v\n", runtime.Version()) + case signal.HeapProfile: + return pprof.WriteHeapProfile(conn) + case signal.CPUProfile: + if err := pprof.StartCPUProfile(conn); err != nil { + return err + } + time.Sleep(30 * time.Second) + pprof.StopCPUProfile() + case signal.Stats: + fmt.Fprintf(conn, "goroutines: %v\n", runtime.NumGoroutine()) + fmt.Fprintf(conn, "OS threads: %v\n", pprof.Lookup("threadcreate").Count()) + fmt.Fprintf(conn, "GOMAXPROCS: %v\n", runtime.GOMAXPROCS(0)) + fmt.Fprintf(conn, "num CPU: %v\n", runtime.NumCPU()) + case signal.BinaryDump: + path, err := os.Executable() + if err != nil { + return err + } + f, err := os.Open(path) + if err != nil { + return err + } + defer f.Close() + + _, err = bufio.NewReader(f).WriteTo(conn) + return err + case signal.Trace: + if err := trace.Start(conn); err != nil { + return err + } + time.Sleep(5 * time.Second) + trace.Stop() + case signal.SetGCPercent: + perc, err := binary.ReadVarint(bufio.NewReader(conn)) + if err != nil { + return err + } + fmt.Fprintf(conn, "New GC percent set to %v. Previous value was %v.\n", perc, debug.SetGCPercent(int(perc))) + } + return nil +} diff --git a/vendor/github.com/google/gops/agent/sockopt_reuseport.go b/vendor/github.com/google/gops/agent/sockopt_reuseport.go new file mode 100644 index 000000000..8311fe399 --- /dev/null +++ b/vendor/github.com/google/gops/agent/sockopt_reuseport.go @@ -0,0 +1,37 @@ +// Copyright 2020 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build !js && !plan9 && !solaris && !windows +// +build !js,!plan9,!solaris,!windows + +package agent + +import ( + "syscall" + + "golang.org/x/sys/unix" +) + +// setReuseAddrAndPortSockopts sets the SO_REUSEADDR and SO_REUSEPORT socket +// options on c's underlying socket in order to increase the chance to re-bind() +// to the same address and port upon agent restart. +func setReuseAddrAndPortSockopts(network, address string, c syscall.RawConn) error { + var soerr error + if err := c.Control(func(su uintptr) { + sock := int(su) + // Allow reuse of recently-used addresses. This socket option is + // set by default on listeners in Go's net package, see + // net.setDefaultSockopts. + soerr = unix.SetsockoptInt(sock, unix.SOL_SOCKET, unix.SO_REUSEADDR, 1) + if soerr != nil { + return + } + // Allow reuse of recently-used ports. This gives the agent a + // better chance to re-bind upon restarts. + soerr = unix.SetsockoptInt(sock, unix.SOL_SOCKET, unix.SO_REUSEPORT, 1) + }); err != nil { + return err + } + return soerr +} diff --git a/vendor/github.com/google/gops/agent/sockopt_unsupported.go b/vendor/github.com/google/gops/agent/sockopt_unsupported.go new file mode 100644 index 000000000..2493e8cad --- /dev/null +++ b/vendor/github.com/google/gops/agent/sockopt_unsupported.go @@ -0,0 +1,14 @@ +// Copyright 2020 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build (js && wasm) || plan9 || solaris || windows +// +build js,wasm plan9 solaris windows + +package agent + +import "syscall" + +func setReuseAddrAndPortSockopts(network, address string, c syscall.RawConn) error { + return nil +} diff --git a/vendor/github.com/google/gops/internal/internal.go b/vendor/github.com/google/gops/internal/internal.go new file mode 100644 index 000000000..ec63f918a --- /dev/null +++ b/vendor/github.com/google/gops/internal/internal.go @@ -0,0 +1,71 @@ +// Copyright 2017 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package internal + +import ( + "errors" + "io/ioutil" + "os" + "os/user" + "path/filepath" + "runtime" + "strconv" + "strings" +) + +const gopsConfigDirEnvKey = "GOPS_CONFIG_DIR" + +func ConfigDir() (string, error) { + if configDir := os.Getenv(gopsConfigDirEnvKey); configDir != "" { + return configDir, nil + } + + if osUserConfigDir := getOSUserConfigDir(); osUserConfigDir != "" { + return filepath.Join(osUserConfigDir, "gops"), nil + } + + if runtime.GOOS == "windows" { + return filepath.Join(os.Getenv("APPDATA"), "gops"), nil + } + + if xdgConfigDir := os.Getenv("XDG_CONFIG_HOME"); xdgConfigDir != "" { + return filepath.Join(xdgConfigDir, "gops"), nil + } + + homeDir := guessUnixHomeDir() + if homeDir == "" { + return "", errors.New("unable to get current user home directory: os/user lookup failed; $HOME is empty") + } + return filepath.Join(homeDir, ".config", "gops"), nil +} + +func guessUnixHomeDir() string { + usr, err := user.Current() + if err == nil { + return usr.HomeDir + } + return os.Getenv("HOME") +} + +func PIDFile(pid int) (string, error) { + gopsdir, err := ConfigDir() + if err != nil { + return "", err + } + return filepath.Join(gopsdir, strconv.Itoa(pid)), nil +} + +func GetPort(pid int) (string, error) { + portfile, err := PIDFile(pid) + if err != nil { + return "", err + } + b, err := ioutil.ReadFile(portfile) + if err != nil { + return "", err + } + port := strings.TrimSpace(string(b)) + return port, nil +} diff --git a/vendor/github.com/google/gops/internal/internal_go1_13.go b/vendor/github.com/google/gops/internal/internal_go1_13.go new file mode 100644 index 000000000..252f79697 --- /dev/null +++ b/vendor/github.com/google/gops/internal/internal_go1_13.go @@ -0,0 +1,20 @@ +// Copyright 2020 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build go1.13 +// +build go1.13 + +package internal + +import ( + "os" +) + +func getOSUserConfigDir() string { + configDir, err := os.UserConfigDir() + if err != nil { + return "" + } + return configDir +} diff --git a/vendor/github.com/google/gops/internal/internal_lt_go1_13.go b/vendor/github.com/google/gops/internal/internal_lt_go1_13.go new file mode 100644 index 000000000..e1bb00e93 --- /dev/null +++ b/vendor/github.com/google/gops/internal/internal_lt_go1_13.go @@ -0,0 +1,12 @@ +// Copyright 2020 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build !go1.13 +// +build !go1.13 + +package internal + +func getOSUserConfigDir() string { + return "" +} diff --git a/vendor/github.com/google/gops/signal/signal.go b/vendor/github.com/google/gops/signal/signal.go new file mode 100644 index 000000000..c70764a0f --- /dev/null +++ b/vendor/github.com/google/gops/signal/signal.go @@ -0,0 +1,38 @@ +// Copyright 2016 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Package signal contains signals used to communicate to the gops agents. +package signal + +const ( + // StackTrace represents a command to print stack trace. + StackTrace = byte(0x1) + + // GC runs the garbage collector. + GC = byte(0x2) + + // MemStats reports memory stats. + MemStats = byte(0x3) + + // Version prints the Go version. + Version = byte(0x4) + + // HeapProfile starts `go tool pprof` with the current memory profile. + HeapProfile = byte(0x5) + + // CPUProfile starts `go tool pprof` with the current CPU profile + CPUProfile = byte(0x6) + + // Stats returns Go runtime statistics such as number of goroutines, GOMAXPROCS, and NumCPU. + Stats = byte(0x7) + + // Trace starts the Go execution tracer, waits 5 seconds and launches the trace tool. + Trace = byte(0x8) + + // BinaryDump returns running binary file. + BinaryDump = byte(0x9) + + // SetGCPercent sets the garbage collection target percentage. + SetGCPercent = byte(0x10) +) diff --git a/vendor/modules.txt b/vendor/modules.txt index e85ffaeb5..9bc08057b 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -416,6 +416,11 @@ github.com/google/go-containerregistry/pkg/v1/types github.com/google/go-querystring/query # github.com/google/gofuzz v1.1.0 => github.com/google/gofuzz v1.1.0 github.com/google/gofuzz +# github.com/google/gops v0.3.23 +## explicit +github.com/google/gops/agent +github.com/google/gops/internal +github.com/google/gops/signal # github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 => github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 github.com/google/shlex # github.com/google/uuid v1.1.2 => github.com/google/uuid v1.1.1 @@ -813,6 +818,10 @@ github.com/rubenv/sql-migrate/sqlparse github.com/russross/blackfriday # github.com/sergi/go-diff v1.1.0 => github.com/sergi/go-diff v1.0.0 github.com/sergi/go-diff/diffmatchpatch +# github.com/shirou/gopsutil v0.0.0-20180427012116-c95755e4bcd7 +## explicit +# github.com/shirou/w32 v0.0.0-20160930032740-bb4de0191aa4 +## explicit # github.com/sirupsen/logrus v1.8.1 => github.com/sirupsen/logrus v1.4.2 github.com/sirupsen/logrus # github.com/sony/sonyflake v0.0.0-20181109022403-6d5bd6181009 => github.com/sony/sonyflake v0.0.0-20181109022403-6d5bd6181009 @@ -871,7 +880,7 @@ github.com/xeipuuv/gojsonreference github.com/xeipuuv/gojsonschema # github.com/xenolf/lego v0.3.2-0.20160613233155-a9d8cec0e656 => github.com/xenolf/lego v0.3.2-0.20160613233155-a9d8cec0e656 ## explicit -# github.com/xlab/treeprint v0.0.0-20181112141820-a009c3971eca => github.com/xlab/treeprint v0.0.0-20180616005107-d6fb6747feb6 +# github.com/xlab/treeprint v1.1.0 => github.com/xlab/treeprint v0.0.0-20180616005107-d6fb6747feb6 github.com/xlab/treeprint # github.com/yashtewari/glob-intersection v0.0.0-20180916065949-5c77d914dd0b => github.com/yashtewari/glob-intersection v0.0.0-20180916065949-5c77d914dd0b github.com/yashtewari/glob-intersection @@ -988,7 +997,7 @@ golang.org/x/oauth2/internal golang.org/x/sync/errgroup golang.org/x/sync/semaphore golang.org/x/sync/singleflight -# golang.org/x/sys v0.0.0-20210817190340-bfb29a6856f2 => golang.org/x/sys v0.0.0-20190228124157-a34e9553db1e +# golang.org/x/sys v0.0.0-20210902050250-f475640dd07b => golang.org/x/sys v0.0.0-20190228124157-a34e9553db1e golang.org/x/sys/cpu golang.org/x/sys/plan9 golang.org/x/sys/unix From 47563af08c3127fa1f93af2ae00e457b9f2bc194 Mon Sep 17 00:00:00 2001 From: LiHui Date: Wed, 1 Jun 2022 15:02:20 +0800 Subject: [PATCH 2/2] add gops agent to ks-apiserver&&controller-manager --- cmd/controller-manager/app/options/options.go | 6 ++++++ cmd/controller-manager/app/server.go | 10 ++++++++++ cmd/ks-apiserver/app/options/options.go | 5 +++++ cmd/ks-apiserver/app/server.go | 10 ++++++++++ 4 files changed, 31 insertions(+) diff --git a/cmd/controller-manager/app/options/options.go b/cmd/controller-manager/app/options/options.go index 6f542397b..b7dc0bb5b 100644 --- a/cmd/controller-manager/app/options/options.go +++ b/cmd/controller-manager/app/options/options.go @@ -82,6 +82,9 @@ type KubeSphereControllerManagerOptions struct { // * has the lowest priority. // e.g. *,-foo, means "disable 'foo'" ControllerGates []string + + // Enable gops or not. + GOPSEnabled bool } func NewKubeSphereControllerManagerOptions() *KubeSphereControllerManagerOptions { @@ -144,6 +147,9 @@ func (s *KubeSphereControllerManagerOptions) Flags(allControllerNameSelectors [] "named 'foo', '-foo' disables the controller named 'foo'.\nAll controllers: %s", strings.Join(allControllerNameSelectors, ", "))) + gfs.BoolVar(&s.GOPSEnabled, "gops", s.GOPSEnabled, "Whether to enable gops or not. When enabled this option, "+ + "controller-manager will listen on a random port on 127.0.0.1, then you can use the gops tool to list and diagnose the controller-manager currently running.") + kfs := fss.FlagSet("klog") local := flag.NewFlagSet("klog", flag.ExitOnError) klog.InitFlags(local) diff --git a/cmd/controller-manager/app/server.go b/cmd/controller-manager/app/server.go index 654a2b154..597b67cc5 100644 --- a/cmd/controller-manager/app/server.go +++ b/cmd/controller-manager/app/server.go @@ -21,6 +21,7 @@ import ( "fmt" "os" + "github.com/google/gops/agent" "github.com/spf13/cobra" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" utilerrors "k8s.io/apimachinery/pkg/util/errors" @@ -79,6 +80,15 @@ func NewControllerManagerCommand() *cobra.Command { klog.Error(utilerrors.NewAggregate(errs)) os.Exit(1) } + + if s.GOPSEnabled { + // Add agent to report additional information such as the current stack trace, Go version, memory stats, etc. + // Bind to a random port on address 127.0.0.1 + if err := agent.Listen(agent.Options{}); err != nil { + klog.Fatal(err) + } + } + if err = Run(s, controllerconfig.WatchConfigChange(), signals.SetupSignalHandler()); err != nil { klog.Error(err) os.Exit(1) diff --git a/cmd/ks-apiserver/app/options/options.go b/cmd/ks-apiserver/app/options/options.go index a8e8905a5..a5cebd046 100644 --- a/cmd/ks-apiserver/app/options/options.go +++ b/cmd/ks-apiserver/app/options/options.go @@ -62,6 +62,9 @@ type ServerRunOptions struct { // DebugMode bool + + // Enable gops or not. + GOPSEnabled bool } func NewServerRunOptions() *ServerRunOptions { @@ -76,6 +79,8 @@ func NewServerRunOptions() *ServerRunOptions { func (s *ServerRunOptions) Flags() (fss cliflag.NamedFlagSets) { fs := fss.FlagSet("generic") fs.BoolVar(&s.DebugMode, "debug", false, "Don't enable this if you don't know what it means.") + fs.BoolVar(&s.GOPSEnabled, "gops", false, "Whether to enable gops or not. When enabled this option, "+ + "ks-apiserver will listen on a random port on 127.0.0.1, then you can use the gops tool to list and diagnose the ks-apiserver currently running.") s.GenericServerRunOptions.AddFlags(fs, s.GenericServerRunOptions) s.KubernetesOptions.AddFlags(fss.FlagSet("kubernetes"), s.KubernetesOptions) s.AuthenticationOptions.AddFlags(fss.FlagSet("authentication"), s.AuthenticationOptions) diff --git a/cmd/ks-apiserver/app/server.go b/cmd/ks-apiserver/app/server.go index 05d6b30da..2265e1494 100644 --- a/cmd/ks-apiserver/app/server.go +++ b/cmd/ks-apiserver/app/server.go @@ -21,6 +21,7 @@ import ( "fmt" "net/http" + "github.com/google/gops/agent" "github.com/spf13/cobra" utilerrors "k8s.io/apimachinery/pkg/util/errors" cliflag "k8s.io/component-base/cli/flag" @@ -57,6 +58,15 @@ cluster's shared state through which all other components interact.`, if errs := s.Validate(); len(errs) != 0 { return utilerrors.NewAggregate(errs) } + + if s.GOPSEnabled { + // Add agent to report additional information such as the current stack trace, Go version, memory stats, etc. + // Bind to a random port on address 127.0.0.1. + if err := agent.Listen(agent.Options{}); err != nil { + klog.Fatal(err) + } + } + return Run(s, apiserverconfig.WatchConfigChange(), signals.SetupSignalHandler()) }, SilenceUsage: true,