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
This commit is contained in:
parent
92f31d8070
commit
07a82c58a7
@ -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_fdopen(File Filedes,const char *name, int Flags,myf MyFlags);
|
||||||
extern FILE *my_freopen(const char *path, const char *mode, FILE *stream);
|
extern FILE *my_freopen(const char *path, const char *mode, FILE *stream);
|
||||||
extern int my_fclose(FILE *fd,myf MyFlags);
|
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 File my_fileno(FILE *fd);
|
||||||
extern int my_chsize(File fd,my_off_t newlength, int filler, myf MyFlags);
|
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);
|
extern int my_chmod(const char *name, mode_t mode, myf my_flags);
|
||||||
|
@ -72,7 +72,7 @@ typedef struct st_mysql_xid MYSQL_XID;
|
|||||||
#define MYSQL_PLUGIN_INTERFACE_VERSION 0x0103
|
#define MYSQL_PLUGIN_INTERFACE_VERSION 0x0103
|
||||||
|
|
||||||
/* MariaDB plugin interface version */
|
/* MariaDB plugin interface version */
|
||||||
#define MARIA_PLUGIN_INTERFACE_VERSION 0x0101
|
#define MARIA_PLUGIN_INTERFACE_VERSION 0x0102
|
||||||
|
|
||||||
/*
|
/*
|
||||||
The allowable types of plugins
|
The allowable types of plugins
|
||||||
|
@ -80,6 +80,24 @@ void thd_progress_next_stage(void* thd);
|
|||||||
void thd_progress_end(void* thd);
|
void thd_progress_end(void* thd);
|
||||||
const char *set_thd_proc_info(void*, const char * info, const char *func,
|
const char *set_thd_proc_info(void*, const char * info, const char *func,
|
||||||
const char *file, unsigned int line);
|
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 {
|
struct st_mysql_xid {
|
||||||
long formatID;
|
long formatID;
|
||||||
long gtrid_length;
|
long gtrid_length;
|
||||||
|
@ -80,6 +80,24 @@ void thd_progress_next_stage(void* thd);
|
|||||||
void thd_progress_end(void* thd);
|
void thd_progress_end(void* thd);
|
||||||
const char *set_thd_proc_info(void*, const char * info, const char *func,
|
const char *set_thd_proc_info(void*, const char * info, const char *func,
|
||||||
const char *file, unsigned int line);
|
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 {
|
struct st_mysql_xid {
|
||||||
long formatID;
|
long formatID;
|
||||||
long gtrid_length;
|
long gtrid_length;
|
||||||
|
@ -80,6 +80,24 @@ void thd_progress_next_stage(void* thd);
|
|||||||
void thd_progress_end(void* thd);
|
void thd_progress_end(void* thd);
|
||||||
const char *set_thd_proc_info(void*, const char * info, const char *func,
|
const char *set_thd_proc_info(void*, const char * info, const char *func,
|
||||||
const char *file, unsigned int line);
|
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 {
|
struct st_mysql_xid {
|
||||||
long formatID;
|
long formatID;
|
||||||
long gtrid_length;
|
long gtrid_length;
|
||||||
|
98
include/mysql/service_logger.h
Normal file
98
include/mysql/service_logger.h
Normal file
@ -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*/
|
||||||
|
|
@ -23,6 +23,8 @@ extern "C" {
|
|||||||
#include <mysql/service_thd_wait.h>
|
#include <mysql/service_thd_wait.h>
|
||||||
#include <mysql/service_thread_scheduler.h>
|
#include <mysql/service_thread_scheduler.h>
|
||||||
#include <mysql/service_progress_report.h>
|
#include <mysql/service_progress_report.h>
|
||||||
|
#include <mysql/service_logger.h>
|
||||||
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
@ -24,3 +24,4 @@
|
|||||||
#define VERSION_thd_wait 0x0100
|
#define VERSION_thd_wait 0x0100
|
||||||
#define VERSION_my_thread_scheduler 0x0100
|
#define VERSION_my_thread_scheduler 0x0100
|
||||||
#define VERSION_progress_report 0x0100
|
#define VERSION_progress_report 0x0100
|
||||||
|
#define VERSION_logger 0x0100
|
||||||
|
@ -20,7 +20,8 @@ SET(MYSQLSERVICES_SOURCES
|
|||||||
thd_alloc_service.c
|
thd_alloc_service.c
|
||||||
thd_wait_service.c
|
thd_wait_service.c
|
||||||
my_thread_scheduler_service.c
|
my_thread_scheduler_service.c
|
||||||
progress_report_service.c)
|
progress_report_service.c
|
||||||
|
logger_service.c)
|
||||||
|
|
||||||
ADD_CONVENIENCE_LIBRARY(mysqlservices ${MYSQLSERVICES_SOURCES})
|
ADD_CONVENIENCE_LIBRARY(mysqlservices ${MYSQLSERVICES_SOURCES})
|
||||||
INSTALL(TARGETS mysqlservices DESTINATION ${INSTALL_LIBDIR} COMPONENT Development)
|
INSTALL(TARGETS mysqlservices DESTINATION ${INSTALL_LIBDIR} COMPONENT Development)
|
||||||
|
20
libservices/logger_service.c
Normal file
20
libservices/logger_service.c
Normal file
@ -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;
|
||||||
|
|
@ -37,7 +37,7 @@ SET(MYSYS_SOURCES array.c charset-def.c charset.c checksum.c default.c
|
|||||||
safemalloc.c my_new.cc
|
safemalloc.c my_new.cc
|
||||||
my_atomic.c my_getncpus.c my_safehash.c my_chmod.c my_rnd.c
|
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_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)
|
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)
|
SET (MYSYS_SOURCES ${MYSYS_SOURCES} my_winthread.c my_wincond.c my_winerr.c my_winfile.c my_windac.c my_conio.c)
|
||||||
|
168
mysys/my_logger.c
Normal file
168
mysys/my_logger.c
Normal file
@ -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;
|
||||||
|
}
|
||||||
|
|
16
plugin/sql_errlog/CMakeLists.txt
Normal file
16
plugin/sql_errlog/CMakeLists.txt
Normal file
@ -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)
|
147
plugin/sql_errlog/sql_errlog.c
Normal file
147
plugin/sql_errlog/sql_errlog.c
Normal file
@ -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;
|
@ -748,6 +748,7 @@ PSI_mutex_key key_LOCK_stats,
|
|||||||
key_LOCK_wakeup_ready;
|
key_LOCK_wakeup_ready;
|
||||||
|
|
||||||
PSI_mutex_key key_LOCK_prepare_ordered, key_LOCK_commit_ordered;
|
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[]=
|
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_LOCK_commit_ordered, "LOCK_commit_ordered", PSI_FLAG_GLOBAL},
|
||||||
{ &key_LOG_INFO_lock, "LOG_INFO::lock", 0},
|
{ &key_LOG_INFO_lock, "LOG_INFO::lock", 0},
|
||||||
{ &key_LOCK_thread_count, "LOCK_thread_count", PSI_FLAG_GLOBAL},
|
{ &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}
|
{ &key_PARTITION_LOCK_auto_inc, "HA_DATA_PARTITION::LOCK_auto_inc", 0}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -54,12 +54,21 @@ static struct progress_report_service_st progress_report_handler= {
|
|||||||
set_thd_proc_info
|
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[]=
|
static struct st_service_ref list_of_services[]=
|
||||||
{
|
{
|
||||||
{ "my_snprintf_service", VERSION_my_snprintf, &my_snprintf_handler },
|
{ "my_snprintf_service", VERSION_my_snprintf, &my_snprintf_handler },
|
||||||
{ "thd_alloc_service", VERSION_thd_alloc, &thd_alloc_handler },
|
{ "thd_alloc_service", VERSION_thd_alloc, &thd_alloc_handler },
|
||||||
{ "thd_wait_service", VERSION_thd_wait, &thd_wait_handler },
|
{ "thd_wait_service", VERSION_thd_wait, &thd_wait_handler },
|
||||||
{ "my_thread_scheduler_service", VERSION_my_thread_scheduler, &my_thread_scheduler_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 },
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -678,3 +678,22 @@ size_t my_snprintf(char* to, size_t n, const char* fmt, ...)
|
|||||||
va_end(args);
|
va_end(args);
|
||||||
return result;
|
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);
|
||||||
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user