blob: 2845fb3cd25e2a0d711544f0c787414431c77545 [file] [log] [blame]
Robert Tarasovdf3962b2019-07-28 00:56:25 -07001
2/**************************************************************************
3 *
4 * Copyright 2011 Jose Fonseca
5 * Copyright 2010 VMware, Inc.
6 * All Rights Reserved.
7 *
8 * Permission is hereby granted, free of charge, to any person obtaining a copy
9 * of this software and associated documentation files (the "Software"), to deal
10 * in the Software without restriction, including without limitation the rights
11 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12 * copies of the Software, and to permit persons to whom the Software is
13 * furnished to do so, subject to the following conditions:
14 *
15 * The above copyright notice and this permission notice shall be included in
16 * all copies or substantial portions of the Software.
17 *
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
24 * THE SOFTWARE.
25 *
26 **************************************************************************/
27
28
29#include <string.h>
30#include <limits.h> // for CHAR_MAX
31#include <getopt.h>
32#ifndef _WIN32
33#include <unistd.h> // for isatty()
34#endif
35
36#include <memory>
37#include <fstream>
38#include <string>
39#include <regex>
40
41#include "cxx_compat.hpp" // for std::to_string, std::make_unique
42
43#include "cli.hpp"
44#include "cli_pager.hpp"
45
46#include "trace_parser.hpp"
47#include "trace_dump_internal.hpp"
48#include "trace_callset.hpp"
49#include "trace_option.hpp"
50
Robert Tarasov67634522020-06-24 16:17:48 -070051static const char *synopsis = "Print given trace file(s) information in JSON format";
Robert Tarasovdf3962b2019-07-28 00:56:25 -070052
53static void
54usage(void)
55{
56 std::cout
57 << "usage: apitrace info [OPTIONS] TRACE_FILE...\n"
58 << synopsis << "\n"
59 "\n"
Robert Tarasovaaa95fc2020-01-30 14:26:37 +000060 " -h, --help show this help message and exit\n"
Robert Tarasov67634522020-06-24 16:17:48 -070061 " --dump-frames dump per frame information\n"
Robert Tarasovdf3962b2019-07-28 00:56:25 -070062 "\n"
63 ;
64}
65
66enum {
Robert Tarasov67634522020-06-24 16:17:48 -070067 DUMP_FRAMES_OPT = CHAR_MAX + 1,
Robert Tarasovdf3962b2019-07-28 00:56:25 -070068};
69
70const static char *
Robert Tarasovaaa95fc2020-01-30 14:26:37 +000071shortOptions = "h";
Robert Tarasovdf3962b2019-07-28 00:56:25 -070072
73const static struct option
74longOptions[] = {
75 {"help", no_argument, 0, 'h'},
Robert Tarasov67634522020-06-24 16:17:48 -070076 {"dump-frames", no_argument, 0, DUMP_FRAMES_OPT},
Robert Tarasovdf3962b2019-07-28 00:56:25 -070077 {0, 0, 0, 0}
78};
79
Robert Tarasovaaa95fc2020-01-30 14:26:37 +000080static const char*
81getApiName(int api) {
82 if (api < trace::API_UNKNOWN || api >= trace::API_MAX)
83 api = trace::API_UNKNOWN;
84 return trace::API_NAMES[api];
Robert Tarasovdf3962b2019-07-28 00:56:25 -070085}
86
Robert Tarasov67634522020-06-24 16:17:48 -070087struct FrameEntry {
88 size_t firstCallId, lastCallId;
89 size_t totalCalls;
90 size_t sizeInBytes;
91};
92
Robert Tarasovdf3962b2019-07-28 00:56:25 -070093static int
94command(int argc, char *argv[])
95{
Robert Tarasov67634522020-06-24 16:17:48 -070096 bool flagDumpFrames = false;
Robert Tarasovdf3962b2019-07-28 00:56:25 -070097 int opt;
98 while ((opt = getopt_long(argc, argv, shortOptions, longOptions, NULL)) != -1) {
99 switch (opt) {
100 case 'h':
101 usage();
102 return 0;
Robert Tarasov67634522020-06-24 16:17:48 -0700103 case DUMP_FRAMES_OPT:
104 flagDumpFrames = true;
Robert Tarasovdf3962b2019-07-28 00:56:25 -0700105 break;
106 default:
107 std::cerr << "error: unexpected option `" << (char)opt << "`\n";
108 usage();
109 return 1;
110 }
111 }
112
Robert Tarasov67634522020-06-24 16:17:48 -0700113 typedef std::vector<FrameEntry> FrameEntries;
114 FrameEntries frames;
115
Robert Tarasovdf3962b2019-07-28 00:56:25 -0700116 for (int i = optind; i < argc; ++i) {
Robert Tarasovaaa95fc2020-01-30 14:26:37 +0000117 unsigned long framesCount = 0;
118 trace::API api = trace::API_UNKNOWN;
Robert Tarasovdf3962b2019-07-28 00:56:25 -0700119 trace::Parser p;
120
Robert Tarasovaaa95fc2020-01-30 14:26:37 +0000121 if (!p.open(argv[i])) {
Robert Tarasovdf3962b2019-07-28 00:56:25 -0700122 return 1;
123 }
124
125 trace::Call *call;
Robert Tarasov67634522020-06-24 16:17:48 -0700126 size_t callsInFrame = 0;
127 size_t firstCallId = 0;
128 size_t frameBytesOffset = 0;
129 bool endFrame = true;
Robert Tarasovdf3962b2019-07-28 00:56:25 -0700130 while ((call = p.parse_call())) {
Robert Tarasov67634522020-06-24 16:17:48 -0700131 if (flagDumpFrames) {
132 ++callsInFrame;
133 if (endFrame) {
134 firstCallId = call->no;
135 endFrame = false;
136 }
137 }
Robert Tarasovaaa95fc2020-01-30 14:26:37 +0000138 if (api == trace::API_UNKNOWN && p.api != trace::API_UNKNOWN)
Robert Tarasov67634522020-06-24 16:17:48 -0700139 api = p.api;
140 if (call->flags & trace::CALL_FLAG_END_FRAME) {
141 ++framesCount;
142 if (flagDumpFrames) {
143 size_t curBytesOffset = p.dataBytesRead();
144 frames.push_back(
145 FrameEntry {
146 firstCallId,
147 call->no,
148 callsInFrame,
149 curBytesOffset-frameBytesOffset
150 }
151 );
152 frameBytesOffset = curBytesOffset;
153 endFrame = true;
154 callsInFrame = 0;
155 }
156 }
Robert Tarasovdf3962b2019-07-28 00:56:25 -0700157 delete call;
158 }
159
Robert Tarasov67634522020-06-24 16:17:48 -0700160 std::cout <<
161 "{" << std::endl <<
162 " \"FileName\": \"" << argv[i] << "\"," << std::endl <<
163 " \"ContainerVersion\": " << p.getVersion() << "," << std::endl <<
164 " \"ContainerType\": \"" << p.containerType() << "\"," << std::endl <<
165 " \"API\": \"" << getApiName(api) << "\"," << std::endl <<
166 " \"FramesCount\": " << framesCount << "," << std::endl <<
167 " \"ActualDataSize\": " << p.dataBytesRead() << "," << std::endl <<
168 " \"ContainerSize\": " << p.containerSizeInBytes();
169 if (flagDumpFrames) {
170 std::cout << "," << std::endl;
Robert Tarasovaaa95fc2020-01-30 14:26:37 +0000171 std::cout <<
Robert Tarasov67634522020-06-24 16:17:48 -0700172 " \"Frames\": [{" << std::endl;
173 for (auto it = frames.begin(); it != frames.end(); ++it) {
174 std::cout <<
175 " \"FirstCallId\": " << it->firstCallId << "," << std::endl <<
176 " \"LastCallId\": " << it->lastCallId << "," << std::endl <<
177 " \"TotalCalls\": " << it->totalCalls << "," << std::endl <<
178 " \"SizeInBytes\": " << it->sizeInBytes << std::endl;
179 if (it != std::prev(frames.end())) {
180 std::cout << " }, {" << std::endl;
181 }
182 }
183 std::cout << " }]" << std::endl;
Robert Tarasovdf3962b2019-07-28 00:56:25 -0700184 } else {
Robert Tarasov67634522020-06-24 16:17:48 -0700185 std::cout << std::endl;
Robert Tarasovdf3962b2019-07-28 00:56:25 -0700186 }
Robert Tarasov67634522020-06-24 16:17:48 -0700187 std::cout << "}" << std::endl;
Robert Tarasovdf3962b2019-07-28 00:56:25 -0700188 }
189
Robert Tarasovaaa95fc2020-01-30 14:26:37 +0000190 return 0;
Robert Tarasovdf3962b2019-07-28 00:56:25 -0700191}
192
193const Command info_command = {
194 "info",
195 synopsis,
196 usage,
197 command
198};