| // 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_ |