Skip to content

Commit 92b5140

Browse files
committed
refactor api profile methods
1 parent 7c30f10 commit 92b5140

File tree

5 files changed

+107
-132
lines changed

5 files changed

+107
-132
lines changed

api/agent.go

+39-71
Original file line numberDiff line numberDiff line change
@@ -290,106 +290,74 @@ func (a *Agent) Monitor(stopCh <-chan struct{}, q *QueryOptions) (<-chan *Stream
290290
return frames, errCh
291291
}
292292

293+
// PprofOptions contain a set of parameters for profiling a node or server.
294+
type PprofOptions struct {
295+
// ServerID is the server ID, name, or special value "leader" to
296+
// specify the server that a given profile should be run on.
297+
ServerID string
298+
299+
// NodeID is the node ID that a given profile should be run on.
300+
NodeID string
301+
302+
// Seconds specifies the amount of time a profile should be run for.
303+
// Seconds only applies for certain runtime profiles like CPU and Trace.
304+
Seconds int
305+
306+
// GC determines if a runtime.GC() should be called before a heap
307+
// profile.
308+
GC int
309+
310+
// Debug specifies if the output of a lookup profile should be returned
311+
// in human readable format instead of binary.
312+
Debug int
313+
}
314+
293315
// CPUProfile returns a runtime/pprof cpu profile for a given server or node.
294316
// The profile will run for the amount of seconds passed in or default to 1.
295317
// If no serverID or nodeID are provided the current Agents server will be
296318
// used.
297319
//
298-
// The parameters are:
299-
// * serverID: server ID or name to query, also accepts "leader"
300-
// * nodeID: client node ID to query
301-
// * seconds: the amount of time to run the trace for.
302-
//
303320
// The call blocks until the profile finishes, and returns the raw bytes of the
304321
// profile.
305-
func (a *Agent) CPUProfile(serverID, nodeID string, seconds int, q *QueryOptions) ([]byte, error) {
306-
if q == nil {
307-
q = &QueryOptions{}
308-
}
309-
if q.Params == nil {
310-
q.Params = make(map[string]string)
311-
}
312-
313-
q.Params["seconds"] = strconv.Itoa(seconds)
314-
q.Params["node_id"] = nodeID
315-
q.Params["server_id"] = serverID
316-
317-
body, err := a.client.rawQuery("/v1/agent/pprof/profile", q)
318-
if err != nil {
319-
return nil, err
320-
}
321-
322-
resp, err := ioutil.ReadAll(body)
323-
if err != nil {
324-
return nil, err
325-
}
326-
327-
return resp, nil
322+
func (a *Agent) CPUProfile(opts PprofOptions, q *QueryOptions) ([]byte, error) {
323+
return a.pprofRequest("profile", opts, q)
328324
}
329325

330326
// Trace returns a runtime/pprof trace for a given server or node.
331327
// The trace will run for the amount of seconds passed in or default to 1.
332328
// If no serverID or nodeID are provided the current Agents server will be
333329
// used.
334330
//
335-
// The parameters are:
336-
// * serverID: server ID or name to query, also accepts "leader"
337-
// * nodeID: client node ID to query
338-
// * seconds: the amount of time to run the trace for.
339-
//
340331
// The call blocks until the profile finishes, and returns the raw bytes of the
341332
// profile.
342-
func (a *Agent) Trace(serverID, nodeID string, seconds int, q *QueryOptions) ([]byte, error) {
343-
if q == nil {
344-
q = &QueryOptions{}
345-
}
346-
if q.Params == nil {
347-
q.Params = make(map[string]string)
348-
}
349-
350-
q.Params["seconds"] = strconv.Itoa(seconds)
351-
q.Params["node_id"] = nodeID
352-
q.Params["server_id"] = serverID
353-
354-
body, err := a.client.rawQuery("/v1/agent/pprof/trace", q)
355-
if err != nil {
356-
return nil, err
357-
}
358-
359-
resp, err := ioutil.ReadAll(body)
360-
if err != nil {
361-
return nil, err
362-
}
363-
364-
return resp, nil
365-
333+
func (a *Agent) Trace(opts PprofOptions, q *QueryOptions) ([]byte, error) {
334+
return a.pprofRequest("trace", opts, q)
366335
}
367336

368-
// Profile returns a runtime/pprof profile using pprof.Lookup to determine
337+
// Lookup returns a runtime/pprof profile using pprof.Lookup to determine
369338
// which profile to run. Accepts a client or server ID but not both simultaneously.
370339
//
371-
// The parameters are:
372-
// * serverID: server ID or name to query, also accepts "leader"
373-
// * nodeID: client node ID to query
374-
// * profile: the name of the runtime/pprof profile to lookup and run.
375-
// * debug: flag to specify if the profile should return human readable output.
376-
//
377340
// The call blocks until the profile finishes, and returns the raw bytes of the
378-
// profile.
379-
func (a *Agent) Profile(serverID, nodeID, profile string, debug, gc int, q *QueryOptions) ([]byte, error) {
341+
// profile unless debug is set.
342+
func (a *Agent) Lookup(profile string, opts PprofOptions, q *QueryOptions) ([]byte, error) {
343+
return a.pprofRequest(profile, opts, q)
344+
}
345+
346+
func (a *Agent) pprofRequest(req string, opts PprofOptions, q *QueryOptions) ([]byte, error) {
380347
if q == nil {
381348
q = &QueryOptions{}
382349
}
383350
if q.Params == nil {
384351
q.Params = make(map[string]string)
385352
}
386353

387-
q.Params["debug"] = strconv.Itoa(debug)
388-
q.Params["qc"] = strconv.Itoa(debug)
389-
q.Params["node_id"] = nodeID
390-
q.Params["server_id"] = serverID
354+
q.Params["seconds"] = strconv.Itoa(opts.Seconds)
355+
q.Params["debug"] = strconv.Itoa(opts.Debug)
356+
q.Params["gc"] = strconv.Itoa(opts.GC)
357+
q.Params["node_id"] = opts.NodeID
358+
q.Params["server_id"] = opts.ServerID
391359

392-
body, err := a.client.rawQuery(fmt.Sprintf("/v1/agent/pprof/%s", profile), q)
360+
body, err := a.client.rawQuery(fmt.Sprintf("/v1/agent/pprof/%s", req), q)
393361
if err != nil {
394362
return nil, err
395363
}

api/agent_test.go

+12-5
Original file line numberDiff line numberDiff line change
@@ -391,14 +391,21 @@ func TestAgentCPUProfile(t *testing.T) {
391391

392392
// Valid local request
393393
{
394-
resp, err := agent.CPUProfile("", "", 1, q)
394+
opts := PprofOptions{
395+
Seconds: 1,
396+
}
397+
resp, err := agent.CPUProfile(opts, q)
395398
require.NoError(t, err)
396399
require.NotNil(t, resp)
397400
}
398401

399402
// Invalid server request
400403
{
401-
resp, err := agent.CPUProfile("unknown.global", "", 1, q)
404+
opts := PprofOptions{
405+
Seconds: 1,
406+
ServerID: "unknown.global",
407+
}
408+
resp, err := agent.CPUProfile(opts, q)
402409
require.Error(t, err)
403410
require.Contains(t, err.Error(), "500 (unknown nomad server unknown.global)")
404411
require.Nil(t, resp)
@@ -418,7 +425,7 @@ func TestAgentTrace(t *testing.T) {
418425
AuthToken: token.SecretID,
419426
}
420427

421-
resp, err := agent.Trace("", "", 1, q)
428+
resp, err := agent.Trace(PprofOptions{}, q)
422429
require.NoError(t, err)
423430
require.NotNil(t, resp)
424431
}
@@ -436,14 +443,14 @@ func TestAgentProfile(t *testing.T) {
436443
}
437444

438445
{
439-
resp, err := agent.Profile("", "", "heap", 0, 1, q)
446+
resp, err := agent.Lookup("heap", PprofOptions{}, q)
440447
require.NoError(t, err)
441448
require.NotNil(t, resp)
442449
}
443450

444451
// unknown profile
445452
{
446-
resp, err := agent.Profile("", "", "invalid", 1, 1, q)
453+
resp, err := agent.Lookup("invalid", PprofOptions{}, q)
447454
require.Error(t, err)
448455
require.Contains(t, err.Error(), "Unexpected response code: 404")
449456
require.Nil(t, resp)

command/agent/bindata_assetfs.go

+55-55
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

e2e/metrics/input/simpleweb.nomad

-1
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@ job "simpleweb" {
88
}
99

1010
group "simpleweb" {
11-
1211
task "simpleweb" {
1312
driver = "docker"
1413

ui/yarn.lock

+1
Original file line numberDiff line numberDiff line change
@@ -12823,3 +12823,4 @@ yup@^0.26.10:
1282312823
property-expr "^1.5.0"
1282412824
synchronous-promise "^2.0.5"
1282512825
toposort "^2.0.2"
12826+

0 commit comments

Comments
 (0)