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
|
/*-------------------------------------------------------------------------
*
* logtofile.c
* Main entry point for logtofile
*
* Copyright (c) 2020-2025, 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,
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_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,
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;
}
|