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 "chrome/common/metrics/metrics_log_base.h" | 5 #include "chrome/common/metrics/metrics_log_base.h" |
6 | 6 |
7 #include "base/base64.h" | 7 #include "base/base64.h" |
8 #include "base/basictypes.h" | 8 #include "base/basictypes.h" |
9 #include "base/md5.h" | 9 #include "base/md5.h" |
10 #include "base/metrics/histogram_base.h" | |
11 #include "base/metrics/histogram_samples.h" | |
10 #include "base/perftimer.h" | 12 #include "base/perftimer.h" |
11 #include "base/string_number_conversions.h" | 13 #include "base/string_number_conversions.h" |
12 #include "base/sys_byteorder.h" | 14 #include "base/sys_byteorder.h" |
13 #include "base/sys_info.h" | 15 #include "base/sys_info.h" |
14 #include "base/third_party/nspr/prtime.h" | 16 #include "base/third_party/nspr/prtime.h" |
15 #include "base/utf_string_conversions.h" | 17 #include "base/utf_string_conversions.h" |
16 #include "chrome/common/chrome_version_info.h" | 18 #include "chrome/common/chrome_version_info.h" |
17 #include "chrome/common/logging_chrome.h" | 19 #include "chrome/common/logging_chrome.h" |
18 #include "chrome/common/metrics/proto/histogram_event.pb.h" | 20 #include "chrome/common/metrics/proto/histogram_event.pb.h" |
19 #include "chrome/common/metrics/proto/system_profile.pb.h" | 21 #include "chrome/common/metrics/proto/system_profile.pb.h" |
20 #include "chrome/common/metrics/proto/user_action_event.pb.h" | 22 #include "chrome/common/metrics/proto/user_action_event.pb.h" |
21 #include "libxml/xmlwriter.h" | 23 #include "libxml/xmlwriter.h" |
22 | 24 |
23 #define OPEN_ELEMENT_FOR_SCOPE(name) ScopedElement scoped_element(this, name) | 25 #define OPEN_ELEMENT_FOR_SCOPE(name) ScopedElement scoped_element(this, name) |
24 | 26 |
25 using base::Histogram; | 27 using base::Histogram; |
28 using base::HistogramBase; | |
29 using base::HistogramSamples; | |
30 using base::SampleCountIterator; | |
26 using base::Time; | 31 using base::Time; |
27 using base::TimeDelta; | 32 using base::TimeDelta; |
28 using metrics::HistogramEventProto; | 33 using metrics::HistogramEventProto; |
29 using metrics::SystemProfileProto; | 34 using metrics::SystemProfileProto; |
30 using metrics::UserActionEventProto; | 35 using metrics::UserActionEventProto; |
31 | 36 |
32 namespace { | 37 namespace { |
33 | 38 |
34 // libxml take xmlChar*, which is unsigned char* | 39 // libxml take xmlChar*, which is unsigned char* |
35 inline const unsigned char* UnsignedChar(const char* input) { | 40 inline const unsigned char* UnsignedChar(const char* input) { |
(...skipping 406 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
442 int result = xmlTextWriterEndElement(xml_wrapper_->writer()); | 447 int result = xmlTextWriterEndElement(xml_wrapper_->writer()); |
443 DCHECK_GE(result, 0); | 448 DCHECK_GE(result, 0); |
444 } | 449 } |
445 | 450 |
446 // TODO(JAR): A The following should really be part of the histogram class. | 451 // TODO(JAR): A The following should really be part of the histogram class. |
447 // Internal state is being needlessly exposed, and it would be hard to reuse | 452 // Internal state is being needlessly exposed, and it would be hard to reuse |
448 // this code. If we moved this into the Histogram class, then we could use | 453 // this code. If we moved this into the Histogram class, then we could use |
449 // the same infrastructure for logging StatsCounters, RatesCounters, etc. | 454 // the same infrastructure for logging StatsCounters, RatesCounters, etc. |
450 void MetricsLogBase::RecordHistogramDelta( | 455 void MetricsLogBase::RecordHistogramDelta( |
451 const Histogram& histogram, | 456 const Histogram& histogram, |
452 const Histogram::SampleSet& snapshot) { | 457 const HistogramSamples& snapshot) { |
453 DCHECK(!locked_); | 458 DCHECK(!locked_); |
454 DCHECK_NE(0, snapshot.TotalCount()); | 459 DCHECK_NE(0, snapshot.TotalCount()); |
455 DCHECK_EQ(histogram.bucket_count(), snapshot.size()); | |
Ilya Sherman
2012/08/23 07:50:54
Why is this DCHECK no longer appropriate?
kaiwang
2012/08/24 04:17:58
There's no "size" anymore. It's just some duplicat
| |
456 | 460 |
457 // We will ignore the MAX_INT/infinite value in the last element of range[]. | 461 // We will ignore the MAX_INT/infinite value in the last element of range[]. |
458 | 462 |
459 OPEN_ELEMENT_FOR_SCOPE("histogram"); | 463 OPEN_ELEMENT_FOR_SCOPE("histogram"); |
460 | 464 |
461 std::string base64_name_hash; | 465 std::string base64_name_hash; |
462 uint64 numeric_name_hash; | 466 uint64 numeric_name_hash; |
463 CreateHashes(histogram.histogram_name(), | 467 CreateHashes(histogram.histogram_name(), |
464 &base64_name_hash, | 468 &base64_name_hash, |
465 &numeric_name_hash); | 469 &numeric_name_hash); |
466 | 470 |
467 // Write the XML version. | 471 // Write the XML version. |
468 WriteAttribute("name", base64_name_hash); | 472 WriteAttribute("name", base64_name_hash); |
469 | 473 |
470 WriteInt64Attribute("sum", snapshot.sum()); | 474 WriteInt64Attribute("sum", snapshot.sum()); |
471 // TODO(jar): Remove sumsquares when protobuffer accepts this as optional. | 475 // TODO(jar): Remove sumsquares when protobuffer accepts this as optional. |
472 WriteInt64Attribute("sumsquares", 0); | 476 WriteInt64Attribute("sumsquares", 0); |
473 | 477 |
474 for (size_t i = 0; i < histogram.bucket_count(); i++) { | 478 HistogramBase::Sample min; |
475 if (snapshot.counts(i)) { | 479 HistogramBase::Sample max; |
476 OPEN_ELEMENT_FOR_SCOPE("histogrambucket"); | 480 HistogramBase::Count count; |
Ilya Sherman
2012/08/23 07:50:54
nit: These should be probably be scoped within the
kaiwang
2012/08/24 04:17:58
Done.
| |
477 WriteIntAttribute("min", histogram.ranges(i)); | 481 for (scoped_ptr<SampleCountIterator> it = snapshot.Iterator(); |
478 WriteIntAttribute("max", histogram.ranges(i + 1)); | 482 !it->Done(); |
479 WriteIntAttribute("count", snapshot.counts(i)); | 483 it->Next()) { |
480 } | 484 it->Get(&min, &max, &count); |
485 WriteIntAttribute("min", min); | |
486 WriteIntAttribute("max", max); | |
487 WriteIntAttribute("count", count); | |
481 } | 488 } |
482 | 489 |
483 // Write the protobuf version. | 490 // Write the protobuf version. |
484 HistogramEventProto* histogram_proto = uma_proto_.add_histogram_event(); | 491 HistogramEventProto* histogram_proto = uma_proto_.add_histogram_event(); |
485 histogram_proto->set_name_hash(numeric_name_hash); | 492 histogram_proto->set_name_hash(numeric_name_hash); |
486 histogram_proto->set_sum(snapshot.sum()); | 493 histogram_proto->set_sum(snapshot.sum()); |
487 | 494 |
488 for (size_t i = 0; i < histogram.bucket_count(); ++i) { | 495 for (scoped_ptr<SampleCountIterator> it = snapshot.Iterator(); |
489 if (snapshot.counts(i)) { | 496 !it->Done(); |
490 HistogramEventProto::Bucket* bucket = histogram_proto->add_bucket(); | 497 it->Next()) { |
491 bucket->set_min(histogram.ranges(i)); | 498 it->Get(&min, &max, &count); |
492 bucket->set_max(histogram.ranges(i + 1)); | 499 HistogramEventProto::Bucket* bucket = histogram_proto->add_bucket(); |
493 bucket->set_bucket_index(i); | 500 bucket->set_min(min); |
494 bucket->set_count(snapshot.counts(i)); | 501 bucket->set_max(max); |
495 } | 502 |
503 // TODO(kaiwang): do we need bucket_index field? | |
Ilya Sherman
2012/08/23 07:50:54
Jim, are we realistically ever going to use this f
| |
504 | |
505 bucket->set_count(count); | |
496 } | 506 } |
497 } | 507 } |
OLD | NEW |