// Copyright 2018 The Chromium Authors // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #ifndef THIRD_PARTY_BLINK_RENDERER_CORE_FRAME_LOCAL_FRAME_UKM_AGGREGATOR_H_ #define THIRD_PARTY_BLINK_RENDERER_CORE_FRAME_LOCAL_FRAME_UKM_AGGREGATOR_H_ #include "base/rand_util.h" #include "base/time/time.h" #include "cc/metrics/frame_sequence_tracker_collection.h" #include "third_party/blink/renderer/core/core_export.h" #include "third_party/blink/renderer/platform/instrumentation/histogram.h" #include "third_party/blink/renderer/platform/wtf/allocator/allocator.h" #include "third_party/blink/renderer/platform/wtf/text/wtf_string.h" namespace base { class TickClock; } namespace cc { struct BeginMainFrameMetrics; } namespace ukm { class UkmRecorder; } namespace blink { enum class DocumentUpdateReason; // This class aggregates and records time based UKM and UMA metrics // for LocalFrameView. The simplest way to use it is via the // SCOPED_UMA_AND_UKM_TIMER macro combined with // LocalFrameView::RecordEndOfFrameMetrics. // // The aggregator manages all of the UKM and UMA names for LocalFrameView. // It constructs and takes ownership of the UMA counters when constructed // itself. We do this to localize all UMA and UKM metrics in one place, so // that adding a metric is localized to the cc file of this class, protected // from errors that might arise when adding names in multiple places. // // After the aggregator is created, one can create ScopedUkmHierarchicalTimer // objects that will measure the time, in microseconds, from creation until // the object is destroyed for sub-metrics. When destroyed, it may record // a sample into the aggregator and the current frame's accumulated time for // that metric, and it always reports UMA values. // // See the MetricNames enum below for the set of metrics recorded. Add an // entry to that enum to add a new metric. // // When the primary timed execution completes, this aggregator stores the // primary time and computes metrics that depend on it. UMA metrics are updated // at this time. // // A UKM event is generated according to a sampling strategy, with the goal // being to choose one frame to report before First Contentful Paint and // one frame to report during the subsequent document lifetime. We maintain // a copy of the current sample, and randomly choose to update it on each frame // such that any given frame is equally likely to be the final sample. // // Sample usage (see also SCOPED_UMA_AND_UKM_TIMER): // std::unique_ptr<LocalFrameUkmAggregator> aggregator( // new LocalFrameUkmAggregator( // GetSourceId(), // GetUkmRecorder()); // ... // { // auto timer = // aggregator->GetScopedTimer(static_cast<size_t>( // LocalFrameUkmAggregator::MetricNames::kMetric2)); // ... // } // // At this point data for kMetric2 is recorded. // ... // // When the primary time completes // aggregator->RecordEndOfFrameMetrics(start, end, trackers); // // This records a primary sample and the sub-metrics that depend on it. // // It may generate an event. trackers is a bit encoding of the active frame //. // sequence trackers, informing us of why the BeginMainFrame was requested. // // In the example above, the event name is "my_event". It will measure 4 // metrics: // "primary_metric", // "sub_metric1", // "sub_metric2", // "sub_metric3" // // It will report 4 UMA values: // "primary_uma_counter", // "sub_uma_metric1", "sub_uma_metric2", "sub_uma_metric3" // // Note that these have to be specified in the appropriate ukm.xml file // and histograms.xml file. Runtime errors indicate missing or mis-named // metrics. // // If the source_id/recorder changes then a new LocalFrameUkmAggregator has to // be created. // Defines a UKM that is part of a hierarchical ukm, recorded in // microseconds equal to the duration of the current lexical scope after // declaration of the macro. Example usage: // // void LocalFrameView::DoExpensiveThing() { // SCOPED_UMA_AND_UKM_TIMER(kUkmEnumName); // // Do computation of expensive thing // // } // // |ukm_enum| should be an entry in LocalFrameUkmAggregator's enum of // metric names (which in turn corresponds to names from ukm.xml). #define SCOPED_UMA_AND_UKM_TIMER(aggregator, ukm_enum) … class CORE_EXPORT LocalFrameUkmAggregator : public RefCounted<LocalFrameUkmAggregator> { … }; } // namespace blink #endif // THIRD_PARTY_BLINK_RENDERER_CORE_FRAME_LOCAL_FRAME_UKM_AGGREGATOR_H_