गोलंग में वैश्विक लॉगिंग के लिए सही दृष्टिकोण


119

Go में एप्लिकेशन लॉगिंग के लिए पैटर्न क्या है? अगर मुझे मिल गया है, तो कहो, मुझे चाहिए कि मैं से 5 goroutines चाहिए ...

  • एक एकल बनाएँ log.Loggerऔर इसे पास करें?
  • एक पॉइंटर के आस-पास से गुजरें log.Logger?
  • क्या प्रत्येक गोरोइन या फ़ंक्शन को लकड़हारा बनाना चाहिए?
  • क्या मुझे एक वैश्विक चर के रूप में लकड़हारा बनाना चाहिए?

जवाबों:


59
  • एक एकल लॉग बनाएं। लॉगर और इसे पास करें?

यह सम्भव है। एक लॉग.लॉगर का उपयोग कई गोरोनाइट्स से समवर्ती रूप से किया जा सकता है।

  • उस लॉग के पास एक पॉइंटर के आसपास से गुजरें। लॉगर

log.New रिटर्न *Loggerजो आमतौर पर एक संकेत है कि आपको ऑब्जेक्ट को पॉइंटर के रूप में पास करना चाहिए। मान के रूप में इसे पास करने से संरचना की एक प्रति (यानी लकड़हारा की एक प्रति) बन जाएगी और फिर कई गोरोइंटिन समान io.Writer को समवर्ती रूप से लिख सकते हैं । लेखक के कार्यान्वयन के आधार पर यह एक गंभीर समस्या हो सकती है।

  • क्या प्रत्येक गोरोइन या फ़ंक्शन को लकड़हारा बनाना चाहिए?

मैं प्रत्येक फ़ंक्शन या गोरोइन के लिए एक अलग लकड़हारा नहीं बनाऊंगा। गोर्यूटाइंस (और फ़ंक्शंस) का उपयोग बहुत हल्के कार्यों के लिए किया जाता है जो एक अलग लकड़हारे के रखरखाव को सही नहीं ठहराएंगे। अपनी परियोजना के प्रत्येक बड़े घटक के लिए लकड़हारा बनाना शायद एक अच्छा विचार है। उदाहरण के लिए, यदि आपकी परियोजना मेल भेजने के लिए SMTP सेवा का उपयोग करती है, तो मेल सेवा के लिए एक अलग लकड़हारा एक अच्छा विचार लगता है, ताकि आप फ़िल्टर कर सकें और आउटपुट को अलग से बंद कर सकें।

  • क्या मुझे एक वैश्विक चर के रूप में लकड़हारा बनाना चाहिए?

जो आपके पैकेज पर निर्भर करता है। पिछले मेल सेवा उदाहरण में, आपकी सेवा के प्रत्येक उदाहरण के लिए एक लकड़हारा होना शायद एक अच्छा विचार होगा, ताकि उपयोगकर्ता जीमेल मेल सेवा का उपयोग करते समय विफलताओं से भिन्न रूप से लॉग इन कर सकें, जो कि स्थानीय एमटीए का उपयोग करते समय उत्पन्न विफलताओं की तुलना में है (उदाहरण के लिए मेल) )।


37

साधारण मामलों के लिए, लॉग पैकेज में एक वैश्विक लकड़हारा परिभाषित है log.Logger। इस वैश्विक लकड़हारा के माध्यम से विन्यस्त किया जा सकता है log.SetFlags

बाद में, बस लॉग पैकेज के शीर्ष स्तर के कार्यों को कॉल कर सकते हैं जैसे log.Printfऔर log.Fatalf, जो उस वैश्विक उदाहरण का उपयोग करते हैं।


सोचा कि आप उन झंडों को सेट कर सकते हैं जिन्हें आप कस्टम लकड़हारे का उपयोग नहीं कर सकते।
0xcaff

@caffinatedmonkey वास्तव में, आप कस्टम लॉगर का उपयोग कर सकते हैं यदि वे io.Writerइंटरफ़ेस को लागू करते हैं और आप डिफ़ॉल्ट लकड़हारा के आउटपुट को बदल देते हैं SetOutput()
कॉंगसबोंगस

16

यह एक साधारण लकड़हारा है

package customlogger

import (
    "log"
    "os"
    "sync"
)

type logger struct {
    filename string
    *log.Logger
}

var logger *logger
var once sync.Once

// start loggeando
func GetInstance() *logger {
    once.Do(func() {
        logger = createLogger("mylogger.log")
    })
    return logger
}

func createLogger(fname string) *logger {
    file, _ := os.OpenFile(fname, os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0777)

    return &logger{
        filename: fname,
        Logger:   log.New(file, "My app Name ", log.Lshortfile),
    }
}

आप इसे इस तरह से उपयोग कर सकते हैं

package main

import (
    "customlogger"
    "fmt"
    "net/http"
)

func main() {
    logger := customlogger.GetInstance()
    logger.Println("Starting")

    http.HandleFunc("/", sroot)
    http.ListenAndServe(":8080", nil)
}

func sroot(w http.ResponseWriter, r *http.Request) {
    logger := customlogger.GetInstance()

    fmt.Fprintf(w, "welcome")
    logger.Println("Starting")
}

10

मुझे पता है कि यह सवाल थोड़ा पुराना है, लेकिन अगर, मेरी तरह, आपकी परियोजनाएं कई छोटी फाइलों से बनती हैं, जिन्हें मैं आपके 4 वें विकल्प के लिए वोट करता हूं - मैंने बनाया है logger.goजो पैकेज मुख्य का हिस्सा है। यह गो फाइल लकड़हारा बनाता है, इसे एक फाइल को असाइन करता है, और बाकी मुख्य को प्रदान करता है। ध्यान दें, मैं एक सुंदर तरीका नहीं आया है जो एरर क्लोज्ड करने के लिए है ...

package main

import (
    "fmt"
    "log"
    "os"
)

var errorlog *os.File
var logger *log.Logger

func init() {
    errorlog, err := os.OpenFile(logfile,  os.O_RDWR|os.O_CREATE|os.O_APPEND, 0666)
    if err != nil {
        fmt.Printf("error opening file: %v", err)
        os.Exit(1)
    }

    logger = log.New(errorlog, "applog: ", log.Lshortfile|log.LstdFlags)
}

8
सुशोभित समापन के लिए, आप शायद defer errorlog.Close()निष्पादन के अंत में, या इसके बंद को बेहतर तरीके से सुनिश्चित करने के लिए, गो सिग्नल के पैकेज golang.org/pkg/os/signal
Anfernee

4

यह एक पुराना प्रश्न है, लेकिन मैं http://github.com/romana/rlog के उपयोग का सुझाव देना चाहूंगा (जिसे हमने विकसित किया है) । यह पर्यावरण चर के माध्यम से कॉन्फ़िगर किया गया है, लकड़हारा वस्तु बनाई जाती है और जब आरोग्य आयात किया जाता है, तो इसे शुरू किया जाता है। इसलिए, एक लकड़हारे के आसपास से गुजरने की कोई जरूरत नहीं है।

rlog में कुछ विशेषताएं हैं:

  • पूरी तरह से विन्यास की तारीख / समय टिकटों
  • Stderr या stdout के साथ-साथ फ़ाइल के साथ-साथ आउटपुट।
  • मानक लॉग स्तर (डीबग, सूचना, आदि) और साथ ही स्वतंत्र रूप से कॉन्फ़िगर करने योग्य बहु-स्तरीय लॉगिंग।
  • कॉलर जानकारी (फ़ाइल, लाइन नंबर, फ़ंक्शन) की लॉगिंग की मांग पर।
  • विभिन्न स्रोत फ़ाइलों के लिए अलग लॉग स्तर सेट करने की क्षमता।

यह बहुत छोटा है, मानक गोलंग लाइब्रेरी को छोड़कर कोई बाहरी निर्भरता नहीं है और इसे सक्रिय रूप से विकसित किया जा रहा है। रेपो में उदाहरण दिए गए हैं।


3
आप जिस उत्पाद की सिफारिश कर रहे हैं, उसके साथ अपनी संबद्धता का खुलासा करने के लिए धन्यवाद! यह सराहनीय है।
रॉबर्ट कोलंबिया

2

मुझे डिफ़ॉल्ट लॉग पैकेज मिला ( https://golang.org/pkg/log/ ) कुछ हद तक सीमित। उदाहरण के लिए, जानकारी बनाम डिबग लॉग के लिए कोई समर्थन नहीं।
आसपास कुछ प्रहार करने के बाद, https://github.com/golang/glog का उपयोग करने पर समझौता किया । यह https://github.com/google/glog का पोर्ट लगता है और लॉगिंग में सभ्य लचीलापन देता है। उदाहरण के लिए जब कोई एप्लिकेशन स्थानीय रूप से चल रहा हो तो आप DEBUG स्तर लॉग कर सकते हैं, लेकिन उत्पादन में केवल INFO / ERROR स्तर पर चलाना चाह सकते हैं। पूर्ण सुविधाओं / मार्गदर्शिका की सूची यहाँ है, https://google-glog.googlecode.com/svn/trunk/doc/glog.html (c ++ मॉड्यूल के लिए, लेकिन अधिकांश भाग के लिए golang पोर्ट में अनुवाद करता है)


0

लॉगिंग मॉड्यूल में से एक जिसे आप विचार कर सकते हैं वह है क्लॉग । यह 'V' लॉगिंग का समर्थन करता है जो निश्चित स्तर पर लॉग इन करने की सुविधा देता है

क्लॉग गॉगल का एक कांटा है और कमियों का पालन करता है

  • glog बहुत सारे "गोच" प्रस्तुत करता है और कंटेनरीकृत वातावरण में चुनौतियों का सामना करता है, जिनमें से सभी को अच्छी तरह से प्रलेखित नहीं किया गया है।
  • glog लॉग का परीक्षण करने का एक आसान तरीका प्रदान नहीं करता है, जो इसका उपयोग करने वाले सॉफ़्टवेयर की स्थिरता से बाधित होता है
  • glog C ++ आधारित है और klog एक शुद्ध गोलंग कार्यान्वयन है

नमूना कार्यान्वयन

package main

import (
    "flag"

    "k8s.io/klog"


)

type myError struct {
    str string
}

func (e myError) Error() string {
    return e.str
}

func main() {
    klog.InitFlags(nil)
    flag.Set("v", "1")
    flag.Parse()

    klog.Info("hello", "val1", 1, "val2", map[string]int{"k": 1})
    klog.V(3).Info("nice to meet you")
    klog.Error(nil, "uh oh", "trouble", true, "reasons", []float64{0.1, 0.11, 3.14})
    klog.Error(myError{"an error occurred"}, "goodbye", "code", -1)
    klog.Flush()
}
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.