Network Security Internet Technology Development Database Servers Mobile Phone Android Software Apple Software Computer Software News IT Information

In addition to Weibo, there is also WeChat

Please pay attention

WeChat public account

Shulou

The method of integrating google/pprof into existing services

2025-01-17 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Internet Technology >

Share

Shulou(Shulou.com)06/02 Report--

This article focuses on "how to integrate google/pprof into existing services". Interested friends may wish to have a look at it. The method introduced in this paper is simple, fast and practical. Let's let the editor take you to learn how to integrate google/pprof into existing services.

Write a monitoring service monitor server to analyze the status of the services registered in the etcd. Most of the services in the project have introduced the pprof library. To view the / debug/pprof of these services, you only need to go through a layer of proxy, here using the httputil.NewSingleHostReverseProxy in the official httputil library.

Func proxy (w http.ResponseWriter, r * http.Request) {_ = r.ParseForm () URL: = r.Form.Get ("url") profile: = r.Form.Get ("profile") target _: = url.Parse ("http://" + URL +" / debug/pprof/ "+ profile +"? debug=1 ") proxy: = httputil.NewSingleHostReverseProxy (target) proxy.Director = func (req * http.Request) {req.URL.Scheme = target.Scheme req.URL.Host = target.Host req.URL.Path = target.Path Req.URL.RawQuery = target.RawQuery if _ Ok: = req.Header ["User-Agent"] ! ok {/ / explicitly disable User-Agent so it's not set to default value req.Header.Set ("User-Agent", "")}} r.Host = r.URL.Host proxy.ServeHTTP (w, r)}

Up to now, 90% of this requirement has been completed, but so far, if you want to see the fire map, you must download the profile file locally, and then use pprof or go tool pprof.

So is there a way to integrate pprof into existing services? Of course, let's start with the main function of pprof, and notice that it is the google/pprof library.

Func main () {if err: = driver.PProf (& driver.Options {UI: newUI ()}); err! = nil {fmt.Fprintf (os.Stderr, "pprof:% v\ n", err) os.Exit (2)}}

You can see that the official option is provided, and the complete option includes:

/ / Options groups all the optional plugins into pprof.type Options struct {Writer Writer Flagset FlagSet Fetch Fetcher Sym Symbolizer Obj ObjTool UI UI HTTPServer func (* HTTPServerArgs) error HTTPTransport http.RoundTripper}

Not all of these option need to be changed, let's talk about them separately.

0. UI interface

UI interface UI: newUI () is removed directly, which is mainly used for terminal interactive control.

1. Flagset API / / A FlagSet creates and parses command-line flags.// It is similar to the standard flag.FlagSet.type FlagSet interface {Bool (name string, def bool, usage string) * bool Int (name string, def int, usage string) * int Float64 (name string, def float64, usage string) * float64 String (name string, def string, usage string) * string BoolVar (pointer * bool, name string, def bool, usage string) IntVar (pointer * int Name string, def int, usage string) Float64Var (pointer * float64, name string, def float64, usage string) StringVar (pointer * string, name string, def string, usage string) StringList (name string, def string, usage string) * [] * string ExtraUsage () string AddExtraUsage (eu string) Parse (usage func ()) [] string}

Literally, this interface is used to parse flag. Since we don't want to write flag in the execution script of the existing service, we need to implement a custom Flagset structure. At the same time, we also need to solve the problem that go does not support the repeated definition of flag.

1) GoFlags

The content of the structure is based on the parameters you need to pass in, and different projects may be different.

/ / GoFlags implements the plugin.FlagSet interface.type GoFlags struct {UsageMsgs [] string Profile string Http string NoBrowser bool} 2) Bool

The parameters that need to be changed are passed in through the variables in the structure, and those that are not needed can be written directly.

/ / Bool implements the plugin.FlagSet interface.func (f * GoFlags) Bool (o string, d bool) C string) * bool {switch o {case "no_browser": return & f.NoBrowser case "trim": t: = true return & t case "flat": t: = true return & t case "functions": t: = true Return & t} return new (bool)} 3) Int

The default value of the parameter can be found in google/pprof/internal/driver/commands.go.

/ / Int implements the plugin.FlagSet interface.func (* GoFlags) Int (o string, d int, c string) * int {switch o {case "nodecount": t: =-1 return & t} return new (int)} 4) Float64// Float64 implements the plugin.FlagSet interface.func (* GoFlags) Float64 (o string, d float64 C string) * float64 {switch o {case "divide_by": t: = 1.0 return & t case "nodefraction": t: = 0.005 return & t case "edgefraction": t: = 0.001 return & t} return new (float64)}

Note that there are some default values that must be assigned, otherwise the picture cannot be displayed properly.

5) String// String implements the plugin.FlagSet interface.func (f * GoFlags) String (o, d, c string) * string {switch o {case "http": return & f.Http case "unit": t: = "minimum" return & t} return new (string)} 6) Parse

The Parse method returns the file name without parsing the parameters.

/ / Parse implements the plugin.FlagSet interface.func (f * GoFlags) Parse (usage func ()) [] string {/ / flag.Usage = usage / / flag.Parse () / / args: = flag.Args () / / if len (args) = 0 {/ / usage () / /} return [] string {f.Profile}} 7) StringList// StringList implements The plugin.FlagSet interface.func (* GoFlags) StringList (o D, c string) * [] * string {return & [] * string {new (string)}}

At this point, the first option change is complete.

If err: = driver.PProf (& driver.Options {Flagset: & internal.GoFlags {Profile: profilePath + profile, Http: "127.0.0.1:" + strconv.Itoa (internal.ListenPort), NoBrowser: true,}}) Err! = nil {fmt.Fprintf (os.Stderr, "pprof:% v\ n", err) os.Exit (2)} 2. HTTPServer function

If you do not register the HTTPServer function, pprof uses the default defaultWebServer.

Func defaultWebServer (args * plugin.HTTPServerArgs) error {ln, err: = net.Listen ("tcp", args.Hostport) if err! = nil {return err} isLocal: = isLocalhost (args.Host) handler: = http.HandlerFunc (func (w http.ResponseWriter) Req * http.Request) {if isLocal {/ / Only allow local clients host, _, err: = net.SplitHostPort (req.RemoteAddr) if err! = nil |! isLocalhost (host) {http.Error (w, "permission denied") Http.StatusForbidden) return} h: = args.Handlers [req.URL.Path] if h = = nil {/ / Fall back to default behavior h = http.DefaultServeMux } h.ServeHTTP (w Req)}) mux: = http.NewServeMux () mux.Handle ("/ ui/", http.StripPrefix ("/ ui", handler)) mux.Handle ("/", redirectWithQuery ("/ ui")) s: = & http.Server {Handler: mux} return s.Serve (ln)} 1) s.Server (ln)

As you can see, by default, pprof automatically listens. However, our service has started listening, and the code can be deleted directly, including the routing part, and it is suggested that it be written in the same form as the project.

2) handler

Handler first determines whether the request is a local request, and then registers the corresponding handler according to path. Since we deleted the routing part mux.Handle () in the previous step, this code can also be deleted.

It is important to note that handler cannot be registered repeatedly, so we need to add a flag bit for this.

At this point, the second option is complete.

Var switcher boolif err: = driver.PProf (& driver.Options {Flagset: & internal.GoFlags {Profile: profilePath + profile, Http: "127.0.0.1:" + strconv.Itoa (internal.ListenPort), NoBrowser: true,} HTTPServer: func (args * driver.HTTPServerArgs) error {if switcher {return nil} for k, v: = range args.Handlers {http.Handle ("/ ui" + k V)} switcher = true return nil}}) Err! = nil {fmt.Fprintf (os.Stderr, "pprof:% v\ n", err) os.Exit (2)} 3. Reuse handler

We package the above code and write it into the http interface.

Func readProfile (w http.ResponseWriter, r * http.Request) {_ = r.ParseForm () go pprof ("profile") time.Sleep (time.Second * 3) http.Redirect (w, r, "/ ui/", http.StatusTemporaryRedirect) return}

After starting pprof, delay three seconds and then redirect to the pprof interface.

On the face of it, this requirement has been done, but.

The above pprof is one-time, and rereading the generated webInterface after replacing the profile will not re-register with the handler.

To solve this last problem, we have to change the pprof source code. I am resistant to this, it is not impossible to change, it is not difficult to change, mainly because pprof is placed in the company's general vendor library, I am afraid of affecting other projects (for this reason, I submitted a feature to the official library, hoping to have a better solution).

Make the following changes under internal/driver/webui.go so that webI can be reused.

Var webI = new (webInterface) func makeWebInterface (p * profile.Profile, opt * plugin.Options) * webInterface {templates: = template.New ("templategroup") addTemplates (templates) report.AddSourceTemplates (templates) webI.prof = p webI.options = opt webI.help = make (map [stri ng] string) webI.templates = templates return webI}

At this point, we can finally see the flame picture smoothly.

At this point, I believe you have a deeper understanding of the "method of integrating google/pprof into existing services". You might as well do it in practice. Here is the website, more related content can enter the relevant channels to inquire, follow us, continue to learn!

Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.

Views: 0

*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.

Share To

Internet Technology

Wechat

© 2024 shulou.com SLNews company. All rights reserved.

12
Report