| /** @file | |
| Logging | |
| @section license License | |
| Licensed to the Apache Software Foundation (ASF) under one | |
| or more contributor license agreements. See the NOTICE file | |
| distributed with this work for additional information | |
| regarding copyright ownership. The ASF licenses this file | |
| to you under the Apache License, Version 2.0 (the | |
| "License"); you may not use this file except in compliance | |
| with the License. You may obtain a copy of the License at | |
| http://www.apache.org/licenses/LICENSE-2.0 | |
| Unless required by applicable law or agreed to in writing, software | |
| distributed under the License is distributed on an "AS IS" BASIS, | |
| WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
| See the License for the specific language governing permissions and | |
| limitations under the License. | |
| @verbatim | |
| int Log::access (LogAccess *entry); | |
| The return value is Log::OK if all log objects successfully logged the | |
| entry. Otherwise, it has the following bits set to indicate what happened | |
| ret_val & Log::SKIP - at least one object filtered the entry | |
| - transaction logging has been disabled | |
| - the logging system is sampling and it is | |
| not yet time for a new sample | |
| - no log objects have been defined | |
| - entry to log is empty | |
| ret_val & Log::FAIL an internal limit of the logging system was | |
| exceeded preventing entry from being logged | |
| ret_val & Log::FULL the logging space has been exhausted | |
| @endverbatim | |
| @section example Example usage of the API | |
| @code | |
| // Populate a TransactionLogData source, then: | |
| LogAccess entry(data); | |
| int ret = Log::access(&entry); | |
| @endcode | |
| */ | |
| #pragma once | |
| #include <cstdarg> | |
| #include "tscore/ink_platform.h" | |
| #include "tscore/EventNotify.h" | |
| #include "tscore/Regression.h" | |
| #include "records/RecProcess.h" | |
| #include "proxy/logging/LogFile.h" | |
| #include "proxy/logging/LogBuffer.h" | |
| #include <unordered_map> | |
| class LogAccess; | |
| class LogFieldList; | |
| class LogFilterList; | |
| class LogFormatList; | |
| struct LogBufferHeader; | |
| class LogFile; | |
| class LogBuffer; | |
| class LogFormat; | |
| class LogObject; | |
| class LogConfig; | |
| class TextLogObject; | |
| class LogFlushData | |
| { | |
| public: | |
| LINK(LogFlushData, link); | |
| Ptr<LogFile> m_logfile; | |
| LogBuffer *logbuffer = nullptr; | |
| void *m_data; | |
| int m_len; | |
| LogFlushData(LogFile *logfile, void *data, int len = -1) : m_logfile(logfile), m_data(data), m_len(len) {} | |
| ~LogFlushData() | |
| { | |
| switch (m_logfile->m_file_format) { | |
| case LOG_FILE_BINARY: | |
| logbuffer = static_cast<LogBuffer *>(m_data); | |
| LogBuffer::destroy(logbuffer); | |
| break; | |
| case LOG_FILE_ASCII: | |
| case LOG_FILE_PIPE: | |
| ats_free(m_data); | |
| break; | |
| case N_LOGFILE_TYPES: | |
| default: | |
| ink_release_assert(!"Unknown file format type!"); | |
| } | |
| } | |
| }; | |
| /** | |
| This object exists to provide a namespace for the logging system. | |
| It contains all data types and global variables relevant to the | |
| logging system. You can't actually create a Log object, so all | |
| members are static. | |
| */ | |
| class Log | |
| { | |
| public: | |
| // Prevent creation of any instances of this class. | |
| // | |
| Log() = delete; | |
| enum ReturnCodeFlags { | |
| LOG_OK = 1, | |
| SKIP = 2, | |
| AGGR = 4, | |
| FAIL = 8, | |
| FULL = 16, | |
| }; | |
| enum LoggingMode { | |
| LOG_MODE_NONE = 0, | |
| LOG_MODE_ERRORS, // log *only* errors | |
| LOG_MODE_TRANSACTIONS, // log *only* transactions | |
| LOG_MODE_FULL | |
| }; | |
| enum InitFlags { | |
| FIELDS_INITIALIZED = 1, | |
| FULLY_INITIALIZED = 2, | |
| }; | |
| enum ConfigFlags { | |
| LOGCAT = 1, | |
| }; | |
| enum RollingEnabledValues { | |
| NO_ROLLING = 0, | |
| ROLL_ON_TIME_ONLY, | |
| ROLL_ON_SIZE_ONLY, | |
| ROLL_ON_TIME_OR_SIZE, | |
| ROLL_ON_TIME_AND_SIZE, | |
| INVALID_ROLLING_VALUE | |
| }; | |
| enum { | |
| MIN_ROLLING_INTERVAL_SEC = 30, // 30 second minimum rolling interval | |
| MAX_ROLLING_INTERVAL_SEC = 86400 // 24 hrs rolling interval max | |
| }; | |
| // main interface | |
| static void init(int configFlags = 0); | |
| static void init_fields(); | |
| static void load_config(); | |
| // Register a field in both global_field_list and field_symbol_hash, keyed by | |
| // its own symbol so the two can never drift apart. | |
| static void register_field(LogField *field); | |
| static bool | |
| transaction_logging_enabled() | |
| { | |
| return (logging_mode == LOG_MODE_FULL || logging_mode == LOG_MODE_TRANSACTIONS); | |
| } | |
| static bool | |
| error_logging_enabled() | |
| { | |
| return (logging_mode == LOG_MODE_FULL || logging_mode == LOG_MODE_ERRORS); | |
| } | |
| static int access(LogAccess *lad); | |
| static int va_error(const char *format, va_list ap); | |
| static int error(const char *format, ...) TS_PRINTFLIKE(1, 2); | |
| static void flush_all_objects(); | |
| // public data members | |
| static LogObject *error_log; | |
| /** The latest fully initialized LogConfig. | |
| * | |
| * This is the safe, fully initialed LogConfig object to query against when | |
| * performing logging operations. | |
| */ | |
| static LogConfig *config; | |
| static LogFieldList global_field_list; | |
| static std::unordered_map<std::string, LogField *> field_symbol_hash; | |
| static LoggingMode logging_mode; | |
| // logging thread stuff | |
| static EventNotify *preproc_notify; | |
| static void *preproc_thread_main(void *args); | |
| static EventNotify *flush_notify; | |
| static InkAtomicList *flush_data_list; | |
| static void *flush_thread_main(void *args); | |
| static int preproc_threads; | |
| // reconfiguration stuff | |
| static void change_configuration(); | |
| static int handle_logging_mode_change(const char *name, RecDataT data_type, RecData data, void *cookie); | |
| static int handle_periodic_tasks_int_change(const char *name, RecDataT data_type, RecData data, void *cookie); | |
| /** Check each log file path to see whether it exists and re-open if not. | |
| * | |
| * This is called when an external log rotation entity has moved log files to | |
| * rolled names. This checks whether the original log file exists and, if | |
| * not, closes the file descriptor and re-opens the file. | |
| */ | |
| static int handle_log_rotation_request(); | |
| friend void RegressionTest_LogObjectManager_Transfer(RegressionTest *, int, int *); | |
| private: | |
| static void periodic_tasks(long time_now); | |
| static void create_threads(); | |
| static void init_when_enabled(); | |
| static int init_status; | |
| static int config_flags; | |
| static bool logging_mode_changed; | |
| static bool log_rotate_signal_received; | |
| static uint32_t periodic_tasks_interval; | |
| }; | |
| static inline bool | |
| LogThrottlingIsValid(int throttling_val) | |
| { | |
| return throttling_val >= 0; | |
| } | |
| static inline bool | |
| LogRollingEnabledIsValid(int enabled) | |
| { | |
| return enabled >= Log::NO_ROLLING && enabled < Log::INVALID_ROLLING_VALUE; | |
| } |