Patch for - Allow server logs to be remotely read - Mailing list pgsql-patches

From Dhanaraj M
Subject Patch for - Allow server logs to be remotely read
Date
Msg-id 448824F8.50706@sun.com
Whole thread Raw
Responses Re: Patch for - Allow server logs to be remotely read
List pgsql-patches
The patch is attached for the following TODO item:

*Allow server logs to be remotely read.


Steps:

1. When the server starts (**pg_ctl start)**, the path of the postmaster file is stored
2. The user can access the logfile using the following 2 functions:
   * pg_file_readlog(int linenumber) -  Retrieves the string for the given line number
   * **pg_file_countlog() -  Retrieves the number of lines existing in the logfile*



I have implemented this based on the suggestions given in the hackers mailing list.
If you know a better way, please share it with me. Waiting for your reply.


Thanks
Dhanaraj

*** ./contrib/adminpack/adminpack.c.orig    Thu Jun  8 17:04:42 2006
--- ./contrib/adminpack/adminpack.c    Thu Jun  8 18:34:37 2006
***************
*** 24,30 ****
--- 24,32 ----
  #include "catalog/pg_type.h"
  #include "funcapi.h"
  #include "utils/datetime.h"
+ #include "utils/builtins.h"

+ #define GET_TEXT(cstrp) DatumGetTextP(DirectFunctionCall1(textin, CStringGetDatum(cstrp)))

  #ifdef WIN32

***************
*** 48,58 ****
--- 50,64 ----
  Datum pg_file_rename(PG_FUNCTION_ARGS);
  Datum pg_file_unlink(PG_FUNCTION_ARGS);
  Datum pg_logdir_ls(PG_FUNCTION_ARGS);
+ Datum pg_file_readlog(PG_FUNCTION_ARGS);
+ Datum pg_file_countlog();

  PG_FUNCTION_INFO_V1(pg_file_write);
  PG_FUNCTION_INFO_V1(pg_file_rename);
  PG_FUNCTION_INFO_V1(pg_file_unlink);
  PG_FUNCTION_INFO_V1(pg_logdir_ls);
+ PG_FUNCTION_INFO_V1(pg_file_readlog);
+ PG_FUNCTION_INFO_V1(pg_file_countlog);

  typedef struct
  {
***************
*** 390,392 ****
--- 396,520 ----
      FreeDir(fctx->dirdesc);
      SRF_RETURN_DONE(funcctx);
  }
+
+ /* Retrieves n-th line from the postmaster logfile */
+
+ Datum pg_file_readlog(PG_FUNCTION_ARGS)
+ {
+     char c, buffer[MAXPGPATH];
+     char file_path2[MAXPGPATH], file_path1[MAXPGPATH];
+     int64 linenumber = PG_GETARG_INT64(0);
+     FILE *filePtr1, *filePtr2;
+     int64 count=1;
+         int index=0;
+
+     if(OutputFileName[0])
+     {
+        filePtr1 = fopen(OutputFileName, "r");
+     }
+     else
+     {
+        /* Finds the logfile path from postmasterlog_path file */
+        snprintf(file_path1, MAXPGPATH, "%s/postmasterlog_path", DataDir);
+        filePtr2 = fopen(file_path1, "r");
+        if(filePtr2 != NULL)
+        {
+          memset(file_path2, 0, MAXPGPATH);
+              fread(file_path2, 1, MAXPGPATH, filePtr2);
+        }
+        else
+        {
+          snprintf(buffer, MAXPGPATH, "Could not find the logfile path in: %s", file_path1);
+          ereport(ERROR, (errcode_for_file_access(), errmsg(buffer)));
+        }
+
+        fclose(filePtr2);
+        filePtr1 = fopen(file_path2, "r");
+     }
+
+      memset(buffer, 0, MAXPGPATH);
+
+     if(filePtr1 == NULL)
+     {
+        snprintf(buffer, MAXPGPATH, "Logfile: %s - Not found", file_path2);
+        ereport(ERROR, (errcode_for_file_access(), errmsg(buffer)));
+     }
+
+     /* Reads the logfile and extract n-th line */
+     while( (c= fgetc(filePtr1))!=EOF)
+     {
+        if (linenumber == count)
+        {
+           buffer[index] = c;
+           index++;
+        }
+
+        /* Counts the number of lines */
+        if(c=='\n')
+            {
+             count++;
+        }
+      }
+
+     if(count <= linenumber)
+     {
+        sprintf(buffer, "Given line number does not exist");
+        ereport(ERROR, (errcode_for_file_access(), errmsg(buffer)));
+     }
+
+         fclose(filePtr1);
+         PG_RETURN_TEXT_P(GET_TEXT(buffer));
+ }
+
+ /* Counts the number of lines in the postmaster logfile */
+
+ Datum pg_file_countlog()
+ {
+     char c, buffer[MAXPGPATH];
+     char file_path2[MAXPGPATH], file_path1[MAXPGPATH];
+     FILE *filePtr1, *filePtr2;
+     int64 count=1;
+
+     if(OutputFileName[0])
+     {
+        filePtr1 = fopen(OutputFileName, "r");
+     }
+     else
+     {
+        /* Finds the logfile path from postmasterlog_path file */
+        snprintf(file_path1, MAXPGPATH, "%s/postmasterlog_path", DataDir);
+        filePtr2 = fopen(file_path1, "r");
+        if(filePtr2 != NULL)
+        {
+          memset(file_path2, 0, MAXPGPATH);
+              fread(file_path2, 1, MAXPGPATH, filePtr2);
+        }
+        else
+        {
+          snprintf(buffer, MAXPGPATH, "Could not find the logfile path in: %s", file_path1);
+          ereport(ERROR, (errcode_for_file_access(), errmsg(buffer)));
+        }
+
+        fclose(filePtr2);
+        filePtr1 = fopen(file_path2, "r");
+     }
+
+      memset(buffer, 0, MAXPGPATH);
+
+     if(filePtr1== NULL)
+     {
+        snprintf(buffer, MAXPGPATH, "Logfile: %s - Not found", file_path2);
+        ereport(ERROR, (errcode_for_file_access(), errmsg(buffer)));
+     }
+
+         /* Counts the number of lines */
+     while( (c= fgetc(filePtr1))!=EOF)
+     {
+        if(c=='\n')
+             count++;
+     }
+
+         fclose(filePtr1);
+     PG_RETURN_INT64(count-1);
+ }
+
*** ./contrib/adminpack/adminpack.sql.in.orig    Thu Jun  8 17:05:16 2006
--- ./contrib/adminpack/adminpack.sql.in    Thu Jun  8 17:06:11 2006
***************
*** 24,30 ****
--- 24,37 ----
     AS 'MODULE_PATHNAME', 'pg_logdir_ls'
      LANGUAGE C VOLATILE STRICT;

+ CREATE FUNCTION pg_catalog.pg_file_readlog(bigint) RETURNS text
+    AS 'MODULE_PATHNAME', 'pg_file_readlog'
+     LANGUAGE C VOLATILE STRICT;

+ CREATE FUNCTION pg_catalog.pg_file_countlog() RETURNS bigint
+    AS 'MODULE_PATHNAME', 'pg_file_countlog'
+     LANGUAGE C VOLATILE STRICT;
+
  /* compatibility redefines */

  CREATE FUNCTION pg_catalog.pg_logfile_rotate() RETURNS int4
*** ./src/bin/pg_ctl/pg_ctl.c.orig    Thu Jun  8 16:47:20 2006
--- ./src/bin/pg_ctl/pg_ctl.c    Thu Jun  8 17:32:48 2006
***************
*** 1719,1724 ****
--- 1719,1752 ----
          snprintf(conf_file, MAXPGPATH, "%s/postgresql.conf", pg_data);
      }

+     /* Store the postmaster logfile name in postmasterlog_path file */
+
+     if( (ctl_command == START_COMMAND) || (ctl_command == RESTART_COMMAND) || (ctl_command == RELOAD_COMMAND))
+     {
+     FILE *filePtr;
+     char file_path[MAXPGPATH];
+         char *cwd;
+
+         snprintf(file_path, MAXPGPATH, "%s/postmasterlog_path", pg_data);
+     filePtr = fopen(file_path, "w+");
+
+     if(log_file[0] == '/')
+     {
+         fprintf(filePtr,"%s", log_file);
+     }
+     else
+     {
+         /* Append the current path string with the logfile name */
+         if ((cwd = getcwd(NULL, 64)) != NULL)
+         {
+          fprintf(filePtr, "%s/%s", cwd, log_file);
+              free(cwd);
+         }
+     }
+     fclose(filePtr);
+      }
+
+
      switch (ctl_command)
      {
          case STATUS_COMMAND:

pgsql-patches by date:

Previous
From: Robert Treat
Date:
Subject: update link / fix spelling error
Next
From: Andrew Dunstan
Date:
Subject: Re: [HACKERS] drop if exists remainder