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

Unified 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, 7 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 side-by-side diff with in-line comments
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 »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: mojo/services/flog/cpp/flog.h
diff --git a/mojo/services/flog/cpp/flog.h b/mojo/services/flog/cpp/flog.h
new file mode 100644
index 0000000000000000000000000000000000000000..5badda1b473a3d024c2cd09fdd69c0985d059228
--- /dev/null
+++ b/mojo/services/flog/cpp/flog.h
@@ -0,0 +1,197 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef MOJO_SERVICES_FLOG_CPP_FLOG_H_
+#define MOJO_SERVICES_FLOG_CPP_FLOG_H_
+
+#include <atomic>
+#include <memory>
+
+#include "mojo/public/cpp/application/application_impl.h"
+#include "mojo/public/cpp/application/connect.h"
+#include "mojo/public/cpp/bindings/array.h"
+#include "mojo/public/cpp/bindings/message.h"
+#include "mojo/public/cpp/environment/logging.h"
+#include "mojo/public/cpp/system/time.h"
+#include "mojo/services/flog/interfaces/flog.mojom.h"
+
+namespace mojo {
+namespace flog {
+
+//
+// FORMATTED LOGGING
+//
+// The Flog class and associated macros provide a means of logging 'formatted'
+// log messages serialized by Mojo. Flog uses an instance of FlogLogger to
+// log events to the FlogService. Messages pulled from the FlogService can be
+// deserialized using Mojo on behalf of log visualization and analysis tools.
+//
+// Message logging is performed using a 'channel', which is bound to a Mojo
+// proxy for a particular interface. Mojo interfaces used for this purpose must
+// be request-only, meaning the constituent methods must not have responses.
+//
+// Assume that we've defined the following interface:
+//
+// [ServiceName="my_namespace::MyFlogChannelInterface"]
+// interface MyFlogChannelInterface {
+// Thing1(int64 a, int32 b);
+// Thing2(string c);
+// };
+//
+// Note that the ServiceName annotation is required.
+//
+// A channel instance may be defined, typically as a member of a class, as
+// follows:
+//
+// FLOG_CHANNEL(MyFlogChannelInterface, my_flog_channel_instance_);
+//
+// If NDEBUG is defined, this compiles to nothing. Otherwise, it declares and
+// initializes my_flog_channel_instance, which can be used via the FLOG macro:
+//
+// FLOG(my_flog_channel_instance_, Thing1(1234, 5678));
+// FLOG(my_flog_channel_instance_, Thing2("To the lifeboats!"));
+//
+// These invocations compile to nothing if NDEBUG is defined. Otherwise, they
+// log messages to the channel represented by my_flog_channel_instance.
+//
+// FLOG_CHANNEL_DECL produces only a declaration for cases in which a channel
+// must be declared but not defined (e.g. as a static class member).
+//
+// Logging to a channel does nothing unless the Flog class has been initialized
+// with a call to Flog::Initialize. Flog::Initialize provides a FlogLogger
+// implementation to be used for logging. Typically, this implementation would
+// be acquired from the FlogService using CreateLogger.
+//
+
+#if defined(NDEBUG)
+
+#define FLOG_INITIALIZE(app_or_logger, label) ((void)0)
+#define FLOG_DESTROY() ((void)0)
+#define FLOG_CHANNEL(channel_type, channel_name)
+#define FLOG_CHANNEL_DECL(channel_type, channel_name)
+#define FLOG(channel_name, call) ((void)0)
+#define FLOG_ID(channel_name) 0
+
+#else
+
+#define FLOG_INITIALIZE(app_or_logger, label) \
+ mojo::flog::Flog::Initialize(app_or_logger, label)
+
+#define FLOG_DESTROY() mojo::flog::Flog::Destroy()
+
+#define FLOG_CHANNEL(channel_type, channel_name) \
+ std::unique_ptr<mojo::flog::FlogProxy<channel_type>> channel_name = \
+ mojo::flog::FlogProxy<channel_type>::Create()
+
+#define FLOG_CHANNEL_DECL(channel_type, channel_name) \
+ std::unique_ptr<mojo::flog::FlogProxy<channel_type>> channel_name
+
+#define FLOG(channel_name, call) channel_name->call
+
+#define FLOG_ID(channel_name) channel_name->channel()->id()
+
+#endif
+
+// Thread-safe logger for all channels in a given process.
+class Flog {
+ public:
+ static void Initialize(ApplicationImpl* app, const std::string& label) {
+ MOJO_DCHECK(!logger_);
+ FlogServicePtr flog_service;
+ FlogLoggerPtr flog_logger;
+ ConnectToService(app->shell(), "mojo:flog", GetProxy(&flog_service));
+ flog_service->CreateLogger(GetProxy(&flog_logger), label);
+ logger_ = flog_logger.Pass();
+ }
+
+ // Sets the flog logger singleton.
+ static void Initialize(FlogLoggerPtr flog_logger) {
+ MOJO_DCHECK(!logger_);
+ logger_ = flog_logger.Pass();
+ }
+
+ // Deletes the flog logger singleton.
+ static void Destroy() {
+ MOJO_DCHECK(logger_);
+ logger_.reset();
+ }
+
+ // Allocates a unique id for a new channel. Never returns 0.
+ static uint32_t AllocateChannelId() { return ++last_allocated_channel_id_; }
+
+ // Logs the creation of a channel.
+ static void LogChannelCreation(uint32_t channel_id,
+ const char* channel_type_name) {
+ if (!logger_) {
+ return;
+ }
+
+ logger_->LogChannelCreation(GetTimeTicksNow(), channel_id,
+ channel_type_name);
+ }
+
+ // Logs a channel message.
+ static void LogChannelMessage(uint32_t channel_id, Message* message) {
+ if (!logger_) {
+ return;
+ }
+
+ Array<uint8_t> array = Array<uint8_t>::New(message->data_num_bytes());
+ memcpy(array.data(), message->data(), message->data_num_bytes());
+ logger_->LogChannelMessage(GetTimeTicksNow(), channel_id, array.Pass());
+ }
+
+ // Logs the deletion of a channel.
+ static void LogChannelDeletion(uint32_t channel_id) {
+ if (!logger_) {
+ return;
+ }
+
+ logger_->LogChannelDeletion(GetTimeTicksNow(), channel_id);
+ }
+
+ private:
+ static std::atomic_ulong last_allocated_channel_id_;
+ static FlogLoggerPtr logger_;
+};
+
+// Channel backing a FlogProxy.
+class FlogChannel : public MessageReceiverWithResponder {
+ public:
+ FlogChannel(const char* channel_type_name);
+
+ ~FlogChannel() override;
+
+ // Returns the channel id.
+ uint32_t id() const { return id_; }
+
+ // MessageReceiverWithResponder implementation.
+ bool Accept(Message* message) override;
+
+ bool AcceptWithResponder(Message* message,
+ MessageReceiver* responder) override;
+
+ private:
+ uint32_t id_ = 0;
+};
+
+template <typename T>
+class FlogProxy : public T::Proxy_ {
+ public:
+ static std::unique_ptr<FlogProxy<T>> Create() {
+ return std::unique_ptr<FlogProxy<T>>(new FlogProxy<T>());
+ }
+
+ FlogChannel* channel() {
+ return reinterpret_cast<FlogChannel*>(this->receiver_);
+ }
+
+ private:
+ explicit FlogProxy() : T::Proxy_(new FlogChannel(T::Name_)) {}
+};
+
+} // namespace flog
+} // namespace mojo
+
+#endif // MOJO_SERVICES_FLOG_CPP_FLOG_H_
« 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