--log file with timestamps
authorAndrey Petrov <andrey.petrov@shazow.net>
Mon, 19 Jan 2015 06:05:49 +0000 (22:05 -0800)
committerAndrey Petrov <andrey.petrov@shazow.net>
Mon, 19 Jan 2015 06:05:49 +0000 (22:05 -0800)
chat/history.go
chat/message.go
chat/room.go
cmd.go

index 44513a657a5027856d4a3345a0069538437f156f..6b999ca134fe97af1f1d8f0627ec60211d18cd63 100644 (file)
@@ -1,13 +1,20 @@
 package chat
 
-import "sync"
+import (
+       "fmt"
+       "io"
+       "sync"
+)
+
+const timestampFmt = "2006-01-02 15:04:05"
 
 // History contains the history entries
 type History struct {
+       sync.RWMutex
        entries []Message
        head    int
        size    int
-       lock    sync.Mutex
+       out     io.Writer
 }
 
 // NewHistory constructs a new history of the given size
@@ -19,8 +26,8 @@ func NewHistory(size int) *History {
 
 // Add adds the given entry to the entries in the history
 func (h *History) Add(entry Message) {
-       h.lock.Lock()
-       defer h.lock.Unlock()
+       h.Lock()
+       defer h.Unlock()
 
        max := cap(h.entries)
        h.head = (h.head + 1) % max
@@ -28,6 +35,10 @@ func (h *History) Add(entry Message) {
        if h.size < max {
                h.size++
        }
+
+       if h.out != nil {
+               fmt.Fprintf(h.out, "[%s] %s\n", entry.Timestamp().UTC().Format(timestampFmt), entry.String())
+       }
 }
 
 // Len returns the number of entries in the history
@@ -37,8 +48,8 @@ func (h *History) Len() int {
 
 // Get the entry with the given number
 func (h *History) Get(num int) []Message {
-       h.lock.Lock()
-       defer h.lock.Unlock()
+       h.RLock()
+       defer h.RUnlock()
 
        max := cap(h.entries)
        if num > h.size {
@@ -56,3 +67,10 @@ func (h *History) Get(num int) []Message {
 
        return r
 }
+
+// SetOutput sets the output for logging added messages
+func (h *History) SetOutput(w io.Writer) {
+       h.Lock()
+       h.out = w
+       h.Unlock()
+}
index b4bfee5dc5fea387153c9dac673bfbd0634ad14b..9a0b30ae64fefa6f53385dc9c1a5aca2bb87121f 100644 (file)
@@ -11,6 +11,7 @@ type Message interface {
        Render(*Theme) string
        String() string
        Command() string
+       Timestamp() time.Time
 }
 
 type MessageTo interface {
@@ -61,6 +62,10 @@ func (m *Msg) Command() string {
        return ""
 }
 
+func (m *Msg) Timestamp() time.Time {
+       return m.timestamp
+}
+
 // PublicMsg is any message from a user sent to the room.
 type PublicMsg struct {
        Msg
index e6f68b5fa604bf00aae46a8ea22550daedac9685..041fe9e124497ab3a25349d34305d94dbedaf3a7 100644 (file)
@@ -3,6 +3,7 @@ package chat
 import (
        "errors"
        "fmt"
+       "io"
        "sync"
 )
 
@@ -59,6 +60,11 @@ func (r *Room) Close() {
        })
 }
 
+// SetLogging sets logging output for the room's history
+func (r *Room) SetLogging(out io.Writer) {
+       r.history.SetOutput(out)
+}
+
 // HandleMsg reacts to a message, will block until done.
 func (r *Room) HandleMsg(m Message) {
        switch m := m.(type) {
diff --git a/cmd.go b/cmd.go
index 721c597c66b98eaedb1c1627a95ffd0380b593ee..a342a029fe84c289c791fa552e6647a088720ca0 100644 (file)
--- a/cmd.go
+++ b/cmd.go
@@ -28,6 +28,7 @@ type Options struct {
        Admin     string `long:"admin" description:"File of public keys who are admins."`
        Whitelist string `long:"whitelist" description:"Optional file of public keys who are allowed to connect."`
        Motd      string `long:"motd" description:"Optional Message of the Day file."`
+       Log       string `long:"log" description:"Write chat log to this file."`
        Pprof     int    `long:"pprof" description:"Enable pprof http server for profiling."`
 }
 
@@ -116,7 +117,7 @@ func main() {
                        return err
                }
                auth.Op(key)
-               logger.Debugf("Added admin: %s", line)
+               logger.Debugf("Added admin: %s", sshd.Fingerprint(key))
                return nil
        })
        if err != nil {
@@ -151,6 +152,17 @@ func main() {
                host.SetMotd(motdString)
        }
 
+       if options.Log == "-" {
+               host.SetLogging(os.Stdout)
+       } else if options.Log != "" {
+               fp, err := os.OpenFile(options.Log, os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0666)
+               if err != nil {
+                       logger.Errorf("Failed to open log file for writing: %v", err)
+                       return
+               }
+               host.SetLogging(fp)
+       }
+
        go host.Serve()
 
        // Construct interrupt handler