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