Skip to content

Instantly share code, notes, and snippets.

@ahf
Created April 24, 2011 20:36
Show Gist options
  • Save ahf/939858 to your computer and use it in GitHub Desktop.
Save ahf/939858 to your computer and use it in GitHub Desktop.
commit ce6c86c7498522eb3d0bef731bfaf4dd76469b68
Author: Alexander Færøy <ahf@0x90.dk>
Date: Sun Apr 24 22:28:37 2011 +0200
Add Logging Process and utilities.
The design of this code is to let NewLogProcess() create a pointer to a
LogProcess instance which acts as the API proxy for the go-routine that
deals with the actual writing of the messages to the log file.
The LogProcess.Log() method lets you log a string to the log file and
its sister method, LogProcess.LogF(), lets you log a format string to a
file.
The LogProcess.Close() method allows you to shutdown the logging
go-routine and mark the LogProcess as being invalid. Any calls to an
invalid LogProcess is considered to be a void operation for now.
Later we might end up making API calls to an invalid LogProcess as a
fatal operation instead of void, but for now it seems to be good enough.
diff --git a/src/Makefile b/src/Makefile
index 0c2d36b..0196bb2 100644
--- a/src/Makefile
+++ b/src/Makefile
@@ -4,6 +4,7 @@ TARG = ircd-novo
GOFILES = \
ircd.go \
- messages.go \
+ log_process.go \
+ messages.go
include $(GOROOT)/src/Make.cmd
diff --git a/src/log_process.go b/src/log_process.go
new file mode 100644
index 0000000..6fdf49a
--- /dev/null
+++ b/src/log_process.go
@@ -0,0 +1,138 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+/*
+ * Copyright (c) 2011 Alexander Færøy <ahf@0x90.dk>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+package main
+
+import (
+ "fmt"
+ "log"
+ "os"
+)
+
+type LogLevel int
+
+const (
+ Silent LogLevel = iota
+ Warning
+ Debug
+)
+
+func (l LogLevel) String() string {
+ switch l {
+ case Silent: return "Silent"
+ case Warning: return "Warning"
+ case Debug: return "Debug"
+ }
+
+ panic("Unhandled Loglevel")
+}
+
+func CreateLogMessage(ll LogLevel, format string, arguments ...interface{}) string {
+ return "(" + ll.String() + "): " + fmt.Sprintf(format, arguments...)
+}
+
+type LogProcess struct {
+ logger *log.Logger
+ file *os.File
+ command_channel chan logProcessCommand
+ logging_channel chan string
+ valid bool
+ log_level LogLevel
+}
+
+func NewLogProcess(filename string) *LogProcess {
+ file, error := os.Open(filename, os.O_APPEND | os.O_WRONLY | os.O_CREAT, 0644)
+
+ if error != nil {
+ panic("Error: " + error.String())
+ }
+
+ logger := log.New(file, nil, "", log.Ldate | log.Ltime)
+ command_channel := make(chan logProcessCommand)
+ logging_channel := make(chan string)
+
+ lp := LogProcess{logger, file, command_channel, logging_channel, true, Silent}
+
+ go func() {
+ for {
+ select {
+ case message := <-lp.logging_channel:
+ lp.logger.Log(message)
+ case command := <-lp.command_channel:
+ lp.logger.Log(CreateLogMessage(Debug, "Received '%s' Command Message", command.String()))
+
+ switch command {
+ case closeCommand:
+ return
+ }
+ }
+ }
+ }()
+
+ return &lp
+}
+
+func (s *LogProcess) LogF(ll LogLevel, format string, arguments ...interface{}) {
+ if ll == Silent {
+ panic("Using LogLevel 'Silent' does not make sense here")
+ }
+
+ if s.valid && ll >= s.log_level {
+ s.logging_channel <- CreateLogMessage(ll, format, arguments...)
+ }
+}
+
+func (s *LogProcess) Log(ll LogLevel, message string) {
+ s.LogF(ll, "%s", message)
+}
+
+func (s *LogProcess) SetLogLevel(ll LogLevel) {
+ s.log_level = ll
+}
+
+func (s *LogProcess) Close() {
+ if s.valid {
+ s.command_channel <- closeCommand
+ s.valid = false
+ s.file.Close()
+ }
+}
+
+type logProcessCommand int
+
+const (
+ closeCommand logProcessCommand = iota
+)
+
+func (l logProcessCommand) String() string {
+ switch l {
+ case closeCommand: return "Close"
+ }
+
+ panic("Unhandled logProcessCommand")
+}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment