Skip to content

Commit

Permalink
[FastPair] Add QP_LOG() logging macro
Browse files Browse the repository at this point in the history
This change adds a log MACRO for Quick Pair implementations (e.g. Fast
Pair).

The logic here matches the logic we've used for our other similar scenarios,
(NS_LOG and PA_LOG). I've filed crbug/1219790 as a tech debt item to refactor
this pattern into something that can be shared across all our features.

Change-Id: I2cf2f32152cd604c3cac6af382dd59bb28cd4ac3
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2960724
Commit-Queue: Shane Fitzpatrick <shanefitz@google.com>
Reviewed-by: Jon Mann <jonmann@chromium.org>
Cr-Commit-Position: refs/heads/master@{#892375}
  • Loading branch information
Shane Fitzpatrick authored and Chromium LUCI CQ committed Jun 15, 2021
1 parent 3f8c9fe commit 3692547
Show file tree
Hide file tree
Showing 8 changed files with 423 additions and 0 deletions.
1 change: 1 addition & 0 deletions chromeos/components/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ test("chromeos_components_unittests") {
"//chromeos/components/power:unit_tests",
"//chromeos/components/proximity_auth:unit_tests",
"//chromeos/components/quick_answers:unit_tests",
"//chromeos/components/quick_pair:unit_tests",
"//chromeos/components/security_token_pin:unit_tests",
"//chromeos/components/sensors:unit_tests",
"//chromeos/components/smbfs:unit_tests",
Expand Down
15 changes: 15 additions & 0 deletions chromeos/components/quick_pair/BUILD.gn
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# Copyright 2021 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.

assert(is_chromeos, "Quick Pair protocols (e.g. Fast Pair) are CrOS only")

source_set("unit_tests") {
testonly = true

deps = [
"//base/test:test_support",
"//chromeos/components/quick_pair/common:unit_tests",
"//testing/gtest",
]
}
15 changes: 15 additions & 0 deletions chromeos/components/quick_pair/common/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,10 @@ assert(is_chromeos, "Quick Pair protocols (e.g. Fast Pair) are CrOS only")

source_set("common") {
sources = [
"log_buffer.cc",
"log_buffer.h",
"logging.cc",
"logging.h",
"quick_pair_features.cc",
"quick_pair_features.h",
]
Expand All @@ -14,3 +18,14 @@ source_set("common") {

deps = []
}

source_set("unit_tests") {
testonly = true
sources = [ "logging_unittest.cc" ]

deps = [
":common",
"//base/test:test_support",
"//testing/gtest",
]
}
65 changes: 65 additions & 0 deletions chromeos/components/quick_pair/common/log_buffer.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
// Copyright 2021 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.

#include "chromeos/components/quick_pair/common/log_buffer.h"

#include "base/lazy_instance.h"

namespace chromeos {
namespace quick_pair {

namespace {

// The maximum number of logs that can be stored in the buffer.
const size_t kMaxBufferSize = 1000;

// The global instance returned by LogBuffer::GetInstance().
base::LazyInstance<LogBuffer>::Leaky g_log_buffer = LAZY_INSTANCE_INITIALIZER;

} // namespace

LogBuffer::LogMessage::LogMessage(const std::string& text,
const base::Time& time,
const std::string& file,
const int line,
logging::LogSeverity severity)
: text(text), time(time), file(file), line(line), severity(severity) {}

// static
LogBuffer* LogBuffer::GetInstance() {
return &g_log_buffer.Get();
}

LogBuffer::LogBuffer() {}

LogBuffer::~LogBuffer() {}

void LogBuffer::AddObserver(Observer* observer) {
observers_.AddObserver(observer);
}

void LogBuffer::RemoveObserver(Observer* observer) {
observers_.RemoveObserver(observer);
}

void LogBuffer::AddLogMessage(const LogMessage& log_message) {
log_messages_.push_back(log_message);
if (log_messages_.size() > MaxBufferSize())
log_messages_.pop_front();
for (auto& observer : observers_)
observer.OnLogMessageAdded(log_message);
}

void LogBuffer::Clear() {
log_messages_.clear();
for (auto& observer : observers_)
observer.OnLogBufferCleared();
}

size_t LogBuffer::MaxBufferSize() const {
return kMaxBufferSize;
}

} // namespace quick_pair
} // namespace chromeos
84 changes: 84 additions & 0 deletions chromeos/components/quick_pair/common/log_buffer.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
// Copyright 2021 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 CHROMEOS_COMPONENTS_QUICK_PAIR_COMMON_LOG_BUFFER_H_
#define CHROMEOS_COMPONENTS_QUICK_PAIR_COMMON_LOG_BUFFER_H_

#include <stddef.h>

#include <list>

#include "base/logging.h"
#include "base/observer_list.h"
#include "base/time/time.h"

namespace chromeos {
namespace quick_pair {

// Contains logs specific to the Quick Pair implementations (e.g. Fast Pair).
// This buffer has a maximum size and will discard entries in FIFO order. Call
// LogBuffer::GetInstance() to get the global LogBuffer instance.
class LogBuffer {
public:
// Represents a single log entry in the log buffer.
struct LogMessage {
const std::string text;
const base::Time time;
const std::string file;
const int line;
const logging::LogSeverity severity;

LogMessage(const std::string& text,
const base::Time& time,
const std::string& file,
int line,
logging::LogSeverity severity);
};

class Observer {
public:
// Called when a new message is added to the log buffer.
virtual void OnLogMessageAdded(const LogMessage& log_message) = 0;

// Called when all messages in the log buffer are cleared.
virtual void OnLogBufferCleared() = 0;
};

LogBuffer();
LogBuffer(const LogBuffer&) = delete;
LogBuffer& operator=(const LogBuffer&) = delete;
~LogBuffer();

// Returns the global instance.
static LogBuffer* GetInstance();

// Adds and removes log buffer observers.
void AddObserver(Observer* observer);
void RemoveObserver(Observer* observer);

// Adds a new log message to the buffer. If the number of log messages exceeds
// the maximum, then the earliest added log will be removed.
void AddLogMessage(const LogMessage& log_message);

// Clears all logs in the buffer.
void Clear();

// Returns the maximum number of logs that can be stored.
size_t MaxBufferSize() const;

// Returns the list logs in the buffer, sorted chronologically.
const std::list<LogMessage>* logs() { return &log_messages_; }

private:
// The messages currently in the buffer.
std::list<LogMessage> log_messages_;

// List of observers.
base::ObserverList<Observer>::Unchecked observers_;
};

} // namespace quick_pair
} // namespace chromeos

#endif // CHROMEOS_COMPONENTS_QUICK_PAIR_COMMON_LOG_BUFFER_H_
54 changes: 54 additions & 0 deletions chromeos/components/quick_pair/common/logging.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
// Copyright 2021 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.

#include "chromeos/components/quick_pair/common/logging.h"

#include "base/time/time.h"
#include "chromeos/components/quick_pair/common/log_buffer.h"

namespace chromeos {
namespace quick_pair {

namespace {

bool g_logging_enabled = true;

} // namespace

ScopedDisableLoggingForTesting::ScopedDisableLoggingForTesting() {
g_logging_enabled = false;
}

ScopedDisableLoggingForTesting::~ScopedDisableLoggingForTesting() {
g_logging_enabled = true;
}

ScopedLogMessage::ScopedLogMessage(const char* file,
int line,
logging::LogSeverity severity)
: file_(file), line_(line), severity_(severity) {}

ScopedLogMessage::~ScopedLogMessage() {
if (!g_logging_enabled)
return;

const std::string string_from_stream = stream_.str();
LogBuffer::GetInstance()->AddLogMessage(LogBuffer::LogMessage(
string_from_stream, base::Time::Now(), file_, line_, severity_));

// Don't emit VERBOSE-level logging to the standard logging system unless
// verbose logging is enabled for the source file.
if (severity_ <= logging::LOG_VERBOSE &&
logging::GetVlogLevelHelper(file_, strlen(file_) + 1) <= 0) {
return;
}

// The destructor of |log_message| also creates a log for the standard logging
// system.
logging::LogMessage log_message(file_, line_, severity_);
log_message.stream() << string_from_stream;
}

} // namespace quick_pair
} // namespace chromeos
61 changes: 61 additions & 0 deletions chromeos/components/quick_pair/common/logging.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
// Copyright 2021 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 CHROMEOS_COMPONENTS_QUICK_PAIR_COMMON_LOGGING_H_
#define CHROMEOS_COMPONENTS_QUICK_PAIR_COMMON_LOGGING_H_

#include <sstream>

#include "base/logging.h"

namespace chromeos {
namespace quick_pair {

// Use the QP_LOG() macro for all logging related to Quick Pair implementations
// (e.g. Fast Pair), so the system is aware of all logs related to this feature.
// We display these logs in the debug WebUI (chrome://nearby-internals).
//
// QP_LOG() has the same interface as the standard LOG() macro and also creates
// a normal log message of the same severity.
// Examples:
// QP_LOG(INFO) << "Waiting for " << x << " pending requests.";
// QP_LOG(ERROR) << "Request failed: " << error_string;
#define QP_LOG(severity) \
chromeos::quick_pair::ScopedLogMessage(__FILE__, __LINE__, \
logging::LOG_##severity) \
.stream()

// Disables all logging while in scope. Intended to be called only from test
// code, to clean up test output.
class ScopedDisableLoggingForTesting {
public:
ScopedDisableLoggingForTesting();
~ScopedDisableLoggingForTesting();
};

// An intermediate object used by the QP_LOG macro, wrapping a
// logging::LogMessage instance. When this object is destroyed, the message will
// be logged with the standard logging system and also added to Proximity Auth
// specific log buffer. You should use the QP_LOG() macro instead of this class
// directly.
class ScopedLogMessage {
public:
ScopedLogMessage(const char* file, int line, logging::LogSeverity severity);
ScopedLogMessage(const ScopedLogMessage&) = delete;
ScopedLogMessage& operator=(const ScopedLogMessage&) = delete;
~ScopedLogMessage();

std::ostream& stream() { return stream_; }

private:
const char* file_;
int line_;
logging::LogSeverity severity_;
std::ostringstream stream_;
};

} // namespace quick_pair
} // namespace chromeos

#endif // CHROMEOS_COMPONENTS_QUICK_PAIR_COMMON_LOGGING_H_

0 comments on commit 3692547

Please sign in to comment.