| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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 "base/debug/trace_event_impl.h" | 5 #include "base/debug/trace_event_impl.h" |
| 6 | 6 |
| 7 #include <algorithm> | 7 #include <algorithm> |
| 8 | 8 |
| 9 #include "base/bind.h" | 9 #include "base/bind.h" |
| 10 #include "base/debug/leak_annotations.h" | 10 #include "base/debug/leak_annotations.h" |
| (...skipping 885 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 896 void TraceLog::SetEnabled(const CategoryFilter& category_filter, | 896 void TraceLog::SetEnabled(const CategoryFilter& category_filter, |
| 897 Options options) { | 897 Options options) { |
| 898 AutoLock lock(lock_); | 898 AutoLock lock(lock_); |
| 899 | 899 |
| 900 if (enable_count_++ > 0) { | 900 if (enable_count_++ > 0) { |
| 901 if (options != trace_options_) { | 901 if (options != trace_options_) { |
| 902 DLOG(ERROR) << "Attemting to re-enable tracing with a different " | 902 DLOG(ERROR) << "Attemting to re-enable tracing with a different " |
| 903 << "set of options."; | 903 << "set of options."; |
| 904 } | 904 } |
| 905 | 905 |
| 906 // Tracing is already enabled, so just merge in enabled categories. | 906 category_filter_.Merge(category_filter); |
| 907 // We only expand the set of enabled categories upon nested SetEnable(). | |
| 908 if (category_filter_.HasIncludedPatterns() && | |
| 909 category_filter.HasIncludedPatterns()) { | |
| 910 category_filter_.Merge(category_filter); | |
| 911 } else { | |
| 912 // If either old or new included categories are empty, allow all events. | |
| 913 category_filter_.Clear(); | |
| 914 } | |
| 915 EnableIncludedCategoryGroups(); | 907 EnableIncludedCategoryGroups(); |
| 916 return; | 908 return; |
| 917 } | 909 } |
| 918 | 910 |
| 919 if (options != trace_options_) { | 911 if (options != trace_options_) { |
| 920 trace_options_ = options; | 912 trace_options_ = options; |
| 921 logged_events_.reset(GetTraceBuffer()); | 913 logged_events_.reset(GetTraceBuffer()); |
| 922 } | 914 } |
| 923 | 915 |
| 924 if (dispatching_to_observer_list_) { | 916 if (dispatching_to_observer_list_) { |
| (...skipping 375 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1300 time_offset_ = offset; | 1292 time_offset_ = offset; |
| 1301 } | 1293 } |
| 1302 | 1294 |
| 1303 bool CategoryFilter::IsEmptyOrContainsLeadingOrTrailingWhitespace( | 1295 bool CategoryFilter::IsEmptyOrContainsLeadingOrTrailingWhitespace( |
| 1304 const std::string& str) { | 1296 const std::string& str) { |
| 1305 return str.empty() || | 1297 return str.empty() || |
| 1306 str.at(0) == ' ' || | 1298 str.at(0) == ' ' || |
| 1307 str.at(str.length() - 1) == ' '; | 1299 str.at(str.length() - 1) == ' '; |
| 1308 } | 1300 } |
| 1309 | 1301 |
| 1310 static bool DoesCategoryGroupContainCategory(const char* category_group, | 1302 bool CategoryFilter::DoesCategoryGroupContainCategory( |
| 1311 const char* category) { | 1303 const char* category_group, |
| 1304 const char* category) const { |
| 1312 DCHECK(category); | 1305 DCHECK(category); |
| 1313 CStringTokenizer category_group_tokens(category_group, | 1306 CStringTokenizer category_group_tokens(category_group, |
| 1314 category_group + strlen(category_group), ","); | 1307 category_group + strlen(category_group), ","); |
| 1315 while (category_group_tokens.GetNext()) { | 1308 while (category_group_tokens.GetNext()) { |
| 1316 std::string category_group_token = category_group_tokens.token(); | 1309 std::string category_group_token = category_group_tokens.token(); |
| 1317 // Don't allow empty tokens, nor tokens with leading or trailing space. | 1310 // Don't allow empty tokens, nor tokens with leading or trailing space. |
| 1318 DCHECK(!CategoryFilter::IsEmptyOrContainsLeadingOrTrailingWhitespace( | 1311 DCHECK(!CategoryFilter::IsEmptyOrContainsLeadingOrTrailingWhitespace( |
| 1319 category_group_token)) | 1312 category_group_token)) |
| 1320 << "Disallowed category string"; | 1313 << "Disallowed category string"; |
| 1321 if (MatchPattern(category_group_token.c_str(), category)) | 1314 if (MatchPattern(category_group_token.c_str(), category)) |
| 1322 return true; | 1315 return true; |
| 1323 } | 1316 } |
| 1324 return false; | 1317 return false; |
| 1325 } | 1318 } |
| 1326 | 1319 |
| 1327 // Enable everything but debug and test categories by default. | 1320 // Enable everything but debug and test categories by default. |
| 1328 const char* CategoryFilter::kDefaultCategoryFilterString = "-*Debug,-*Test"; | 1321 const char* CategoryFilter::kDefaultCategoryFilterString = "-*Debug,-*Test"; |
| 1329 | 1322 |
| 1330 CategoryFilter::CategoryFilter(const std::string& filter_string) { | 1323 CategoryFilter::CategoryFilter(const std::string& filter_string) { |
| 1331 if (!filter_string.empty()) | 1324 if (!filter_string.empty()) |
| 1332 Initialize(filter_string); | 1325 Initialize(filter_string); |
| 1333 else | 1326 else |
| 1334 Initialize(CategoryFilter::kDefaultCategoryFilterString); | 1327 Initialize(CategoryFilter::kDefaultCategoryFilterString); |
| 1335 } | 1328 } |
| 1336 | 1329 |
| 1337 CategoryFilter::CategoryFilter(const CategoryFilter& cf) | 1330 CategoryFilter::CategoryFilter(const CategoryFilter& cf) |
| 1338 : included_(cf.included_), | 1331 : included_(cf.included_), |
| 1332 disabled_(cf.disabled_), |
| 1339 excluded_(cf.excluded_) { | 1333 excluded_(cf.excluded_) { |
| 1340 } | 1334 } |
| 1341 | 1335 |
| 1342 CategoryFilter::~CategoryFilter() { | 1336 CategoryFilter::~CategoryFilter() { |
| 1343 } | 1337 } |
| 1344 | 1338 |
| 1345 CategoryFilter& CategoryFilter::operator=(const CategoryFilter& rhs) { | 1339 CategoryFilter& CategoryFilter::operator=(const CategoryFilter& rhs) { |
| 1346 if (this == &rhs) | 1340 if (this == &rhs) |
| 1347 return *this; | 1341 return *this; |
| 1348 | 1342 |
| 1349 included_ = rhs.included_; | 1343 included_ = rhs.included_; |
| 1344 disabled_ = rhs.disabled_; |
| 1350 excluded_ = rhs.excluded_; | 1345 excluded_ = rhs.excluded_; |
| 1351 return *this; | 1346 return *this; |
| 1352 } | 1347 } |
| 1353 | 1348 |
| 1354 void CategoryFilter::Initialize(const std::string& filter_string) { | 1349 void CategoryFilter::Initialize(const std::string& filter_string) { |
| 1355 // Tokenize list of categories, delimited by ','. | 1350 // Tokenize list of categories, delimited by ','. |
| 1356 StringTokenizer tokens(filter_string, ","); | 1351 StringTokenizer tokens(filter_string, ","); |
| 1357 // Add each token to the appropriate list (included_,excluded_). | 1352 // Add each token to the appropriate list (included_,excluded_). |
| 1358 while (tokens.GetNext()) { | 1353 while (tokens.GetNext()) { |
| 1359 std::string category = tokens.token(); | 1354 std::string category = tokens.token(); |
| 1360 // Ignore empty categories. | 1355 // Ignore empty categories. |
| 1361 if (category.empty()) | 1356 if (category.empty()) |
| 1362 continue; | 1357 continue; |
| 1363 // Excluded categories start with '-'. | 1358 // Excluded categories start with '-'. |
| 1364 if (category.at(0) == '-') { | 1359 if (category.at(0) == '-') { |
| 1365 // Remove '-' from category string. | 1360 // Remove '-' from category string. |
| 1366 category = category.substr(1); | 1361 category = category.substr(1); |
| 1367 excluded_.push_back(category); | 1362 excluded_.push_back(category); |
| 1363 } else if (category.compare(0, strlen(TRACE_DISABLED_BY_DEFAULT("")), |
| 1364 TRACE_DISABLED_BY_DEFAULT("")) == 0) { |
| 1365 disabled_.push_back(category); |
| 1368 } else { | 1366 } else { |
| 1369 included_.push_back(category); | 1367 included_.push_back(category); |
| 1370 } | 1368 } |
| 1371 } | 1369 } |
| 1372 } | 1370 } |
| 1373 | 1371 |
| 1374 void CategoryFilter::WriteString(std::string* out, | 1372 void CategoryFilter::WriteString(const StringList& values, |
| 1373 std::string* out, |
| 1375 bool included) const { | 1374 bool included) const { |
| 1376 std::vector<std::string>::const_iterator ci; | 1375 bool prepend_comma = !out->empty(); |
| 1377 std::vector<std::string>::const_iterator end; | |
| 1378 if (included) { | |
| 1379 ci = included_.begin(); | |
| 1380 end = included_.end(); | |
| 1381 } else { | |
| 1382 ci = excluded_.begin(); | |
| 1383 end = excluded_.end(); | |
| 1384 } | |
| 1385 | |
| 1386 // Prepend commas for all excluded categories IF we have included categories. | |
| 1387 bool prepend_comma_for_first_excluded = !included && !included_.empty(); | |
| 1388 int token_cnt = 0; | 1376 int token_cnt = 0; |
| 1389 for (; ci != end; ++ci) { | 1377 for (StringList::const_iterator ci = values.begin(); |
| 1390 if (token_cnt > 0 || prepend_comma_for_first_excluded) | 1378 ci != values.end(); ++ci) { |
| 1379 if (token_cnt > 0 || prepend_comma) |
| 1391 StringAppendF(out, ","); | 1380 StringAppendF(out, ","); |
| 1392 StringAppendF(out, "%s%s", (included ? "" : "-"), ci->c_str()); | 1381 StringAppendF(out, "%s%s", (included ? "" : "-"), ci->c_str()); |
| 1393 ++token_cnt; | 1382 ++token_cnt; |
| 1394 } | 1383 } |
| 1395 } | 1384 } |
| 1396 | 1385 |
| 1397 std::string CategoryFilter::ToString() const { | 1386 std::string CategoryFilter::ToString() const { |
| 1398 std::string filter_string; | 1387 std::string filter_string; |
| 1399 WriteString(&filter_string, true); | 1388 WriteString(included_, &filter_string, true); |
| 1400 WriteString(&filter_string, false); | 1389 WriteString(disabled_, &filter_string, true); |
| 1401 | 1390 WriteString(excluded_, &filter_string, false); |
| 1402 return filter_string; | 1391 return filter_string; |
| 1403 } | 1392 } |
| 1404 | 1393 |
| 1405 bool CategoryFilter::IsCategoryGroupEnabled( | 1394 bool CategoryFilter::IsCategoryGroupEnabled( |
| 1406 const char* category_group_name) const { | 1395 const char* category_group_name) const { |
| 1407 // TraceLog should call this method only as part of enabling/disabling | 1396 // TraceLog should call this method only as part of enabling/disabling |
| 1408 // categories. | 1397 // categories. |
| 1409 std::vector<std::string>::const_iterator ci = included_.begin(); | 1398 StringList::const_iterator ci; |
| 1410 for (; ci != included_.end(); ++ci) { | 1399 |
| 1400 // Check the disabled- filters and the disabled-* wildcard first so that a |
| 1401 // "*" filter does not include the disabled. |
| 1402 for (ci = disabled_.begin(); ci != disabled_.end(); ++ci) { |
| 1411 if (DoesCategoryGroupContainCategory(category_group_name, ci->c_str())) | 1403 if (DoesCategoryGroupContainCategory(category_group_name, ci->c_str())) |
| 1412 return true; | 1404 return true; |
| 1413 } | 1405 } |
| 1414 ci = excluded_.begin(); | 1406 if (DoesCategoryGroupContainCategory(category_group_name, |
| 1415 for (; ci != excluded_.end(); ++ci) { | 1407 TRACE_DISABLED_BY_DEFAULT("*"))) |
| 1408 return false; |
| 1409 |
| 1410 for (ci = included_.begin(); ci != included_.end(); ++ci) { |
| 1411 if (DoesCategoryGroupContainCategory(category_group_name, ci->c_str())) |
| 1412 return true; |
| 1413 } |
| 1414 |
| 1415 for (ci = excluded_.begin(); ci != excluded_.end(); ++ci) { |
| 1416 if (DoesCategoryGroupContainCategory(category_group_name, ci->c_str())) | 1416 if (DoesCategoryGroupContainCategory(category_group_name, ci->c_str())) |
| 1417 return false; | 1417 return false; |
| 1418 } | 1418 } |
| 1419 // If the category group is not excluded, and there are no included patterns | 1419 // If the category group is not excluded, and there are no included patterns |
| 1420 // we consider this pattern enabled. | 1420 // we consider this pattern enabled. |
| 1421 return included_.empty(); | 1421 return included_.empty(); |
| 1422 } | 1422 } |
| 1423 | 1423 |
| 1424 void CategoryFilter::Merge(const CategoryFilter& nested_filter) { | |
| 1425 included_.insert(included_.end(), | |
| 1426 nested_filter.included_.begin(), | |
| 1427 nested_filter.included_.end()); | |
| 1428 excluded_.insert(excluded_.end(), | |
| 1429 nested_filter.excluded_.begin(), | |
| 1430 nested_filter.excluded_.end()); | |
| 1431 } | |
| 1432 | |
| 1433 bool CategoryFilter::HasIncludedPatterns() const { | 1424 bool CategoryFilter::HasIncludedPatterns() const { |
| 1434 return !included_.empty(); | 1425 return !included_.empty(); |
| 1435 } | 1426 } |
| 1436 | 1427 |
| 1428 void CategoryFilter::Merge(const CategoryFilter& nested_filter) { |
| 1429 // Keep included patterns only if both filters have an included entry. |
| 1430 // Otherwise, one of the filter was specifying "*" and we want to honour the |
| 1431 // broadest filter. |
| 1432 if (HasIncludedPatterns() && nested_filter.HasIncludedPatterns()) { |
| 1433 included_.insert(included_.end(), |
| 1434 nested_filter.included_.begin(), |
| 1435 nested_filter.included_.end()); |
| 1436 } else { |
| 1437 included_.clear(); |
| 1438 } |
| 1439 |
| 1440 disabled_.insert(disabled_.end(), |
| 1441 nested_filter.disabled_.begin(), |
| 1442 nested_filter.disabled_.end()); |
| 1443 excluded_.insert(excluded_.end(), |
| 1444 nested_filter.excluded_.begin(), |
| 1445 nested_filter.excluded_.end()); |
| 1446 } |
| 1447 |
| 1437 void CategoryFilter::Clear() { | 1448 void CategoryFilter::Clear() { |
| 1438 included_.clear(); | 1449 included_.clear(); |
| 1450 disabled_.clear(); |
| 1439 excluded_.clear(); | 1451 excluded_.clear(); |
| 1440 } | 1452 } |
| 1441 | 1453 |
| 1442 } // namespace debug | 1454 } // namespace debug |
| 1443 } // namespace base | 1455 } // namespace base |
| 1444 | 1456 |
| 1445 namespace trace_event_internal { | 1457 namespace trace_event_internal { |
| 1446 | 1458 |
| 1447 ScopedTrace::ScopedTrace( | 1459 ScopedTrace::ScopedTrace( |
| 1448 TRACE_EVENT_API_ATOMIC_WORD* event_uid, const char* name) { | 1460 TRACE_EVENT_API_ATOMIC_WORD* event_uid, const char* name) { |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1484 NULL, // arg_names | 1496 NULL, // arg_names |
| 1485 NULL, // arg_types | 1497 NULL, // arg_types |
| 1486 NULL, // arg_values | 1498 NULL, // arg_values |
| 1487 NULL, // convertable values | 1499 NULL, // convertable values |
| 1488 TRACE_EVENT_FLAG_NONE); // flags | 1500 TRACE_EVENT_FLAG_NONE); // flags |
| 1489 } | 1501 } |
| 1490 } | 1502 } |
| 1491 | 1503 |
| 1492 } // namespace trace_event_internal | 1504 } // namespace trace_event_internal |
| 1493 | 1505 |
| OLD | NEW |