From 797d8c92be3bbb20761cb899a402a39106da59e9 Mon Sep 17 00:00:00 2001 From: Andrey Petrov Date: Sun, 18 Jan 2015 22:05:49 -0800 Subject: [PATCH] --log file with timestamps --- chat/history.go | 30 ++++++++++++++++++++++++------ chat/message.go | 5 +++++ chat/room.go | 6 ++++++ cmd.go | 14 +++++++++++++- 4 files changed, 48 insertions(+), 7 deletions(-) diff --git a/chat/history.go b/chat/history.go index 44513a6..6b999ca 100644 --- a/chat/history.go +++ b/chat/history.go @@ -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() +} diff --git a/chat/message.go b/chat/message.go index b4bfee5..9a0b30a 100644 --- a/chat/message.go +++ b/chat/message.go @@ -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 diff --git a/chat/room.go b/chat/room.go index e6f68b5..041fe9e 100644 --- a/chat/room.go +++ b/chat/room.go @@ -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 721c597..a342a02 100644 --- 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