Changeset 221388 in webkit


Ignore:
Timestamp:
Aug 30, 2017 12:06:49 PM (7 years ago)
Author:
eric.carlson@apple.com
Message:

Add Logger observer and helper class
https://bugs.webkit.org/show_bug.cgi?id=176106

Reviewed by Andy Estes.

Source/WebCore/PAL:

  • pal/Logger.h:

(PAL::LogArgument::toString): Add new variants.
(PAL::Logger::Observer::~Observer):
(PAL::Logger::logAlways const): Constify.
(PAL::Logger::error const): Ditto.
(PAL::Logger::warning const): Ditto.
(PAL::Logger::notice const): Ditto.
(PAL::Logger::info const): Ditto.
(PAL::Logger::debug const): Ditto.
(PAL::Logger::willLog const): Ditto.
(PAL::Logger::MethodAndPointer::MethodAndPointer): Add class name, make object pointer const.
(PAL::Logger::addObserver): New.
(PAL::Logger::removeObserver): New.
(PAL::Logger::Logger):
(PAL::Logger::log):
(PAL::Logger::observers):
(PAL::LogHelper::willLog const):
(PAL::LogArgument<Logger::MethodAndPointer>::toString):

Tools:

  • TestWebKitAPI/Tests/WebCore/Logging.cpp:

(TestWebKitAPI::LoggingTest::LoggingTest):
(TestWebKitAPI::LoggingTest::Logger::create):
(TestWebKitAPI::TEST_F):
(TestWebKitAPI::LogObserver::log):
(TestWebKitAPI::LogObserver::channel const):

Location:
trunk
Files:
4 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/WebCore/PAL/ChangeLog

    r221381 r221388  
     12017-08-30  Eric Carlson  <eric.carlson@apple.com>
     2
     3        Add Logger observer and helper class
     4        https://bugs.webkit.org/show_bug.cgi?id=176106
     5
     6        Reviewed by Andy Estes.
     7
     8        * pal/Logger.h:
     9        (PAL::LogArgument::toString): Add new variants.
     10        (PAL::Logger::Observer::~Observer):
     11        (PAL::Logger::logAlways const): Constify.
     12        (PAL::Logger::error const): Ditto.
     13        (PAL::Logger::warning const): Ditto.
     14        (PAL::Logger::notice const): Ditto.
     15        (PAL::Logger::info const): Ditto.
     16        (PAL::Logger::debug const): Ditto.
     17        (PAL::Logger::willLog const): Ditto.
     18        (PAL::Logger::MethodAndPointer::MethodAndPointer): Add class name, make object pointer const.
     19        (PAL::Logger::addObserver): New.
     20        (PAL::Logger::removeObserver): New.
     21        (PAL::Logger::Logger):
     22        (PAL::Logger::log):
     23        (PAL::Logger::observers):
     24        (PAL::LogHelper::willLog const):
     25        (PAL::LogArgument<Logger::MethodAndPointer>::toString):
     26
    1272017-08-30  Andy Estes  <aestes@apple.com>
    228
  • trunk/Source/WebCore/PAL/pal/Logger.h

    r221288 r221388  
    3838template<typename T>
    3939struct LogArgument {
     40    template<typename U = T> static typename std::enable_if<std::is_same<U, bool>::value, String>::type toString(bool argument) { return argument ? ASCIILiteral("true") : ASCIILiteral("false"); }
    4041    template<typename U = T> static typename std::enable_if<std::is_same<U, int>::value, String>::type toString(int argument) { return String::number(argument); }
    4142    template<typename U = T> static typename std::enable_if<std::is_same<U, float>::value, String>::type toString(float argument) { return String::number(argument); }
    4243    template<typename U = T> static typename std::enable_if<std::is_same<U, double>::value, String>::type toString(double argument) { return String::number(argument); }
    43     template<typename U = T> static typename std::enable_if<std::is_same<U, String>::value, String>::type toString(String argument) { return argument; }
     44    template<typename U = T> static typename std::enable_if<std::is_same<typename std::remove_reference<U>::type, AtomicString>::value, String>::type toString(AtomicString argument) { return argument.string(); }
     45    template<typename U = T> static typename std::enable_if<std::is_same<typename std::remove_reference<U>::type, String>::value, String>::type toString(String argument) { return argument; }
    4446    template<typename U = T> static typename std::enable_if<std::is_same<U, const char*>::value, String>::type toString(const char* argument) { return String(argument); }
    4547    template<size_t length> static String toString(const char (&argument)[length]) { return String(argument); }
     
    4951    WTF_MAKE_NONCOPYABLE(Logger);
    5052public:
     53
     54    class Observer {
     55    public:
     56        virtual ~Observer() { }
     57        virtual void didLogMessage(const WTFLogChannel&, const String&) = 0;
     58    };
     59
    5160    static Ref<Logger> create(const void* owner)
    5261    {
     
    5564
    5665    template<typename... Arguments>
    57     inline void logAlways(WTFLogChannel& channel, const Arguments&... arguments)
     66    inline void logAlways(WTFLogChannel& channel, const Arguments&... arguments) const
    5867    {
    5968#if RELEASE_LOG_DISABLED
     
    7079
    7180    template<typename... Arguments>
    72     inline void error(WTFLogChannel& channel, const Arguments&... arguments)
     81    inline void error(WTFLogChannel& channel, const Arguments&... arguments) const
    7382    {
    7483        if (!willLog(channel, WTFLogLevelError))
     
    7988
    8089    template<typename... Arguments>
    81     inline void warning(WTFLogChannel& channel, const Arguments&... arguments)
     90    inline void warning(WTFLogChannel& channel, const Arguments&... arguments) const
    8291    {
    8392        if (!willLog(channel, WTFLogLevelWarning))
     
    8897
    8998    template<typename... Arguments>
    90     inline void notice(WTFLogChannel& channel, const Arguments&... arguments)
     99    inline void notice(WTFLogChannel& channel, const Arguments&... arguments) const
    91100    {
    92101        if (!willLog(channel, WTFLogLevelNotice))
     
    97106
    98107    template<typename... Arguments>
    99     inline void info(WTFLogChannel& channel, const Arguments&... arguments)
     108    inline void info(WTFLogChannel& channel, const Arguments&... arguments) const
    100109    {
    101110        if (!willLog(channel, WTFLogLevelInfo))
     
    106115
    107116    template<typename... Arguments>
    108     inline void debug(WTFLogChannel& channel, const Arguments&... arguments)
     117    inline void debug(WTFLogChannel& channel, const Arguments&... arguments) const
    109118    {
    110119        if (!willLog(channel, WTFLogLevelDebug))
     
    114123    }
    115124
    116     inline bool willLog(WTFLogChannel& channel, WTFLogLevel level) const
     125    inline bool willLog(const WTFLogChannel& channel, WTFLogLevel level) const
    117126    {
    118127        if (level != WTFLogLevelAlways && level > channel.level)
     
    134143
    135144    struct MethodAndPointer {
    136         MethodAndPointer(const char* methodName, void* objectPtr)
    137             : methodName(methodName)
    138             , objectPtr(reinterpret_cast<uintptr_t>(objectPtr))
     145        MethodAndPointer(const char* methodName, const void* objectPtr)
     146            : methodName { methodName }
     147            , objectPtr { reinterpret_cast<uintptr_t>(objectPtr) }
    139148        {
    140149        }
    141150
    142         const char* methodName;
    143         uintptr_t objectPtr;
     151        MethodAndPointer(const char* className, const char* methodName, const void* objectPtr)
     152            : className { className }
     153            , methodName { methodName }
     154            , objectPtr { reinterpret_cast<uintptr_t>(objectPtr) }
     155        {
     156        }
     157
     158        const char* className { nullptr };
     159        const char* methodName { nullptr };
     160        const uintptr_t objectPtr { 0 };
    144161    };
    145162
     163    static inline void addObserver(Observer& observer)
     164    {
     165        observers().append(observer);
     166    }
     167    static inline void removeObserver(Observer& observer)
     168    {
     169        observers().removeFirstMatching([&observer](auto anObserver) {
     170            return &anObserver.get() == &observer;
     171        });
     172    }
     173
    146174private:
    147     Logger(const void* owner) { m_owner = owner; }
     175    Logger(const void* owner)
     176        : m_owner { owner }
     177    {
     178    }
    148179
    149180    template<typename... Argument>
    150181    static inline void log(WTFLogChannel& channel, const Argument&... arguments)
    151182    {
    152         String string = makeString(LogArgument<Argument>::toString(arguments)...);
     183        String logMessage = makeString(LogArgument<Argument>::toString(arguments)...);
    153184
    154185#if RELEASE_LOG_DISABLED
    155         WTFLog(&channel, "%s", string.utf8().data());
     186        WTFLog(&channel, "%s", logMessage.utf8().data());
    156187#else
    157         os_log(channel.osLogChannel, "%{public}s", string.utf8().data());
     188        os_log(channel.osLogChannel, "%{public}s", logMessage.utf8().data());
    158189#endif
     190
     191        for (Observer& observer : observers())
     192            observer.didLogMessage(channel, logMessage);
     193    }
     194
     195    static Vector<std::reference_wrapper<Observer>>& observers()
     196    {
     197        static NeverDestroyed<Vector<std::reference_wrapper<Observer>>> observers;
     198        return observers;
    159199    }
    160200
    161201    const void* m_owner;
    162202    bool m_enabled { true };
     203};
     204
     205class LogHelper {
     206public:
     207    virtual ~LogHelper() = default;
     208
     209    virtual const Logger& logger() const = 0;
     210    virtual const char* className() const = 0;
     211    virtual WTFLogChannel& logChannel() const = 0;
     212
     213    inline bool willLog(WTFLogLevel level) const { return logger().willLog(logChannel(), level); }
     214
     215#define ALWAYS_LOG(...)     logger().logAlways(logChannel(), Logger::MethodAndPointer(className(), __func__, this), ##__VA_ARGS__)
     216#define ERROR_LOG(...)      logger().error(logChannel(), Logger::MethodAndPointer(className(), __func__, this), ##__VA_ARGS__)
     217#define WARNING_LOG(...)    logger().warning(logChannel(), Logger::MethodAndPointer(className(), __func__, this), ##__VA_ARGS__)
     218#define NOTICE_LOG(...)     logger().notice(logChannel(), Logger::MethodAndPointer(className(), __func__, this), ##__VA_ARGS__)
     219#define INFO_LOG(...)       logger().info(logChannel(), Logger::MethodAndPointer(className(), __func__, this), ##__VA_ARGS__)
     220#define DEBUG_LOG(...)      logger().debug(logChannel(), Logger::MethodAndPointer(className(), __func__, this), ##__VA_ARGS__)
     221
    163222};
    164223
     
    168227    {
    169228        StringBuilder builder;
     229
     230        if (value.className) {
     231            builder.append(value.className);
     232            builder.appendLiteral("::");
     233        }
    170234        builder.append(value.methodName);
    171235        builder.appendLiteral("(0x");
     
    177241
    178242} // namespace PAL
    179 
  • trunk/Tools/ChangeLog

    r221380 r221388  
     12017-08-30  Eric Carlson  <eric.carlson@apple.com>
     2
     3        Add Logger observer and helper class
     4        https://bugs.webkit.org/show_bug.cgi?id=176106
     5
     6        Reviewed by Andy Estes.
     7
     8        * TestWebKitAPI/Tests/WebCore/Logging.cpp:
     9        (TestWebKitAPI::LoggingTest::LoggingTest):
     10        (TestWebKitAPI::LoggingTest::Logger::create):
     11        (TestWebKitAPI::TEST_F):
     12        (TestWebKitAPI::LogObserver::log):
     13        (TestWebKitAPI::LogObserver::channel const):
     14
    1152017-08-29  Filip Pizlo  <fpizlo@apple.com>
    216
  • trunk/Tools/TestWebKitAPI/Tests/WebCore/Logging.cpp

    r221288 r221388  
    5656namespace TestWebKitAPI {
    5757
    58 class LoggingTest : public testing::Test {
     58class LoggingTest : public testing::Test, public LogHelper {
    5959public:
     60    LoggingTest()
     61        : m_logger { Logger::create(this) }
     62    {
     63    }
     64
    6065    void SetUp() final
    6166    {
     
    95100    }
    96101
     102    const Logger& logger() const final { return m_logger.get(); }
     103    const char* className() const final { return "LoggingTest"; }
     104    WTFLogChannel& logChannel() const final { return TestChannel1; }
     105
    97106private:
     107
     108    Ref<Logger> m_logger;
    98109    int m_descriptors[2];
    99110    FILE* m_stderr;
     
    268279
    269280    WTFSetLogChannelLevel(&TestChannel1, WTFLogLevelError);
     281    EXPECT_TRUE(logger->willLog(TestChannel1, WTFLogLevelError));
    270282    logger->error(TestChannel1, "You're using coconuts!");
    271283    EXPECT_TRUE(output().contains("You're using coconuts!", false));
     
    303315
    304316    logger->setEnabled(this, false);
     317    EXPECT_FALSE(logger->willLog(TestChannel1, WTFLogLevelError));
     318    EXPECT_FALSE(logger->willLog(TestChannel1, WTFLogLevelWarning));
     319    EXPECT_FALSE(logger->willLog(TestChannel1, WTFLogLevelNotice));
     320    EXPECT_FALSE(logger->willLog(TestChannel1, WTFLogLevelInfo));
     321    EXPECT_FALSE(logger->willLog(TestChannel1, WTFLogLevelDebug));
    305322    EXPECT_FALSE(logger->enabled());
    306323    logger->logAlways(TestChannel1, "You've got two empty halves of coconuts");
    307324    EXPECT_EQ(0u, output().length());
    308 }
     325
     326    logger->setEnabled(this, true);
     327    AtomicString string1("AtomicString", AtomicString::ConstructFromLiteral);
     328    const AtomicString string2("const AtomicString", AtomicString::ConstructFromLiteral);
     329    logger->logAlways(TestChannel1, string1, " and ", string2);
     330    EXPECT_TRUE(output().contains("AtomicString and const AtomicString", false));
     331
     332    String string3("String");
     333    const String string4("const String");
     334    logger->logAlways(TestChannel1, string3, " and ", string4);
     335    EXPECT_TRUE(output().contains("String and const String", false));
     336}
     337
     338TEST_F(LoggingTest, LogHelper)
     339{
     340    EXPECT_TRUE(logger().enabled());
     341
     342    StringBuilder builder;
     343    builder.appendLiteral("LoggingTest::TestBody(0x");
     344    appendUnsigned64AsHex(reinterpret_cast<uintptr_t>(this), builder);
     345    builder.appendLiteral(")");
     346    String signature = builder.toString();
     347
     348    ALWAYS_LOG();
     349    EXPECT_TRUE(this->output().contains(signature, false));
     350
     351    ALWAYS_LOG("Welcome back", " my friends", " to the show", " that never ends");
     352    String result = this->output();
     353    EXPECT_TRUE(result.contains(signature, false));
     354    EXPECT_TRUE(result.contains("to the show that never", false));
     355
     356    WTFSetLogChannelLevel(&TestChannel1, WTFLogLevelWarning);
     357    EXPECT_TRUE(willLog(WTFLogLevelWarning));
     358
     359    ERROR_LOG("We're so glad you could attend");
     360    EXPECT_TRUE(output().contains("We're so glad you could attend", false));
     361
     362    WARNING_LOG("Come inside! ", "Come inside!");
     363    EXPECT_TRUE(output().contains("Come inside! Come inside!", false));
     364
     365    NOTICE_LOG("There behind a glass is a real blade of grass");
     366    EXPECT_EQ(0u, output().length());
     367
     368    INFO_LOG("be careful as you pass.");
     369    EXPECT_EQ(0u, output().length());
     370
     371    DEBUG_LOG("Move along! Move along!");
     372    EXPECT_EQ(0u, output().length());
     373}
     374
     375class LogObserver : public Logger::Observer {
     376public:
     377    LogObserver() = default;
     378
     379    String log()
     380    {
     381        String log = m_logBuffer.toString();
     382        m_logBuffer.clear();
     383
     384        return log;
     385    }
     386
     387    WTFLogChannel channel() const { return m_lastChannel; }
     388
     389private:
     390    void didLogMessage(const WTFLogChannel& channel, const String& logMessage) final
     391    {
     392        m_logBuffer.append(logMessage);
     393        m_lastChannel = channel;
     394    }
     395
     396    StringBuilder m_logBuffer;
     397    WTFLogChannel m_lastChannel;
     398};
     399
     400TEST_F(LoggingTest, LogObserver)
     401{
     402    LogObserver observer;
     403
     404    EXPECT_TRUE(logger().enabled());
     405
     406    logger().addObserver(observer);
     407    ALWAYS_LOG("testing 1, 2, 3");
     408    EXPECT_TRUE(this->output().contains("testing 1, 2, 3", false));
     409    EXPECT_TRUE(observer.log().contains("testing 1, 2, 3", false));
     410    EXPECT_STREQ(observer.channel().name, logChannel().name);
     411
     412    logger().removeObserver(observer);
     413    ALWAYS_LOG("testing ", 1, ", ", 2, ", 3");
     414    EXPECT_TRUE(this->output().contains("testing 1, 2, 3", false));
     415    EXPECT_EQ(0u, observer.log().length());
     416}
     417
    309418#endif
    310419
Note: See TracChangeset for help on using the changeset viewer.