@@ -18,35 +18,36 @@ import (
1818
1919// flamegraph table names
2020const (
21- CallStackFrequencyTableName = "Call Stack Frequency "
21+ FlameGraphTableName = "Flamegraph "
2222)
2323
2424// flamegraph tables
2525var tableDefinitions = map [string ]table.TableDefinition {
26- CallStackFrequencyTableName : {
27- Name : CallStackFrequencyTableName ,
28- MenuLabel : CallStackFrequencyTableName ,
26+ FlameGraphTableName : {
27+ Name : FlameGraphTableName ,
28+ MenuLabel : FlameGraphTableName ,
2929 ScriptNames : []string {
30- script .CollapsedCallStacksScriptName ,
30+ script .FlameGraphScriptName ,
3131 },
32- FieldsFunc : callStackFrequencyTableValues },
32+ FieldsFunc : flameGraphTableValues },
3333}
3434
35- func callStackFrequencyTableValues (outputs map [string ]script.ScriptOutput ) []table.Field {
35+ func flameGraphTableValues (outputs map [string ]script.ScriptOutput ) []table.Field {
3636 fields := []table.Field {
3737 {Name : "Native Stacks" , Values : []string {nativeFoldedFromOutput (outputs )}},
3838 {Name : "Java Stacks" , Values : []string {javaFoldedFromOutput (outputs )}},
3939 {Name : "Maximum Render Depth" , Values : []string {maxRenderDepthFromOutput (outputs )}},
40+ {Name : "Perf Event" , Values : []string {perfEventFromOutput (outputs )}},
4041 }
4142 return fields
4243}
4344
4445func javaFoldedFromOutput (outputs map [string ]script.ScriptOutput ) string {
45- if outputs [script .CollapsedCallStacksScriptName ].Stdout == "" {
46+ if outputs [script .FlameGraphScriptName ].Stdout == "" {
4647 slog .Warn ("collapsed call stack output is empty" )
4748 return ""
4849 }
49- sections := extract .GetSectionsFromOutput (outputs [script .CollapsedCallStacksScriptName ].Stdout )
50+ sections := extract .GetSectionsFromOutput (outputs [script .FlameGraphScriptName ].Stdout )
5051 if len (sections ) == 0 {
5152 slog .Warn ("no sections in collapsed call stack output" )
5253 return ""
@@ -84,11 +85,11 @@ func javaFoldedFromOutput(outputs map[string]script.ScriptOutput) string {
8485}
8586
8687func nativeFoldedFromOutput (outputs map [string ]script.ScriptOutput ) string {
87- if outputs [script .CollapsedCallStacksScriptName ].Stdout == "" {
88+ if outputs [script .FlameGraphScriptName ].Stdout == "" {
8889 slog .Warn ("collapsed call stack output is empty" )
8990 return ""
9091 }
91- sections := extract .GetSectionsFromOutput (outputs [script .CollapsedCallStacksScriptName ].Stdout )
92+ sections := extract .GetSectionsFromOutput (outputs [script .FlameGraphScriptName ].Stdout )
9293 if len (sections ) == 0 {
9394 slog .Warn ("no sections in collapsed call stack output" )
9495 return ""
@@ -103,6 +104,11 @@ func nativeFoldedFromOutput(outputs map[string]script.ScriptOutput) string {
103104 }
104105 }
105106 if dwarfFolded == "" && fpFolded == "" {
107+ slog .Warn ("no native folded stacks found" )
108+ // "event syntax error: 'foo'" indicates that the perf event specified is invalid/unsupported
109+ if strings .Contains (outputs [script .FlameGraphScriptName ].Stderr , "event syntax error" ) {
110+ slog .Error ("unsupported perf event specified" , slog .String ("error" , outputs [script .FlameGraphScriptName ].Stderr ))
111+ }
106112 return ""
107113 }
108114 folded , err := mergeSystemFolded (fpFolded , dwarfFolded )
@@ -113,11 +119,11 @@ func nativeFoldedFromOutput(outputs map[string]script.ScriptOutput) string {
113119}
114120
115121func maxRenderDepthFromOutput (outputs map [string ]script.ScriptOutput ) string {
116- if outputs [script .CollapsedCallStacksScriptName ].Stdout == "" {
122+ if outputs [script .FlameGraphScriptName ].Stdout == "" {
117123 slog .Warn ("collapsed call stack output is empty" )
118124 return ""
119125 }
120- sections := extract .GetSectionsFromOutput (outputs [script .CollapsedCallStacksScriptName ].Stdout )
126+ sections := extract .GetSectionsFromOutput (outputs [script .FlameGraphScriptName ].Stdout )
121127 if len (sections ) == 0 {
122128 slog .Warn ("no sections in collapsed call stack output" )
123129 return ""
@@ -130,6 +136,24 @@ func maxRenderDepthFromOutput(outputs map[string]script.ScriptOutput) string {
130136 return ""
131137}
132138
139+ func perfEventFromOutput (outputs map [string ]script.ScriptOutput ) string {
140+ if outputs [script .FlameGraphScriptName ].Stdout == "" {
141+ slog .Warn ("collapsed call stack output is empty" )
142+ return ""
143+ }
144+ sections := extract .GetSectionsFromOutput (outputs [script .FlameGraphScriptName ].Stdout )
145+ if len (sections ) == 0 {
146+ slog .Warn ("no sections in collapsed call stack output" )
147+ return ""
148+ }
149+ for header , content := range sections {
150+ if header == "perf_event" {
151+ return strings .TrimSpace (content )
152+ }
153+ }
154+ return ""
155+ }
156+
133157// ProcessStacks ...
134158// [processName][callStack]=count
135159type ProcessStacks map [string ]Stacks
0 commit comments