// ball_attributecollectorregistry.h -*-C++-*- #ifndef INCLUDED_BALL_ATTRIBUTECOLLECTORREGISTRY #define INCLUDED_BALL_ATTRIBUTECOLLECTORREGISTRY #include <bsls_ident.h> BSLS_IDENT("$Id: $") //@PURPOSE: Provide a registry for attribute collector functors. // //@CLASSES: // ball::AttributeCollectorRegistry: registry of attribute collector functors // //@SEE_ALSO: ball_record, ball_loggermanager // //@DESCRIPTION: This component provides a mechanism, // 'ball::AttributeCollectorRegistry', that allows clients to register // 'ball::Attribute' collection functions, and to separately apply a visitor to // all the attributes collected using those collection functions. A client can // register a 'ball::Attribute' collection function by calling 'addCollector' // and supplying a function matching the // 'AttributeCollectorRegistry::Collector' signature. Clients can also apply a // visitor to collected 'ball::Attribute' objects by calling 'collect' and // supplying a function matching the // 'ball::AttributeCollectorRegistry::Visitor' signature. This call to // 'collect' will use the supplied 'Visitor' as the argument when calling each // of the 'Collector' functors registered with 'addCollector'. // ///Thread Safety ///------------- // 'ball::AttributeCollectorRegistry' is fully *thread-safe*, meaning that all // non-creator operations on an object can be safely invoked simultaneously // from multiple threads. // ///Usage ///----- // This section illustrates intended use of this component. // ///Example 1: Collecting Attributes From Non-uniform Sources ///- - - - - - - - - - - - - - - - - - - - - - - - - - - - - // In this example we will collect a set of application properties and perform // some manipulation of the collected data. Note that this usage example uses // lambdas and requires C++11. Lambdas can be replaced with named functions // for C++03. // // First, we define a few collector functions that will collect the application // properties from various parts of an application and call the specified // visitor functor for every collected attribute: //.. // void userInfo(const bsl::function<void(const ball::Attribute &)>& visitor) // { // int uuid = 12345; // getUuid(); // bsl::string userName = "proxy"; // getUserName(); // // visitor(ball::Attribute("myLib.uuid", uuid)); // visitor(ball::Attribute("myLib.user", userName)); // } // // void threadInfo( // const bsl::function<void(const ball::Attribute &)>& visitor) // { // int threadId = 87654; // getThreadId(); // // visitor(ball::Attribute("myLib.threadId", threadId)); // } //.. // Then, we register collector functions with the attribute collector // registry: //.. // ball::AttributeCollectorRegistry registry; // // int rc = registry.addCollector(&userInfo, "userInfoCollector"); // assert(0 == rc); // assert(true == registry.hasCollector("userInfoCollector")); // rc = registry.addCollector(&threadInfo, "threadInfoCollector"); // assert(0 == rc); // assert(true == registry.hasCollector("threadInfoCollector")); // assert(2 == registry.numCollectors()); //.. // Next, we print every attribute gathered by all registered attribute // collectors in the registry: //.. // bsl::stringstream output1; // // registry.collect([&output1](const ball::Attribute& attribute) // { // output1 << attribute.name() << "=" << attribute.value() << " "; // }); // // assert("myLib.uuid=12345 myLib.user=proxy myLib.threadId=87654 " // == output1.str()); //.. // Finally, we remove one of the collectors and collect attributes again: //.. // int rc = registry.removeCollector("threadInfoCollector"); // assert(0 == rc); // assert(false == registry.hasCollector("threadInfoCollectory")); // assert(1 == registry.numCollectors()); // // bsl::stringstream output2; // registry.collect([&output2](const ball::Attribute& attribute) // { // output2 << attribute.name() << "=" << attribute.value() << " "; // }); // // assert("myLib.uuid=12345 myLib.user=proxy " == output2.str()); //.. #include <balscm_version.h> #include <ball_attribute.h> #include <bslma_allocator.h> #include <bslma_stdallocator.h> #include <bslma_usesbslmaallocator.h> #include <bslmf_nestedtraitdeclaration.h> #include <bslmt_readerwritermutex.h> #include <bsls_compilerfeatures.h> #include <bsl_functional.h> #include <bsl_memory.h> #include <bsl_string.h> #include <bsl_utility.h> #include <bsl_vector.h> namespace BloombergLP { namespace ball { // ================================ // class AttributeCollectorRegistry // ================================ class AttributeCollectorRegistry { // This component maintains a registry of named functors ("collectors") // that are used to transform opaque user data into a set of // 'ball::Attribute' objects. public: // TYPES typedef bsl::function<void(const ball::Attribute&)> Visitor; // 'Visitor' is the type of a user-supplied visit functor. typedef bsl::function<void(const Visitor&)> Collector; // 'Collector' is the type of a user-supplied attribute collector // functor. typedef bsl::allocator<char> allocator_type; // This 'typedef' is an alias for the allocator used by this object. private: // PRIVATE TYPES typedef bsl::pair<bsl::string, Collector> CollectorEntry; // This 'typedef' is an alias for a single named attribute collector. typedef bsl::vector<CollectorEntry> Registry; // This 'typedef' is an alias for the type of the registry maintained // by this object. Note that 'vector' is used to preserve the order in // which collectors are registered. // DATA Registry d_collectors; // collector registry mutable bslmt::ReaderWriterMutex d_rwMutex; // protects concurrent // access to 'd_collectors' // NOT IMPLEMENTED AttributeCollectorRegistry(const AttributeCollectorRegistry&); AttributeCollectorRegistry& operator=(const AttributeCollectorRegistry&); public: // TRAITS BSLMF_NESTED_TRAIT_DECLARATION(AttributeCollectorRegistry, bslma::UsesBslmaAllocator); // CREATORS AttributeCollectorRegistry(); explicit AttributeCollectorRegistry(const allocator_type& allocator); // Create a registry having no registered collectors. Optionally // specify an 'allocator' (e.g., the address of a 'bslma::Allocator' // object) to supply memory; otherwise, the default allocator is used. #ifdef BSLS_COMPILERFEATURES_SUPPORT_DEFAULTED_FUNCTIONS ~AttributeCollectorRegistry() = default; // Destroy this registry. #endif // MANIPULATORS int addCollector(const Collector& collector, const bsl::string_view& name); // Add the specified 'collector' with the specified 'name' to this // registry. Return 0 if 'collector' was successfully registered, and // a non-zero value (with no effect) otherwise. Note that this method // will fail if a collector having 'name' is already registered. void removeAll(); // Remove all collectors from this registry. int removeCollector(const bsl::string_view& name); // Remove the collector having the specified 'name' from this registry. // Return 0 if the collector with 'name' was successfully removed, and // a non-zero value (with no effect) otherwise. // ACCESSORS void collect(const Visitor& visitor) const; // Invoke all registered collectors with the specified 'visitor' // functor. Note that collectors are invoked in the order in which // collectors are registered. allocator_type get_allocator() const; // Return the allocator used by this object to supply memory. Note // that if no allocator was supplied at construction the default // allocator in effect at construction is used. bool hasCollector(const bsl::string_view& name) const; // Return 'true' if a collector having the specified 'name' is in the // registry maintained by this object, and 'false' otherwise. Note // that this method is provided primarily for debugging purposes (i.e., // its return value can be invalidated from another thread). int numCollectors() const; // Return the number of collectors registered with this object. Note // that this method is provided primarily for debugging purposes (i.e., // its return value can be invalidated from another thread). }; // ============================================================================ // INLINE DEFINITIONS // ============================================================================ // -------------------------------- // class AttributeCollectorRegistry // -------------------------------- // CREATORS inline AttributeCollectorRegistry::AttributeCollectorRegistry() : d_collectors() { } inline AttributeCollectorRegistry::AttributeCollectorRegistry( const allocator_type& allocator) : d_collectors(allocator) { } // ACCESSORS inline AttributeCollectorRegistry::allocator_type AttributeCollectorRegistry::get_allocator() const { return d_collectors.get_allocator(); } } // close package namespace } // close enterprise namespace #endif // ---------------------------------------------------------------------------- // Copyright 2020 Bloomberg Finance L.P. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // ----------------------------- END-OF-FILE ----------------------------------