blob: 8cbc09f2ffe17916c9bb3ab84adfa33053fcf8c7 [file] [log] [blame]
Takuto Ikuta9af233a2018-11-29 03:53:53 +00001#!/usr/bin/env python
2# Copyright 2018 The Chromium Authors. All rights reserved.
3# Use of this source code is governed by a BSD-style license that can be
4# found in the LICENSE file.
5
6"""
7This is script to upload ninja_log from googler.
8
9Server side implementation is in
10https://cs.chromium.org/chromium/infra/go/src/infra/appengine/chromium_build_stats/
11
12Uploaded ninjalog is stored in BigQuery table having following schema.
13https://cs.chromium.org/chromium/infra/go/src/infra/appengine/chromium_build_stats/ninjaproto/ninjalog.proto
14
15The log will be used to analyze user side build performance.
16"""
17
18import argparse
19import cStringIO
20import gzip
21import json
22import logging
23import multiprocessing
24import os
25import platform
26import socket
27import sys
28
29from third_party import httplib2
30
31def IsGoogler(server):
32 """Check whether this script run inside corp network."""
33 try:
34 h = httplib2.Http()
35 _, content = h.request('https://'+server+'/should-upload', 'GET')
36 return content == 'Success'
37 except httplib2.HttpLib2Error:
38 return False
39
40def GetMetadata(cmdline, ninjalog):
41 """Get metadata for uploaded ninjalog."""
42
43 # TODO(tikuta): Support build_configs from args.gn.
44
45 build_dir = os.path.dirname(ninjalog)
46 metadata = {
47 'platform': platform.system(),
48 'cwd': build_dir,
49 'hostname': socket.gethostname(),
50 'cpu_core': multiprocessing.cpu_count(),
51 'cmdline': cmdline,
52 }
53
54 return metadata
55
56def GetNinjalog(cmdline):
57 """GetNinjalog returns the path to ninjalog from cmdline.
58
59 >>> GetNinjalog(['ninja'])
60 './.ninja_log'
61 >>> GetNinjalog(['ninja', '-C', 'out/Release'])
62 'out/Release/.ninja_log'
63 >>> GetNinjalog(['ninja', '-Cout/Release'])
64 'out/Release/.ninja_log'
65 >>> GetNinjalog(['ninja', '-C'])
66 './.ninja_log'
67 >>> GetNinjalog(['ninja', '-C', 'out/Release', '-C', 'out/Debug'])
68 'out/Debug/.ninja_log'
69 """
70 # ninjalog is in current working directory by default.
71 ninjalog_dir = '.'
72
73 i = 0
74 while i < len(cmdline):
75 cmd = cmdline[i]
76 i += 1
77 if cmd == '-C' and i < len(cmdline):
78 ninjalog_dir = cmdline[i]
79 i += 1
80 continue
81
82 if cmd.startswith('-C') and len(cmd) > len('-C'):
83 ninjalog_dir = cmd[len('-C'):]
84
85 return os.path.join(ninjalog_dir, '.ninja_log')
86
87def main():
88 parser = argparse.ArgumentParser()
89 parser.add_argument('--server',
90 default='chromium-build-stats.appspot.com',
91 help='server to upload ninjalog file.')
92 parser.add_argument('--ninjalog', help='ninjalog file to upload.')
93 parser.add_argument('--verbose', action='store_true',
94 help='Enable verbose logging.')
95 parser.add_argument('--cmdline', required=True, nargs=argparse.REMAINDER,
96 help='command line args passed to ninja.')
97
98 args = parser.parse_args()
99
100 if args.verbose:
101 logging.basicConfig(level=logging.INFO)
102 else:
103 # Disable logging.
104 logging.disable(logging.CRITICAL)
105
106 if not IsGoogler(args.server):
107 return 0
108
109
110 ninjalog = args.ninjalog or GetNinjalog(args.cmdline)
111 if not os.path.isfile(ninjalog):
112 logging.warn("ninjalog is not found in %s", ninjalog)
113 return 1
114
115 output = cStringIO.StringIO()
116
117 with open(ninjalog) as f:
118 with gzip.GzipFile(fileobj=output, mode='wb') as g:
119 g.write(f.read())
120 g.write('# end of ninja log\n')
121
122 metadata = GetMetadata(args.cmdline, ninjalog)
123 logging.info('send metadata: %s', metadata)
124 g.write(json.dumps(metadata))
125
126 h = httplib2.Http()
127 resp_headers, content = h.request(
128 'https://'+args.server+'/upload_ninja_log/', 'POST',
129 body=output.getvalue(), headers={'Content-Encoding': 'gzip'})
130
131 if resp_headers.status != 200:
132 logging.warn("unexpected status code for response: %s",
133 resp_headers.status)
134 return 1
135
136 logging.info('response header: %s', resp_headers)
137 logging.info('response content: %s', content)
138 return 0
139
140if __name__ == '__main__':
141 sys.exit(main())