mirror of
https://github.com/mainflux/mainflux.git
synced 2025-04-27 13:48:49 +08:00

* Use normalizer as stream source Renamed 'writer' service to 'normalizer' and dropped Cassandra facilities from it. Extracted the common dependencies to 'mainflux' package for easier sharing. Fixed the API docs and unified environment variables. Signed-off-by: Dejan Mijic <dejan@mainflux.com> * Use docker build arguments to specify build Signed-off-by: Dejan Mijic <dejan@mainflux.com> * Remove cassandra libraries Signed-off-by: Dejan Mijic <dejan@mainflux.com> * Update go-kit version to 0.6.0 Signed-off-by: Dejan Mijic <dejan@mainflux.com> * Fix manager configuration Signed-off-by: Dejan Mijic <dejan@mainflux.com> * Refactor docker-compose Merged individual compose files and dropped external links. Remove CoAP container since it is not referenced from NginX config at the moment. Update port mapping in compose and nginx.conf. Dropped bin scripts. Updated service documentation. Signed-off-by: Dejan Mijic <dejan@mainflux.com> * Drop content-type check Signed-off-by: Dejan Mijic <dejan@mainflux.com> * Implement users data access layer in PostgreSQL Signed-off-by: Dejan Mijic <dejan@mainflux.com> * Bump version to 0.1.0 Signed-off-by: Dejan Mijic <dejan@mainflux.com> * Use go-kit logger everywhere (except CoAP) Signed-off-by: Dejan Mijic <dejan@mainflux.com> * Improve factory methods naming Signed-off-by: Dejan Mijic <dejan@mainflux.com> * Implement clients data access layer on PostgreSQL Signed-off-by: Dejan Mijic <dejan@mainflux.com> * Make tests stateless All tests are refactored to use map-based table-driven tests. No cross-tests dependencies is present anymore. Signed-off-by: Dejan Mijic <dejan@mainflux.com> * Remove gitignore Signed-off-by: Dejan Mijic <dejan@mainflux.com> * Fix nginx proxying Signed-off-by: Dejan Mijic <dejan@mainflux.com> * Mark client-user FK explicit Signed-off-by: Dejan Mijic <dejan@mainflux.com> * Update API documentation Signed-off-by: Dejan Mijic <dejan@mainflux.com> * Update channel model Signed-off-by: Dejan Mijic <dejan@mainflux.com> * Add channel PostgreSQL repository tests Signed-off-by: Dejan Mijic <dejan@mainflux.com> * Implement PostgreSQL channels DAO Replaced update queries with raw SQL. Explicitly defined M2M table due to difficulties of ensuring the referential integrity through GORM. Signed-off-by: Dejan Mijic <dejan@mainflux.com> * Expose connection endpoints Signed-off-by: Dejan Mijic <dejan@mainflux.com> * Fix swagger docs and remove DB logging Signed-off-by: Dejan Mijic <dejan@mainflux.com> * Fix nested query remarks Signed-off-by: Dejan Mijic <dejan@mainflux.com> * Add unique indices Signed-off-by: Dejan Mijic <dejan@mainflux.com>
117 lines
3.2 KiB
Go
117 lines
3.2 KiB
Go
package log
|
|
|
|
import (
|
|
"io"
|
|
"sync"
|
|
"sync/atomic"
|
|
)
|
|
|
|
// SwapLogger wraps another logger that may be safely replaced while other
|
|
// goroutines use the SwapLogger concurrently. The zero value for a SwapLogger
|
|
// will discard all log events without error.
|
|
//
|
|
// SwapLogger serves well as a package global logger that can be changed by
|
|
// importers.
|
|
type SwapLogger struct {
|
|
logger atomic.Value
|
|
}
|
|
|
|
type loggerStruct struct {
|
|
Logger
|
|
}
|
|
|
|
// Log implements the Logger interface by forwarding keyvals to the currently
|
|
// wrapped logger. It does not log anything if the wrapped logger is nil.
|
|
func (l *SwapLogger) Log(keyvals ...interface{}) error {
|
|
s, ok := l.logger.Load().(loggerStruct)
|
|
if !ok || s.Logger == nil {
|
|
return nil
|
|
}
|
|
return s.Log(keyvals...)
|
|
}
|
|
|
|
// Swap replaces the currently wrapped logger with logger. Swap may be called
|
|
// concurrently with calls to Log from other goroutines.
|
|
func (l *SwapLogger) Swap(logger Logger) {
|
|
l.logger.Store(loggerStruct{logger})
|
|
}
|
|
|
|
// NewSyncWriter returns a new writer that is safe for concurrent use by
|
|
// multiple goroutines. Writes to the returned writer are passed on to w. If
|
|
// another write is already in progress, the calling goroutine blocks until
|
|
// the writer is available.
|
|
//
|
|
// If w implements the following interface, so does the returned writer.
|
|
//
|
|
// interface {
|
|
// Fd() uintptr
|
|
// }
|
|
func NewSyncWriter(w io.Writer) io.Writer {
|
|
switch w := w.(type) {
|
|
case fdWriter:
|
|
return &fdSyncWriter{fdWriter: w}
|
|
default:
|
|
return &syncWriter{Writer: w}
|
|
}
|
|
}
|
|
|
|
// syncWriter synchronizes concurrent writes to an io.Writer.
|
|
type syncWriter struct {
|
|
sync.Mutex
|
|
io.Writer
|
|
}
|
|
|
|
// Write writes p to the underlying io.Writer. If another write is already in
|
|
// progress, the calling goroutine blocks until the syncWriter is available.
|
|
func (w *syncWriter) Write(p []byte) (n int, err error) {
|
|
w.Lock()
|
|
n, err = w.Writer.Write(p)
|
|
w.Unlock()
|
|
return n, err
|
|
}
|
|
|
|
// fdWriter is an io.Writer that also has an Fd method. The most common
|
|
// example of an fdWriter is an *os.File.
|
|
type fdWriter interface {
|
|
io.Writer
|
|
Fd() uintptr
|
|
}
|
|
|
|
// fdSyncWriter synchronizes concurrent writes to an fdWriter.
|
|
type fdSyncWriter struct {
|
|
sync.Mutex
|
|
fdWriter
|
|
}
|
|
|
|
// Write writes p to the underlying io.Writer. If another write is already in
|
|
// progress, the calling goroutine blocks until the fdSyncWriter is available.
|
|
func (w *fdSyncWriter) Write(p []byte) (n int, err error) {
|
|
w.Lock()
|
|
n, err = w.fdWriter.Write(p)
|
|
w.Unlock()
|
|
return n, err
|
|
}
|
|
|
|
// syncLogger provides concurrent safe logging for another Logger.
|
|
type syncLogger struct {
|
|
mu sync.Mutex
|
|
logger Logger
|
|
}
|
|
|
|
// NewSyncLogger returns a logger that synchronizes concurrent use of the
|
|
// wrapped logger. When multiple goroutines use the SyncLogger concurrently
|
|
// only one goroutine will be allowed to log to the wrapped logger at a time.
|
|
// The other goroutines will block until the logger is available.
|
|
func NewSyncLogger(logger Logger) Logger {
|
|
return &syncLogger{logger: logger}
|
|
}
|
|
|
|
// Log logs keyvals to the underlying Logger. If another log is already in
|
|
// progress, the calling goroutine blocks until the syncLogger is available.
|
|
func (l *syncLogger) Log(keyvals ...interface{}) error {
|
|
l.mu.Lock()
|
|
err := l.logger.Log(keyvals...)
|
|
l.mu.Unlock()
|
|
return err
|
|
}
|