लाइब्रेरी बनाम एप्लिकेशन: मूल रूप से अलग logging आवश्यकताएँ
- एप्लिकेशन logging: ऐसे environment में स्पष्ट configuration और management जहाँ developer का सीधा control होता है
- लाइब्रेरी logging: दूसरे लोगों के project में शामिल होने के कारण user environment और उनकी choice का सम्मान करना ज़रूरी
- मौजूदा तरीकों की सीमाएँ: एप्लिकेशन-केंद्रित logger (winston, Pino) को लाइब्रेरी पर लागू करने पर थोपे जाने की समस्या
- लाइब्रेरी बनाने वालों की दुविधा: debugging जानकारी देना बनाम user पर बोझ न डालना
मौजूदा लाइब्रेरी logging की समस्याएँ
- खंडित logging ecosystem: Express में
DEBUG=express:*, Mongoose में mongoose.set('debug', true) जैसी अलग-अलग विधियाँ
- dependency दुविधा: winston, Pino जैसी एप्लिकेशन-केंद्रित लाइब्रेरी इस्तेमाल करने पर user पर अनचाही dependency और configuration थोपना
- चुप्पी बनाम थोपना: या तो logging को पूरी तरह छोड़ देना, या user पर logging का तरीका थोप देना — यही दो चरम विकल्प
- dependency injection की जटिलता: अधिक परिष्कृत तरीका, लेकिन API जटिलता और user burden दोनों बढ़ते हैं
LogTape का "library-first" दर्शन
- शर्त-आधारित सक्रियता: logging configure न होने पर पूरी तरह निष्क्रिय, configure होने पर एकीकृत रूप से प्रबंधित
- user की choice की गारंटी: लाइब्रेरी logging का तरीका नहीं थोपती, user जब चाहे तभी इसे सक्रिय कर सकता है
- zero dependency: 5.3KB आकार के साथ supply chain security risk हटाता है और version conflict रोकता है
- ESM/CJS का पूर्ण समर्थन: compatibility chain की समस्या हल करता है और tree shaking के जरिए bundle optimization देता है
व्यावहारिक फायदे
- performance optimization: निष्क्रिय होने पर लगभग zero overhead, सक्रिय होने पर बेहतरीन console output performance
- namespace अलगाव:
["my-lib", "feature"] जैसे hierarchical category रूप से conflict की रोकथाम
- TypeScript-first design: अतिरिक्त type package के बिना पूरी type safety
- मौजूदा सिस्टम के साथ bridging: winston, Pino adapter के माध्यम से क्रमिक adoption का समर्थन
व्यावहारिक विचार बिंदु
- adapter का महत्व: यह मानना कि अभी ecosystem standard मौजूद नहीं है, और उसी के अनुसार व्यावहारिक समझौता
- Python ecosystem से प्रेरणा: standard
logging लाइब्रेरी के जरिए एकीकृत Python की सफलता का संदर्भ
- भविष्य-उन्मुख दृष्टिकोण: लाइब्रेरी ecosystem के क्रमिक सुधार के लिए एक विकल्प के रूप में प्रस्तुति
7 टिप्पणियां
मुझे ठीक से समझ नहीं आ रहा कि बिना configuration के यह non-functional कैसे है।
जब
getLoggerकिया जाता है, तभी logger बन जाता है, औरdebugलॉग करें तो वह काम भी करता है।मैंने कोड देखा तो यह बस ऐसा लगता है मानो यह काम नहीं कर रहा हो,
और यह string operations को भी defer नहीं करता,
तो फिर log level सेट करने पर लॉग न दिखाने वाली दूसरी libraries से यह non-functional किस तरह अलग है, यह मुझे ठीक से समझ नहीं आ रहा।
अरे,
configure()/configureSync()को कॉल नहीं किया फिर भी लॉग प्रिंट हो रहे हैं? वे कहाँ प्रिंट हो रहे हैं? क्या वे console screen पर प्रिंट हो रहे हैं?आह, यहाँ "काम करता है" कहने से मेरा मतलब यह नहीं था कि log
consoleया file में सेव होता है, बल्कि मैं यह कह रहा था कि क्या function वास्तव में execute होता है और उससे कोई वास्तविक overhead आता है।गलतफ़हमी होना स्वाभाविक है
बेशक, अगर यह माना जाए कि logger का मुख्य overhead system call है, तो यह नहीं कहा जा सकता कि इसमें overhead नहीं है
लेकिन क्या इसे दूसरे logger से अलग करने वाला बिंदु यही है? ऐसा कहना मुश्किल है, क्योंकि दूसरे logger भी इसी तरह काम करते हैं।
आह, आप यही कहना चाह रहे थे। पहले, जब null output के आधार पर benchmark चलाया गया, तो लगा कि overhead लगभग न के बराबर है। लेकिन performance overhead से भी ज़्यादा महत्वपूर्ण बात मुझे यह लगी कि default behavior no-op है या नहीं। लाइब्रेरी लेखक के नज़रिए से, भले ही लाइब्रेरी के अंदर logs लिखे जाएँ, लेकिन अगर उस लाइब्रेरी का उपयोग करने वाला application चलते समय अपनी मर्ज़ी से console या file में logs output करने लगे, तो यह परेशानी वाली बात हो सकती है।
आह, यह SHOW GN था।
हाल के दिनों में ecosystem में अक्सर ऐसा रूप चुना जाता है जहाँ logger को बाहर से inject किया जाता है, इसलिए शायद मुझे उससे उतना जुड़ाव महसूस नहीं हुआ।
क्योंकि अगर वह configure न हो, तो स्वाभाविक रूप से काम नहीं करता।
फिर भी, यह उस ecosystem में अब तक न रहा एक logger interface भी है, और इसकी flexibility भी काफी ज़्यादा है, इसलिए यह और बेहतर लगता है।
आपके दिए हुए benchmark मानक के मामले में, system call को छोड़कर null output निकाला जा रहा है,
तो मुझे लगता है कि इस हिस्से में internal logger के रूप के अनुसार अंतर निश्चित रूप से हो सकता है।
इस हिस्से में तो यह Pino से तीन गुना तक का अंतर दिखा रहा है। वाह।
FYI: अतिरिक्त रूप से, जिस बाहर से inject किए जाने वाले logger के रूप का मैंने ज़िक्र किया था, उसे आप सिर्फ Openai Node sdk देखकर भी आसानी से समझ सकते हैं, क्योंकि वह भी logger को बाहर से inject लेकर output देने वाले रूप का उपयोग करता है.
https://github.com/dahlia/logtape/…