Skip to content

Commit

Permalink
Merge pull request #96 from fbelzunc/daily-rotation
Browse files Browse the repository at this point in the history
  • Loading branch information
PierreBtz committed Jan 31, 2023
2 parents 83ffd0d + ffedd60 commit b9e0b9c
Show file tree
Hide file tree
Showing 10 changed files with 491 additions and 117 deletions.
2 changes: 1 addition & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
<artifactId>mockito-inline</artifactId>
<scope>test</scope>
</dependency>
<dependency>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,140 @@
package hudson.plugins.audit_trail;

import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
import hudson.EnvVars;
import hudson.Util;

import javax.annotation.Nonnull;
import java.io.File;
import java.io.IOException;
import java.nio.file.NoSuchFileException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Optional;
import java.util.logging.FileHandler;
import java.util.logging.Formatter;
import java.util.logging.Level;
import java.util.logging.LogRecord;
import java.util.logging.Logger;

import static java.util.logging.Level.CONFIG;

public abstract class AbstractLogFileAuditLogger extends AuditLogger {

private static final Logger LOGGER = Logger.getLogger(AbstractLogFileAuditLogger.class.getName());
static final String DEFAULT_LOG_SEPARATOR =" ";

@Nonnull
private String logSeparator;
private String log;
private int count = 1;

private transient FileHandler handler;

public AbstractLogFileAuditLogger(String log, int count, String logSeparator) {
this.log = Util.replaceMacro(log, EnvVars.masterEnvVars);
this.count = count;
this.logSeparator = Optional.ofNullable(logSeparator).orElse(DEFAULT_LOG_SEPARATOR);
}

@SuppressFBWarnings(
value = "RCN_REDUNDANT_NULLCHECK_OF_NONNULL_VALUE",
justification = "value can be null if no config file exists")
Object readResolve() {
if (logSeparator == null) {
logSeparator = DEFAULT_LOG_SEPARATOR;
}
return this;
}

final void configure() {
// looks like https://bugs.java.com/bugdatabase/view_bug.do?bug_id=6244047 is somehow still there
// there is no way for us to know before hand what path we are looking to create as it would
// mean having access to FileHandler#generate so either reflexion or catching the exception and retrieving
// the path. Let's go with number 2.
try {
FileHandler h = null;
try {
h = getLogFileHandler();
} catch (NoSuchFileException ex) {
LOGGER.info("Couldn't create the file handler lock file, forcing creation of intermediate directories");
String lockFileName = ex.getFile();
boolean mkdirs = new File(lockFileName).getParentFile().mkdirs();
if (mkdirs) {
h = getLogFileHandler();
}
}
if (h != null) {
h.setFormatter(new Formatter() {
SimpleDateFormat dateFormat = new SimpleDateFormat("MMM d, yyyy h:mm:ss,SSS aa");

@Override
public synchronized String format(LogRecord record) {
return dateFormat.format(new Date(record.getMillis())) + getLogSeparator()
+ record.getMessage() + '\n';
}
});
h.setLevel(CONFIG);
handler = h;
} else {
LOGGER.severe("Couldn't configure the plugin, as the file handler wasn't successfully created. You should report this issue");
}
} catch (IOException ex) {
LOGGER.log(Level.SEVERE, "Couldn't configure the plugin, you should report this issue", ex);
}
}

@Override
public void log(String event) {
if (handler == null) return;
handler.publish(new LogRecord(CONFIG, event));
}

@Override
public void cleanUp() throws SecurityException {
if(handler != null) {
handler.close();
}
}

abstract FileHandler getLogFileHandler() throws IOException;

@Nonnull
public String getLogSeparator() {
return logSeparator;
}

public String getLog() {
return log;
}

public int getCount() {
return count;
}

public FileHandler getHandler() {
return handler;
}

@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;

AbstractLogFileAuditLogger that = (AbstractLogFileAuditLogger) o;

if (count != that.count) return false;
if (!logSeparator.equals(that.logSeparator)) return false;
if (log != null ? !log.equals(that.log) : that.log != null) return false;
return handler != null ? handler.equals(that.handler) : that.handler == null;
}

@Override
public int hashCode() {
int result = logSeparator.hashCode();
result = 31 * result + (log != null ? log.hashCode() : 0);
result = 31 * result + count;
result = 31 * result + (handler != null ? handler.hashCode() : 0);
return result;
}
}
126 changes: 11 additions & 115 deletions src/main/java/hudson/plugins/audit_trail/LogFileAuditLogger.java
Original file line number Diff line number Diff line change
@@ -1,147 +1,44 @@
package hudson.plugins.audit_trail;

import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
import hudson.EnvVars;
import hudson.Extension;
import hudson.Util;
import hudson.model.Descriptor;
import org.kohsuke.stapler.DataBoundConstructor;

import javax.annotation.Nonnull;
import java.io.File;
import java.io.IOException;
import java.nio.file.NoSuchFileException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Optional;
import java.util.logging.FileHandler;
import java.util.logging.Formatter;
import java.util.logging.Level;
import java.util.logging.LogRecord;
import java.util.logging.Logger;

import static java.util.logging.Level.CONFIG;

/**
* @author <a href="mailto:nicolas.deloof@gmail.com">Nicolas De Loof</a>
* @author Pierre Beitz
*/
public class LogFileAuditLogger extends AuditLogger {

private static final Logger LOGGER = Logger.getLogger(LogFileAuditLogger.class.getName());
static final String DEFAULT_LOG_SEPARATOR=" ";
@Nonnull
private String logSeparator;
public class LogFileAuditLogger extends AbstractLogFileAuditLogger {

private transient FileHandler handler;
private int limit = 1;

@DataBoundConstructor
public LogFileAuditLogger(String log, int limit, int count, String logSeparator) {
this.log = Util.replaceMacro(log, EnvVars.masterEnvVars);
super(log, count, logSeparator);
this.limit = limit;
this.count = count;
this.logSeparator = Optional.ofNullable(logSeparator).orElse(DEFAULT_LOG_SEPARATOR);
configure();
}

@SuppressFBWarnings(
value="RCN_REDUNDANT_NULLCHECK_OF_NONNULL_VALUE",
value = "RCN_REDUNDANT_NULLCHECK_OF_NONNULL_VALUE",
justification = "value can be null if no config file exists")
private Object readResolve() {
if(logSeparator == null) {
logSeparator = DEFAULT_LOG_SEPARATOR;
}
Object readResolve() {
super.readResolve();
configure();
return this;
}

@Override
public void log(String event) {
if (handler == null) return;
handler.publish(new LogRecord(CONFIG, event));
FileHandler getLogFileHandler() throws IOException {
return new FileHandler(getLog(), getLimit() * 1024 * 1024, getCount(), true);
}

private String log;
private int limit = 1;
private int count = 1;

public String getLog() { return log; }

public int getLimit() { return limit; }

public int getCount() { return count; }

@Nonnull
public String getLogSeparator() {
return logSeparator;
}

@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof LogFileAuditLogger)) return false;

LogFileAuditLogger that = (LogFileAuditLogger) o;

if (count != that.count) return false;
if (limit != that.limit) return false;
if (!logSeparator.equals(that.logSeparator)) return false;
if (log != null ? !log.equals(that.log) : that.log != null) return false;

return true;
}

@Override
public int hashCode() {
int result = log != null ? log.hashCode() : 0;
result = 31 * result + limit;
result = 31 * result + count;
result = 31 * result + logSeparator.hashCode();
return result;
}

private void configure() {
// looks like https://bugs.java.com/bugdatabase/view_bug.do?bug_id=6244047 is somehow still there
// there is no way for us to know before hand what path we are looking to create as it would
// mean having access to FileHandler#generate so either reflexion or catching the exception and retrieving
// the path. Let's go with number 2.
try {
FileHandler h = null;
try {
h = new FileHandler(log, limit * 1024 * 1024, count, true);
} catch (NoSuchFileException ex) {
LOGGER.info("Couldn't create the file handler lock file, forcing creation of intermediate directories");
String lockFileName = ex.getFile();
boolean mkdirs = new File(lockFileName).getParentFile().mkdirs();
if (mkdirs) {
h = new FileHandler(log, limit * 1024 * 1024, count, true);
}
}
if (h != null) {
h.setFormatter(new Formatter() {
SimpleDateFormat dateFormat = new SimpleDateFormat("MMM d, yyyy h:mm:ss,SSS aa");

@Override
public synchronized String format(LogRecord record) {
return dateFormat.format(new Date(record.getMillis())) + getLogSeparator()
+ record.getMessage() + '\n';
}
});
h.setLevel(CONFIG);
handler = h;
} else {
LOGGER.severe("Couldn't configure the plugin, as the file handler wasn't successfully created. You should report this issue");
}
} catch (IOException ex) {
LOGGER.log(Level.SEVERE, "Couldn't configure the plugin, you should report this issue", ex);
}
}

@Override
public void cleanUp() throws SecurityException {
if(handler != null) {
handler.close();
}
public int getLimit() {
return limit;
}

@Extension
Expand All @@ -152,5 +49,4 @@ public String getDisplayName() {
return "Log file";
}
}

}
}

0 comments on commit b9e0b9c

Please sign in to comment.