1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158
|
/*-------------------------------------------------------------------------
*
* logtofile.c
* Main entry point for logtofile
*
* Copyright (c) 2020-2026, Francisco Miguel Biete Banon
*
* This code is released under the PostgreSQL licence, as given at
* http://www.postgresql.org/about/licence/
*-------------------------------------------------------------------------
*/
#include "logtofile.h"
#include "logtofile_bgw.h"
#include "logtofile_connect.h"
#include "logtofile_guc.h"
#include "logtofile_log.h"
#include "logtofile_shmem.h"
#include "logtofile_vars.h"
#include <postgres.h>
/* these are always necessary for a bgworker */
#include <miscadmin.h>
#include <postmaster/bgworker.h>
#include <storage/ipc.h>
#include <storage/latch.h>
#include <storage/lwlock.h>
#include <storage/proc.h>
#include <storage/shm_mq.h>
#include <storage/shm_toc.h>
#include <storage/shmem.h>
#include <utils/guc.h>
#include <datatype/timestamp.h>
#include <pgstat.h>
/**
* @brief Main entry point for the extension
* @param void
* @return void
*/
void _PG_init(void)
{
BackgroundWorker worker;
if (!process_shared_preload_libraries_in_progress)
{
ereport(ERROR, (
errmsg("pgauditlogtofile can only be loaded via shared_preload_libraries"),
errhint("Add pgauditlogtofile to the shared_preload_libraries configuration variable in postgresql.conf.")));
}
/* guc variables */
DefineCustomStringVariable(
"pgaudit.log_directory",
"Directory where to spool log data", NULL,
&guc_pgaudit_ltf_log_directory,
"log",
PGC_SIGHUP, GUC_NOT_IN_SAMPLE | GUC_SUPERUSER_ONLY,
PgAuditLogToFile_guc_check_directory, NULL, NULL);
DefineCustomStringVariable(
"pgaudit.log_filename",
"Filename with time patterns (up to minutes) where to spool audit data", NULL,
&guc_pgaudit_ltf_log_filename,
"audit-%Y%m%d_%H%M.log",
PGC_SIGHUP, GUC_NOT_IN_SAMPLE | GUC_SUPERUSER_ONLY,
NULL, NULL, NULL);
DefineCustomIntVariable(
"pgaudit.log_file_mode",
"Sets the file permissions for log files", NULL,
&guc_pgaudit_ltf_log_file_mode,
0600, 0000, 0666,
PGC_SIGHUP, GUC_NOT_IN_SAMPLE | GUC_SUPERUSER_ONLY,
NULL, NULL, PgAuditLogToFile_guc_show_file_mode);
DefineCustomIntVariable(
"pgaudit.log_rotation_age",
"Automatic spool file rotation will occur after N minutes", NULL,
&guc_pgaudit_ltf_log_rotation_age,
HOURS_PER_DAY * MINS_PER_HOUR, 1, INT_MAX / SECS_PER_MINUTE,
PGC_SIGHUP, GUC_NOT_IN_SAMPLE | GUC_UNIT_MIN | GUC_SUPERUSER_ONLY,
NULL, NULL, NULL);
DefineCustomBoolVariable(
"pgaudit.log_connections",
"Intercepts log_connections messages", NULL,
&guc_pgaudit_ltf_log_connections,
false,
PGC_SIGHUP, GUC_NOT_IN_SAMPLE | GUC_SUPERUSER_ONLY,
NULL, NULL, NULL);
DefineCustomBoolVariable(
"pgaudit.log_disconnections",
"Intercepts log_disconnections messages", NULL,
&guc_pgaudit_ltf_log_disconnections,
false,
PGC_SIGHUP, GUC_NOT_IN_SAMPLE | GUC_SUPERUSER_ONLY,
NULL, NULL, NULL);
DefineCustomIntVariable(
"pgaudit.log_autoclose_minutes",
"Automatic spool file closure by backend after N minutes of inactivity", NULL,
&guc_pgaudit_ltf_auto_close_minutes,
0, 0, INT_MAX / MINS_PER_HOUR,
PGC_SIGHUP,
GUC_NOT_IN_SAMPLE | GUC_UNIT_MIN | GUC_SUPERUSER_ONLY, NULL, NULL, NULL);
DefineCustomStringVariable(
"pgaudit.log_format",
"Format of the audit data (csv or json)", NULL,
&guc_pgaudit_ltf_log_format,
"csv",
PGC_SIGHUP, GUC_NOT_IN_SAMPLE | GUC_SUPERUSER_ONLY,
PgAuditLogToFile_guc_check_log_format, NULL, NULL);
EmitWarningsOnPlaceholders("pgauditlogtofile");
/* background worker */
MemSet(&worker, 0, sizeof(BackgroundWorker));
worker.bgw_flags = BGWORKER_SHMEM_ACCESS;
worker.bgw_start_time = BgWorkerStart_ConsistentState;
worker.bgw_restart_time = 1;
worker.bgw_main_arg = Int32GetDatum(0);
worker.bgw_notify_pid = 0;
sprintf(worker.bgw_library_name, "pgauditlogtofile");
sprintf(worker.bgw_function_name, "PgAuditLogToFileMain");
snprintf(worker.bgw_name, BGW_MAXLEN, "pgauditlogtofile launcher");
RegisterBackgroundWorker(&worker);
/* backend hooks */
#if (PG_VERSION_NUM >= 150000)
pgaudit_ltf_prev_shmem_request_hook = shmem_request_hook;
shmem_request_hook = PgAuditLogToFile_shmem_request;
#else
RequestAddinShmemSpace(MAXALIGN(sizeof(PgAuditLogToFileShm)));
RequestNamedLWLockTranche("pgauditlogtofile", 1);
#endif
pgaudit_ltf_prev_shmem_startup_hook = shmem_startup_hook;
shmem_startup_hook = PgAuditLogToFile_shmem_startup;
pgaudit_ltf_prev_emit_log_hook = emit_log_hook;
emit_log_hook = PgAuditLogToFile_emit_log;
}
/**
* @brief Extension finalization
* @param void
* @return void
*/
void _PG_fini(void)
{
emit_log_hook = pgaudit_ltf_prev_emit_log_hook;
shmem_startup_hook = pgaudit_ltf_prev_shmem_startup_hook;
}
|