2016-07-29 13 views
5

Ich habe danach gesucht und nur gefunden here und here, aber es löst nicht mein Problem.Wie arbeite ich mit parallelen Logs bei Golang?

Wie kann ich mit einer Standard-Art und Weise identifiziere das Protokoll die gleichzeitigen Protokolle wie JAVA funktioniert mit Thread-ID Trennung ?. Denn wenn ich eine gleichzeitige Methode sie protokolliert wird am Ausgang gemischt gedruckt werden, so dass ich glaube, dass der Logger einen Weg zur Identifizierung jeder Anforderung „thread“ haben muß

Ex:

package main 

import "log" 

func main() { 

    /* simulating 10000 users requests */ 
    i := 1; 
    for ;i < 10000; i++ { 
     go getHello(i) 
    } 

} 

func getHello(d int){ 
    log.Printf("m=getHello, i=%d,begin", d) 
    log.Println("m=getHello, processing the hello message") 
    log.Printf("m=getHello, i=%d, end", d) 
} 

Ausgang

2016/07/29 15:59:46 m=getHello, i=1017,begin 
2016/07/29 15:59:46 m=getHello, processing the hello message 
2016/07/29 15:59:46 m=getHello, i=1017, end 
2016/07/29 15:59:46 m=getHello, processing the hello message 
2016/07/29 15:59:46 m=getHello, i=1038, end 
2016/07/29 15:59:46 m=getHello, i=311,begin 
2016/07/29 15:59:46 m=getHello, processing the hello message 
2016/07/29 15:59:46 m=getHello, i=311, end 
2016/07/29 15:59:46 m=getHello, i=1023,begin 
2016/07/29 15:59:46 m=getHello, processing the hello message 
2016/07/29 15:59:46 m=getHello, i=1023, end 
2016/07/29 15:59:46 m=getHello, i=991,begin 
2016/07/29 15:59:46 m=getHello, processing the hello message 
2016/07/29 15:59:46 m=getHello, i=991, end 

Wie Sie sehen können, wenn ich kein int-Flag habe, ist es unmöglich zu wissen, welche der Anfragen protokolliert haben. In Java, C, C#, Delphy zum Beispiel protokolliere ich einfach die Thread-ID und alles ist in Ordnung.

Können Sie mir helfen, so etwas in Golang zu tun? Vielen Dank.

Obs: Wenn meine Frage bitte mich nicht gut erklären, warum auf Kommentare

Antwort

5

Es ist keine Goroutine-ID in der Laufzeit verfügbar. Goroutinen werden liberaler als Threads in anderen Sprachen verwendet, so dass die Idee, welche Goroutine eine bestimmte Anfrage oder ein bestimmtes Item behandelt, in einem größeren Programm weniger gut definiert ist.

Also irgendwie müssen Sie selbst eine ID für die Protokollierung übergeben. Sie könnten einfach selbst eine int übergeben, aber das context Modul ist dafür praktisch: abgesehen von benutzerdefinierten Werten zuzulassen, kann es Artikel Stornierung und Fristen behandeln, die auch für Sie nützlich sein können.

Hier ist ein grobes Beispiel, wie es verwendet werden könnte. Ich habe ein einfaches Logging-Objekt hinzugefügt, das als kontextsensitiver Logger verwendet werden kann. Es protokolliert die ID, mit der der Kontext erstellt wurde. Wahrscheinlich würde dieser Logger in einem echten Programm in ein eigenes Paket gehen und mehr Funktionen des Log-Pakets unterstützen als nur Printf und Println.

package main 

import (
    "fmt" 
    "log" 
    "sync" 
    "context" 
) 

type logger int 
const loggerID = "logger_id" 

func (l logger) Printf(s string, args ...interface{}) { 
    log.Printf("[id=%d] %s", l, fmt.Sprintf(s, args...)) 
} 

func (l logger) Println(s string) { 
    log.Printf("[id=%d] %s\n", l, s) 
} 

func ctxWithLoggerID(ctx context.Context, id int) context.Context { 
    return context.WithValue(ctx, loggerID, id) 
} 

func getLogger(ctx context.Context) logger { 
    return logger(ctx.Value(loggerID).(int)) 
} 

func main() { 
    ctx := context.Background() 
    var wg sync.WaitGroup 
    for i := 0; i < 10; i++ { 
     wg.Add(1) 
     go hello(ctxWithLoggerID(ctx, i), &wg) 
    } 
    wg.Wait() 
} 

func hello(ctx context.Context, wg *sync.WaitGroup){ 
    def wg.Done() 
    log := getLogger(ctx) 
    log.Printf("hello begin") 
    log.Println("hello, processing the hello message") 
    log.Printf("hello, end") 
} 

Es ist auf Ihre Frage nebensächlich, aber ich hinzugefügt Verlassen ein WaitGroup zu Ihrem Programm, so dass main warten, bis alle Arbeiter fertig sind, bevor. Dadurch kann der Code mit einer geringeren Anzahl von Arbeitern getestet werden (10 anstatt der ursprünglichen 10000).

+0

Ist 'context' Paket in welcher Version verfügbar ?, habe ich bei '1.6.3' getestet und das Paket existiert nicht für mich – deFreitas

+0

In meinem Fall wurde genadelt Änderung von' Kontext' nach '" golang.org/x/ net/context "' und run 'go get' – deFreitas

+1

' context' ist neu in der stdlib in 1.7, aber 'golang.org/x/net/context' ist fast identisch. –

0

goroutines von Fäden sehr unterschiedlich sind oder sogar Prozesse. Sie werden von der Go-Runtime verwaltet und nicht von Ihrem Betriebssystem. Wenn Sie wirklich schweres Heben machen, ist es sogar möglich, dass der gleiche Goroutinensprung zwischen Prozessen stattfindet, daher ist es schwierig, ihnen eindeutige IDs zu geben.

Sie zum Beispiel der gegebenen int verwendet, ist völlig in Ordnung, da nur jeder goroutine eine Zahl verarbeitet.

+1

es ist wahr, das Problem ist, dass es schwer ist, das int-Flag in jeder Methode bei allen Anwendungen zu übergeben, dies ist auch nicht umfassend. – deFreitas

0

Wenn Sie keine int in jeder Goroutine übergeben wollen, dann können Sie versuchen, eine Zufallszahl darin mit math/rand Paket in goroutine iself zu generieren. Wenn die Anzahl hoch genug ist (abhängig von Ihrer Auslastung), erhalten Sie eine Art von Goroutine-ID.

Sie können Beispiele für Zufallszahl-Erzeugungs here finden.

Sie können es auch in Hex drucken, so wird es leicht sein, dass die ID von anderen int-Werten unterscheiden Sie in Programm haben.

Diese den Trick tun sollten:

log.Printf("m=getHello, i=%#x,begin", d)

EDIT: Wenn Sie sicher sein wollen auch Ihre ID in jedem goroutine eindeutig zuzuordnen sind, dann können Sie einige globale Zähler hinzu und erhöhen es in jede Goroutine.

import sync 

var txCounter int 
var counterMutex = &sync.Mutex{} 

for { 
    go func() { 
     id := txCounter 
     counterMutex.Lock() 
     txCounter++ 
     counterMutex.Unlock() 
     log.Printf("m=getHello, i=%#x,begin", id) 
    }() 
} 
+0

Letztes Beispiel ist wirklich kurz, aber ich hoffe, Sie bekommen die Idee. –