1/*
2 * Copyright (C) 2019 Apple Inc. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 *
13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
14 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
15 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
17 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
18 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
19 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
20 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
21 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
22 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
23 * THE POSSIBILITY OF SUCH DAMAGE.
24 */
25
26#pragma once
27
28#include <wtf/Algorithms.h>
29#include <wtf/Logger.h>
30
31namespace WTF {
32
33class AggregateLogger : public Logger {
34 WTF_MAKE_NONCOPYABLE(AggregateLogger);
35public:
36
37 static Ref<AggregateLogger> create(const void* owner)
38 {
39 return adoptRef(*new AggregateLogger(owner));
40 }
41
42 void addLogger(const Logger& logger)
43 {
44 m_loggers.add(&logger);
45 }
46
47 void removeLogger(const Logger& logger)
48 {
49 m_loggers.remove(&logger);
50 }
51
52 template<typename... Arguments>
53 inline void logAlways(WTFLogChannel& channel, UNUSED_FUNCTION const Arguments&... arguments) const
54 {
55#if RELEASE_LOG_DISABLED
56 // "Standard" WebCore logging goes to stderr, which is captured in layout test output and can generally be a problem
57 // on some systems, so don't allow it.
58 UNUSED_PARAM(channel);
59#else
60 log(channel, WTFLogLevel::Always, arguments...);
61#endif
62 }
63
64 template<typename... Arguments>
65 inline void error(WTFLogChannel& channel, const Arguments&... arguments) const
66 {
67 log(channel, WTFLogLevel::Error, arguments...);
68 }
69
70 template<typename... Arguments>
71 inline void warning(WTFLogChannel& channel, const Arguments&... arguments) const
72 {
73 log(channel, WTFLogLevel::Warning, arguments...);
74 }
75
76 template<typename... Arguments>
77 inline void info(WTFLogChannel& channel, const Arguments&... arguments) const
78 {
79 log(channel, WTFLogLevel::Info, arguments...);
80 }
81
82 template<typename... Arguments>
83 inline void debug(WTFLogChannel& channel, const Arguments&... arguments) const
84 {
85 log(channel, WTFLogLevel::Debug, arguments...);
86 }
87
88 inline bool willLog(const WTFLogChannel& channel, WTFLogLevel level) const
89 {
90 return allOf(m_loggers, [channel, level] (auto& logger) { return logger->willLog(channel, level); });
91 }
92
93private:
94 AggregateLogger(const void* owner)
95 : Logger(owner)
96 {
97 }
98
99 template<typename... Argument>
100 inline void log(WTFLogChannel& channel, WTFLogLevel level, const Argument&... arguments) const
101 {
102 if (!willLog(channel, level))
103 return;
104
105 Logger::log(channel, level, arguments...);
106
107 for (auto logger : m_loggers) {
108 for (Observer& observer : logger->observers())
109 observer.didLogMessage(channel, level, { ConsoleLogValue<Argument>::toValue(arguments)... });
110 }
111 }
112
113 HashSet<RefPtr<const Logger>> m_loggers;
114};
115
116} // namespace WTF
117
118using WTF::AggregateLogger;
119