2016-04-12 5 views
2

So verwende ich eine strukturierte Logging-Bibliothek (logrus), und ich habe ein core-Paket als Basis für einige andere Pakete verwendet, rufen Sie dieses Paket me/core, dann einzelne Pakete wie me/foo-service , me/bar-service etc., die diese Core-Bibliothek für allgemeine Abhängigkeiten/Dienstprogramme wie Setup, Konfiguration laden, und ich wollte es auch für standardisierte Dinge wie Protokollierung verwenden, so dass ich me/core in der Lage sein soll, die Protokollierung für die anderen Pakete zu konfigurieren Logrus können Sie Dinge tun wieZentralisierte Logging-Konfiguration beim Freigeben von Bibliotheken zwischen Paketen

import(
    log "github.com/Sirupsen/logrus" 
) 
[...] 
log.SetLevel(log.DebugLevel) 
log.SetFormatter(&log.TextFormatter{FullTimestamp:true}) 

Dann tun;

log.Debug("Moo") 
log.WithFields(log.Fields{"structured":"data"}).Debug("I have structure data") 

bekommen eine Ausgabe wie

> DEBU[2016-04-12T22:11:38+01:00] Moo 
> DEBU[2016-04-12T22:11:38+01:00] I have structure data   structured=data 

Deshalb möchte ich dies mit etwas in meinem me/foo-service Paket konfigurieren, wie

import(
    "me/core/logging" 
) 

func main(){ 
    logging.Setup() 
} 

Nur aus verschiedenen Gründen, die ich in Probleme laufen lasse. Das Hauptproblem scheint, dass sowohl me/core zu sein, und me/foo-service haben eine weiterverkauft Version der logrus Bibliothek, diese log.Set* Befehle die Variable logrus.std Logger ändern, die den Standard, global Logger hält, aber dies ist eine separate Instanz für beide Pakete, weil me/core/vendor/.../logrus/std und me/foo-service/vendor/.../logrus/std sind verschiedene Objekte.

Der erste, was ich versuchte, wurde eine Variable in me/core/logging schaffen, die ich in den Eltern, so etwas wie

package logging 

import(
    log "github.com/Sirupsen/logrus" 
) 

var Log *log.Logger 

func Setup(verbose bool){ 
    Log = log.New() 
    if verbose{ 
    Log.Level = log.DebugLevel 
    } else { 
    Log.Level = log.InfoLevel 
    } 
    Log.Formatter = &log.TextFormatter{FullTimestamp:true} 
    Log.Debug("Logging verbosely") 
} 

und das funktioniert für einfache Fälle wie dies

package main 

import(
    "me/core/logging" 
) 

func main() { 
    logging.Setup(parsedOptions.Verbose) 
    logging.Log.Debug("Moo") 
} 

jedoch versuchen, nutzen könnte Verwenden Sie die strukturierten Daten Fields verursacht Probleme, kann ich nicht die lokalen vectored logrus Felder wie

verwenden 10

wie ich

cannot use "me/foo-service/vendor/github.com/Sirupsen/logrus".Fields literal (type "me/foo-service/vendor/github.com/Sirupsen/logrus".Fields) as type "me/core/vendor/github.com/Sirupsen/logrus".Fields in argument to logging.Log.WithFields 

Und versuchen, das Feld in me/core/logging mit etwas zu spiegeln wie

type Fields log.Fields 

Hat Äther nicht funktionieren, weil es ist immer noch eine andere Art

cannot use logging.Fields literal (type logging.Fields) as type "me/core/vendor/github.com/Sirupsen/logrus".Fields in argument to logging.Log.WithFields 

Ich kann mir auch keine Möglichkeit vorstellen, meinen lokalen log.std von me/foo-service an 0 zu übergebenwie es ist auch eine andere Art aufgrund der Vendored-Paket.

Meine Arbeit um für den Moment beinhaltet einen Spiegel jedes Verfahren zu schaffen, so in me/core/logging Ich habe ein wie

package logging 

import(
    log "github.com/Sirupsen/logrus" 
) 

var Log *log.Logger 
type Fields map[string]interface{} 

func Setup(verbose bool){ 
    Log = log.New() 
    if verbose{ 
    Log.Level = log.DebugLevel 
    } else { 
    Log.Level = log.InfoLevel 
    } 
    Log.Formatter = &log.TextFormatter{FullTimestamp:true} 
    Log.Debug("Logging verbosely") 
} 

func Debug(msg interface{}){ 
    Log.Debug(msg) 
} 

func WithFields(fields Fields) *log.Entry{ 
    lf := log.Fields{} 
    for k,v := range fields{ 
    lf[k] = v 
    } 
    return Log.WithFields(lf) 
} 

einrichten Aber das bedeuten würde einen Spiegel für jedes Verfahren zu schaffen, die wirklich ineffizient scheint .

Also ich möchte einen Vorschlag dafür, wie ich me/core/vendor/.../logrus/std verfügbar machen kann me/foo-service, oder wenn ich darüber völlig falsch denke, eine bessere Möglichkeit, es zu tun.

+0

nenne ich denke, es ist im allgemeinen unerwünscht ist eine Bibliothek Anbieter haben es eigene deps ist, und zwar aus Gründen der Versionsinkompatibilität und der Duplizierung. Die App (Hauptpaket) sollte die Erwartungen der Verkäufer erfüllen und Konflikte lösen. –

Antwort

1

Sie können nur WithFields spiegeln, da die anderen eingebauten Typen akzeptieren. Auch da logging.Fields und logrus.Fields vom gleichen Typ sind Sie einfacher könnte

func WithFields(f Fields) log.*Entry { 
    return Log.WithFields(log.Fields(f)) 
} 

Dann in Ihren Dienst tun, könnten Sie

logging.Log.Debug("message") 
logging.WithFields(logging.Fields{"k":"v"}).Debug("message") 
Verwandte Themen