Skip to content

Commit

Permalink
feat(kubectl): load profiles from a local path
Browse files Browse the repository at this point in the history
Create a new command called `kubectl profefe load` to push a profile
from your local laptop to profefe.

Signed-off-by: Gianluca Arbezzano <gianarb92@gmail.com>
  • Loading branch information
Gianluca Arbezzano committed Jan 7, 2020
1 parent f225c4f commit 148e3a5
Show file tree
Hide file tree
Showing 3 changed files with 120 additions and 0 deletions.
71 changes: 71 additions & 0 deletions pkg/cmd/load.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
package cmd

import (
"context"
"fmt"
"net/http"
"os"

"github.com/gianarb/kube-profefe/pkg/profefe"
"github.com/google/pprof/profile"
"github.com/spf13/cobra"
"github.com/spf13/pflag"
)

func NewLoadCmd() *cobra.Command {
var serviceName string
flags := pflag.NewFlagSet("load", pflag.ExitOnError)
cmd := &cobra.Command{
Use: "load",
Short: "Load a profile you have locally to profefe",
RunE: func(cmd *cobra.Command, args []string) error {
if len(args) == 0 {
return fmt.Errorf("You have to specify at least one profile as argument")
}

pClient := profefe.NewClient(profefe.Config{
HostPort: ProfefeHostPort,
}, http.Client{})

for _, path := range args {
file, err := os.Open(path)
if err != nil {
return fmt.Errorf("Error (%s): %s", path, err)
}
p, err := profile.Parse(file)
if err != nil {
return fmt.Errorf("Error (%s): %s", path, err)
}

profefeType := profefe.NewProfileTypeFromString(p.PeriodType.Type)
if profefeType == profefe.UnknownProfile {
return fmt.Errorf("Error (%s) Unknown profile type it can not be sent to profefe. Skip this profile", path)
}

req := profefe.SavePprofRequest{
Profile: p,
Service: serviceName,
InstanceID: func() string {
h, err := os.Hostname()
if err != nil {
return "local"
}
return h
}(),
Type: profefeType,
}
saved, err := pClient.SavePprof(context.Background(), req)
if err != nil {
return fmt.Errorf("Error (%s): %s", err, path)
} else {
println(fmt.Sprintf("Profile (%s) stored in profefe: %s/api/0/profiles/%s", path, ProfefeHostPort, saved.Body.ID))
}
}
return nil
},
}
flags.StringVar(&ProfefeHostPort, "profefe-hostport", "http://localhost:10100", `where profefe is located`)
flags.StringVar(&serviceName, "service", "", `The service name`)
cmd.Flags().AddFlagSet(flags)
return cmd
}
48 changes: 48 additions & 0 deletions pkg/cmd/load_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
package cmd

import (
"context"
"fmt"
"testing"

"github.com/testcontainers/testcontainers-go"
"github.com/testcontainers/testcontainers-go/wait"
)

func TestLoadProfileTest(t *testing.T) {
ctx := context.Background()
req := testcontainers.ContainerRequest{
Image: "profefe/profefe:git-10551f2",
ExposedPorts: []string{"10100/tcp"},
WaitingFor: wait.ForLog("server is running"),
}
nginxC, err := testcontainers.GenericContainer(ctx, testcontainers.GenericContainerRequest{
ContainerRequest: req,
Started: true,
})
if err != nil {
t.Error(err)
}
defer nginxC.Terminate(ctx)
ip, err := nginxC.Host(ctx)
if err != nil {
t.Error(err)
}
port, err := nginxC.MappedPort(ctx, "10100")
if err != nil {
t.Error(err)
}

cmd := NewLoadCmd()
cmd.SetArgs([]string{
"--profefe-hostport",
fmt.Sprintf("http://%s:%d", ip, port.Int()),
"--service",
"test",
"../../test/pprof.profefe.samples.cpu.001.pb.gz",
})
err = cmd.Execute()
if err != nil {
t.Fatal(err)
}
}
1 change: 1 addition & 0 deletions pkg/cmd/profefe.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ func NewProfefeCmd(logger *zap.Logger, streams genericclioptions.IOStreams) *cob
captureCmd.Flags().AddFlagSet(flagsCapture)
rootCmd.AddCommand(captureCmd)
rootCmd.AddCommand(NewGetCmd())
rootCmd.AddCommand(NewLoadCmd())

return rootCmd
}

0 comments on commit 148e3a5

Please sign in to comment.