1 /** @file
2
3 Logging
4
5 @section license License
6
7 Licensed to the Apache Software Foundation (ASF) under one
8 or more contributor license agreements. See the NOTICE file
9 distributed with this work for additional information
10 regarding copyright ownership. The ASF licenses this file
11 to you under the Apache License, Version 2.0 (the
12 "License"); you may not use this file except in compliance
13 with the License. You may obtain a copy of the License at
14
15 http://www.apache.org/licenses/LICENSE-2.0
16
17 Unless required by applicable law or agreed to in writing, software
18 distributed under the License is distributed on an "AS IS" BASIS,
19 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
20 See the License for the specific language governing permissions and
21 limitations under the License.
22
23 @verbatim
24 int Log::access (LogAccess *entry);
25
26 The return value is Log::OK if all log objects successfully logged the
27 entry. Otherwise, it has the following bits set to indicate what happened
28
29 ret_val & Log::SKIP - at least one object filtered the entry
30 - transaction logging has been disabled
31 - the logging system is sampling and it is
32 not yet time for a new sample
33 - no log objects have been defined
34 - entry to log is empty
35
36 ret_val & Log::FAIL an internal limit of the logging system was
37 exceeded preventing entry from being logged
38
39 ret_val & Log::FULL the logging space has been exhausted
40
41 @endverbatim
42
43 @section example Example usage of the API
44
45 @code
46 LogAccess entry(this);
47 int ret = Log::access(&entry);
48 @endcode
49
50 */
51
52 #pragma once
53
54 #include <cstdarg>
55 #include "tscore/ink_platform.h"
56 #include "tscore/EventNotify.h"
57 #include "tscore/Regression.h"
58 #include "records/P_RecProcess.h"
59 #include "LogFile.h"
60 #include "LogBuffer.h"
61
62 #include <unordered_map>
63
64 class LogAccess;
65 class LogFieldList;
66 class LogFilterList;
67 class LogFormatList;
68 struct LogBufferHeader;
69 class LogFile;
70 class LogBuffer;
71 class LogFormat;
72 class LogObject;
73 class LogConfig;
74 class TextLogObject;
75
76 class LogFlushData
77 {
78 public:
79 LINK(LogFlushData, link);
80 Ptr<LogFile> m_logfile;
81 LogBuffer *logbuffer = nullptr;
82 void *m_data;
83 int m_len;
84
m_logfile(logfile)85 LogFlushData(LogFile *logfile, void *data, int len = -1) : m_logfile(logfile), m_data(data), m_len(len) {}
~LogFlushData()86 ~LogFlushData()
87 {
88 switch (m_logfile->m_file_format) {
89 case LOG_FILE_BINARY:
90 logbuffer = static_cast<LogBuffer *>(m_data);
91 LogBuffer::destroy(logbuffer);
92 break;
93 case LOG_FILE_ASCII:
94 case LOG_FILE_PIPE:
95 free(m_data);
96 break;
97 case N_LOGFILE_TYPES:
98 default:
99 ink_release_assert(!"Unknown file format type!");
100 }
101 }
102 };
103
104 /**
105 This object exists to provide a namespace for the logging system.
106 It contains all data types and global variables relevant to the
107 logging system. You can't actually create a Log object, so all
108 members are static.
109 */
110 class Log
111 {
112 public:
113 // Prevent creation of any instances of this class.
114 //
115 Log() = delete;
116
117 enum ReturnCodeFlags {
118 LOG_OK = 1,
119 SKIP = 2,
120 AGGR = 4,
121 FAIL = 8,
122 FULL = 16,
123 };
124
125 enum LoggingMode {
126 LOG_MODE_NONE = 0,
127 LOG_MODE_ERRORS, // log *only* errors
128 LOG_MODE_TRANSACTIONS, // log *only* transactions
129 LOG_MODE_FULL
130 };
131
132 enum InitFlags {
133 FIELDS_INITIALIZED = 1,
134 FULLY_INITIALIZED = 2,
135 };
136
137 enum ConfigFlags {
138 NO_REMOTE_MANAGEMENT = 1,
139 LOGCAT = 4,
140 };
141
142 enum RollingEnabledValues {
143 NO_ROLLING = 0,
144 ROLL_ON_TIME_ONLY,
145 ROLL_ON_SIZE_ONLY,
146 ROLL_ON_TIME_OR_SIZE,
147 ROLL_ON_TIME_AND_SIZE,
148 INVALID_ROLLING_VALUE
149 };
150
151 enum {
152 MIN_ROLLING_INTERVAL_SEC = 30, // 30 second minimum rolling interval
153 MAX_ROLLING_INTERVAL_SEC = 86400 // 24 hrs rolling interval max
154 };
155
156 // main interface
157 static void init(int configFlags = 0);
158 static void init_fields();
159
160 static bool
transaction_logging_enabled()161 transaction_logging_enabled()
162 {
163 return (logging_mode == LOG_MODE_FULL || logging_mode == LOG_MODE_TRANSACTIONS);
164 }
165
166 static bool
error_logging_enabled()167 error_logging_enabled()
168 {
169 return (logging_mode == LOG_MODE_FULL || logging_mode == LOG_MODE_ERRORS);
170 }
171
172 static int access(LogAccess *lad);
173 static int va_error(const char *format, va_list ap);
174 static int error(const char *format, ...) TS_PRINTFLIKE(1, 2);
175
176 /////////////////////////////////////////////////////////////////////////
177 // 'Wire tracing' enabled by source ip or by percentage of connections //
178 /////////////////////////////////////////////////////////////////////////
179 static void trace_in(const sockaddr *peer_addr, uint16_t peer_port, const char *format_string, ...) TS_PRINTFLIKE(3, 4);
180 static void trace_out(const sockaddr *peer_addr, uint16_t peer_port, const char *format_string, ...) TS_PRINTFLIKE(3, 4);
181 static void trace_va(bool in, const sockaddr *peer_addr, uint16_t peer_port, const char *format_string, va_list ap);
182
183 // public data members
184 static LogObject *error_log;
185 /** The latest fully initialized LogConfig.
186 *
187 * This is the safe, fully initialed LogConfig object to query against when
188 * performing logging operations.
189 */
190 static LogConfig *config;
191 static LogFieldList global_field_list;
192 static std::unordered_map<std::string, LogField *> field_symbol_hash;
193 static LoggingMode logging_mode;
194
195 // logging thread stuff
196 static EventNotify *preproc_notify;
197 static void *preproc_thread_main(void *args);
198 static EventNotify *flush_notify;
199 static InkAtomicList *flush_data_list;
200 static void *flush_thread_main(void *args);
201
202 static int preproc_threads;
203
204 // reconfiguration stuff
205 static void change_configuration();
206
207 static int handle_logging_mode_change(const char *name, RecDataT data_type, RecData data, void *cookie);
208 static int handle_periodic_tasks_int_change(const char *name, RecDataT data_type, RecData data, void *cookie);
209
210 /** Check each log file path to see whether it exists and re-open if not.
211 *
212 * This is called when an external log rotation entity has moved log files to
213 * rolled names. This checks whether the original log file exists and, if
214 * not, closes the file descriptor and re-opens the file.
215 */
216 static int handle_log_rotation_request();
217
218 friend void RegressionTest_LogObjectManager_Transfer(RegressionTest *, int, int *);
219
220 private:
221 static void periodic_tasks(long time_now);
222 static void create_threads();
223 static void init_when_enabled();
224
225 static int init_status;
226 static int config_flags;
227 static bool logging_mode_changed;
228 static bool log_rotate_signal_received;
229 static uint32_t periodic_tasks_interval;
230 };
231
232 static inline bool
LogRollingEnabledIsValid(int enabled)233 LogRollingEnabledIsValid(int enabled)
234 {
235 return (enabled >= Log::NO_ROLLING || enabled < Log::INVALID_ROLLING_VALUE);
236 }
237
238 #define TraceIn(flag, ...) \
239 do { \
240 if (unlikely(flag)) \
241 Log::trace_in(__VA_ARGS__); \
242 } while (0)
243
244 #define TraceOut(flag, ...) \
245 do { \
246 if (unlikely(flag)) \
247 Log::trace_out(__VA_ARGS__); \
248 } while (0)
249