J'ai du code fortement instrumenté qui utilise le package log
. Il est maintenant temps de désactiver la journalisation, et je ne peux pas déterminer comment désactiver l'enregistreur standard.
Ai-je raté quelque chose? Dois-je vérifier un indicateur avant d'effectuer des appels de journal ou de les commenter en production?
Pour désactiver complètement les journaux, il est préférable d'appeler log.SetFlags(0)
Joril et définissez la sortie sur un no-op io.Writer
(c'est-à-dire log.SetOutput(ioutil.Discard)
)
Mais même après cela, les opérations tourneront au ralenti 500-600 ns/op 1
Cela peut toujours être raccourci (à environ 100 ns/op) en utilisant une implémentation personnalisée de Logger
, et en implémentant toutes les fonctions pour être sans opération - comme démontré - ici (ne remplace que Println
pour la bervité).
L'alternative à tout cela est d'utiliser un cadre de journalisation personnalisé avec des niveaux et de le régler sur OFF.
Notez cependant que l'une des bibliothèques couramment utilisées pour la journalisation ( logrus ) a implications en termes de performances - la même chose peut être trouvée dans benchmarks où elle effectuer avec 3K + ns/op, peu importe.
Opinion biaisée: à partir des benchmarks, la bibliothèque go-logging fonctionne au même niveau que l'implémentation personnalisée Logger
lors du paramétrage de Level
sur -1
, quels que soient le backend et le formatage
(la source de référence peut être trouvée ici )
la sortie de l'indice de référence est la suivante:
testing: warning: no tests to run
PASS
BenchmarkGoLogging-4 1000000 2068 ns/op
BenchmarkGoLoggingNullBackend-4 5000000 308 ns/op
BenchmarkGoLoggingNullBackendWithFancyFormatter-4 3000000 435 ns/op
BenchmarkGoLoggingOffLevel-4 20000000 109 ns/op
BenchmarkGoLoggingNullBackendAndOffLevel-4 20000000 108 ns/op
BenchmarkGoLoggingNullBackendWithFancyFormatterAndOffLevel-4 20000000 109 ns/op
BenchmarkLog15-4 200000 7359 ns/op
BenchmarkLog15WithDiscardHandler-4 2000000 922 ns/op
BenchmarkLog15WithDiscardHandlerAndOffLevel-4 2000000 926 ns/op
BenchmarkLog15WithNopLogger-4 20000000 108 ns/op
BenchmarkLog15WithNopLoggerDiscardHandlerA-4 20000000 112 ns/op
BenchmarkLog15WithNopLoggerAndDiscardHandlerAndOffLevel-4 20000000 112 ns/op
BenchmarkLog-4 1000000 1217 ns/op
BenchmarkLogIoDiscardWriter-4 2000000 724 ns/op
BenchmarkLogIoDiscardWriterWithoutFlags-4 3000000 543 ns/op
BenchmarkLogCustomNullWriter-4 2000000 731 ns/op
BenchmarkLogCustomNullWriterWithoutFlags-4 3000000 549 ns/op
BenchmarkNopLogger-4 20000000 113 ns/op
BenchmarkNopLoggerWithoutFlags-4 20000000 112 ns/op
BenchmarkLogrus-4 300000 3832 ns/op
BenchmarkLogrusWithDiscardWriter-4 500000 3032 ns/op
BenchmarkLogrusWithNullFormatter-4 500000 3814 ns/op
BenchmarkLogrusWithPanicLevel-4 500000 3872 ns/op
BenchmarkLogrusWithDiscardWriterAndPanicLevel-4 500000 3085 ns/op
BenchmarkLogrusWithDiscardWriterAndNullFormatterAndPanicLevel-4 500000 3064 ns/op
ok log-benchmarks 51.378s
go test -bench . 62.17s user 3.90s system 126% cpu 52.065 total
# 1: [~ # ~] ymmv [~ # ~] , testé sur un processeur i7-4500U à 1,80 GHz =
Aucune raison de créer votre propre type pour un io.Writer commun lorsqu'il en existe un dans le package io/ioutil.
import (
"log"
"io/ioutil"
)
func init() {
log.SetOutput(ioutil.Discard)
}
type NullWriter int
func (NullWriter) Write([]byte) (int, error) { return 0, nil }
// ...
log.SetOutput(new(NullWriter))
Cette approche vous permet d'activer et de désactiver la journalisation lors de l'exécution:
type LogWriter struct{
enabled bool
}
func (l *LogWriter) Enable() {
l.enabled = true
}
func (l *LogWriter) Disable() {
l.enabled = false
}
func (l *LogWriter) Write([]byte) (int, error) {
if l.enabled {
//...
}
return 0, nil
}
Et cette approche active ou désactive la journalisation pour l'ensemble du runtime:
type LogWriter struct{}
func (l *LogWriter) Write([]byte) (int, error) {
if some.Constant {
//...
}
return 0, nil
}
Où some.Constant
serait soit une constante que vous définissez avant de compiler (produisant un "production" binaire) ou une variable qui n'est définie qu'une seule fois lors de l'exécution du programme via des drapeaux de ligne de commande (quelque chose comme myprogram --enable-logging=true
)
Avec les deux approches, vous pouvez laisser votre code actuel presque entièrement intact.
Puisque SetOutput()
n'est défini que pour l'enregistreur global, un écrivain personnalisé est toujours pratique pour les autres enregistreurs. Une façon courte d'en écrire une est comme ceci:
type LogWriter struct{ io.Writer }
func (w *LogWriter) Enable() { w.Writer = os.Stdout }
func (w *LogWriter) Disable() { w.Writer = ioutil.Discard }
Une note pour ceux qui viennent ici à la recherche de cela et d'autres fonctionnalités de journalisation: jetez un œil au package log4go car il couvre la désactivation de la journalisation, la définition des niveaux de journal, la rotation des journaux, la redirection vers un fichier, etc. qui pourraient être utiles.
Voir le doc sur http://godoc.org/code.google.com/p/log4go