66 "encoding/json"
77 "fmt"
88 "github.com/google/pprof/driver"
9+ "github.com/google/pprof/profile"
910 "github.com/spf13/cobra"
1011 "io"
1112 "io/ioutil"
@@ -38,6 +39,16 @@ func exportLogic() func(cmd *cobra.Command, args []string) {
3839 log .Fatalf ("Exactly one profile file is required" )
3940 }
4041 if local {
42+ err , finalTree := generateFlameGraph (args [0 ])
43+ if err != nil {
44+ log .Fatalf ("An Error Occured %v" , err )
45+ }
46+ postBody , err := json .Marshal (finalTree )
47+ if err != nil {
48+ log .Fatalf ("An Error Occured %v" , err )
49+ }
50+ fmt .Println (string (postBody ))
51+
4152 for _ , granularity := range granularityOptions {
4253 err , report := generateTextReports (granularity , args [0 ])
4354 if err == nil {
@@ -59,12 +70,42 @@ func exportLogic() func(cmd *cobra.Command, args []string) {
5970 log .Fatal (err )
6071 }
6172 }
73+ err , finalTree := generateFlameGraph (args [0 ])
74+ if err != nil {
75+ log .Fatalf ("An Error Occured %v" , err )
76+ }
77+ remoteFlameGraphExport (finalTree )
6278 log .Printf ("Successfully published profile data. Check it at: %s/gh/%s/%s/commit/%s/bench/%s/cpu" , codeperfUrl , gitOrg , gitRepo , gitCommit , bench )
6379 }
6480
6581 }
6682}
6783
84+ func remoteFlameGraphExport (tree treeNodeSlice ) {
85+ postBody , err := json .Marshal (tree )
86+ if err != nil {
87+ log .Fatalf ("An Error Occured %v" , err )
88+ }
89+ responseBody := bytes .NewBuffer (postBody )
90+ endPoint := fmt .Sprintf ("%s/v1/gh/%s/%s/commit/%s/bench/%s/cpu/flamegraph" , codeperfApiUrl , gitOrg , gitRepo , gitCommit , bench )
91+ resp , err := http .Post (endPoint , "application/json" , responseBody )
92+ //Handle Error
93+ if err != nil {
94+ log .Fatalf ("An Error Occured %v" , err )
95+ }
96+ defer resp .Body .Close ()
97+
98+ //Read the response body
99+ reply , err := ioutil .ReadAll (resp .Body )
100+ if err != nil {
101+ log .Fatalln (err )
102+ }
103+ if resp .StatusCode != 200 {
104+ log .Fatalf ("An error ocurred while phusing data to remote %s. Status code %d. Reply: %s" , codeperfApiUrl , resp .StatusCode , string (reply ))
105+ }
106+
107+ }
108+
68109func remoteExportLogic (report TextReport , granularity string ) {
69110 postBody , err := json .Marshal (report )
70111 if err != nil {
@@ -111,6 +152,48 @@ func localExportLogic(w io.Writer, report TextReport) {
111152 }
112153}
113154
155+ func generateFlameGraph (input string ) (err error , tree treeNodeSlice ) {
156+ f := baseFlags ()
157+
158+ // Read the profile from the encoded protobuf
159+ outputTempFile , err := ioutil .TempFile ("" , "profile_output" )
160+ if err != nil {
161+ log .Fatalf ("cannot create tempfile: %v" , err )
162+ }
163+ log .Printf ("Generating temp file %s" , outputTempFile .Name ())
164+ //defer os.Remove(outputTempFile.Name())
165+ defer outputTempFile .Close ()
166+ f .strings ["output" ] = outputTempFile .Name ()
167+ f .bools ["proto" ] = true
168+ f .bools ["text" ] = false
169+ f .args = []string {
170+ input ,
171+ }
172+ reader := bufio .NewReader (os .Stdin )
173+ options := & driver.Options {
174+ Flagset : f ,
175+ UI : & UI {r : reader },
176+ }
177+
178+ if err = driver .PProf (options ); err != nil {
179+ log .Fatalf ("cannot read pprof profile from %s. Error: %v" , input , err )
180+ return
181+ }
182+
183+ file , err := os .Open (outputTempFile .Name ())
184+ if err != nil {
185+ log .Fatal (err )
186+ }
187+ defer file .Close ()
188+ r := bufio .NewReader (file )
189+ profile , err := profile .Parse (r )
190+ if err != nil {
191+ log .Fatal (err )
192+ }
193+ tree = profileToFolded (profile )
194+ return
195+ }
196+
114197func generateTextReports (granularity string , input string ) (err error , report TextReport ) {
115198 f := baseFlags ()
116199
0 commit comments