summaryrefslogtreecommitdiff
path: root/startop/scripts/app_startup/parse_metrics
blob: 036609ff02be6e9889131ab3c636efcad5d102f7 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
#!/bin/bash
#
# Copyright 2019, The Android Open Source Project
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

usage() {
    cat <<EOF
Usage: launch_application package activity | parse_metrics --package <name> --timestamp <timestamp> [OPTIONS]...

  Reads from stdin the result of 'am start' metrics. May also parse logcat
  for additional metrics.

  Output form:

    MetricName_unit=numeric_value
    MetricName2_unit=numeric_value2

  This may block until all desired metrics are parsed from logcat.
  To get a list of metrics without doing real parsing, use --simulate.

  To add package-specific metrics, add a script called 'metrics/\$full_package_name'
  that exposes additional metrics in same way as above.

  (required)
    -p, --package <name>        package of the app that is being used
    -ts, --timestamp <name>     logcat timestamp [only looks at logcat entries after this timestamp].

  (optional)
    -s, --simulate              prints dummy values instead of real metrics
    -a, --activity <name>       activity to use (default: inferred)
    -h, --help                  usage information (this)
    -v, --verbose               enable extra verbose printing
    -t, --timeout <sec>         how many seconds to timeout when trying to wait for logcat to change
EOF
}

DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
source "$DIR/lib/common"

package=""
activity=""
timeout=5
simulate="n"
parse_arguments() {
  while [[ $# -gt 0 ]]; do
    case "$1" in
      -h|--help)
        usage
        exit 0
        ;;
      -p|--package)
        package="$2"
        shift
        ;;
      -a|--activity)
        activity="$2"
        shift
        ;;
      -v|--verbose)
        export verbose="y"
        ;;
      -t|--timeout)
        timeout="$2"
        shift
        ;;
      -ts|--timestamp)
        timestamp="$2"
        shift
        ;;
      -s|--simulate)
        simulate="y"
        ;;
      *)
        echo "Invalid argument: $1" >&2
        exit 1
    esac
    shift
  done
}

# Main entry point
if [[ $# -eq 0 ]]; then
  usage
  exit 1
else
  parse_arguments "$@"

  # if we do not have have package exit early with an error
  [[ "$package" == "" ]] && echo "--package not specified" 1>&2 && exit 64

  # ignore timestamp for --simulate. it's optional.
  if [[ $simulate == y ]]; then
    timestamp=0
  fi

  # if we do not have timestamp, exit early with an error
  [[ "$timestamp" == "" ]] && echo "--timestamp not specified" 1>&2 && exit 64

  if [[ "$activity" == "" ]] && [[ "$simulate" != "y" ]]; then
    activity="$(get_activity_name "$package")"
    if [[ "$activity" == "" ]]; then
      echo "Activity name could not be found, invalid package name?" 1>&2
      exit 64
    else
      verbose_print "Activity name inferred: " "$activity"
    fi
  fi
fi

parse_metric_from_logcat() {
  local metric_name="$1"
  local pattern="$2"
  local re_pattern="$3"
  local retcode
  local result
  local sec
  local ms

  # parse logcat for 'Displayed...' and that other one...

  # 05-06 14:34:08.854 29460 29481 I ActivityTaskManager: Displayed com.google.android.dialer/.extensions.GoogleDialtactsActivity: +361ms
  verbose_print "parse_metric_from_logcat: $re_pattern"


  echo -ne "$metric_name="

  if [[ $simulate == y ]]; then
    echo "-1"
    return 0
  fi

  result="$(logcat_extract_pattern "$timeout" "$timestamp" "$pattern" "$re_pattern")"
  retcode=$?

  if [[ $retcode -ne 0 ]]; then
    # Timed out before finding the pattern. Could also mean the pattern is wrong.
    echo "Parse $re_pattern from logcat TIMED OUT after $timeout seconds." >&2
    echo "-$?"
    return $retcode
  fi

  # "10s123ms" -> "10s123"
  result=${result/ms/}
  if [[ $result =~ s ]]; then
    ms=${result/*s/}
    sec=${result/s*/}
  else
    sec=0
    ms=$result
  fi
  ((result=sec*1000+ms))

  echo "$result"
  return $retcode
}


total_time="-1"
if [[ $simulate != y ]]; then
  verbose_print 'logcat timestamp NOW: ' $(logcat_save_timestamp)

  # parse stdin for 'am start' result
  while read -t "$timeout" -r input_line; do
    verbose_print 'stdin:' "$input_line"
    if [[ $input_line == *TotalTime:* ]]; then
      total_time="$(echo "$input_line" | sed 's/TotalTime: \([[:digit:]]\+\)/\1/g')"
      # but keep reading the rest from stdin until <EOF>
    fi
  done
fi

echo "TotalTime_ms=$total_time"

# parse logcat for 'Displayed...' and that other one...

# 05-06 14:34:08.854 29460 29481 I ActivityTaskManager: Displayed com.google.android.dialer/.extensions.GoogleDialtactsActivity: +361ms
pattern="ActivityTaskManager: Displayed ${package}"
re_pattern='.*Displayed[[:blank:]]\+'"${package}"'[/][^[:blank:]]\+[[:blank:]]+\([[:digit:]]\+ms\|[[:digit:]]\+s[[:digit:]]\+ms\).*'

parse_metric_from_logcat "Displayed_ms" "$pattern" "$re_pattern"

# 01-16 17:31:44.550 11172 11204 I ActivityTaskManager: Fully drawn com.google.android.GoogleCamera/com.android.camera.CameraLauncher: +10s897ms
pattern="ActivityTaskManager: Fully drawn ${package}"
#re_pattern='.*Fully drawn[[:blank:]]\+'"${package}"'[/][^[:blank:]]\+[[:blank:]]+\([[:digit:]]\+\).*'
re_pattern='.*Fully drawn[[:blank:]]\+'"${package}"'[/][^[:blank:]]\+[[:blank:]]+\([[:digit:]]\+ms\|[[:digit:]]\+s[[:digit:]]\+ms\).*'

parse_metric_from_logcat "Fully_drawn_ms" "$pattern" "$re_pattern"

# also call into package-specific scripts if there are additional metrics
if [[ -x "$DIR/metrics/$package" ]]; then
  source "$DIR/metrics/$package" "$timestamp"
else
  verbose_print parse_metrics: no per-package metrics script found at "$DIR/metrics/$package"
fi