da37d435bc5a72dd8724b0ce9f4e20d6ae9614bd
[WebKit-https.git] / Source / WebCore / PAL / pal / Logger.h
1 /*
2  * Copyright (C) 2017 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. ``AS IS'' AND ANY
14  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
17  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24  */
25
26 #pragma once
27
28 #include <wtf/Assertions.h>
29 #include <wtf/HexNumber.h>
30 #include <wtf/Noncopyable.h>
31 #include <wtf/RefCounted.h>
32 #include <wtf/RefPtr.h>
33 #include <wtf/text/StringBuilder.h>
34 #include <wtf/text/WTFString.h>
35
36 namespace PAL {
37
38 template<typename T>
39 struct LogArgument {
40     template<typename U = T> static typename std::enable_if<std::is_same<U, int>::value, String>::type toString(int argument) { return String::number(argument); }
41     template<typename U = T> static typename std::enable_if<std::is_same<U, float>::value, String>::type toString(float argument) { return String::number(argument); }
42     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<U, const char*>::value, String>::type toString(const char* argument) { return String(argument); }
45     template<size_t length> static String toString(const char (&argument)[length]) { return String(argument); }
46 };
47
48 class Logger : public RefCounted<Logger> {
49     WTF_MAKE_NONCOPYABLE(Logger);
50 public:
51     static Ref<Logger> create(const void* owner)
52     {
53         return adoptRef(*new Logger(owner));
54     }
55
56     template<typename... Arguments>
57     inline void logAlways(WTFLogChannel& channel, const Arguments&... arguments)
58     {
59 #if RELEASE_LOG_DISABLED
60         // "Standard" WebCore logging goes to stderr, which is captured in layout test output and can generally be a problem
61         //  on some systems, so don't allow it.
62         UNUSED_PARAM(channel);
63 #else
64         if (!willLog(channel, WTFLogLevelAlways))
65             return;
66
67         log(channel, arguments...);
68 #endif
69     }
70
71     template<typename... Arguments>
72     inline void error(WTFLogChannel& channel, const Arguments&... arguments)
73     {
74         if (!willLog(channel, WTFLogLevelError))
75             return;
76
77         log(channel, arguments...);
78     }
79
80     template<typename... Arguments>
81     inline void warning(WTFLogChannel& channel, const Arguments&... arguments)
82     {
83         if (!willLog(channel, WTFLogLevelWarning))
84             return;
85
86         log(channel, arguments...);
87     }
88
89     template<typename... Arguments>
90     inline void notice(WTFLogChannel& channel, const Arguments&... arguments)
91     {
92         if (!willLog(channel, WTFLogLevelNotice))
93             return;
94
95         log(channel, arguments...);
96     }
97
98     template<typename... Arguments>
99     inline void info(WTFLogChannel& channel, const Arguments&... arguments)
100     {
101         if (!willLog(channel, WTFLogLevelInfo))
102             return;
103
104         log(channel, arguments...);
105     }
106
107     template<typename... Arguments>
108     inline void debug(WTFLogChannel& channel, const Arguments&... arguments)
109     {
110         if (!willLog(channel, WTFLogLevelDebug))
111             return;
112
113         log(channel, arguments...);
114     }
115
116     inline bool willLog(WTFLogChannel& channel, WTFLogLevel level) const
117     {
118         if (level != WTFLogLevelAlways && level > channel.level)
119             return false;
120
121         if (channel.level != WTFLogLevelAlways && channel.state == WTFLogChannelOff)
122             return false;
123
124         return m_enabled;
125     }
126
127     bool enabled() const { return m_enabled; }
128     void setEnabled(const void* owner, bool enabled)
129     {
130         ASSERT(owner == m_owner);
131         if (owner == m_owner)
132             m_enabled = enabled;
133     }
134
135     struct MethodAndPointer {
136         MethodAndPointer(const char* methodName, void* objectPtr)
137             : methodName(methodName)
138             , objectPtr(reinterpret_cast<uintptr_t>(objectPtr))
139         {
140         }
141
142         const char* methodName;
143         uintptr_t objectPtr;
144     };
145
146 private:
147     Logger(const void* owner) { m_owner = owner; }
148
149     template<typename... Argument>
150     static inline void log(WTFLogChannel& channel, const Argument&... arguments)
151     {
152         String string = makeString(LogArgument<Argument>::toString(arguments)...);
153
154 #if RELEASE_LOG_DISABLED
155         WTFLog(&channel, "%s", string.utf8().data());
156 #else
157         os_log(channel.osLogChannel, "%{public}s", string.utf8().data());
158 #endif
159     }
160
161     const void* m_owner;
162     bool m_enabled { true };
163 };
164
165 template <>
166 struct LogArgument<Logger::MethodAndPointer> {
167     static String toString(const Logger::MethodAndPointer& value)
168     {
169         StringBuilder builder;
170         builder.append(value.methodName);
171         builder.appendLiteral("(0x");
172         appendUnsigned64AsHex(value.objectPtr, builder);
173         builder.appendLiteral(") ");
174         return builder.toString();
175     }
176 };
177
178 } // namespace PAL
179