github.imxd.top/hashicorp/consul@v1.4.5/api/debug.go (about)

     1  package api
     2  
     3  import (
     4  	"fmt"
     5  	"io/ioutil"
     6  	"strconv"
     7  )
     8  
     9  // Debug can be used to query the /debug/pprof endpoints to gather
    10  // profiling information about the target agent.Debug
    11  //
    12  // The agent must have enable_debug set to true for profiling to be enabled
    13  // and for these endpoints to function.
    14  type Debug struct {
    15  	c *Client
    16  }
    17  
    18  // Debug returns a handle that exposes the internal debug endpoints.
    19  func (c *Client) Debug() *Debug {
    20  	return &Debug{c}
    21  }
    22  
    23  // Heap returns a pprof heap dump
    24  func (d *Debug) Heap() ([]byte, error) {
    25  	r := d.c.newRequest("GET", "/debug/pprof/heap")
    26  	_, resp, err := d.c.doRequest(r)
    27  	if err != nil {
    28  		return nil, fmt.Errorf("error making request: %s", err)
    29  	}
    30  	defer resp.Body.Close()
    31  
    32  	// We return a raw response because we're just passing through a response
    33  	// from the pprof handlers
    34  	body, err := ioutil.ReadAll(resp.Body)
    35  	if err != nil {
    36  		return nil, fmt.Errorf("error decoding body: %s", err)
    37  	}
    38  
    39  	return body, nil
    40  }
    41  
    42  // Profile returns a pprof CPU profile for the specified number of seconds
    43  func (d *Debug) Profile(seconds int) ([]byte, error) {
    44  	r := d.c.newRequest("GET", "/debug/pprof/profile")
    45  
    46  	// Capture a profile for the specified number of seconds
    47  	r.params.Set("seconds", strconv.Itoa(seconds))
    48  
    49  	_, resp, err := d.c.doRequest(r)
    50  	if err != nil {
    51  		return nil, fmt.Errorf("error making request: %s", err)
    52  	}
    53  	defer resp.Body.Close()
    54  
    55  	// We return a raw response because we're just passing through a response
    56  	// from the pprof handlers
    57  	body, err := ioutil.ReadAll(resp.Body)
    58  	if err != nil {
    59  		return nil, fmt.Errorf("error decoding body: %s", err)
    60  	}
    61  
    62  	return body, nil
    63  }
    64  
    65  // Trace returns an execution trace
    66  func (d *Debug) Trace(seconds int) ([]byte, error) {
    67  	r := d.c.newRequest("GET", "/debug/pprof/trace")
    68  
    69  	// Capture a trace for the specified number of seconds
    70  	r.params.Set("seconds", strconv.Itoa(seconds))
    71  
    72  	_, resp, err := d.c.doRequest(r)
    73  	if err != nil {
    74  		return nil, fmt.Errorf("error making request: %s", err)
    75  	}
    76  	defer resp.Body.Close()
    77  
    78  	// We return a raw response because we're just passing through a response
    79  	// from the pprof handlers
    80  	body, err := ioutil.ReadAll(resp.Body)
    81  	if err != nil {
    82  		return nil, fmt.Errorf("error decoding body: %s", err)
    83  	}
    84  
    85  	return body, nil
    86  }
    87  
    88  // Goroutine returns a pprof goroutine profile
    89  func (d *Debug) Goroutine() ([]byte, error) {
    90  	r := d.c.newRequest("GET", "/debug/pprof/goroutine")
    91  
    92  	_, resp, err := d.c.doRequest(r)
    93  	if err != nil {
    94  		return nil, fmt.Errorf("error making request: %s", err)
    95  	}
    96  	defer resp.Body.Close()
    97  
    98  	// We return a raw response because we're just passing through a response
    99  	// from the pprof handlers
   100  	body, err := ioutil.ReadAll(resp.Body)
   101  	if err != nil {
   102  		return nil, fmt.Errorf("error decoding body: %s", err)
   103  	}
   104  
   105  	return body, nil
   106  }