blob: 8acf561c96ab0d358e122b6e91eb9a0e0235b21a [file] [log] [blame]
Dan Willemsenb82471a2018-05-17 16:37:09 -07001// Copyright 2018 Google Inc. All rights reserved.
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15package tracer
16
17import (
Dan Alberte82234e2023-06-01 23:09:38 +000018 "strings"
Dan Willemsenb82471a2018-05-17 16:37:09 -070019 "time"
Yu Liua58467a2024-03-05 01:12:19 +000020
21 "android/soong/ui/status"
Dan Willemsenb82471a2018-05-17 16:37:09 -070022)
23
24func (t *tracerImpl) StatusTracer() status.StatusOutput {
25 return &statusOutput{
26 tracer: t,
27
28 running: map[*status.Action]actionStatus{},
29 }
30}
31
32type actionStatus struct {
33 cpu int
34 start time.Time
35}
36
37type statusOutput struct {
38 tracer *tracerImpl
39
40 cpus []bool
41 running map[*status.Action]actionStatus
42}
43
44func (s *statusOutput) StartAction(action *status.Action, counts status.Counts) {
45 cpu := -1
46 for i, busy := range s.cpus {
47 if !busy {
48 cpu = i
49 s.cpus[i] = true
50 break
51 }
52 }
53
54 if cpu == -1 {
55 cpu = len(s.cpus)
56 s.cpus = append(s.cpus, true)
57 }
58
59 s.running[action] = actionStatus{
60 cpu: cpu,
61 start: time.Now(),
62 }
63}
64
Dan Alberte82234e2023-06-01 23:09:38 +000065func (s *statusOutput) parseTags(rawTags string) map[string]string {
66 if rawTags == "" {
67 return nil
68 }
69
70 tags := map[string]string{}
71 for _, pair := range strings.Split(rawTags, ";") {
72 if pair == "" {
73 // Ignore empty tag pairs. It's hard to generate these cleanly from
74 // make so some tag strings might be something like ";key=value".
75 continue
76 }
77 parts := strings.SplitN(pair, "=", 2)
78 tags[parts[0]] = parts[1]
79 }
80 return tags
81}
82
Dan Willemsenb82471a2018-05-17 16:37:09 -070083func (s *statusOutput) FinishAction(result status.ActionResult, counts status.Counts) {
84 start, ok := s.running[result.Action]
85 if !ok {
86 return
87 }
88 delete(s.running, result.Action)
89 s.cpus[start.cpu] = false
90
91 str := result.Action.Description
92 if len(result.Action.Outputs) > 0 {
93 str = result.Action.Outputs[0]
94 }
95
96 s.tracer.writeEvent(&viewerEvent{
97 Name: str,
98 Phase: "X",
99 Time: uint64(start.start.UnixNano()) / 1000,
100 Dur: uint64(time.Since(start.start).Nanoseconds()) / 1000,
101 Pid: 1,
102 Tid: uint64(start.cpu),
Colin Crossd888b6b2020-10-15 13:46:32 -0700103 Arg: &statsArg{
104 UserTime: result.Stats.UserTime,
105 SystemTime: result.Stats.SystemTime,
106 MaxRssKB: result.Stats.MaxRssKB,
107 MinorPageFaults: result.Stats.MinorPageFaults,
108 MajorPageFaults: result.Stats.MajorPageFaults,
109 IOInputKB: result.Stats.IOInputKB,
110 IOOutputKB: result.Stats.IOOutputKB,
111 VoluntaryContextSwitches: result.Stats.VoluntaryContextSwitches,
112 InvoluntaryContextSwitches: result.Stats.InvoluntaryContextSwitches,
Dan Alberte82234e2023-06-01 23:09:38 +0000113 Tags: s.parseTags(result.Stats.Tags),
Yu Liua58467a2024-03-05 01:12:19 +0000114 ChangedInputs: result.Action.ChangedInputs,
Colin Crossd888b6b2020-10-15 13:46:32 -0700115 },
Dan Willemsenb82471a2018-05-17 16:37:09 -0700116 })
117}
118
Colin Crossd888b6b2020-10-15 13:46:32 -0700119type statsArg struct {
Dan Alberte82234e2023-06-01 23:09:38 +0000120 UserTime uint32 `json:"user_time"`
121 SystemTime uint32 `json:"system_time_ms"`
122 MaxRssKB uint64 `json:"max_rss_kb"`
123 MinorPageFaults uint64 `json:"minor_page_faults"`
124 MajorPageFaults uint64 `json:"major_page_faults"`
125 IOInputKB uint64 `json:"io_input_kb"`
126 IOOutputKB uint64 `json:"io_output_kb"`
127 VoluntaryContextSwitches uint64 `json:"voluntary_context_switches"`
128 InvoluntaryContextSwitches uint64 `json:"involuntary_context_switches"`
129 Tags map[string]string `json:"tags"`
Yu Liua58467a2024-03-05 01:12:19 +0000130 ChangedInputs []string `json:"changed_inputs"`
Colin Crossd888b6b2020-10-15 13:46:32 -0700131}
132
Dan Willemsenb82471a2018-05-17 16:37:09 -0700133func (s *statusOutput) Flush() {}
134func (s *statusOutput) Message(level status.MsgLevel, message string) {}
Colin Crosse0df1a32019-06-09 19:40:08 -0700135
136func (s *statusOutput) Write(p []byte) (int, error) {
137 // Discard writes
138 return len(p), nil
139}