blob: d0d670224e8efc6189229ab17be39c370c6fc391 [file] [log] [blame]
/** @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
LogAccess entry(this);
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/I_RecProcess.h"
#include "LogFile.h"
#include "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:
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 {
NO_REMOTE_MANAGEMENT = 1,
LOGCAT = 4,
};
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 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);
// 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); // lgtm[cpp/constant-comparison]
}