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 #include <cobalt-client/cpp/collector.h>
6 #include <cobalt-client/cpp/counter-internal.h>
7 #include <cobalt-client/cpp/histogram-internal.h>
8 #include <cobalt-client/cpp/metric-options.h>
9 #include <cobalt-client/cpp/types-internal.h>
10 
11 #ifdef __Fuchsia__
12 #include <cobalt-client/cpp/collector-internal.h>
13 
14 #include <fuchsia/cobalt/c/fidl.h>
15 #include <lib/fdio/util.h>
16 #include <lib/fidl/cpp/vector_view.h>
17 #include <lib/zx/channel.h>
18 #endif
19 
20 #include <utility>
21 
22 namespace cobalt_client {
23 namespace internal {
24 namespace {
25 
26 #ifdef __Fuchsia__
MakeCobaltOptions(CollectorOptions options)27 internal::CobaltOptions MakeCobaltOptions(CollectorOptions options) {
28     ZX_DEBUG_ASSERT_MSG(options.load_config, "Must define a load_config function.");
29     internal::CobaltOptions cobalt_options;
30     cobalt_options.logger_deadline_first_attempt = options.initial_response_deadline;
31     cobalt_options.logger_deadline = options.response_deadline;
32     cobalt_options.config_reader = std::move(options.load_config);
33     cobalt_options.service_connect = [](const char* service_path,
34                                         zx::channel service) -> zx_status_t {
35         return fdio_service_connect(service_path, service.release());
36     };
37     cobalt_options.service_path.AppendPrintf("/svc/%s", fuchsia_cobalt_LoggerFactory_Name);
38     cobalt_options.release_stage = static_cast<internal::ReleaseStage>(options.release_stage);
39     return cobalt_options;
40 }
41 #else
42 // Host side implementation, which does nothing, just provides safety that all methods wont
43 // fault.
44 class HostLogger : public internal::Logger {
45 public:
46     ~HostLogger() override = default;
47 
48     bool Log(const RemoteMetricInfo& remote_info, const HistogramBucket* buckets,
49              size_t num_buckets) override {
50         return true;
51     };
52 
53     bool Log(const RemoteMetricInfo& remote_info, int64_t count) override { return true; };
54 };
55 #endif // __Fuchsia__
56 } // namespace
57 } // namespace internal
58 
59 #ifdef __Fuchsia__
Collector(CollectorOptions options)60 Collector::Collector(CollectorOptions options)
61     : logger_(std::make_unique<internal::CobaltLogger>(
62           internal::MakeCobaltOptions(std::move(options)))) {
63     flushing_.store(false);
64 }
65 #else
Collector(CollectorOptions options)66 Collector::Collector(CollectorOptions options) : logger_(std::make_unique<internal::HostLogger>()) {
67     flushing_.store(false);
68 }
69 #endif // __Fuchsia__
70 
Collector(std::unique_ptr<internal::Logger> logger)71 Collector::Collector(std::unique_ptr<internal::Logger> logger) : logger_(std::move(logger)) {
72     flushing_.store(false);
73 }
74 
~Collector()75 Collector::~Collector() {
76     if (logger_ != nullptr) {
77         Flush();
78     }
79 };
80 
Flush()81 void Collector::Flush() {
82     // If we are already flushing we just return and do nothing.
83     // First come first serve.
84     if (flushing_.exchange(true)) {
85         return;
86     }
87 
88     for (internal::FlushInterface* flushable : flushables_) {
89         if (!flushable->Flush(logger_.get())) {
90             flushable->UndoFlush();
91         }
92     }
93 
94     // Once we are finished we allow flushing again.
95     flushing_.store(false);
96 }
97 
UnSubscribe(internal::FlushInterface * flushable)98 void Collector::UnSubscribe(internal::FlushInterface* flushable) {
99     // TODO(gevalentino): Replace the vector for an unordered_map/hash_map.
100     for (size_t i = 0; i < flushables_.size(); ++i) {
101         if (flushable == flushables_[i]) {
102             flushables_.erase(i);
103             break;
104         }
105     }
106 }
107 
GeneralAvailability()108 CollectorOptions CollectorOptions::GeneralAvailability() {
109     CollectorOptions options;
110     options.release_stage = static_cast<uint32_t>(internal::ReleaseStage::kGa);
111     return options;
112 }
113 
Dogfood()114 CollectorOptions CollectorOptions::Dogfood() {
115     CollectorOptions options;
116     options.release_stage = static_cast<uint32_t>(internal::ReleaseStage::kDogfood);
117     return options;
118 }
119 
Fishfood()120 CollectorOptions CollectorOptions::Fishfood() {
121     CollectorOptions options;
122     options.release_stage = static_cast<uint32_t>(internal::ReleaseStage::kFishfood);
123     return options;
124 }
125 
Debug()126 CollectorOptions CollectorOptions::Debug() {
127     CollectorOptions options;
128     options.release_stage = static_cast<uint32_t>(internal::ReleaseStage::kDebug);
129     return options;
130 }
131 
132 } // namespace cobalt_client
133