diff options
author | Alexey Botchkov <holyfoot@askmonty.org> | 2012-03-14 00:55:56 +0400 |
---|---|---|
committer | Alexey Botchkov <holyfoot@askmonty.org> | 2012-03-14 00:55:56 +0400 |
commit | 07a82c58a7306bd8ef889dd912cdc437a9f83a89 (patch) | |
tree | edd7edc02e96ad32d8f7d8d5137db548562be16e | |
parent | 92f31d8070738206c5b64d3ab5cc9a0cb05c56fa (diff) | |
download | mariadb-git-07a82c58a7306bd8ef889dd912cdc437a9f83a89.tar.gz |
MDEV-15 Log all SQL errors.
Added the logger service that provides us with the rotating logs.
The plugin SQL_ERROR_LOG added. It logs the errors using the 'logger service'
for the rotating log files.
the example record from the log:
2012-03-09 15:07:29 root[root] @ localhost [] ERROR 1146: Table 'test.xyz' doesn't exist : select * from test.xyz
-rw-r--r-- | include/my_sys.h | 1 | ||||
-rw-r--r-- | include/mysql/plugin.h | 2 | ||||
-rw-r--r-- | include/mysql/plugin_audit.h.pp | 18 | ||||
-rw-r--r-- | include/mysql/plugin_auth.h.pp | 18 | ||||
-rw-r--r-- | include/mysql/plugin_ftparser.h.pp | 18 | ||||
-rw-r--r-- | include/mysql/service_logger.h | 98 | ||||
-rw-r--r-- | include/mysql/services.h | 2 | ||||
-rw-r--r-- | include/service_versions.h | 1 | ||||
-rw-r--r-- | libservices/CMakeLists.txt | 3 | ||||
-rw-r--r-- | libservices/logger_service.c | 20 | ||||
-rw-r--r-- | mysys/CMakeLists.txt | 2 | ||||
-rw-r--r-- | mysys/my_logger.c | 168 | ||||
-rw-r--r-- | plugin/sql_errlog/CMakeLists.txt | 16 | ||||
-rw-r--r-- | plugin/sql_errlog/sql_errlog.c | 147 | ||||
-rw-r--r-- | sql/mysqld.cc | 3 | ||||
-rw-r--r-- | sql/sql_plugin_services.h | 11 | ||||
-rw-r--r-- | strings/my_vsnprintf.c | 19 |
17 files changed, 543 insertions, 4 deletions
diff --git a/include/my_sys.h b/include/my_sys.h index fa79af51c7e..3fcaea95f7b 100644 --- a/include/my_sys.h +++ b/include/my_sys.h @@ -636,6 +636,7 @@ extern FILE *my_fopen(const char *FileName,int Flags,myf MyFlags); extern FILE *my_fdopen(File Filedes,const char *name, int Flags,myf MyFlags); extern FILE *my_freopen(const char *path, const char *mode, FILE *stream); extern int my_fclose(FILE *fd,myf MyFlags); +extern int my_vfprintf(FILE *stream, const char* format, va_list args); extern File my_fileno(FILE *fd); extern int my_chsize(File fd,my_off_t newlength, int filler, myf MyFlags); extern int my_chmod(const char *name, mode_t mode, myf my_flags); diff --git a/include/mysql/plugin.h b/include/mysql/plugin.h index e46bea9f24f..614bb028a0d 100644 --- a/include/mysql/plugin.h +++ b/include/mysql/plugin.h @@ -72,7 +72,7 @@ typedef struct st_mysql_xid MYSQL_XID; #define MYSQL_PLUGIN_INTERFACE_VERSION 0x0103 /* MariaDB plugin interface version */ -#define MARIA_PLUGIN_INTERFACE_VERSION 0x0101 +#define MARIA_PLUGIN_INTERFACE_VERSION 0x0102 /* The allowable types of plugins diff --git a/include/mysql/plugin_audit.h.pp b/include/mysql/plugin_audit.h.pp index cdd9324a5f7..42ad957e556 100644 --- a/include/mysql/plugin_audit.h.pp +++ b/include/mysql/plugin_audit.h.pp @@ -80,6 +80,24 @@ void thd_progress_next_stage(void* thd); void thd_progress_end(void* thd); const char *set_thd_proc_info(void*, const char * info, const char *func, const char *file, unsigned int line); +#include <mysql/service_logger.h> +typedef struct logger_handle_st LOGGER_HANDLE; +extern struct logger_service_st { + LOGGER_HANDLE* (*open)(const char *path, + unsigned long size_limit, + unsigned int rotations); + int (*close)(LOGGER_HANDLE *log); + int (*vprintf)(LOGGER_HANDLE *log, const char *fmt, va_list argptr); + int (*printf)(LOGGER_HANDLE *log, const char *fmt, ...); + int (*rotate)(LOGGER_HANDLE *log); +} *logger_service; + LOGGER_HANDLE *logger_open(const char *path, + unsigned long size_limit, + unsigned int rotations); + int logger_close(LOGGER_HANDLE *log); + int logger_vprintf(LOGGER_HANDLE *log, const char *fmt, va_list argptr); + int logger_rotate(LOGGER_HANDLE *log); + int logger_printf(LOGGER_HANDLE *log, const char *fmt, ...); struct st_mysql_xid { long formatID; long gtrid_length; diff --git a/include/mysql/plugin_auth.h.pp b/include/mysql/plugin_auth.h.pp index e06494746dd..146768f9575 100644 --- a/include/mysql/plugin_auth.h.pp +++ b/include/mysql/plugin_auth.h.pp @@ -80,6 +80,24 @@ void thd_progress_next_stage(void* thd); void thd_progress_end(void* thd); const char *set_thd_proc_info(void*, const char * info, const char *func, const char *file, unsigned int line); +#include <mysql/service_logger.h> +typedef struct logger_handle_st LOGGER_HANDLE; +extern struct logger_service_st { + LOGGER_HANDLE* (*open)(const char *path, + unsigned long size_limit, + unsigned int rotations); + int (*close)(LOGGER_HANDLE *log); + int (*vprintf)(LOGGER_HANDLE *log, const char *fmt, va_list argptr); + int (*printf)(LOGGER_HANDLE *log, const char *fmt, ...); + int (*rotate)(LOGGER_HANDLE *log); +} *logger_service; + LOGGER_HANDLE *logger_open(const char *path, + unsigned long size_limit, + unsigned int rotations); + int logger_close(LOGGER_HANDLE *log); + int logger_vprintf(LOGGER_HANDLE *log, const char *fmt, va_list argptr); + int logger_rotate(LOGGER_HANDLE *log); + int logger_printf(LOGGER_HANDLE *log, const char *fmt, ...); struct st_mysql_xid { long formatID; long gtrid_length; diff --git a/include/mysql/plugin_ftparser.h.pp b/include/mysql/plugin_ftparser.h.pp index a990c62e8e9..59afe4276b4 100644 --- a/include/mysql/plugin_ftparser.h.pp +++ b/include/mysql/plugin_ftparser.h.pp @@ -80,6 +80,24 @@ void thd_progress_next_stage(void* thd); void thd_progress_end(void* thd); const char *set_thd_proc_info(void*, const char * info, const char *func, const char *file, unsigned int line); +#include <mysql/service_logger.h> +typedef struct logger_handle_st LOGGER_HANDLE; +extern struct logger_service_st { + LOGGER_HANDLE* (*open)(const char *path, + unsigned long size_limit, + unsigned int rotations); + int (*close)(LOGGER_HANDLE *log); + int (*vprintf)(LOGGER_HANDLE *log, const char *fmt, va_list argptr); + int (*printf)(LOGGER_HANDLE *log, const char *fmt, ...); + int (*rotate)(LOGGER_HANDLE *log); +} *logger_service; + LOGGER_HANDLE *logger_open(const char *path, + unsigned long size_limit, + unsigned int rotations); + int logger_close(LOGGER_HANDLE *log); + int logger_vprintf(LOGGER_HANDLE *log, const char *fmt, va_list argptr); + int logger_rotate(LOGGER_HANDLE *log); + int logger_printf(LOGGER_HANDLE *log, const char *fmt, ...); struct st_mysql_xid { long formatID; long gtrid_length; diff --git a/include/mysql/service_logger.h b/include/mysql/service_logger.h new file mode 100644 index 00000000000..315c382791e --- /dev/null +++ b/include/mysql/service_logger.h @@ -0,0 +1,98 @@ +/* Copyright (C) 2012 Monty Program Ab + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + +#ifndef MYSQL_SERVICE_LOGGER_INCLUDED +#define MYSQL_SERVICE_LOGGER_INCLUDED + +#ifndef MYSQL_ABI_CHECK +#include <stdarg.h> +#endif + +/** + @file + logger service + + Log file with rotation implementation. + + This service implements logging with possible rotation + of the log files. Interface intentionally tries to be similar to FILE* + related functions. + + So that one can open the log with logger_open(), specifying + the limit on the logfile size and the rotations number. + + Then it's possible to write messages to the log with + logger_printf or logger_vprintf functions. + + As the size of the logfile grows over the specified limit, + it is renamed to 'logfile.1'. The former 'logfile.1' becomes + 'logfile.2', etc. The file 'logfile.rotations' is removed. + That's how the rotation works. + + The rotation can be forced with the logger_rotate() call. + + Finally the log should be closed with logger_close(). + +@notes: + Implementation checks the size of the log file before it starts new + printf into it. So the size of the file gets over the limit when it rotates. + + The access is secured with the mutex, so the log is threadsafe. +*/ + + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct logger_handle_st LOGGER_HANDLE; + +extern struct logger_service_st { + LOGGER_HANDLE* (*open)(const char *path, + unsigned long size_limit, + unsigned int rotations); + int (*close)(LOGGER_HANDLE *log); + int (*vprintf)(LOGGER_HANDLE *log, const char *fmt, va_list argptr); + int (*printf)(LOGGER_HANDLE *log, const char *fmt, ...); + int (*rotate)(LOGGER_HANDLE *log); +} *logger_service; + +#ifdef MYSQL_DYNAMIC_PLUGIN + +#define logger_open(path, size_limit, rotations) \ + (logger_service->open(path, size_limit, rotations)) +#define logger_close(log) (logger_service->close(log)) +#define logger_rotate(log) (logger_service->rotate(log)) +#define logger_vprintf(log, fmt, argptr) (logger_service->\ + vprintf(log, fmt, argptr)) +#define logger_printf logger_service->printf +#else + + LOGGER_HANDLE *logger_open(const char *path, + unsigned long size_limit, + unsigned int rotations); + int logger_close(LOGGER_HANDLE *log); + int logger_vprintf(LOGGER_HANDLE *log, const char *fmt, va_list argptr); + int logger_rotate(LOGGER_HANDLE *log); + int logger_printf(LOGGER_HANDLE *log, const char *fmt, ...); +#endif + + +#ifdef __cplusplus +} +#endif + +#endif /*MYSQL_SERVICE_LOGGER_INCLUDED*/ + diff --git a/include/mysql/services.h b/include/mysql/services.h index eca0e88c8da..258f7b90658 100644 --- a/include/mysql/services.h +++ b/include/mysql/services.h @@ -23,6 +23,8 @@ extern "C" { #include <mysql/service_thd_wait.h> #include <mysql/service_thread_scheduler.h> #include <mysql/service_progress_report.h> +#include <mysql/service_logger.h> + #ifdef __cplusplus } diff --git a/include/service_versions.h b/include/service_versions.h index ee50d4856e9..8a397d71b12 100644 --- a/include/service_versions.h +++ b/include/service_versions.h @@ -24,3 +24,4 @@ #define VERSION_thd_wait 0x0100 #define VERSION_my_thread_scheduler 0x0100 #define VERSION_progress_report 0x0100 +#define VERSION_logger 0x0100 diff --git a/libservices/CMakeLists.txt b/libservices/CMakeLists.txt index ee6a7c73abe..dd16558ef9c 100644 --- a/libservices/CMakeLists.txt +++ b/libservices/CMakeLists.txt @@ -20,7 +20,8 @@ SET(MYSQLSERVICES_SOURCES thd_alloc_service.c thd_wait_service.c my_thread_scheduler_service.c - progress_report_service.c) + progress_report_service.c + logger_service.c) ADD_CONVENIENCE_LIBRARY(mysqlservices ${MYSQLSERVICES_SOURCES}) INSTALL(TARGETS mysqlservices DESTINATION ${INSTALL_LIBDIR} COMPONENT Development) diff --git a/libservices/logger_service.c b/libservices/logger_service.c new file mode 100644 index 00000000000..896b0714293 --- /dev/null +++ b/libservices/logger_service.c @@ -0,0 +1,20 @@ +/* Copyright (C) 2012 Monty Program Ab + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + +#include <service_versions.h> + + +SERVICE_VERSION *logger_service= (void *) VERSION_logger; + diff --git a/mysys/CMakeLists.txt b/mysys/CMakeLists.txt index 7397990eddb..5204f7e873c 100644 --- a/mysys/CMakeLists.txt +++ b/mysys/CMakeLists.txt @@ -37,7 +37,7 @@ SET(MYSYS_SOURCES array.c charset-def.c charset.c checksum.c default.c safemalloc.c my_new.cc my_atomic.c my_getncpus.c my_safehash.c my_chmod.c my_rnd.c my_uuid.c wqueue.c waiting_threads.c ma_dyncol.c - my_rdtsc.c my_context.c) + my_rdtsc.c my_context.c my_logger.c) IF (WIN32) SET (MYSYS_SOURCES ${MYSYS_SOURCES} my_winthread.c my_wincond.c my_winerr.c my_winfile.c my_windac.c my_conio.c) diff --git a/mysys/my_logger.c b/mysys/my_logger.c new file mode 100644 index 00000000000..292c98f4ad1 --- /dev/null +++ b/mysys/my_logger.c @@ -0,0 +1,168 @@ +/* Copyright (C) 2012 Monty Program Ab + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + + +#include "my_global.h" +#include <my_sys.h> +#include <mysql/service_logger.h> + +extern char *mysql_data_home; +extern PSI_mutex_key key_LOCK_logger_service; + +typedef struct logger_handle_st { + FILE *file; + char path[FN_REFLEN]; + long size_limit; + unsigned int rotations; + size_t path_len; + mysql_mutex_t lock; +} LSFS; + + +static unsigned int n_dig(unsigned int i) +{ + return (i == 0) ? 0 : ((i < 10) ? 1 : ((i < 100) ? 2 : 3)); +} + + +LOGGER_HANDLE *logger_open(const char *path, + unsigned long size_limit, + unsigned int rotations) +{ + LOGGER_HANDLE new_log, *l_perm; + + /* + I don't think we ever need more rotations, + but if it's so, the rotation procedure should be adapted to it. + */ + if (rotations > 999) + return 0; + + new_log.rotations= rotations; + new_log.size_limit= size_limit; + new_log.path_len= strlen(fn_format(new_log.path, path, + mysql_data_home, "", MY_UNPACK_FILENAME)); + + if (new_log.path_len+n_dig(rotations)+1 > FN_REFLEN) + { + errno= ENAMETOOLONG; + /* File path too long */ + return 0; + } + if (!(new_log.file= fopen(new_log.path, "a+"))) + { + /* Check errno for the cause */ + return 0; + } + + setbuf(new_log.file, 0); + fseek(new_log.file, 0, SEEK_END); + if (!(l_perm= (LOGGER_HANDLE *) + my_malloc(sizeof(LOGGER_HANDLE), MYF(0)))) + { + fclose(new_log.file); + new_log.file= NULL; + return 0; /* End of memory */ + } + *l_perm= new_log; + mysql_mutex_init(key_LOCK_logger_service, &l_perm->lock, MY_MUTEX_INIT_FAST); + return l_perm; +} + +int logger_close(LOGGER_HANDLE *log) +{ + int result; + mysql_mutex_destroy(&log->lock); + result= fclose(log->file); + my_free(log); + return result; +} + + +static char *logname(LOGGER_HANDLE *log, char *buf, unsigned int n_log) +{ + sprintf(buf+log->path_len, ".%0*u", n_dig(log->rotations), n_log); + return buf; +} + + +static int do_rotate(LOGGER_HANDLE *log) +{ + char namebuf[FN_REFLEN]; + int result; + unsigned int i; + char *buf_old, *buf_new, *tmp; + + memcpy(namebuf, log->path, log->path_len); + + buf_new= logname(log, namebuf, log->rotations); + buf_old= log->path; + for (i=log->rotations-1; i>0; i--) + { + logname(log, buf_old, i); + if (!access(buf_old, F_OK) && + (result= my_rename(buf_old, buf_new, MYF(0)))) + return result; + tmp= buf_old; + buf_old= buf_new; + buf_new= tmp; + } + if ((result= fclose(log->file))) + return result; + namebuf[log->path_len]= 0; + result= my_rename(namebuf, logname(log, log->path, 1), MYF(0)); + log->file= fopen(namebuf, "a+"); + return log->file==NULL || result; +} + + +int logger_vprintf(LOGGER_HANDLE *log, const char* fmt, va_list ap) +{ + int result; + mysql_mutex_lock(&log->lock); + if (ftell(log->file) >= log->size_limit && + do_rotate(log)) + { + result= -1; + goto exit; /* Log rotation needed but failed */ + } + + result= my_vfprintf(log->file, fmt, ap); +exit: + mysql_mutex_unlock(&log->lock); + return result; +} + + +int logger_rotate(LOGGER_HANDLE *log) +{ + int result; + mysql_mutex_lock(&log->lock); + result= do_rotate(log); + mysql_mutex_unlock(&log->lock); + return result; +} + + +int logger_printf(LOGGER_HANDLE *log, const char *fmt, ...) +{ + int result; + va_list args; + va_start(args,fmt); + result= logger_vprintf(log, fmt, args); + va_end(args); + return result; +} + diff --git a/plugin/sql_errlog/CMakeLists.txt b/plugin/sql_errlog/CMakeLists.txt new file mode 100644 index 00000000000..18fb9f5421d --- /dev/null +++ b/plugin/sql_errlog/CMakeLists.txt @@ -0,0 +1,16 @@ +# Copyright (C) 2012 Monty Program Ab. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; version 2 of the License. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +MYSQL_ADD_PLUGIN(sql_errlog sql_errlog.c MODULE_ONLY) diff --git a/plugin/sql_errlog/sql_errlog.c b/plugin/sql_errlog/sql_errlog.c new file mode 100644 index 00000000000..53d804feeb3 --- /dev/null +++ b/plugin/sql_errlog/sql_errlog.c @@ -0,0 +1,147 @@ +/* Copyright (C) 2012 Monty Program Ab. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + +#include <mysql/plugin_audit.h> +#include <stdio.h> +#include <time.h> + +/* + rate 0 means the logging was disabled. +*/ + +static char *filename; +static unsigned int rate; +static unsigned int size_limit; +static unsigned int rotations; +static char rotate; + +static unsigned int count; +LOGGER_HANDLE *logfile; + +static void rotate_log(MYSQL_THD thd, struct st_mysql_sys_var *var, + void *var_ptr, const void *save); + +static MYSQL_SYSVAR_UINT(rate, rate, PLUGIN_VAR_RQCMDARG, + "Sampling rate. If set to 0(zero), the logging is disabled.", NULL, NULL, + 1, 0, 1000000, 1); + +static MYSQL_SYSVAR_UINT(size_limit, size_limit, + PLUGIN_VAR_READONLY, "Log file size limit", NULL, NULL, + 1000000, 100, 1024*1024L*1024L, 1); + +static MYSQL_SYSVAR_UINT(rotations, rotations, + PLUGIN_VAR_READONLY, "Number of rotations before log is removed.", + NULL, NULL, 9, 1, 999, 1); + +static MYSQL_SYSVAR_BOOL(rotate, rotate, + PLUGIN_VAR_OPCMDARG, "Force log rotation", NULL, rotate_log, + 0); + +static MYSQL_SYSVAR_STR(filename, filename, + PLUGIN_VAR_READONLY | PLUGIN_VAR_RQCMDARG, + "The file to log sql errors to", NULL, NULL, + "sql_errors.log"); + +static struct st_mysql_sys_var* vars[] = { + MYSQL_SYSVAR(rate), + MYSQL_SYSVAR(size_limit), + MYSQL_SYSVAR(rotations), + MYSQL_SYSVAR(rotate), + MYSQL_SYSVAR(filename), + NULL +}; + + +static void log_sql_errors(MYSQL_THD thd __attribute__((unused)), + unsigned int event_class __attribute__((unused)), + const void *ev) +{ + const struct mysql_event_general *event = + (const struct mysql_event_general*)ev; + if (rate && + event->event_subclass == MYSQL_AUDIT_GENERAL_ERROR) + { + if (++count >= rate) + { + struct tm t; + time_t event_time = event->general_time; + + count = 0; + localtime_r(&event_time, &t); + logger_printf(logfile, "%04d-%02d-%02d %2d:%02d:%02d " + "%s ERROR %d: %s : %s\n", + t.tm_year + 1900, t.tm_mon + 1, + t.tm_mday, t.tm_hour, t.tm_min, t.tm_sec, + event->general_user, event->general_error_code, + event->general_command, event->general_query); + } + } +} + + +static int sql_error_log_init(void *p __attribute__((unused))) +{ + logfile= logger_open(filename, size_limit, rotations); + if (logfile == NULL) { + fprintf(stderr, "Could not create file '%s'\n", + filename); + return 1; + } + count = 0; + return 0; +} + + +static int sql_error_log_deinit(void *p __attribute__((unused))) +{ + logger_close(logfile); + return 0; +} + + +static void rotate_log(MYSQL_THD thd __attribute__((unused)), + struct st_mysql_sys_var *var __attribute__((unused)), + void *var_ptr __attribute__((unused)), + const void *save __attribute__((unused))) +{ + (void) logger_rotate(logfile); +} + + +static struct st_mysql_audit descriptor = +{ + MYSQL_AUDIT_INTERFACE_VERSION, + NULL, + log_sql_errors, + { MYSQL_AUDIT_GENERAL_CLASSMASK } +}; + +maria_declare_plugin(sql_errlog) +{ + MYSQL_AUDIT_PLUGIN, + &descriptor, + "SQL_ERROR_LOG", + "Alexey Botchkov", + "Log SQL level errors to a file with rotation", + PLUGIN_LICENSE_GPL, + sql_error_log_init, + sql_error_log_deinit, + 0x0100, + NULL, + vars, + "1.0", + MariaDB_PLUGIN_MATURITY_ALPHA +} +maria_declare_plugin_end; diff --git a/sql/mysqld.cc b/sql/mysqld.cc index 36b6897c56d..7394ce5c931 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -748,6 +748,7 @@ PSI_mutex_key key_LOCK_stats, key_LOCK_wakeup_ready; PSI_mutex_key key_LOCK_prepare_ordered, key_LOCK_commit_ordered; +PSI_mutex_key key_LOCK_logger_service; static PSI_mutex_info all_server_mutexes[]= { @@ -807,6 +808,8 @@ static PSI_mutex_info all_server_mutexes[]= { &key_LOCK_commit_ordered, "LOCK_commit_ordered", PSI_FLAG_GLOBAL}, { &key_LOG_INFO_lock, "LOG_INFO::lock", 0}, { &key_LOCK_thread_count, "LOCK_thread_count", PSI_FLAG_GLOBAL}, + { &key_LOCK_logger_service, "logger_service_file_st::lock", + PSI_FLAG_GLOBAL}, { &key_PARTITION_LOCK_auto_inc, "HA_DATA_PARTITION::LOCK_auto_inc", 0} }; diff --git a/sql/sql_plugin_services.h b/sql/sql_plugin_services.h index 7f2a4e5f955..bd6d136585a 100644 --- a/sql/sql_plugin_services.h +++ b/sql/sql_plugin_services.h @@ -54,12 +54,21 @@ static struct progress_report_service_st progress_report_handler= { set_thd_proc_info }; +static struct logger_service_st logger_handler= { + logger_open, + logger_close, + logger_vprintf, + logger_printf, + logger_rotate +}; + static struct st_service_ref list_of_services[]= { { "my_snprintf_service", VERSION_my_snprintf, &my_snprintf_handler }, { "thd_alloc_service", VERSION_thd_alloc, &thd_alloc_handler }, { "thd_wait_service", VERSION_thd_wait, &thd_wait_handler }, { "my_thread_scheduler_service", VERSION_my_thread_scheduler, &my_thread_scheduler_handler }, - { "progress_report_service", VERSION_progress_report, &progress_report_handler } + { "progress_report_service", VERSION_progress_report, &progress_report_handler }, + { "logger_service", VERSION_logger, &logger_handler }, }; diff --git a/strings/my_vsnprintf.c b/strings/my_vsnprintf.c index 8d8c078849c..64c37ca0537 100644 --- a/strings/my_vsnprintf.c +++ b/strings/my_vsnprintf.c @@ -678,3 +678,22 @@ size_t my_snprintf(char* to, size_t n, const char* fmt, ...) va_end(args); return result; } + + +/** + Writes output to the stream according to a format string. + + @param stream file to write to + @param format string format + @param args list of parameters + + @retval + number of the characters written. +*/ + +int my_vfprintf(FILE *stream, const char* format, va_list args) +{ + char cvtbuf[1024]; + (void) my_vsnprintf(cvtbuf, sizeof(cvtbuf), format, args); + return fprintf(stream, "%s\n", cvtbuf); +} |