blob: 3a6cbd873dba73bb7eaad1857fbc03b8fb339ec4 [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 SRC_LIB_STORAGE_VFS_CPP_METRICS_OBJECT_GENERATOR_H_
#define SRC_LIB_STORAGE_VFS_CPP_METRICS_OBJECT_GENERATOR_H_
#include <lib/inspect/cpp/inspect.h>
#include <vector>
#include <fbl/string_buffer.h>
namespace fs_metrics {
// This library provides mechanisms for auto generating inspect::vmo::objects. In order to so,
// operations tracked by |Offsets| that desire to take advantge of this helper class, need to
// provide the following compile time interface:
//
// Each operations' |OperationInfo| must provide:
// OperationInfo::kPrefix -> Unique identifier for the operation.
// OperationInfo::CreateTracker -> Callable type with signature (void(const char* name,
// zx::vmo::Object* root, std::vector<InspectObjectType>*
// collection);
//
// Each |Attribute| must provide:
// Attribute::ToString(size_t index) -> Human readablle string of bucket[index] or the value
// at index.
//
// The generated objects are added as childs to root |zx::vmo::Object| with the following name:
// -> kPrefix_ToString(Offset(AttributeValue))... applies for each interesting attribute for the
// operation.
//
// The recommended use is an alias with:
// using ObjectGenerator = ObjectGenerator<Attribute1, Attribute2, ...>
//
// When using in conjunction with |Offset|, prefer |ObjectOffset<>|;
// Maximum size for object names. We limit this, so an intermediate buffer can be used as scratch
// surface when generating all objects for all attributes, effectively reducing the amount of
// allocations.
constexpr uint64_t kNameMaxLength = 80;
namespace internal {
template <typename OperationInfo, typename ObjectType>
void AddObjects(inspect::Node* root, std::vector<ObjectType>* object_collection,
fbl::StringBuffer<kNameMaxLength>* name_buffer, size_t last_character) {
OperationInfo::CreateTracker(name_buffer->c_str(), root, object_collection);
}
template <typename OperationInfo, typename ObjectType, typename Attribute,
typename... RemainingAttributes>
void AddObjects(inspect::Node* root, std::vector<ObjectType>* object_collection,
fbl::StringBuffer<kNameMaxLength>* name_buffer, size_t last_character) {
// Skip if this is not an attribute being tracked for the given operation.
if constexpr (!std::is_base_of<Attribute, OperationInfo>::value) {
AddObjects<OperationInfo, ObjectType, RemainingAttributes...>(
root, object_collection, name_buffer, name_buffer->length());
return;
}
// Clear any remainder from other invocations.
for (size_t i = 0; i < Attribute::kSize; ++i) {
name_buffer->Resize(last_character);
name_buffer->AppendPrintf("_%s", Attribute::ToString(i).c_str());
AddObjects<OperationInfo, ObjectType, RemainingAttributes...>(
root, object_collection, name_buffer, name_buffer->length());
}
}
} // namespace internal
template <typename... Attributes>
struct ObjectGenerator {
// Adds all tracking objects for the |OperationInfo|. The tracking objects can be counters,
// histograms, etc.
template <typename OperationInfo, typename ObjectType>
static void AddObjects(inspect::Node* root, std::vector<ObjectType>* object_collection) {
fbl::StringBuffer<kNameMaxLength> name_buffer;
name_buffer.AppendPrintf("%s", OperationInfo::kPrefix);
internal::AddObjects<OperationInfo, ObjectType, Attributes...>(
root, object_collection, &name_buffer, name_buffer.length());
}
};
} // namespace fs_metrics
#endif // SRC_LIB_STORAGE_VFS_CPP_METRICS_OBJECT_GENERATOR_H_