module Locd::Newsyslog
Use `newsyslog` to rotate {Locd::Agent} log files.
Public Class Methods
log_dir()
click to toggle source
# File lib/locd/newsyslog.rb, line 327 def self.log_dir @log_dir ||= Locd.config.log_dir.join( Locd::Agent::RotateLogs.label ) end
log_to_file(&block)
click to toggle source
# File lib/locd/newsyslog.rb, line 337 def self.log_to_file &block time = Time.now.iso8601 date = time.split( 'T', 2 )[0] # Like # # ~/.locd/log/com.nrser.locd.rotate-logs/2018-02-14/2018-02-14T03:46:57+08:00.log # path = self.log_dir / date / "#{ time }.log" FileUtils.mkdir_p( path.dirname ) unless path.dirname.exist? appender = SemanticLogger.add_appender \ file_name: path.to_s begin result = block.call ensure SemanticLogger.remove_appender appender end end
run(agent, tmp_conf_dir: self.tmp_conf_dir, keep_conf_files: false)
click to toggle source
Run `newsyslog` for an agent to rotate it's log files (if present and needed).
@param [Locd::Agent] agent:
Agent to run for.
@param [Pathname | String] tmp_conf_dir
:
Directory to write working files to, which are removed after successful runs.
@return [Cmds::Result]
Result of running the `newsyslog` command.
@return [nil]
If we didn't run the command 'cause the agent doesn't have any logs (that we know/care about).
# File lib/locd/newsyslog.rb, line 207 def self.run agent, tmp_conf_dir: self.tmp_conf_dir, keep_conf_files: false logger.debug "Calling {.run_for} agent #{ agent.label }...", agent: agent, tmp_conf_dir: tmp_conf_dir # Make sure `tmp_conf_dir` is a {Pathname} tmp_conf_dir = tmp_conf_dir.to_pn # Collect the unique log paths log_paths = agent.log_paths if log_paths.empty? logger.info "Agent #{ agent.label } has no log files." return nil end logger.info "Setting up to run `newsyslog` for agent `#{ agent.label }`", log_paths: log_paths.map( &:to_s ) # NOTE Total race condition since agent may be started after this and # before we rotate... f-it for now. pid_path = nil if pid = agent.pid( refresh: true ) logger.debug "Agent is running", pid: pid pid_path = tmp_conf_dir / 'pids' / "#{ agent.label }.pid" FileUtils.mkdir_p( pid_path.dirname ) unless pid_path.dirname.exist? pid_path.write pid logger.debug "Wrote PID #{ pid } to file", pid_path: pid_path end entries = log_paths.map { |log_path| Entry.new log_path: log_path, pid_path: pid_path } conf_contents = entries.map( &:render ).join( "\n" ) + "\n" logger.debug "Generated conf entries", entries.map { |entry| [ entry.log_path.to_s, entry.instance_variables.map { |name| entry.instance_variable_get name } ] }.to_h conf_path = tmp_conf_dir / 'confs' / "#{ agent.label }.conf" FileUtils.mkdir_p( conf_path.dirname ) unless conf_path.dirname.exist? conf_path.write conf_contents logger.debug "Wrote entries to conf file", conf_path: conf_path.to_s, conf_contents: conf_contents cmd = Cmds.new "newsyslog <%= opts %>", kwds: { opts: { # Turn on verbose output v: true, # Point to the conf file f: conf_path, # Don't run as root r: true, } } logger.info "Executing `#{ cmd.prepare }`" result = cmd.capture if result.ok? logger.info \ "`newsyslog` command succeeded for agent `#{ agent.label }`" + ( result.out.empty? ? nil : ", output:\n" + result.out.indent(1, indent_string: '> ') ) FileUtils.rm( pid_path ) if pid_path FileUtils.rm( conf_path ) unless keep_conf_files logger.debug "Files cleaned up." else logger.error "`newsyslog` command failed for agent #{ agent.label }", result: result.to_h end logger.debug "Returning", result: result.to_h result end
run_all(tmp_conf_dir: self.tmp_conf_dir, trim_logs: true)
click to toggle source
Call {.run} for each agent.
@param tmp_conf_dir
: (see .run)
@return [Hash<Locd::Agent, Cmds::Result?>]
Hash mapping each agent to it's {.run} result (which may be `nil`).
# File lib/locd/newsyslog.rb, line 310 def self.run_all tmp_conf_dir: self.tmp_conf_dir, trim_logs: true log_to_file do Locd::Agent.all.values. reject { |agent| agent.label == Locd::Agent::RotateLogs.label }. map { |agent| [agent, run( agent, tmp_conf_dir: tmp_conf_dir )] }. to_h. tap { |_| self.trim_logs if trim_logs } end end
tmp_conf_dir()
click to toggle source
# File lib/locd/newsyslog.rb, line 332 def self.tmp_conf_dir @tmp_conf_dir ||= Locd.config.tmp_dir.join( Locd::Agent::RotateLogs.label ) end
trim_logs(keep_days: 7)
click to toggle source
# File lib/locd/newsyslog.rb, line 360 def self.trim_logs keep_days: 7 logger.info "Removing old self run log directories...", log_dir: self.log_dir.to_s, keep_days: keep_days unless self.log_dir.directory? logger.warn "{Locd::Newsyslog.log_dir} does not exist!", log_dir: self.log_dir return nil end day_dirs = self.log_dir.entries.select { |dir_name| dir_name.to_s =~ /\d{4}\-\d{2}\-\d{2}/ && (self.log_dir / dir_name).directory? } to_remove = day_dirs.sort[0...(-1 * keep_days)] if to_remove.empty? logger.info "No old self run log directories to remove." else to_remove.each { |dir_name| path = self.log_dir / dir_name logger.info "Removing old day directory", path: path FileUtils.rm_rf path } logger.info "Done.", log_dir: self.log_dir.to_s, keep_days: keep_days end to_remove end