logconfig.pm 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200
  1. package eyelib::logconfig;
  2. use utf8;
  3. use open ":encoding(utf8)";
  4. use strict;
  5. use English;
  6. use FindBin '$Bin';
  7. use lib "/opt/Eye/scripts";
  8. use eyelib::config;
  9. use Data::Dumper;
  10. use Log::Log4perl;
  11. use Fcntl qw(:mode);
  12. use base 'Exporter';
  13. use vars qw(@EXPORT @ISA);
  14. our @ISA = qw(Exporter);
  15. our @EXPORT = qw(
  16. log_init
  17. set_log_permissions
  18. get_logger
  19. log_info
  20. log_error
  21. log_warning
  22. log_verbose
  23. log_session
  24. set_log_level
  25. log_debug
  26. log_die
  27. wrlog
  28. );
  29. BEGIN
  30. {
  31. # === Инициализация ===
  32. sub log_init {
  33. my ($logfile) = @_;
  34. $LOG_FILE = $logfile if $logfile;
  35. my $conf = <<"LOG4PERL";
  36. log4perl.rootLogger = DEBUG, MainLog
  37. log4perl.appender.MainLog = Log::Log4perl::Appender::File
  38. log4perl.appender.MainLog.filename = $LOG_FILE
  39. log4perl.appender.MainLog.mode = append
  40. log4perl.appender.MainLog.umask = 0022
  41. log4perl.appender.MainLog.utf8 = 1
  42. log4perl.appender.MainLog.layout = Log::Log4perl::Layout::PatternLayout
  43. log4perl.appender.MainLog.layout.ConversionPattern = %d{yyyy-MM-dd HH:mm:ss} [%p] [PID:%P] %m%n
  44. log4perl.appender.MainLog.recreate = 1
  45. log4perl.appender.MainLog.Threshold = DEBUG
  46. LOG4PERL
  47. Log::Log4perl::init(\$conf);
  48. # === Устанавливаем права ПОСЛЕ создания файла ===
  49. _set_log_file_permissions();
  50. if (!$log_enable) {
  51. Log::Log4perl->get_logger()->level($Log::Log4perl::OFF);
  52. }
  53. }
  54. # === Установка прав и владельца ===
  55. sub _set_log_file_permissions {
  56. return unless -e $LOG_FILE; # Файл должен существовать
  57. # Если не root — проверяем, что мы владелец
  58. if ($< != 0) {
  59. my $stat = stat($LOG_FILE);
  60. my $file_uid = (stat($LOG_FILE))[4];
  61. if ($file_uid != $<) {
  62. warn "WARNING: Cannot change ownership of $LOG_FILE (not running as root)\n";
  63. return;
  64. }
  65. }
  66. # Владелец и группа
  67. my $uid = getpwnam($log_owner_user);
  68. my $gid = getgrnam($log_owner_group);
  69. # Fallback на root если пользователь не найден
  70. if (!defined $uid) {
  71. warn "WARNING: User '$log_owner_user' not found, using current UID\n";
  72. $uid = $<;
  73. }
  74. if (!defined $gid) {
  75. warn "WARNING: Group '$log_owner_group' not found, using current GID\n";
  76. $gid = $) ;
  77. }
  78. # chown
  79. if (!chown($uid, $gid, $LOG_FILE)) {
  80. warn "WARNING: chown failed for $LOG_FILE: $!\n";
  81. }
  82. # chmod
  83. if (!chmod(oct($log_file_mode), $LOG_FILE)) {
  84. warn "WARNING: chmod failed for $LOG_FILE: $!\n";
  85. }
  86. # Логгируем успех (если уже можно)
  87. my $log = get_logger();
  88. $log->debug("Log file permissions set: uid=$uid, gid=$gid, mode=$log_file_mode") if $debug;
  89. }
  90. # === Публичная функция для смены прав на лету (если нужно) ===
  91. sub set_log_permissions {
  92. my (%opts) = @_;
  93. $log_owner_user = $opts{user} if defined $opts{user};
  94. $log_owner_group = $opts{group} if defined $opts{group};
  95. $log_file_mode = $opts{mode} if defined $opts{mode};
  96. _set_log_file_permissions();
  97. }
  98. # === Конвертер уровней ===
  99. sub _lvl_to_log4perl {
  100. my ($lvl) = @_;
  101. my %map = (
  102. $L_ERROR => 'ERROR',
  103. $L_WARNING => 'WARN',
  104. $L_INFO => 'INFO',
  105. $L_VERBOSE => 'INFO',
  106. $L_DEBUG => 'DEBUG',
  107. );
  108. return $map{$lvl} || 'INFO';
  109. }
  110. # === Логгер ===
  111. sub get_logger {
  112. my ($category) = @_;
  113. return Log::Log4perl->get_logger($category || 'root');
  114. }
  115. # === Обёртки ===
  116. sub log_info { _log_wrapper('info', @_); }
  117. sub log_error { _log_wrapper('error', @_); }
  118. sub log_warning { _log_wrapper('warn', @_); }
  119. sub log_verbose { _log_wrapper('info', @_); }
  120. sub log_session { _log_wrapper('info', "SESSION: $_[0]"); }
  121. sub log_debug {
  122. return unless $log_enable;
  123. _log_wrapper('debug', @_) if ($debug);
  124. }
  125. sub log_die {
  126. _log_wrapper('error', @_);
  127. die ($_[0]);
  128. }
  129. sub _log_wrapper {
  130. return unless $log_enable;
  131. my ($method, @msgs) = @_;
  132. my $log = get_logger();
  133. for my $msg (@msgs) {
  134. next unless defined $msg && length $msg;
  135. for my $line (split /\n/, $msg) {
  136. next unless length $line;
  137. $log->$method($line);
  138. }
  139. }
  140. }
  141. # === Динамическая смена уровня логирования ===
  142. sub set_log_level {
  143. my ($new_level) = @_;
  144. $log_level = $new_level;
  145. my $l4p_level = _lvl_to_log4perl($new_level);
  146. my %level_map = (
  147. 'ERROR' => $Log::Log4perl::ERROR,
  148. 'WARN' => $Log::Log4perl::WARN,
  149. 'INFO' => $Log::Log4perl::INFO,
  150. 'DEBUG' => $Log::Log4perl::DEBUG,
  151. 'TRACE' => $Log::Log4perl::TRACE,
  152. 'OFF' => $Log::Log4perl::OFF,
  153. );
  154. my $numeric_level = $level_map{$l4p_level} || $Log::Log4perl::INFO;
  155. my $logger = Log::Log4perl->get_logger();
  156. $logger->level($numeric_level);
  157. my $appender = Log::Log4perl->appender_by_name('MainLog');
  158. if ($appender) {
  159. $appender->threshold($numeric_level);
  160. }
  161. }
  162. sub wrlog {
  163. return unless $log_enable;
  164. my ($level, $string) = @_;
  165. my %map = (
  166. $W_INFO => 'info',
  167. $W_WARN => 'warn',
  168. $W_ERROR => 'error',
  169. $W_DEBUG => 'debug',
  170. );
  171. my $method = $map{$level} || 'info';
  172. my $log = get_logger();
  173. for my $line (split /\n/, $string) {
  174. next unless length $line;
  175. $log->$method($line);
  176. if ($level == $W_ERROR) { print STDERR "[$method] $line\n"; } else { print "[$method] $line\n"; }
  177. }
  178. }
  179. log_init;
  180. 1;
  181. }