Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: rubinius/rubinius
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: 1132e25ebec5
Choose a base ref
...
head repository: rubinius/rubinius
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: e5769d60a16b
Choose a head ref
  • 2 commits
  • 4 files changed
  • 1 contributor

Commits on Jun 30, 2015

  1. Copy the full SHA
    f35dfb5 View commit details

Commits on Jul 1, 2015

  1. Added config items -Xsystem.log.limit, -Xsystem.log.archives.

    The -Xsystem.log.limit sets the maximum size of the -Xsystem.log file
    before log rotation is performed. The -Xsystem.log.archives sets the
    number of prior log files that are retained as zip files.
    brixen committed Jul 1, 2015

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    e5769d6 View commit details
Showing with 116 additions and 27 deletions.
  1. +6 −0 library/rubinius/configuration.rb
  2. +3 −1 vm/environment.cpp
  3. +98 −21 vm/util/logger.cpp
  4. +9 −5 vm/util/logger.hpp
6 changes: 6 additions & 0 deletions library/rubinius/configuration.rb
Original file line number Diff line number Diff line change
@@ -167,6 +167,12 @@
s.vm_variable "log", "$TMPDIR/$PROGRAM_NAME-$USER.log",
"Logging facility to use: 'syslog', 'console', or path"

s.vm_variable "log.limit", (10 * 1024 * 1024),
"The maximum size of the log file before log rotation is performed"

s.vm_variable "log.archives", 5,
"The number of prior logs that will be saved as '$(system.log).N.Z' zip files"

s.vm_variable "log.level", "warn",
"Logging level: fatal, error, warn, info, debug"

4 changes: 3 additions & 1 deletion vm/environment.cpp
Original file line number Diff line number Diff line change
@@ -233,7 +233,9 @@ namespace rubinius {
expand_config_value(config.system_log.value, "$USER", shared->username.c_str());

utilities::logger::open(utilities::logger::eFileLogger,
config.system_log.value.c_str(), level);
config.system_log.value.c_str(), level,
config.system_log_limit.value,
config.system_log_archives.value);
}
}

119 changes: 98 additions & 21 deletions vm/util/logger.cpp
Original file line number Diff line number Diff line change
@@ -9,6 +9,10 @@
#include <fcntl.h>
#include <string.h>
#include <time.h>
#include <sys/stat.h>
#include <sys/syslimits.h>

#include <zlib.h>

#include <ostream>

@@ -19,8 +23,9 @@ namespace rubinius {
static Logger* logger_ = 0;
static logger_level loglevel_ = eWarn;

void open(logger_type type, const char* identifier, logger_level level) {
void open(logger_type type, const char* identifier, logger_level level, ...) {
lock_.init();
va_list varargs;

switch(type) {
case eSyslog:
@@ -30,7 +35,9 @@ namespace rubinius {
logger_ = new ConsoleLogger(identifier);
break;
case eFileLogger:
logger_ = new FileLogger(identifier);
va_start(varargs, level);
logger_ = new FileLogger(identifier, varargs);
va_end(varargs);
break;
}

@@ -239,15 +246,11 @@ namespace rubinius {
std::ostringstream str;
str << identifier << "[" << getpid() << "]";

identifier_ = new std::string(str.str());
}

ConsoleLogger::~ConsoleLogger() {
delete identifier_;
identifier_ = std::string(str.str());
}

void ConsoleLogger::write_log(const char* level, const char* message, int size) {
fprintf(stderr, "%s %s %s %s", timestamp(), identifier_->c_str(), level, message);
fprintf(stderr, "%s %s %s %s", timestamp(), identifier_.c_str(), level, message);
}

#define LOGGER_LEVEL_FATAL "<Fatal>"
@@ -257,7 +260,7 @@ namespace rubinius {
#define LOGGER_LEVEL_DEBUG "<Debug>"

void ConsoleLogger::write(const char* message, int size) {
fprintf(stderr, "%s %s %s", timestamp(), identifier_->c_str(), message);
fprintf(stderr, "%s %s %s", timestamp(), identifier_.c_str(), message);
}

void ConsoleLogger::fatal(const char* message, int size) {
@@ -280,42 +283,116 @@ namespace rubinius {
write_log(LOGGER_LEVEL_DEBUG, message, size);
}

#define LOGGER_MAX_FILE 5242880
#define LOGGER_MAX_COPY_BUF 1048576
#define LOGGER_OPEN_FLAGS (O_CREAT | O_APPEND | O_WRONLY | O_CLOEXEC)
#define LOGGER_REOPEN_FLAGS (O_CREAT | O_TRUNC | O_APPEND | O_WRONLY | O_CLOEXEC)
#define LOGGER_FROM_FLAGS (O_RDONLY | O_CLOEXEC)
#define LOGGER_TO_FLAGS (O_CREAT | O_TRUNC | O_APPEND | O_WRONLY | O_CLOEXEC)
#define LOGGER_OPEN_PERMS 0600

FileLogger::FileLogger(const char* identifier)
FileLogger::FileLogger(const char* path, va_list varargs)
: Logger()
, path_(path)
{
std::ostringstream str;
str << " [" << getpid() << "] ";
std::ostringstream label;
label << " [" << getpid() << "] ";

identifier_ = new std::string(str.str());
identifier_ = label.str();

logger_fd_ = ::open(identifier, LOGGER_OPEN_FLAGS, LOGGER_OPEN_PERMS);
limit_ = va_arg(varargs, long);
archives_ = va_arg(varargs, long);

// Round robin if log file exceeds the limit
if(lseek(logger_fd_, 0, SEEK_END) > LOGGER_MAX_FILE) {
lseek(logger_fd_, 0, SEEK_SET);
}
logger_fd_ = ::open(path, LOGGER_OPEN_FLAGS, LOGGER_OPEN_PERMS);
}

FileLogger::~FileLogger() {
delete identifier_;
cleanup();
}

void FileLogger::cleanup() {
::close(logger_fd_);
logger_fd_ = -1;
}

void FileLogger::rotate() {
struct stat st;

cleanup();

void* buf = malloc(LOGGER_MAX_COPY_BUF);
if(!buf) return;

char* from = (char*)malloc(PATH_MAX);
if(!from) return;

char* to = (char*)malloc(PATH_MAX);
if(!to) return;

for(int i = archives_; i > 0; i--) {
if(i > 1) {
snprintf(from, PATH_MAX, "%s.%d.Z", path_.c_str(), i - 1);
} else {
snprintf(from, PATH_MAX, "%s", path_.c_str());
}

if(stat(from, &st) || !S_ISREG(st.st_mode)) continue;

snprintf(to, PATH_MAX, "%s.%d.Z", path_.c_str(), i);

int from_fd = ::open(from, LOGGER_FROM_FLAGS, LOGGER_OPEN_PERMS);
if(from_fd < 0) continue;

int to_fd = ::open(to, LOGGER_TO_FLAGS, LOGGER_OPEN_PERMS);
if(to_fd < 0) {
::close(from_fd);
continue;
}

int bytes;

if(i > 0) {
while((bytes = ::read(from_fd, buf, LOGGER_MAX_COPY_BUF)) > 0) {
if(::write(to_fd, buf, bytes) < 0) break;
}
} else {
gzFile gzf;

gzf = gzdopen(to_fd, "a");
if(gzf == Z_NULL) continue;

while((bytes = ::read(from_fd, buf, LOGGER_MAX_COPY_BUF)) > 0) {
if(gzwrite(gzf, buf, bytes) <= 0) break;
}

gzclose(gzf);
}

::close(from_fd);
::close(to_fd);
}

free(buf);
free(from);
free(to);

logger_fd_ = ::open(path_.c_str(), LOGGER_REOPEN_FLAGS, LOGGER_OPEN_PERMS);
}

void FileLogger::write_log(const char* level, const char* message, int size) {
utilities::file::LockGuard guard(logger_fd_, LOCK_EX);

const char* time = timestamp();
write_status_ = ::write(logger_fd_, time, strlen(time));
write_status_ = ::write(logger_fd_, identifier_->c_str(), identifier_->size());
write_status_ = ::write(logger_fd_, identifier_.c_str(), identifier_.size());
if(level) {
write_status_ = ::write(logger_fd_, level, strlen(level));
write_status_ = ::write(logger_fd_, " ", 1);
}
write_status_ = ::write(logger_fd_, message, size);

if(lseek(logger_fd_, 0, SEEK_END) > limit_) {
rotate();
}
}

void FileLogger::write(const char* message, int size) {
14 changes: 9 additions & 5 deletions vm/util/logger.hpp
Original file line number Diff line number Diff line change
@@ -21,7 +21,7 @@ namespace rubinius {
};


void open(logger_type type, const char* identifier, logger_level level=eWarn);
void open(logger_type type, const char* identifier, logger_level level=eWarn, ...);
void close();

void write(const char* message, ...);
@@ -68,14 +68,13 @@ namespace rubinius {
};

class ConsoleLogger : public Logger {
std::string* identifier_;
std::string identifier_;

void write_log(const char* level, const char* message, int size);

public:

ConsoleLogger(const char* identifier);
~ConsoleLogger();

void write(const char* message, int size);
void fatal(const char* message, int size);
@@ -86,15 +85,20 @@ namespace rubinius {
};

class FileLogger : public Logger {
std::string* identifier_;
std::string path_;
std::string identifier_;
int logger_fd_;
long limit_;
long archives_;
int write_status_;

void write_log(const char* level, const char* message, int size);
void rotate();
void cleanup();

public:

FileLogger(const char* identifier);
FileLogger(const char* path, va_list varargs);
~FileLogger();

void write(const char* message, int size);