Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(14)

Side by Side Diff: blimp/common/logging.cc

Issue 2026053002: Blimp: change logger to use switch/case for types. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Inline the logging helper function. Created 4 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « blimp/common/logging.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2016 The Chromium Authors. All rights reserved. 1 // Copyright 2016 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "blimp/common/logging.h" 5 #include "blimp/common/logging.h"
6 6
7 #include <iostream> 7 #include <iostream>
8 #include <string> 8 #include <string>
9 #include <utility>
9 #include <vector> 10 #include <vector>
10 11
11 #include "base/format_macros.h" 12 #include "base/format_macros.h"
12 #include "base/json/string_escape.h" 13 #include "base/json/string_escape.h"
13 #include "base/lazy_instance.h" 14 #include "base/lazy_instance.h"
14 #include "base/memory/ptr_util.h" 15 #include "base/memory/ptr_util.h"
15 #include "base/strings/string_number_conversions.h" 16 #include "base/strings/string_number_conversions.h"
16 #include "base/strings/string_util.h" 17 #include "base/strings/string_util.h"
17 #include "base/strings/stringprintf.h" 18 #include "base/strings/stringprintf.h"
18 #include "blimp/common/create_blimp_message.h" 19 #include "blimp/common/create_blimp_message.h"
19 #include "blimp/common/proto/blimp_message.pb.h" 20 #include "blimp/common/proto/blimp_message.pb.h"
20 21
21 namespace blimp { 22 namespace blimp {
22 namespace { 23 namespace {
23 24
24 static base::LazyInstance<BlimpMessageLogger> g_logger = 25 typedef std::vector<std::pair<std::string, std::string>> LogFields;
Wez 2016/06/03 00:07:54 nit: Style-guide says using using instead of typed
Kevin M 2016/06/07 00:05:50 Done.
25 LAZY_INSTANCE_INITIALIZER;
26 26
27 // The AddField() suite of functions are used to convert KV pairs with 27 // The AddField() suite of functions are used to convert KV pairs with
28 // arbitrarily typed values into string/string KV pairs for logging. 28 // arbitrarily typed values into string/string KV pairs for logging.
29 29
30 // Specialization for string values, surrounding them with quotes and escaping 30 // Specialization for string values, surrounding them with quotes and escaping
31 // characters as necessary. 31 // characters as necessary.
32 void AddField(const std::string& key, 32 void AddField(const std::string& key,
33 const std::string& value, 33 const std::string& value,
34 LogFields* output) { 34 LogFields* output) {
35 std::string escaped_value; 35 std::string escaped_value;
(...skipping 26 matching lines...) Expand all
62 // Uses std::to_string() to serialize |value|. 62 // Uses std::to_string() to serialize |value|.
63 template <typename T> 63 template <typename T>
64 void AddField(const std::string& key, const T& value, LogFields* output) { 64 void AddField(const std::string& key, const T& value, LogFields* output) {
65 output->push_back(std::make_pair(key, std::to_string(value))); 65 output->push_back(std::make_pair(key, std::to_string(value)));
66 } 66 }
67 67
68 // The following LogExtractor subclasses contain logic for extracting loggable 68 // The following LogExtractor subclasses contain logic for extracting loggable
69 // fields from BlimpMessages. 69 // fields from BlimpMessages.
70 70
71 // Logs fields from COMPOSITOR messages. 71 // Logs fields from COMPOSITOR messages.
72 class CompositorLogExtractor : public LogExtractor { 72 void ExtractCompositorMessageFields(const BlimpMessage& message,
73 void ExtractFields(const BlimpMessage& message, 73 LogFields* output) {
74 LogFields* output) const override { 74 AddField("render_widget_id", message.compositor().render_widget_id(), output);
75 AddField("render_widget_id", message.compositor().render_widget_id(), 75 }
76
77 // Logs fields from INPUT messages.
78 void ExtractInputMessageFields(const BlimpMessage& message, LogFields* output) {
79 AddField("render_widget_id", message.input().render_widget_id(), output);
80 AddField("timestamp_seconds", message.input().timestamp_seconds(), output);
81 switch (message.input().type()) {
82 case InputMessage::Type_GestureScrollBegin:
83 AddField("subtype", "GestureScrollBegin", output);
84 break;
85 case InputMessage::Type_GestureScrollEnd:
86 AddField("subtype", "GestureScrollEnd", output);
87 break;
88 case InputMessage::Type_GestureScrollUpdate:
89 AddField("subtype", "GestureScrollUpdate", output);
90 break;
91 case InputMessage::Type_GestureFlingStart:
92 AddField("subtype", "GestureFlingStart", output);
93 break;
94 case InputMessage::Type_GestureFlingCancel:
95 AddField("subtype", "GestureFlingCancel", output);
96 AddField("prevent_boosting",
97 message.input().gesture_fling_cancel().prevent_boosting(),
98 output);
99 break;
100 case InputMessage::Type_GestureTap:
101 AddField("subtype", "GestureTap", output);
102 break;
103 case InputMessage::Type_GesturePinchBegin:
104 AddField("subtype", "GesturePinchBegin", output);
105 break;
106 case InputMessage::Type_GesturePinchEnd:
107 AddField("subtype", "GesturePinchEnd", output);
108 break;
109 case InputMessage::Type_GesturePinchUpdate:
110 AddField("subtype", "GesturePinchUpdate", output);
111 break;
112 default: // unknown
Wez 2016/06/03 00:07:54 Replace the default's, here and below, with explic
Kevin M 2016/06/07 00:05:50 Done.
113 break;
114 }
115 }
116
117 // Logs fields from NAVIGATION messages.
118 void ExtractNavigationMessageFields(const BlimpMessage& message,
119 LogFields* output) {
120 switch (message.navigation().type()) {
121 case NavigationMessage::NAVIGATION_STATE_CHANGED:
122 AddField("subtype", "NAVIGATION_STATE_CHANGED", output);
123 if (message.navigation().navigation_state_changed().has_url()) {
124 AddField("url", message.navigation().navigation_state_changed().url(),
125 output);
126 }
127 if (message.navigation().navigation_state_changed().has_favicon()) {
128 AddField(
129 "favicon_size",
130 message.navigation().navigation_state_changed().favicon().size(),
131 output);
132 }
133 if (message.navigation().navigation_state_changed().has_title()) {
134 AddField("title",
135 message.navigation().navigation_state_changed().title(),
136 output);
137 }
138 if (message.navigation().navigation_state_changed().has_loading()) {
139 AddField("loading",
140 message.navigation().navigation_state_changed().loading(),
141 output);
142 }
143 break;
144 case NavigationMessage::LOAD_URL:
145 AddField("subtype", "LOAD_URL", output);
146 AddField("url", message.navigation().load_url().url(), output);
147 break;
148 case NavigationMessage::GO_BACK:
149 AddField("subtype", "GO_BACK", output);
150 break;
151 case NavigationMessage::GO_FORWARD:
152 AddField("subtype", "GO_FORWARD", output);
153 break;
154 case NavigationMessage::RELOAD:
155 AddField("subtype", "RELOAD", output);
156 break;
157 default:
158 break;
159 }
160 }
161
162 // Logs fields from PROTOCOL_CONTROL messages.
163 void ExtractProtocolControlMessageFields(const BlimpMessage& message,
164 LogFields* output) {
165 switch (message.protocol_control().connection_message_case()) {
166 case ProtocolControlMessage::kStartConnection:
167 AddField("subtype", "START_CONNECTION", output);
168 AddField("client_token",
169 message.protocol_control().start_connection().client_token(),
170 output);
171 AddField("protocol_version",
172 message.protocol_control().start_connection().protocol_version(),
173 output);
174 break;
175 case ProtocolControlMessage::kCheckpointAck:
176 AddField("subtype", "CHECKPOINT_ACK", output);
177 AddField("checkpoint_id",
178 message.protocol_control().checkpoint_ack().checkpoint_id(),
179 output);
180 break;
181 default:
182 break;
183 }
184 }
185
186 // Logs fields from RENDER_WIDGET messages.
187 void ExtractRenderWidgetMessageFields(const BlimpMessage& message,
188 LogFields* output) {
189 switch (message.render_widget().type()) {
190 case RenderWidgetMessage::INITIALIZE:
191 AddField("subtype", "INITIALIZE", output);
192 break;
193 case RenderWidgetMessage::CREATED:
194 AddField("subtype", "CREATED", output);
195 break;
196 case RenderWidgetMessage::DELETED:
197 AddField("subtype", "DELETED", output);
198 break;
199 }
200 AddField("render_widget_id", message.render_widget().render_widget_id(),
201 output);
202 }
203
204 // Logs fields from SETTINGS messages.
205 void ExtractSettingsMessageFields(const BlimpMessage& message,
206 LogFields* output) {
207 if (message.settings().has_engine_settings()) {
208 const EngineSettingsMessage& engine_settings =
209 message.settings().engine_settings();
210 AddField("subtype", "ENGINE_SETTINGS", output);
211 AddField("record_whole_document", engine_settings.record_whole_document(),
76 output); 212 output);
77 } 213 AddField("client_os_info", engine_settings.client_os_info(), output);
78 }; 214 }
79 215 }
80 // Logs fields from INPUT messages.
81 class InputLogExtractor : public LogExtractor {
82 void ExtractFields(const BlimpMessage& message,
83 LogFields* output) const override {
84 AddField("render_widget_id", message.input().render_widget_id(), output);
85 AddField("timestamp_seconds", message.input().timestamp_seconds(), output);
86 switch (message.input().type()) {
87 case InputMessage::Type_GestureScrollBegin:
88 AddField("subtype", "GestureScrollBegin", output);
89 break;
90 case InputMessage::Type_GestureScrollEnd:
91 AddField("subtype", "GestureScrollEnd", output);
92 break;
93 case InputMessage::Type_GestureScrollUpdate:
94 AddField("subtype", "GestureScrollUpdate", output);
95 break;
96 case InputMessage::Type_GestureFlingStart:
97 AddField("subtype", "GestureFlingStart", output);
98 break;
99 case InputMessage::Type_GestureFlingCancel:
100 AddField("subtype", "GestureFlingCancel", output);
101 AddField("prevent_boosting",
102 message.input().gesture_fling_cancel().prevent_boosting(),
103 output);
104 break;
105 case InputMessage::Type_GestureTap:
106 AddField("subtype", "GestureTap", output);
107 break;
108 case InputMessage::Type_GesturePinchBegin:
109 AddField("subtype", "GesturePinchBegin", output);
110 break;
111 case InputMessage::Type_GesturePinchEnd:
112 AddField("subtype", "GesturePinchEnd", output);
113 break;
114 case InputMessage::Type_GesturePinchUpdate:
115 AddField("subtype", "GesturePinchUpdate", output);
116 break;
117 default: // unknown
118 break;
119 }
120 }
121 };
122
123 // Logs fields from NAVIGATION messages.
124 class NavigationLogExtractor : public LogExtractor {
125 void ExtractFields(const BlimpMessage& message,
126 LogFields* output) const override {
127 switch (message.navigation().type()) {
128 case NavigationMessage::NAVIGATION_STATE_CHANGED:
129 AddField("subtype", "NAVIGATION_STATE_CHANGED", output);
130 if (message.navigation().navigation_state_changed().has_url()) {
131 AddField("url", message.navigation().navigation_state_changed().url(),
132 output);
133 }
134 if (message.navigation().navigation_state_changed().has_favicon()) {
135 AddField(
136 "favicon_size",
137 message.navigation().navigation_state_changed().favicon().size(),
138 output);
139 }
140 if (message.navigation().navigation_state_changed().has_title()) {
141 AddField("title",
142 message.navigation().navigation_state_changed().title(),
143 output);
144 }
145 if (message.navigation().navigation_state_changed().has_loading()) {
146 AddField("loading",
147 message.navigation().navigation_state_changed().loading(),
148 output);
149 }
150 break;
151 case NavigationMessage::LOAD_URL:
152 AddField("subtype", "LOAD_URL", output);
153 AddField("url", message.navigation().load_url().url(), output);
154 break;
155 case NavigationMessage::GO_BACK:
156 AddField("subtype", "GO_BACK", output);
157 break;
158 case NavigationMessage::GO_FORWARD:
159 AddField("subtype", "GO_FORWARD", output);
160 break;
161 case NavigationMessage::RELOAD:
162 AddField("subtype", "RELOAD", output);
163 break;
164 default:
165 break;
166 }
167 }
168 };
169
170 // Logs fields from PROTOCOL_CONTROL messages.
171 class ProtocolControlLogExtractor : public LogExtractor {
172 void ExtractFields(const BlimpMessage& message,
173 LogFields* output) const override {
174 switch (message.protocol_control().connection_message_case()) {
175 case ProtocolControlMessage::kStartConnection:
176 AddField("subtype", "START_CONNECTION", output);
177 AddField("client_token",
178 message.protocol_control().start_connection().client_token(),
179 output);
180 AddField(
181 "protocol_version",
182 message.protocol_control().start_connection().protocol_version(),
183 output);
184 break;
185 case ProtocolControlMessage::kCheckpointAck:
186 AddField("subtype", "CHECKPOINT_ACK", output);
187 AddField("checkpoint_id",
188 message.protocol_control().checkpoint_ack().checkpoint_id(),
189 output);
190 break;
191 default:
192 break;
193 }
194 }
195 };
196
197 // Logs fields from RENDER_WIDGET messages.
198 class RenderWidgetLogExtractor : public LogExtractor {
199 void ExtractFields(const BlimpMessage& message,
200 LogFields* output) const override {
201 switch (message.render_widget().type()) {
202 case RenderWidgetMessage::INITIALIZE:
203 AddField("subtype", "INITIALIZE", output);
204 break;
205 case RenderWidgetMessage::CREATED:
206 AddField("subtype", "CREATED", output);
207 break;
208 case RenderWidgetMessage::DELETED:
209 AddField("subtype", "DELETED", output);
210 break;
211 }
212 AddField("render_widget_id", message.render_widget().render_widget_id(),
213 output);
214 }
215 };
216
217 // Logs fields from SETTINGS messages.
218 class SettingsLogExtractor : public LogExtractor {
219 void ExtractFields(const BlimpMessage& message,
220 LogFields* output) const override {
221 if (message.settings().has_engine_settings()) {
222 const EngineSettingsMessage& engine_settings =
223 message.settings().engine_settings();
224 AddField("subtype", "ENGINE_SETTINGS", output);
225 AddField("record_whole_document", engine_settings.record_whole_document(),
226 output);
227 AddField("client_os_info", engine_settings.client_os_info(), output);
228 }
229 }
230 };
231 216
232 // Logs fields from TAB_CONTROL messages. 217 // Logs fields from TAB_CONTROL messages.
233 class TabControlLogExtractor : public LogExtractor { 218 void ExtractTabControlMessageFields(const BlimpMessage& message,
234 void ExtractFields(const BlimpMessage& message, 219 LogFields* output) {
235 LogFields* output) const override { 220 switch (message.tab_control().tab_control_case()) {
236 switch (message.tab_control().tab_control_case()) { 221 case TabControlMessage::kCreateTab:
237 case TabControlMessage::kCreateTab: 222 AddField("subtype", "CREATE_TAB", output);
238 AddField("subtype", "CREATE_TAB", output); 223 break;
239 break; 224 case TabControlMessage::kCloseTab:
240 case TabControlMessage::kCloseTab: 225 AddField("subtype", "CLOSE_TAB", output);
241 AddField("subtype", "CLOSE_TAB", output); 226 break;
242 break; 227 case TabControlMessage::kSize:
243 case TabControlMessage::kSize: 228 AddField("subtype", "SIZE", output);
244 AddField("subtype", "SIZE", output); 229 AddField("size", message.tab_control().size(), output);
245 AddField("size", message.tab_control().size(), output); 230 break;
246 break; 231 default: // unknown
247 default: // unknown 232 break;
248 break; 233 }
249 } 234 }
250 }
251 };
252 235
253 // Logs fields from BLOB_CHANNEL messages. 236 // Logs fields from BLOB_CHANNEL messages.
254 class BlobChannelLogExtractor : public LogExtractor { 237 void ExtractBlobChannelMessageFields(const BlimpMessage& message,
255 void ExtractFields(const BlimpMessage& message, 238 LogFields* output) {
256 LogFields* output) const override { 239 switch (message.blob_channel().type_case()) {
257 switch (message.blob_channel().type_case()) { 240 case BlobChannelMessage::TypeCase::kTransferBlob:
258 case BlobChannelMessage::TypeCase::kTransferBlob: 241 AddField("subtype", "TRANSFER_BLOB", output);
259 AddField("subtype", "TRANSFER_BLOB", output); 242 AddField("id",
260 AddField("id", 243 base::HexEncode(
261 base::HexEncode( 244 message.blob_channel().transfer_blob().blob_id().data(),
262 message.blob_channel().transfer_blob().blob_id().data(), 245 message.blob_channel().transfer_blob().blob_id().size()),
263 message.blob_channel().transfer_blob().blob_id().size()), 246 output);
264 output); 247 AddField("payload_size",
265 AddField("payload_size", 248 message.blob_channel().transfer_blob().payload().size(), output);
266 message.blob_channel().transfer_blob().payload().size(), 249 break;
267 output); 250 case BlobChannelMessage::TypeCase::TYPE_NOT_SET: // unknown
268 break; 251 break;
269 case BlobChannelMessage::TypeCase::TYPE_NOT_SET: // unknown 252 }
270 break; 253 }
271 }
272 }
273 };
274
275 // No fields are extracted from |message|.
276 class NullLogExtractor : public LogExtractor {
277 void ExtractFields(const BlimpMessage& message,
278 LogFields* output) const override {}
279 };
280 254
281 } // namespace 255 } // namespace
282 256
283 BlimpMessageLogger::BlimpMessageLogger() { 257 std::ostream& operator<<(std::ostream& out, const BlimpMessage& message) {
284 AddHandler("COMPOSITOR", BlimpMessage::kCompositor,
285 base::WrapUnique(new CompositorLogExtractor));
286 AddHandler("INPUT", BlimpMessage::kInput,
287 base::WrapUnique(new InputLogExtractor));
288 AddHandler("NAVIGATION", BlimpMessage::kNavigation,
289 base::WrapUnique(new NavigationLogExtractor));
290 AddHandler("PROTOCOL_CONTROL", BlimpMessage::kProtocolControl,
291 base::WrapUnique(new ProtocolControlLogExtractor));
292 AddHandler("RENDER_WIDGET", BlimpMessage::kRenderWidget,
293 base::WrapUnique(new RenderWidgetLogExtractor));
294 AddHandler("SETTINGS", BlimpMessage::kSettings,
295 base::WrapUnique(new SettingsLogExtractor));
296 AddHandler("TAB_CONTROL", BlimpMessage::kTabControl,
297 base::WrapUnique(new TabControlLogExtractor));
298 AddHandler("BLOB_CHANNEL", BlimpMessage::kBlobChannel,
299 base::WrapUnique(new BlobChannelLogExtractor));
300 }
301
302 BlimpMessageLogger::~BlimpMessageLogger() {}
303
304 void BlimpMessageLogger::AddHandler(const std::string& feature_name,
305 BlimpMessage::FeatureCase feature_case,
306 std::unique_ptr<LogExtractor> extractor) {
307 DCHECK(extractors_.find(feature_case) == extractors_.end());
308 DCHECK(!feature_name.empty());
309 extractors_[feature_case] = make_pair(feature_name, std::move(extractor));
310 }
311
312 void BlimpMessageLogger::LogMessageToStream(const BlimpMessage& message,
313 std::ostream* out) const {
314 LogFields fields; 258 LogFields fields;
315 259
316 auto extractor = extractors_.find(message.feature_case()); 260 switch (message.feature_case()) {
317 if (extractor != extractors_.end()) { 261 case BlimpMessage::kCompositor:
318 // An extractor is registered for |message|. 262 fields.push_back(std::make_pair("type", "COMPOSITOR"));
Wez 2016/06/03 00:07:54 What was wrong with AddField() here? Seems shorter
Kevin M 2016/06/07 00:05:50 Done.
319 // Add the human-readable name of |message.type|. 263 ExtractCompositorMessageFields(message, &fields);
320 fields.push_back(make_pair("type", extractor->second.first)); 264 break;
321 extractor->second.second->ExtractFields(message, &fields); 265 case BlimpMessage::kInput:
322 } else { 266 fields.push_back(std::make_pair("type", "INPUT"));
323 // Don't know the human-readable name of |message.type|. 267 ExtractInputMessageFields(message, &fields);
324 // Just represent it using its numeric form instead. 268 break;
325 AddField("type", message.feature_case(), &fields); 269 case BlimpMessage::kNavigation:
270 fields.push_back(std::make_pair("type", "NAVIGATION"));
271 ExtractNavigationMessageFields(message, &fields);
272 break;
273 case BlimpMessage::kProtocolControl:
274 fields.push_back(std::make_pair("type", "PROTOCOL_CONTROL"));
275 ExtractProtocolControlMessageFields(message, &fields);
276 break;
277 case BlimpMessage::kRenderWidget:
278 fields.push_back(std::make_pair("type", "RENDER_WIDGET"));
279 ExtractRenderWidgetMessageFields(message, &fields);
280 break;
281 case BlimpMessage::kSettings:
282 fields.push_back(std::make_pair("type", "SETTINGS"));
283 ExtractSettingsMessageFields(message, &fields);
284 break;
285 case BlimpMessage::kTabControl:
286 fields.push_back(std::make_pair("type", "TAB_CONTROL"));
287 ExtractTabControlMessageFields(message, &fields);
288 break;
289 case BlimpMessage::kBlobChannel:
290 fields.push_back(std::make_pair("type", "BLOB_CHANNEL"));
291 ExtractBlobChannelMessageFields(message, &fields);
292 break;
293 case BlimpMessage::kIme:
294 fields.push_back(std::make_pair("type", "IME"));
295 break;
296 case BlimpMessage::FEATURE_NOT_SET:
297 fields.push_back(std::make_pair("type", "<UNKNOWN>"));
Wez 2016/06/03 00:07:54 Off-topic: This is an interesting limitation of us
Kevin M 2016/06/07 00:05:50 Yeah, there's no analogue to unknown_fields :(
298 break;
326 } 299 }
327 300
328 // Append "target_tab_id" (if present) and "byte_size" to the field set. 301 // Append "target_tab_id" (if present) and "byte_size" to the field set.
329 if (message.has_target_tab_id()) { 302 if (message.has_target_tab_id()) {
330 AddField("target_tab_id", message.target_tab_id(), &fields); 303 AddField("target_tab_id", message.target_tab_id(), &fields);
331 } 304 }
332 AddField("byte_size", message.ByteSize(), &fields); 305 AddField("byte_size", message.ByteSize(), &fields);
333 306
334 // Format message using the syntax: 307 // Format message using the syntax:
335 // <BlimpMessage field1=value1 field2="value 2"> 308 // <BlimpMessage field1=value1 field2="value 2">
336 *out << "<BlimpMessage "; 309 out << "<BlimpMessage ";
337 for (size_t i = 0; i < fields.size(); ++i) { 310 for (size_t i = 0; i < fields.size(); ++i) {
338 *out << fields[i].first << "=" << fields[i].second 311 out << fields[i].first << "=" << fields[i].second
339 << (i != fields.size() - 1 ? " " : ""); 312 << (i != fields.size() - 1 ? " " : "");
340 } 313 }
341 *out << ">"; 314 out << ">";
342 }
343 315
344 std::ostream& operator<<(std::ostream& out, const BlimpMessage& message) {
345 g_logger.Get().LogMessageToStream(message, &out);
346 return out; 316 return out;
347 } 317 }
348 318
349 } // namespace blimp 319 } // namespace blimp
OLDNEW
« no previous file with comments | « blimp/common/logging.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698