1 // Copyright 2018 The Fuchsia Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #pragma once 6 7 #include <limits.h> 8 #include <stdint.h> 9 10 #include <cobalt-client/cpp/counter-internal.h> 11 #include <cobalt-client/cpp/histogram-internal.h> 12 #include <cobalt-client/cpp/types-internal.h> 13 #include <fbl/string_buffer.h> 14 #include <lib/zx/channel.h> 15 #include <lib/zx/time.h> 16 #include <lib/zx/vmo.h> 17 #include <zircon/types.h> 18 19 namespace cobalt_client { 20 namespace internal { 21 22 struct CobaltOptions { 23 // Service path to LoggerFactory interface. 24 fbl::StringBuffer<PATH_MAX> service_path; 25 26 // Maximum time to wait for Cobalt Service to respond for the CreateLogger request. 27 // Unless the channel is closed, we will keep checking if the channel is readable. 28 zx::duration logger_deadline; 29 30 // The maximum time to wait, after the request has been written to the channel. 31 // This allows amortizing the wait time in future calls. 32 zx::duration logger_deadline_first_attempt; 33 34 // Sets the input VMO to point to the serialized config for this logger and the size 35 // of the serialized data. 36 fbl::Function<bool(zx::vmo*, size_t*)> config_reader; 37 38 // Performs a connection to a service at a given path. 39 fbl::Function<zx_status_t(const char* service_path, zx::channel service)> service_connect; 40 41 // Which release stage to use for persisting metrics. 42 ReleaseStage release_stage; 43 }; 44 45 class CobaltLogger : public Logger { 46 public: 47 CobaltLogger() = delete; 48 explicit CobaltLogger(CobaltOptions options); 49 CobaltLogger(const CobaltLogger&) = delete; 50 CobaltLogger(CobaltLogger&&) = delete; 51 CobaltLogger& operator=(const CobaltLogger&) = delete; 52 CobaltLogger& operator=(CobaltLogger&&) = delete; ~CobaltLogger()53 ~CobaltLogger() override{}; 54 55 // Returns true if the histogram was persisted. 56 bool Log(const RemoteMetricInfo& metric_info, const HistogramBucket* buckets, 57 size_t bucket_count) override; 58 59 // Returns true if the counter was persisted. 60 bool Log(const RemoteMetricInfo& metric_info, int64_t count) override; 61 IsListeningForReply()62 bool IsListeningForReply() const { return logger_factory_.is_valid(); } 63 64 // Blocks until the reply from LoggerFactory arrives into |logger_factory_| 65 // channel or the peer is closed. |observed| will be set to the observed signals 66 // if provided. Useful for testing to enforce a deterministic order of operations. 67 zx_status_t WaitForReply(zx_signals_t* observed = nullptr) const { 68 return zx_object_wait_one(logger_factory_.get(), 69 ZX_CHANNEL_READABLE | ZX_CHANNEL_PEER_CLOSED, 70 zx::time::infinite().get(), observed); 71 } 72 73 protected: 74 // If returns true, a channel has been established with the endpoint, 75 // and the handshake to set up a logger started. 76 bool TrySendLoggerRequest(); 77 78 // The service replied and the status is ok. 79 bool HasCobaltReplied(zx::duration deadline); 80 81 // Returns true if the logger request has been sent, and Cobalt Service 82 // replied successfully already. If any error happens that prevents 83 // writing to the current channel(ZX_ERR_PEER_CLOSED), we guarantee 84 // the next time this method is called will return false. 85 bool IsLoggerReady(); 86 87 // Set of options for this logger. 88 CobaltOptions options_; 89 90 zx::channel logger_; 91 zx::channel logger_factory_; 92 93 bool is_first_attempt_; 94 }; 95 96 } // namespace internal 97 } // namespace cobalt_client 98