Skip to content

Commit

Permalink
# This is a combination of 4 commits.
Browse files Browse the repository at this point in the history
# The first commit's message is:
added syslog support

# This is the 2nd commit message:

Fixed Julia 0.4 depwarns maintaining 0.3 compatibility.

# This is the 3rd commit message:

Set the max message log for syslog to 1024, also is configurable.

# This is the 4th commit message:

TEMP: address code review comments
  • Loading branch information
sbchisholm committed Nov 17, 2015
1 parent e5a6eb5 commit ff675cf
Show file tree
Hide file tree
Showing 3 changed files with 82 additions and 17 deletions.
96 changes: 80 additions & 16 deletions src/Logging.jl
Original file line number Diff line number Diff line change
@@ -1,34 +1,83 @@
module Logging

using Compat
using Compat.Libc: strftime

import Base: show, info, warn

export debug, info, warn, err, critical, log,
@debug, @info, @warn, @err, @error, @critical, @log,
Logger,
LogLevel, DEBUG, INFO, WARNING, ERROR, CRITICAL, OFF
LogLevel, DEBUG, INFO, WARNING, ERROR, CRITICAL, OFF,
LogFacility,
SysLog

if VERSION < v"0.4.0-dev+3587"
include("enum.jl")
end

@enum LogLevel DEBUG INFO WARNING ERROR CRITICAL OFF
@enum LogLevel OFF=-1 CRITICAL=2 ERROR WARNING INFO=6 DEBUG

try
DEBUG < CRITICAL
catch
Base.isless(x::LogLevel, y::LogLevel) = isless(x.val, y.val)
end

function Base.convert(::Type{LogLevel}, x::AbstractString)
Dict("OFF"=>OFF,
"CRITICAL"=>CRITICAL,
"ERROR"=>ERROR,
"WARNING"=>WARNING,
"INFO"=>INFO,
"DEBUG"=>DEBUG)[x]
end

@enum LogFacility LOG_KERN LOG_USER LOG_MAIL LOG_DAEMON LOG_AUTH LOG_SYSLOG LOG_LPR LOG_NEWS LOG_UUCP LOG_CRON LOG_AUTHPRIV LOG_LOCAL0=16 LOG_LOCAL1 LOG_LOCAL2 LOG_LOCAL3 LOG_LOCAL4 LOG_LOCAL5 LOG_LOCAL6 LOG_LOCAL7

try
LOG_KERN < LOG_USER
catch
Base.isless(x::LogFacility, y::LogFacility) = isless(x.val, y.val)
end

type SysLog
socket::UDPSocket
ip::IPv4
port::UInt16
facility::LogFacility
machine::AbstractString
user::AbstractString
maxlength::UInt16

SysLog(host::AbstractString,
port::Int,
facility::LogFacility=LOG_USER,
machine::AbstractString=gethostname(),
user::AbstractString=Base.source_path()==nothing ? "" : basename(Base.source_path()),
maxlength::Int=1024) = new(
UDPSocket(),
getaddrinfo(host),
(@compat UInt16(port)),
facility,
machine,
user,
(@compat UInt16(maxlength))
)
end

LogOutput = @compat Union{IO,SysLog}

type Logger
name::AbstractString
level::LogLevel
output::IO
output::Array{LogOutput,1}
parent::Logger

Logger(name::AbstractString, level::LogLevel, output::IO, parent::Logger) = new(name, level, output, parent)
Logger(name::AbstractString, level::LogLevel, output::IO) = (x = new(); x.name = name; x.level=level; x.output=output; x.parent=x)
Logger(name::AbstractString, level::LogLevel, output::IO, parent::Logger) = new(name, level, [output], parent)
Logger(name::AbstractString, level::LogLevel, output::IO) = (x = new(); x.name = name; x.level=level; x.output=[output]; x.parent=x)
Logger(name::AbstractString, level::LogLevel, output::Array{LogOutput,1}, parent::Logger) = new(name, level, output, parent)
Logger(name::AbstractString, level::LogLevel, output::Array{LogOutput,1}) = (x = new(); x.name = name; x.level=level; x.output=output; x.parent=x)
end

show(io::IO, logger::Logger) = print(io, "Logger(", join([logger.name,
Expand All @@ -37,23 +86,36 @@ show(io::IO, logger::Logger) = print(io, "Logger(", join([logger.name,
logger.parent.name], ","), ")")

const _root = Logger("root", WARNING, STDERR)
Logger(name::AbstractString;args...) = configure(Logger(name, WARNING, STDERR, _root); args...)
Logger(name::AbstractString;args...) = configure(Logger(name, WARNING, [STDERR], _root); args...)
Logger() = Logger("logger")

write_log(syslog::SysLog, color::Symbol, msg::AbstractString) = send(syslog.socket, syslog.ip, syslog.port, length(msg) > syslog.maxlength ? msg[1:syslog.maxlength] : msg)
write_log{T<:IO}(output::T, color::Symbol, msg::AbstractString) = (print(output, msg); flush(output))
write_log(output::Base.TTY, color::Symbol, msg::AbstractString) = Base.print_with_color(color, output, msg)

function log(syslog::SysLog, level::LogLevel, color::Symbol, logger_name::AbstractString, msg...)
# syslog needs a timestamp in the form: YYYY-MM-DDTHH:MM:SS-TZ:TZ
t = time()
timestamp = string(strftime("%Y-%m-%dT%H:%M:%S",t), strftime("%z",t)[1:end-2], ":", strftime("%z",t)[end-1:end])
logstring = string("<", ((@compat UInt16(syslog.facility)) << 3) + (@compat UInt16(level)), ">1 ", timestamp, " ", syslog.machine, " ", syslog.user, " - - - ", level, ":", logger_name,":", msg...)
write_log(syslog, color, logstring)
end

function log{T<:IO}(output::T, level::LogLevel, color::Symbol, logger_name::AbstractString, msg...)
logstring = string(strftime("%d-%b %H:%M:%S",time()),":",level, ":",logger_name,":", msg...,"\n")
write_log(output, color, logstring)
end

for (fn,lvl,clr) in ((:debug, DEBUG, :cyan),
(:info, INFO, :blue),
(:warn, WARNING, :magenta),
(:err, ERROR, :red),
(:critical, CRITICAL, :red))

@eval function $fn(logger::Logger, msg...)
if $lvl >= logger.level
logstring = string(Libc.strftime("%d-%b %H:%M:%S",time()),":",$lvl, ":",logger.name,":", msg...,"\n")
if isa(logger.output, Base.TTY)
Base.print_with_color($(Expr(:quote, clr)), logger.output, logstring )
else
print(logger.output, logstring)
flush(logger.output)
if $lvl <= logger.level
for output in logger.output
log(output, $lvl, $(Expr(:quote, clr)), logger.name, msg...)
end
end
end
Expand All @@ -72,9 +134,11 @@ function configure(logger=_root; args...)
end

for (tag, val) in args
tag == :io ? (logger.output = val::IO) :
tag == :output ? (logger.output = val::IO) :
tag == :filename ? (logger.output = open(val, "a")) :
tag == :io ? typeof(val) <: AbstractArray ? (logger.output = val) :
(logger.output = [val::LogOutput]) :
tag == :output ? typeof(val) <: AbstractArray ? (logger.output = val) :
(logger.output = [val::LogOutput]) :
tag == :filename ? (logger.output = [open(val, "a")]) :
tag == :level ? (logger.level = val::LogLevel) :
tag == :override_info ? nothing : # handled below
tag == :parent ? nothing : # handled above
Expand Down
2 changes: 1 addition & 1 deletion src/enum.jl
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ macro enum(T,syms...)
if max(abs(lo),abs(hi)) < typemax(Uint32)
enumT = Uint32
else
enumT = Uint64
enumT = UInt64
end
end
blk = quote
Expand Down
1 change: 1 addition & 0 deletions test/runtests.jl
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
using Logging: debug, info, warn
include("log_test.jl")
include("macro_test1.jl")
include("macro_test2.jl")
Expand Down

0 comments on commit ff675cf

Please sign in to comment.