9
9
"fmt"
10
10
"html/template"
11
11
"internal/trace"
12
+ "internal/trace/traceviewer"
12
13
"log"
13
- "math"
14
14
"net/http"
15
15
"net/url"
16
16
"reflect"
@@ -808,122 +808,9 @@ func newRegionFilter(r *http.Request) (*regionFilter, error) {
808
808
}, nil
809
809
}
810
810
811
- type durationHistogram struct {
812
- Count int
813
- Buckets []int
814
- MinBucket , MaxBucket int
815
- }
816
-
817
- // Five buckets for every power of 10.
818
- var logDiv = math .Log (math .Pow (10 , 1.0 / 5 ))
819
-
820
- func (h * durationHistogram ) add (d time.Duration ) {
821
- var bucket int
822
- if d > 0 {
823
- bucket = int (math .Log (float64 (d )) / logDiv )
824
- }
825
- if len (h .Buckets ) <= bucket {
826
- h .Buckets = append (h .Buckets , make ([]int , bucket - len (h .Buckets )+ 1 )... )
827
- h .Buckets = h .Buckets [:cap (h .Buckets )]
828
- }
829
- h .Buckets [bucket ]++
830
- if bucket < h .MinBucket || h .MaxBucket == 0 {
831
- h .MinBucket = bucket
832
- }
833
- if bucket > h .MaxBucket {
834
- h .MaxBucket = bucket
835
- }
836
- h .Count ++
837
- }
838
-
839
- func (h * durationHistogram ) BucketMin (bucket int ) time.Duration {
840
- return time .Duration (math .Exp (float64 (bucket ) * logDiv ))
841
- }
842
-
843
- func niceDuration (d time.Duration ) string {
844
- var rnd time.Duration
845
- var unit string
846
- switch {
847
- case d < 10 * time .Microsecond :
848
- rnd , unit = time .Nanosecond , "ns"
849
- case d < 10 * time .Millisecond :
850
- rnd , unit = time .Microsecond , "µs"
851
- case d < 10 * time .Second :
852
- rnd , unit = time .Millisecond , "ms"
853
- default :
854
- rnd , unit = time .Second , "s "
855
- }
856
- return fmt .Sprintf ("%d%s" , d / rnd , unit )
857
- }
858
-
859
- func (h * durationHistogram ) ToHTML (urlmaker func (min , max time.Duration ) string ) template.HTML {
860
- if h == nil || h .Count == 0 {
861
- return template .HTML ("" )
862
- }
863
-
864
- const barWidth = 400
865
-
866
- maxCount := 0
867
- for _ , count := range h .Buckets {
868
- if count > maxCount {
869
- maxCount = count
870
- }
871
- }
872
-
873
- w := new (strings.Builder )
874
- fmt .Fprintf (w , `<table>` )
875
- for i := h .MinBucket ; i <= h .MaxBucket ; i ++ {
876
- // Tick label.
877
- if h .Buckets [i ] > 0 {
878
- fmt .Fprintf (w , `<tr><td class="histoTime" align="right"><a href=%s>%s</a></td>` , urlmaker (h .BucketMin (i ), h .BucketMin (i + 1 )), niceDuration (h .BucketMin (i )))
879
- } else {
880
- fmt .Fprintf (w , `<tr><td class="histoTime" align="right">%s</td>` , niceDuration (h .BucketMin (i )))
881
- }
882
- // Bucket bar.
883
- width := h .Buckets [i ] * barWidth / maxCount
884
- fmt .Fprintf (w , `<td><div style="width:%dpx;background:blue;position:relative"> </div></td>` , width )
885
- // Bucket count.
886
- fmt .Fprintf (w , `<td align="right"><div style="position:relative">%d</div></td>` , h .Buckets [i ])
887
- fmt .Fprintf (w , "</tr>\n " )
888
-
889
- }
890
- // Final tick label.
891
- fmt .Fprintf (w , `<tr><td align="right">%s</td></tr>` , niceDuration (h .BucketMin (h .MaxBucket + 1 )))
892
- fmt .Fprintf (w , `</table>` )
893
- return template .HTML (w .String ())
894
- }
895
-
896
- func (h * durationHistogram ) String () string {
897
- const barWidth = 40
898
-
899
- labels := []string {}
900
- maxLabel := 0
901
- maxCount := 0
902
- for i := h .MinBucket ; i <= h .MaxBucket ; i ++ {
903
- // TODO: This formatting is pretty awful.
904
- label := fmt .Sprintf ("[%-12s%-11s)" , h .BucketMin (i ).String ()+ "," , h .BucketMin (i + 1 ))
905
- labels = append (labels , label )
906
- if len (label ) > maxLabel {
907
- maxLabel = len (label )
908
- }
909
- count := h .Buckets [i ]
910
- if count > maxCount {
911
- maxCount = count
912
- }
913
- }
914
-
915
- w := new (strings.Builder )
916
- for i := h .MinBucket ; i <= h .MaxBucket ; i ++ {
917
- count := h .Buckets [i ]
918
- bar := count * barWidth / maxCount
919
- fmt .Fprintf (w , "%*s %-*s %d\n " , maxLabel , labels [i - h .MinBucket ], barWidth , strings .Repeat ("█" , bar ), count )
920
- }
921
- return w .String ()
922
- }
923
-
924
811
type regionStats struct {
925
812
regionTypeID
926
- Histogram durationHistogram
813
+ Histogram traceviewer. TimeHistogram
927
814
}
928
815
929
816
func (s * regionStats ) UserRegionURL () func (min , max time.Duration ) string {
@@ -933,7 +820,7 @@ func (s *regionStats) UserRegionURL() func(min, max time.Duration) string {
933
820
}
934
821
935
822
func (s * regionStats ) add (region regionDesc ) {
936
- s .Histogram .add (region .duration ())
823
+ s .Histogram .Add (region .duration ())
937
824
}
938
825
939
826
var templUserRegionTypes = template .Must (template .New ("" ).Parse (`
@@ -966,8 +853,8 @@ var templUserRegionTypes = template.Must(template.New("").Parse(`
966
853
967
854
type taskStats struct {
968
855
Type string
969
- Count int // Complete + incomplete tasks
970
- Histogram durationHistogram // Complete tasks only
856
+ Count int // Complete + incomplete tasks
857
+ Histogram traceviewer. TimeHistogram // Complete tasks only
971
858
}
972
859
973
860
func (s * taskStats ) UserTaskURL (complete bool ) func (min , max time.Duration ) string {
@@ -979,7 +866,7 @@ func (s *taskStats) UserTaskURL(complete bool) func(min, max time.Duration) stri
979
866
func (s * taskStats ) add (task * taskDesc ) {
980
867
s .Count ++
981
868
if task .complete () {
982
- s .Histogram .add (task .duration ())
869
+ s .Histogram .Add (task .duration ())
983
870
}
984
871
}
985
872
@@ -1169,7 +1056,7 @@ func isUserAnnotationEvent(ev *trace.Event) (taskID uint64, ok bool) {
1169
1056
var templUserRegionType = template .Must (template .New ("" ).Funcs (template.FuncMap {
1170
1057
"prettyDuration" : func (nsec int64 ) template.HTML {
1171
1058
d := time .Duration (nsec ) * time .Nanosecond
1172
- return template .HTML (niceDuration ( d ))
1059
+ return template .HTML (d . String ( ))
1173
1060
},
1174
1061
"percent" : func (dividend , divisor int64 ) template.HTML {
1175
1062
if divisor == 0 {
0 commit comments