blob: 3940eecddb285c4efc6101663053af72568fd730 [file] [log] [blame]
// Copyright 2018 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// This file contains information for gathering Blobfs metrics.
#ifndef ZIRCON_SYSTEM_ULIB_BLOBFS_METRICS_H_
#define ZIRCON_SYSTEM_ULIB_BLOBFS_METRICS_H_
#ifndef __Fuchsia__
#error Fuchsia-only Header
#endif
#include <lib/async-loop/cpp/loop.h>
#include <lib/async-loop/default.h>
#include <lib/inspect/cpp/inspect.h>
#include <lib/zx/time.h>
#include <blobfs/format.h>
#include <cobalt-client/cpp/collector.h>
#include <fs/metrics/cobalt_metrics.h>
#include <fs/metrics/composite_latency_event.h>
#include <fs/metrics/events.h>
#include <fs/metrics/histograms.h>
#include <fs/ticker.h>
namespace blobfs {
// Alias for the LatencyEvent used in blobfs.
using LatencyEvent = fs_metrics::CompositeLatencyEvent;
class BlobfsMetrics {
public:
~BlobfsMetrics();
// Print information about metrics to stdout.
//
// TODO(ZX-1999): This is a stop-gap solution; long-term, this information
// should be extracted from devices.
void Dump() const;
// Begin collecting blobfs metrics. Metrics collection is not implicitly enabled
// with the creation of a "BlobfsMetrics" object.
void Collect();
bool Collecting() const { return cobalt_metrics_.IsEnabled(); }
// Updates aggregate information about the total number of created
// blobs since mounting.
void UpdateAllocation(uint64_t size_data, const fs::Duration& duration);
// Updates aggregate information about the number of blobs opened
// since mounting.
void UpdateLookup(uint64_t size);
// Updates aggregates information about blobs being written back
// to blobfs since mounting.
void UpdateClientWrite(uint64_t data_size, uint64_t merkle_size,
const fs::Duration& enqueue_duration,
const fs::Duration& generate_duration);
// Updates aggregate information about flushing bits down
// to the underlying storage driver.
void UpdateWriteback(uint64_t size, const fs::Duration& duration);
// Updates aggregate information about reading blobs from storage
// since mounting.
void UpdateMerkleDiskRead(uint64_t size, const fs::Duration& duration);
// Updates aggregate information about decompressing blobs from storage
// since mounting.
void UpdateMerkleDecompress(uint64_t size_compressed, uint64_t size_uncompressed,
const fs::Duration& read_duration,
const fs::Duration& decompress_duration);
// Updates aggregate information about general verification info
// since mounting.
void UpdateMerkleVerify(uint64_t size_data, uint64_t size_merkle, const fs::Duration& duration);
// Returns a new Latency event for the given event. This requires the event to be backed up by
// an histogram in both cobalt metrics and Inspect.
LatencyEvent NewLatencyEvent(fs_metrics::Event event) {
return LatencyEvent(event, &histograms_, cobalt_metrics_.mutable_vnode_metrics());
}
// Increments Cobalt metrics tracking compression formats. Extracts the compression format from
// the |inode| header, and increments the counter for that format with the inode's |blob_size|.
void IncrementCompressionFormatMetric(const Inode& inode);
private:
// Returns the underlying collector of cobalt metrics.
cobalt_client::Collector* mutable_collector() { return cobalt_metrics_.mutable_collector(); }
// Flushes the metrics to the cobalt client and schedules itself to flush again.
void ScheduleMetricFlush();
// ALLOCATION STATS
// Created with external-facing "Create".
uint64_t blobs_created_ = 0;
// Measured by space allocated with "Truncate".
uint64_t blobs_created_total_size_ = 0;
zx::ticks total_allocation_time_ticks_ = {};
// WRITEBACK STATS
// Measurements, from the client's perspective, of writing and enqueing
// data that will later be written to disk.
uint64_t data_bytes_written_ = 0;
uint64_t merkle_bytes_written_ = 0;
zx::ticks total_write_enqueue_time_ticks_ = {};
zx::ticks total_merkle_generation_time_ticks_ = {};
// Measured by true time writing back to disk. This may be distinct from
// the client time because of asynchronous writeback buffers.
zx::ticks total_writeback_time_ticks_ = {};
uint64_t total_writeback_bytes_written_ = 0;
// LOOKUP STATS
// Total time waiting for reads from disk.
zx::ticks total_read_from_disk_time_ticks_ = {};
uint64_t bytes_read_from_disk_ = 0;
zx::ticks total_read_compressed_time_ticks_ = {};
zx::ticks total_decompress_time_ticks_ = {};
uint64_t bytes_compressed_read_from_disk_ = 0;
uint64_t bytes_decompressed_from_disk_ = 0;
// Opened via "LookupBlob".
uint64_t blobs_opened_ = 0;
uint64_t blobs_opened_total_size_ = 0;
// Verified blob data (includes both blobs read and written).
uint64_t blobs_verified_ = 0;
uint64_t blobs_verified_total_size_data_ = 0;
uint64_t blobs_verified_total_size_merkle_ = 0;
zx::ticks total_verification_time_ticks_ = {};
// FVM STATS
// TODO(smklein)
// Inspect instrumentation data, with an initial size of the current histogram size.
inspect::Inspector inspector_ = inspect::Inspector(
inspect::InspectSettings{.maximum_size = 2 * fs_metrics::Histograms::Size()});
inspect::Node& root_ = inspector_.GetRoot();
fs_metrics::Histograms histograms_ = fs_metrics::Histograms(&root_);
// local_storage project ID as defined in cobalt-analytics projects.yaml.
static constexpr uint32_t kCobaltProjectId = 3676913920;
// Cobalt metrics.
fs_metrics::Metrics cobalt_metrics_ =
fs_metrics::Metrics(std::make_unique<cobalt_client::Collector>(kCobaltProjectId), "blobfs",
fs_metrics::CompressionSource::kBlobfs);
// Loop for flushing the collector periodically.
async::Loop flush_loop_ = async::Loop(&kAsyncLoopConfigNoAttachToCurrentThread);
};
} // namespace blobfs
#endif // ZIRCON_SYSTEM_ULIB_BLOBFS_METRICS_H_