Added logger to write log messages that grow over time. Not working yet.
authormishaz <misha@curoverse.com>
Thu, 8 Jan 2015 01:47:51 +0000 (01:47 +0000)
committerTom Clegg <tom@curoverse.com>
Fri, 13 Feb 2015 21:23:53 +0000 (16:23 -0500)
sdk/go/logger/logger.go [new file with mode: 0644]
sdk/go/logger/main/testlogger.go [new file with mode: 0644]

diff --git a/sdk/go/logger/logger.go b/sdk/go/logger/logger.go
new file mode 100644 (file)
index 0000000..6835750
--- /dev/null
@@ -0,0 +1,79 @@
+// Periodically writes a log to the Arvados SDK.
+//
+// This package is useful for maintaining a log object that is built
+// up over time. Every time the object is modified, it will be written
+// to the log. Writes will be throttled to no more than one every
+// WriteFrequencySeconds
+//
+// This package is safe for concurrent use.
+//
+// Usage:
+// arvLogger := logger.NewLogger(params)
+// logData := arvLogger.Acquire()  // This will block if others are using the logger
+// // Modify the logObject however you want here ..
+// logData = arvLogger.Release()  // This triggers the actual write, and replaces logObject with a nil pointer so you don't try to modify it when you're no longer holding the lock
+
+package logger
+
+import (
+       "git.curoverse.com/arvados.git/sdk/go/arvadosclient"
+       "log"
+       "sync"
+       "time"
+)
+
+const (
+       eventTypeLabel string = "event-type"
+       propertiesLabel string = "properties"
+)
+
+type LoggerParams struct {
+       Client arvadosclient.ArvadosClient  // The client we use to write log entries
+       EventType string  // The event type to assign to the log entry.
+       MinimumWriteInterval time.Duration  // Wait at least this long between log writes
+}
+
+type Logger struct {
+       data map[string]interface{}
+       lock sync.Locker
+       params LoggerParams
+}
+
+func NewLogger(params LoggerParams) *Logger {
+       l := &Logger{data: make(map[string]interface{}),
+               lock: &sync.Mutex{},
+               // TODO(misha): Consider copying the params so they're not
+               // modified after creation.
+               params: params}
+       l.data[propertiesLabel] = make(map[string]interface{})
+       return l
+}
+
+func (l *Logger) Acquire() map[string]interface{} {
+       l.lock.Lock()
+       return l.data[propertiesLabel].(map[string]interface{})
+}
+
+func (l *Logger) Release() map[string]interface{} {
+       // TODO(misha): Add a check (and storage) to make sure we respect MinimumWriteInterval
+       l.write()
+       l.lock.Unlock()
+       return nil
+}
+
+func (l *Logger) write() {
+       // Update the event type in case it was modified or is missing.
+       // l.data[eventTypeLabel] = l.params.EventType
+       // m := make(map[string]interface{})
+       // m["body"] = l.data
+       // //err := l.params.Client.Create("logs", l.data, nil)
+       // //err := l.params.Client.Create("logs", m, nil)
+       // var results map[string]interface{}
+       err := l.params.Client.Create("logs",
+               arvadosclient.Dict{"log": arvadosclient.Dict{
+                       eventTypeLabel: l.params.EventType,
+                       propertiesLabel: l.data}}, nil)
+       if err != nil {
+               log.Fatalf("Received error writing log: %v", err)
+       }
+}
diff --git a/sdk/go/logger/main/testlogger.go b/sdk/go/logger/main/testlogger.go
new file mode 100644 (file)
index 0000000..5a12352
--- /dev/null
@@ -0,0 +1,32 @@
+// This binary tests the logger package.
+// It's not a standard unit test. Instead it writes to the actual log
+// and you have to clean up after it.
+
+package main
+
+import (
+       "git.curoverse.com/arvados.git/sdk/go/arvadosclient"
+       "git.curoverse.com/arvados.git/sdk/go/logger"
+       "log"
+)
+
+const (
+       eventType string = "experimental-logger-testing"
+)
+
+
+func main() {
+       arv, err := arvadosclient.MakeArvadosClient()
+       if err != nil {
+               log.Fatalf("Error setting up arvados client %v", err)
+       }
+
+       l := logger.NewLogger(logger.LoggerParams{Client: arv,
+               EventType: eventType,
+               // No minimum write interval
+       })
+
+       logData := l.Acquire()
+       logData["Ninja"] = "Misha"
+       logData = l.Release()
+}