Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(120)

Side by Side Diff: mojo/services/flog/cpp/flog.h

Issue 2008553006: Add 'Flog' formatted logging to mojo/services (Closed) Base URL: https://github.com/domokit/mojo.git@master
Patch Set: Created 4 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « mojo/services/flog/cpp/BUILD.gn ('k') | mojo/services/flog/cpp/flog.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright 2016 The Chromium 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 #ifndef MOJO_SERVICES_FLOG_CPP_FLOG_H_
6 #define MOJO_SERVICES_FLOG_CPP_FLOG_H_
7
8 #include <atomic>
9 #include <memory>
10
11 #include "mojo/public/cpp/application/application_impl.h"
12 #include "mojo/public/cpp/application/connect.h"
13 #include "mojo/public/cpp/bindings/array.h"
14 #include "mojo/public/cpp/bindings/message.h"
15 #include "mojo/public/cpp/environment/logging.h"
16 #include "mojo/public/cpp/system/time.h"
17 #include "mojo/services/flog/interfaces/flog.mojom.h"
18
19 namespace mojo {
20 namespace flog {
21
22 //
23 // FORMATTED LOGGING
24 //
25 // The Flog class and associated macros provide a means of logging 'formatted'
26 // log messages serialized by Mojo. Flog uses an instance of FlogLogger to
27 // log events to the FlogService. Messages pulled from the FlogService can be
28 // deserialized using Mojo on behalf of log visualization and analysis tools.
29 //
30 // Message logging is performed using a 'channel', which is bound to a Mojo
31 // proxy for a particular interface. Mojo interfaces used for this purpose must
32 // be request-only, meaning the constituent methods must not have responses.
33 //
34 // Assume that we've defined the following interface:
35 //
36 // [ServiceName="my_namespace::MyFlogChannelInterface"]
37 // interface MyFlogChannelInterface {
38 // Thing1(int64 a, int32 b);
39 // Thing2(string c);
40 // };
41 //
42 // Note that the ServiceName annotation is required.
43 //
44 // A channel instance may be defined, typically as a member of a class, as
45 // follows:
46 //
47 // FLOG_CHANNEL(MyFlogChannelInterface, my_flog_channel_instance_);
48 //
49 // If NDEBUG is defined, this compiles to nothing. Otherwise, it declares and
50 // initializes my_flog_channel_instance, which can be used via the FLOG macro:
51 //
52 // FLOG(my_flog_channel_instance_, Thing1(1234, 5678));
53 // FLOG(my_flog_channel_instance_, Thing2("To the lifeboats!"));
54 //
55 // These invocations compile to nothing if NDEBUG is defined. Otherwise, they
56 // log messages to the channel represented by my_flog_channel_instance.
57 //
58 // FLOG_CHANNEL_DECL produces only a declaration for cases in which a channel
59 // must be declared but not defined (e.g. as a static class member).
60 //
61 // Logging to a channel does nothing unless the Flog class has been initialized
62 // with a call to Flog::Initialize. Flog::Initialize provides a FlogLogger
63 // implementation to be used for logging. Typically, this implementation would
64 // be acquired from the FlogService using CreateLogger.
65 //
66
67 #if defined(NDEBUG)
68
69 #define FLOG_INITIALIZE(app_or_logger, label) ((void)0)
70 #define FLOG_DESTROY() ((void)0)
71 #define FLOG_CHANNEL(channel_type, channel_name)
72 #define FLOG_CHANNEL_DECL(channel_type, channel_name)
73 #define FLOG(channel_name, call) ((void)0)
74 #define FLOG_ID(channel_name) 0
75
76 #else
77
78 #define FLOG_INITIALIZE(app_or_logger, label) \
79 mojo::flog::Flog::Initialize(app_or_logger, label)
80
81 #define FLOG_DESTROY() mojo::flog::Flog::Destroy()
82
83 #define FLOG_CHANNEL(channel_type, channel_name) \
84 std::unique_ptr<mojo::flog::FlogProxy<channel_type>> channel_name = \
85 mojo::flog::FlogProxy<channel_type>::Create()
86
87 #define FLOG_CHANNEL_DECL(channel_type, channel_name) \
88 std::unique_ptr<mojo::flog::FlogProxy<channel_type>> channel_name
89
90 #define FLOG(channel_name, call) channel_name->call
91
92 #define FLOG_ID(channel_name) channel_name->channel()->id()
93
94 #endif
95
96 // Thread-safe logger for all channels in a given process.
97 class Flog {
98 public:
99 static void Initialize(ApplicationImpl* app, const std::string& label) {
100 MOJO_DCHECK(!logger_);
101 FlogServicePtr flog_service;
102 FlogLoggerPtr flog_logger;
103 ConnectToService(app->shell(), "mojo:flog", GetProxy(&flog_service));
104 flog_service->CreateLogger(GetProxy(&flog_logger), label);
105 logger_ = flog_logger.Pass();
106 }
107
108 // Sets the flog logger singleton.
109 static void Initialize(FlogLoggerPtr flog_logger) {
110 MOJO_DCHECK(!logger_);
111 logger_ = flog_logger.Pass();
112 }
113
114 // Deletes the flog logger singleton.
115 static void Destroy() {
116 MOJO_DCHECK(logger_);
117 logger_.reset();
118 }
119
120 // Allocates a unique id for a new channel. Never returns 0.
121 static uint32_t AllocateChannelId() { return ++last_allocated_channel_id_; }
122
123 // Logs the creation of a channel.
124 static void LogChannelCreation(uint32_t channel_id,
125 const char* channel_type_name) {
126 if (!logger_) {
127 return;
128 }
129
130 logger_->LogChannelCreation(GetTimeTicksNow(), channel_id,
131 channel_type_name);
132 }
133
134 // Logs a channel message.
135 static void LogChannelMessage(uint32_t channel_id, Message* message) {
136 if (!logger_) {
137 return;
138 }
139
140 Array<uint8_t> array = Array<uint8_t>::New(message->data_num_bytes());
141 memcpy(array.data(), message->data(), message->data_num_bytes());
142 logger_->LogChannelMessage(GetTimeTicksNow(), channel_id, array.Pass());
143 }
144
145 // Logs the deletion of a channel.
146 static void LogChannelDeletion(uint32_t channel_id) {
147 if (!logger_) {
148 return;
149 }
150
151 logger_->LogChannelDeletion(GetTimeTicksNow(), channel_id);
152 }
153
154 private:
155 static std::atomic_ulong last_allocated_channel_id_;
156 static FlogLoggerPtr logger_;
157 };
158
159 // Channel backing a FlogProxy.
160 class FlogChannel : public MessageReceiverWithResponder {
161 public:
162 FlogChannel(const char* channel_type_name);
163
164 ~FlogChannel() override;
165
166 // Returns the channel id.
167 uint32_t id() const { return id_; }
168
169 // MessageReceiverWithResponder implementation.
170 bool Accept(Message* message) override;
171
172 bool AcceptWithResponder(Message* message,
173 MessageReceiver* responder) override;
174
175 private:
176 uint32_t id_ = 0;
177 };
178
179 template <typename T>
180 class FlogProxy : public T::Proxy_ {
181 public:
182 static std::unique_ptr<FlogProxy<T>> Create() {
183 return std::unique_ptr<FlogProxy<T>>(new FlogProxy<T>());
184 }
185
186 FlogChannel* channel() {
187 return reinterpret_cast<FlogChannel*>(this->receiver_);
188 }
189
190 private:
191 explicit FlogProxy() : T::Proxy_(new FlogChannel(T::Name_)) {}
192 };
193
194 } // namespace flog
195 } // namespace mojo
196
197 #endif // MOJO_SERVICES_FLOG_CPP_FLOG_H_
OLDNEW
« no previous file with comments | « mojo/services/flog/cpp/BUILD.gn ('k') | mojo/services/flog/cpp/flog.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698