| # Cobalt Client |
| |
| The cobalt client library provides a set of metrics than can be logged through cobalt. |
| |
| Classes in this module are categorized in two groups: |
| - Metrics: Represent data and provide methods to update them. |
| - Collector: Owns the data, and is in charge of flushing data to services. |
| |
| ## Collector Options |
| ```c++ |
| cobalt_client::CollectorOptions MakeOptions() { |
| cobalt_client::CollectorOptions options; |
| |
| |
| // The collector preallocates space for the metrics to be collected, so when |
| // instantiated we set the number of each metric type we want to store. |
| options.max_histograms = 4; |
| options.max_counters = 4; |
| |
| // The collector also needs to define how it should behave when attempting |
| // to reach a remote service(IPC/FIDL), such as cobalt. The response |
| // deadline, is for setting up the remote logger in the remote service. |
| // This is the time it will block when checking if the service already |
| // replied. |
| options.response_deadline = zx::nsec(0); |
| |
| // Just as before, but this is when we write the remote logger request, we |
| // immediately wait for this amount of time. |
| options.initial_response_deadline = zx::nsec(100); |
| |
| // Cobalt service requires the serialized config for setting up the service. |
| // Since we cannot assume that the filesystem is ready by the time we are |
| // instantiating the collector (e.g. a filesystem collecting metrics) |
| // we defer it by passing a fbl::Function. |
| options.load_config = [] (zx::vmo* vmo, size_t* total_bytes) -> bool { |
| // We could speed this up by a fidl call to obtain a VMO to a file. |
| zx::vmo::create(....., vmo); |
| *total_bytes = read(.....); |
| // We check if we can read. |
| return vmo->write(buffer,0, total_bytes) == ZX_OK; |
| }; |
| return std::move(options); |
| } |
| ``` |
| |
| ## Collector |
| ```c++ |
| class Delorean { |
| private: |
| cobalt_client::Collector collector_ = Collector::Debug(MakeOptions()); |
| } |
| |
| ... |
| // Attempt to send the metrics to cobalt. |
| collector_.Flush(); |
| ``` |
| Collector can only be instantiated by users through the public factory methods, |
| which describe the target release stage(Debug, Fishfood, Dogfood, General |
| Availability). |
| |
| The collector is in charge of flushing or sending the metrics to the cobalt |
| service. Because we make no assumptions on the existence of the service, or the |
| availability of the service, the following decisions were made: |
| |
| - Best effort: Try to send the metrics to cobalt process. If we fail, undo the |
| flush, and try again later. |
| - Reconnect: We assume the channel can be closed at any time, which is why we |
| re-stablish the connection when this happens and we attempt to flush. |
| - Delegate when to flush: The user determines when is the best momento to send |
| the metrics to FIDL. |
| |
| |
| The Collector also owns the storage for the metrics, so any metric that was |
| instantiated from a Collector should be used after a collector's destruction. |
| Usually the collector and the metrics should be members of the same class |
| (either directly or indirectly). |
| |
| ## Counter |
| ```c++ |
| enum TimeTravelDirection : uint32_t { |
| kUnknown = 0, |
| kPast = 1, |
| kFuture = 2, |
| }; |
| |
| MetricOptions options; |
| options.Remote(); |
| options.metric_id = kTimeTravelYears; |
| options.event_code = kPast; |
| options.component = "Great Scott!"; |
| |
| cobalt_client::Counter years_traveled = collector_.AddCounter(options); |
| if (total_years == 1) { |
| // By default Increment increments by 1 unit. |
| years_travelled.Increment(); |
| } else { |
| // Or you can increment a single time. |
| years_travelled.Increment(num_events); |
| } |
| ``` |
| |
| Counter is a shallow proxy, which is why it can be copied or moved, with no |
| effect what so ever. |
| |
| ## Histogram |
| ```c++ |
| HistogramOptions options = HistogramOptions::Exponential( |
| /*bucket_count=*/10, /*base=*/2, /*scalar=*/1, /*offset=*/2); |
| options.Remote(); |
| options.metric_id = kTimeTravelYears; |
| options.event_code = kPast; |
| options.component = "Great Scott!"; |
| |
| cobalt_client::Histogram years_per_travel = collector_.AddHistogram(options); |
| uint64_t current_year = 1955; |
| uint64_t original_year = 1985; |
| uint64_t years_traveled = abs(current_year - original_year); |
| uint64_t nums_of_travels = 1; |
| if (years_traveled == 1) { |
| years_per_travel.Add(years_traveled); |
| } else { |
| years_per_travel.Add(years_traveled, nums_of_travels); |
| } |
| ``` |
| Histogram is a shallow proxy for the data owned by the collector, and provides |
| methods for adding observed values. The Options must mimick those set up in |
| your cobalt project configuration. |
| |
| |
| ## Remote Vs Local values |
| |
| Eventually the library will provide the ability to instantiate local version of |
| the metrics for the Introspection API. So GetRemoteCount methods, reference |
| the values that have not yet been sent to Cobalt. |