blob: 0ab70dc0cc9baf5a6b1b60dd70d3d01ff0edeb5e [file] [log] [blame]
// Copyright 2019 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.
#ifndef ZIRCON_SYSTEM_ULIB_STORAGE_METRICS_STORAGE_METRICS_H_
#define ZIRCON_SYSTEM_ULIB_STORAGE_METRICS_STORAGE_METRICS_H_
#include <atomic>
#include <optional>
#include <stdio.h>
#include <fbl/macros.h>
#include <fuchsia/storage/metrics/c/fidl.h>
namespace storage_metrics {
constexpr uint64_t kUninitializedMinimumLatency = UINT64_MAX;
using CallStatFidl = fuchsia_storage_metrics_CallStat;
using CallStatRawFidl = fuchsia_storage_metrics_CallStatRaw;
// The class provides light weight mechanism to maintain stats for system calls.
// The updates are pseudo-atomic - meaning each field gets updated atomically
// but class as a whole may not get updated atomically, This will allow class
// to be updated in a lock-free manner in almost all intended use cases
// i.e. filesystem and block device.
class CallStat {
public:
DISALLOW_COPY_ASSIGN_AND_MOVE(CallStat);
CallStat();
~CallStat() = default;
// Copies fields of fidl structure into corresponding fields of CallStat
void CopyFromFidl(const CallStatFidl* istat);
// Copies to fields of fidl structure the corresponding fields of CallStat
void CopyToFidl(CallStatFidl* out) const;
// Prints the fields of CallStat to file |stream|. If |success| is nullopt,
// prints aggregate of successful and failed calls. If |success| is true,
// then only stats from success_stat_ are printed otherwise failure_stat_
// are printed.
void Dump(FILE* stream, const char* stat_name,
std::optional<bool> success = std::nullopt) const;
// Prints stats of both sucess_stat_ and failure_stat_ to |stream| file.
void DumpAll(FILE* stream, const char* stat_name) const;
// Updates fields of success_stat_ or of failure_stat_ if |success| is true
// or false respectively.
void UpdateCallStat(bool success, zx_ticks_t delta_time, uint64_t bytes_transferred);
// Resets the stats to initial state.
void Reset();
// Following functions returns fields within CallStatRaw. If |success| is
// true then success_stat_ is chosen for CallStatRaw, is false then
// failures_stat_ is chosen for CallStatRaw, or if ||success| is nullopt
// then an aggregate of success_stat_ and failures_stat_ is returned.
uint64_t minimum_latency(std::optional<bool> success = std::nullopt) const;
uint64_t maximum_latency(std::optional<bool> success = std::nullopt) const;
uint64_t total_time_spent(std::optional<bool> success = std::nullopt) const;
uint64_t total_calls(std::optional<bool> success = std::nullopt) const;
uint64_t bytes_transferred(std::optional<bool> success = std::nullopt) const;
private:
// This is atomic C++ class version of fuchsia_storage_metrics_CallStat
struct CallStatRaw {
DISALLOW_COPY_ASSIGN_AND_MOVE(CallStatRaw);
CallStatRaw();
void Reset();
// Copies fields of fidl structure into corresponding fields of CallStat
void CopyFromRawFidl(const CallStatRawFidl* istat);
// Copies to fields of fidl structure the corresponding fields of CallStat
void CopyToRawFidl(CallStatRawFidl* out) const;
void UpdateRawCallStat(zx_ticks_t delta_time, uint64_t bytes_transferred);
// Minimum time taken by a request to be served.
std::atomic<uint64_t> minimum_latency;
// Maximum time taken by a request to be served.
std::atomic<uint64_t> maximum_latency;
// Total time spent to serve requests.
std::atomic<uint64_t> total_time_spent;
// Total number of calls.
std::atomic<uint64_t> total_calls;
// bytes_transferred has special meaning if the succeeded or failed.
// On success:
// Partitally succeeded calls, bytes fetched is less than bytes
// requested, can be considered as successful. To keep latency and
// time_spent numbers accurate, on success, bytes transferred is
// number bytes returned to caller. It is NOT the number of bytes
// fetched from underlying subsystem and it is NOT number of bytes
// requested by the caller.
// On failure:
// On failure, bytes_transferred is the number of bytes requested by
// the caller.
std::atomic<uint64_t> bytes_transferred;
};
// success_stat_ keeps track of successful calls.
CallStatRaw success_stat_;
// failure_stat_ keeps tracks of failed calls.
CallStatRaw failure_stat_;
};
class Metrics {
public:
DISALLOW_COPY_ASSIGN_AND_MOVE(Metrics);
Metrics() = default;
~Metrics() = default;
void SetEnable(bool enable);
bool Enabled() const;
private:
std::atomic<bool> enabled_ = true;
};
} // namespace storage_metrics
#endif // ZIRCON_SYSTEM_ULIB_STORAGE_METRICS_STORAGE_METRICS_H_