xref: /aosp_15_r20/external/cronet/net/tools/truncate_net_log.py (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
1*6777b538SAndroid Build Coastguard Worker#!/usr/bin/env python
2*6777b538SAndroid Build Coastguard Worker# Copyright 2017 The Chromium Authors
3*6777b538SAndroid Build Coastguard Worker# Use of this source code is governed by a BSD-style license that can be
4*6777b538SAndroid Build Coastguard Worker# found in the LICENSE file.
5*6777b538SAndroid Build Coastguard Worker
6*6777b538SAndroid Build Coastguard Workerimport os
7*6777b538SAndroid Build Coastguard Workerimport re
8*6777b538SAndroid Build Coastguard Workerimport sys
9*6777b538SAndroid Build Coastguard Worker
10*6777b538SAndroid Build Coastguard WorkerkUsage = '''Usage: truncate_net_log.py INPUT_FILE OUTPUT_FILE TRUNCATED_SIZE
11*6777b538SAndroid Build Coastguard Worker
12*6777b538SAndroid Build Coastguard WorkerCreates a smaller version of INPUT_FILE (which is a chrome-net-export-log.json
13*6777b538SAndroid Build Coastguard Workerformatted NetLog file) and saves it to OUTPUT_FILE. Note that this works by
14*6777b538SAndroid Build Coastguard Workerreading the file line by line and not fully parsing the JSON, so it must match
15*6777b538SAndroid Build Coastguard Workerthe exact format (whitespace and all).
16*6777b538SAndroid Build Coastguard Worker
17*6777b538SAndroid Build Coastguard WorkerFile truncation is done by dropping the oldest events and keeping everything
18*6777b538SAndroid Build Coastguard Workerelse.
19*6777b538SAndroid Build Coastguard Worker
20*6777b538SAndroid Build Coastguard WorkerParameters:
21*6777b538SAndroid Build Coastguard Worker
22*6777b538SAndroid Build Coastguard Worker  INPUT_FILE:
23*6777b538SAndroid Build Coastguard Worker    Path to net-export JSON file
24*6777b538SAndroid Build Coastguard Worker
25*6777b538SAndroid Build Coastguard Worker  OUTPUT_FILE:
26*6777b538SAndroid Build Coastguard Worker    Path to save truncated file to
27*6777b538SAndroid Build Coastguard Worker
28*6777b538SAndroid Build Coastguard Worker  TRUNCATED_SIZE:
29*6777b538SAndroid Build Coastguard Worker    The desired (approximate) size for the truncated file. May use a suffix to
30*6777b538SAndroid Build Coastguard Worker    indicate units. Examples:
31*6777b538SAndroid Build Coastguard Worker          2003  -->  2003 bytes
32*6777b538SAndroid Build Coastguard Worker          100K  -->  100 KiB
33*6777b538SAndroid Build Coastguard Worker          8M    -->  8 MiB
34*6777b538SAndroid Build Coastguard Worker          1.5m  -->  1.5 MiB
35*6777b538SAndroid Build Coastguard Worker'''
36*6777b538SAndroid Build Coastguard Worker
37*6777b538SAndroid Build Coastguard Workerdef get_file_size(path):
38*6777b538SAndroid Build Coastguard Worker  '''Returns the filesize of |path| in bytes'''
39*6777b538SAndroid Build Coastguard Worker  return os.stat(path).st_size
40*6777b538SAndroid Build Coastguard Worker
41*6777b538SAndroid Build Coastguard Worker
42*6777b538SAndroid Build Coastguard Workerdef truncate_log_file(in_path, out_path, desired_size):
43*6777b538SAndroid Build Coastguard Worker  '''Copies |in_path| to |out_path| such that it is approximately
44*6777b538SAndroid Build Coastguard Worker  |desired_size| bytes large. This is accomplished by dropping the oldest
45*6777b538SAndroid Build Coastguard Worker  events first. The final file size may not be exactly |desired_size| as only
46*6777b538SAndroid Build Coastguard Worker  complete event lines are skipped.'''
47*6777b538SAndroid Build Coastguard Worker  orig_size = get_file_size(in_path)
48*6777b538SAndroid Build Coastguard Worker  bytes_to_truncate = orig_size - desired_size
49*6777b538SAndroid Build Coastguard Worker
50*6777b538SAndroid Build Coastguard Worker  # This variable is True if the current line being processed is an Event line.
51*6777b538SAndroid Build Coastguard Worker  inside_events = False
52*6777b538SAndroid Build Coastguard Worker  with open(out_path, 'w') as out_file:
53*6777b538SAndroid Build Coastguard Worker    with open(in_path, 'r') as in_file:
54*6777b538SAndroid Build Coastguard Worker      for line in in_file:
55*6777b538SAndroid Build Coastguard Worker        # The final line before polledData closes the events array, and hence
56*6777b538SAndroid Build Coastguard Worker        # ends in "],". The check for polledData is more for documentation
57*6777b538SAndroid Build Coastguard Worker        # sake.
58*6777b538SAndroid Build Coastguard Worker        if inside_events and (line.startswith('"polledData": {' or
59*6777b538SAndroid Build Coastguard Worker                              line.endswith('],\n'))):
60*6777b538SAndroid Build Coastguard Worker          inside_events = False
61*6777b538SAndroid Build Coastguard Worker
62*6777b538SAndroid Build Coastguard Worker        # If this is an event line and need to drop more bytes, go ahead and
63*6777b538SAndroid Build Coastguard Worker        # skip the line. Otherwise copy it to the output file.
64*6777b538SAndroid Build Coastguard Worker        if inside_events and bytes_to_truncate > 0:
65*6777b538SAndroid Build Coastguard Worker          bytes_to_truncate -= len(line)
66*6777b538SAndroid Build Coastguard Worker        else:
67*6777b538SAndroid Build Coastguard Worker          out_file.write(line)
68*6777b538SAndroid Build Coastguard Worker
69*6777b538SAndroid Build Coastguard Worker        # All lines after this are events (up until the closing square
70*6777b538SAndroid Build Coastguard Worker        # bracket).
71*6777b538SAndroid Build Coastguard Worker        if line.startswith('"events": ['):
72*6777b538SAndroid Build Coastguard Worker          inside_events = True
73*6777b538SAndroid Build Coastguard Worker
74*6777b538SAndroid Build Coastguard Worker  sys.stdout.write(
75*6777b538SAndroid Build Coastguard Worker      'Truncated file from %d to %d bytes\n' % (orig_size,
76*6777b538SAndroid Build Coastguard Worker                                                get_file_size(out_path)))
77*6777b538SAndroid Build Coastguard Worker
78*6777b538SAndroid Build Coastguard Workerdef parse_filesize_str(filesize_str):
79*6777b538SAndroid Build Coastguard Worker  '''Parses a string representation of a file size into a byte value, or None
80*6777b538SAndroid Build Coastguard Worker  on failure'''
81*6777b538SAndroid Build Coastguard Worker  filesize_str = filesize_str.lower()
82*6777b538SAndroid Build Coastguard Worker  m = re.match('([0-9\.]+)([km]?)', filesize_str)
83*6777b538SAndroid Build Coastguard Worker
84*6777b538SAndroid Build Coastguard Worker  if not m:
85*6777b538SAndroid Build Coastguard Worker    return None
86*6777b538SAndroid Build Coastguard Worker
87*6777b538SAndroid Build Coastguard Worker  # Try to parse as decimal (regex above accepts some invalid decimals too).
88*6777b538SAndroid Build Coastguard Worker  float_value = 0.0
89*6777b538SAndroid Build Coastguard Worker  try:
90*6777b538SAndroid Build Coastguard Worker    float_value = float(m.group(1))
91*6777b538SAndroid Build Coastguard Worker  except ValueError:
92*6777b538SAndroid Build Coastguard Worker    return None
93*6777b538SAndroid Build Coastguard Worker
94*6777b538SAndroid Build Coastguard Worker  kSuffixValueBytes = {
95*6777b538SAndroid Build Coastguard Worker    'k': 1024,
96*6777b538SAndroid Build Coastguard Worker    'm': 1024 * 1024,
97*6777b538SAndroid Build Coastguard Worker    '': 1,
98*6777b538SAndroid Build Coastguard Worker  }
99*6777b538SAndroid Build Coastguard Worker
100*6777b538SAndroid Build Coastguard Worker  suffix = m.group(2)
101*6777b538SAndroid Build Coastguard Worker  return int(float_value * kSuffixValueBytes[suffix])
102*6777b538SAndroid Build Coastguard Worker
103*6777b538SAndroid Build Coastguard Worker
104*6777b538SAndroid Build Coastguard Workerdef main():
105*6777b538SAndroid Build Coastguard Worker  if len(sys.argv) != 4:
106*6777b538SAndroid Build Coastguard Worker    sys.stderr.write('ERROR: Requires 3 command line arguments\n')
107*6777b538SAndroid Build Coastguard Worker    sys.stderr.write(kUsage)
108*6777b538SAndroid Build Coastguard Worker    sys.exit(1)
109*6777b538SAndroid Build Coastguard Worker
110*6777b538SAndroid Build Coastguard Worker  in_path = os.path.normpath(sys.argv[1])
111*6777b538SAndroid Build Coastguard Worker  out_path = os.path.normpath(sys.argv[2])
112*6777b538SAndroid Build Coastguard Worker
113*6777b538SAndroid Build Coastguard Worker  if in_path == out_path:
114*6777b538SAndroid Build Coastguard Worker    sys.stderr.write('ERROR: OUTPUT_FILE must be different from INPUT_FILE\n')
115*6777b538SAndroid Build Coastguard Worker    sys.stderr.write(kUsage)
116*6777b538SAndroid Build Coastguard Worker    sys.exit(1)
117*6777b538SAndroid Build Coastguard Worker
118*6777b538SAndroid Build Coastguard Worker  size_str = sys.argv[3]
119*6777b538SAndroid Build Coastguard Worker  size_bytes = parse_filesize_str(size_str)
120*6777b538SAndroid Build Coastguard Worker  if size_bytes is None:
121*6777b538SAndroid Build Coastguard Worker    sys.stderr.write('ERROR: Could not parse TRUNCATED_SIZE: %s\n' % size_str)
122*6777b538SAndroid Build Coastguard Worker    sys.stderr.write(kUsage)
123*6777b538SAndroid Build Coastguard Worker    sys.exit(1)
124*6777b538SAndroid Build Coastguard Worker
125*6777b538SAndroid Build Coastguard Worker  truncate_log_file(in_path, out_path, size_bytes)
126*6777b538SAndroid Build Coastguard Worker
127*6777b538SAndroid Build Coastguard Worker
128*6777b538SAndroid Build Coastguard Workerif __name__ == '__main__':
129*6777b538SAndroid Build Coastguard Worker  main()
130