7

मैं जीसीपी ऐपइंजिन के लिए नया हूं और मैंने कई कारणों से लचीला वातावरण चुना है। हालांकि, मुझे यह पता लगाने में आश्चर्य हुआ कि लचीला वातावरण का गैर-संगत "रनटाइम मुझे क्लाउड लॉगिंग में उचित लॉग स्तर पर मेरे ऐप की लॉगिंग ईवेंट मैप करने की अनुमति नहीं देता है। क्या मैं इसे सही ढंग से पढ़ रहा हूं? https://cloud.google.com/appengine/docs/flexible/java/writing-application-logs#writing_application_logs_1मैं जीसीपी फ्लेक्सिबल गैर-कॉम्पैट ऐप इंजन में संबंधित क्लाउड लॉगिंग ईवेंट स्तर पर अपने जावा ऐप लॉगिंग ईवेंट कैसे मैप करूं?

और यह पृष्ठ वास्तव में अनुपयोगी था। https://cloud.google.com/java/getting-started/logging-application-events

यह जीएई लॉगिंग की समस्याओं को पढ़ने के कई घंटों बाद और यह निर्धारित करने की कोशिश कर रहा है कि मानक पर्यावरण बनाम फ्लेक्सिबल पर कौन सा लागू होता है। सर्वश्रेष्ठ मैं बता सकता हूं, मानक वातावरण में इवेंट लेवल मैपिंग संभव है।

हालांकि, मेघ प्लेटफ़ॉर्म कंसोल में लॉग स्तर प्रदर्शन के और अधिक कुशल नियंत्रण के लिए, प्रवेश ढांचा एक java.util.logging अनुकूलक का उपयोग करना चाहिए। https://cloud.google.com/appengine/docs/java/how-requests-are-handled#Java_Logging

ठीक है। यह एक अस्पष्ट संदर्भ है, लेकिन मुझे लगता है कि मैंने कहीं और कुछ और स्पष्ट देखा है।

भले ही, यह "लचीला" वातावरण में आसान नहीं होना चाहिए? लॉगिंग स्तरों से घटनाओं को आसानी से फ़िल्टर नहीं करना चाहते हैं?

अद्यतन: मैंने यह संकेत देने के लिए प्रश्न स्पष्ट किया कि मैं जीएई लचीला वातावरण में गैर-संगत रनटाइम के बारे में पूछ रहा हूं।

उत्तर

4

यहां बताया गया है कि मुझे SLF4J का उपयोग करके काम करने के लिए क्लाउड लॉगिंग कैसे मिली। यह गैर-संगत जावा जीएई फ्लेक्स पर्यावरण पर काम करता है।

logback.xml

<configuration debug="true"> 
    <appender name="FILE" class="ch.qos.logback.core.FileAppender"> 
     <file>/var/log/app_engine/custom_logs/app.log.json</file> 
     <append>true</append> 
     <!-- encoders are assigned the type ch.qos.logback.classic.encoder.PatternLayoutEncoder by default --> 
     <encoder class="ch.qos.logback.core.encoder.LayoutWrappingEncoder"> 
      <layout 
       class="putyourpackagenamehere.GCPCloudLoggingJSONLayout"> 
       <pattern>%-4relative [%thread] %-5level %logger{35} - %msg</pattern> 
      </layout> 
     </encoder> 
    </appender> 
    <root level="DEBUG"> 
     <appender-ref ref="FILE" /> 
    </root> 
</configuration> 

यहाँ PatternLayout वर्ग मैं लॉग फ़ाइल में एक पंक्ति पर JSON का उत्पादन किया जाता है।

import static ch.qos.logback.classic.Level.DEBUG_INT; 
import static ch.qos.logback.classic.Level.ERROR_INT; 
import static ch.qos.logback.classic.Level.INFO_INT; 
import static ch.qos.logback.classic.Level.TRACE_INT; 
import static ch.qos.logback.classic.Level.WARN_INT; 

import java.util.Map; 

import org.json.JSONObject; 

import com.homedepot.ta.wh.common.logging.GCPCloudLoggingJSONLayout.GCPCloudLoggingEvent.GCPCloudLoggingTimestamp; 

import ch.qos.logback.classic.Level; 
import ch.qos.logback.classic.PatternLayout; 
import ch.qos.logback.classic.spi.ILoggingEvent; 

/** 
* Format a LoggingEvent as a single line JSON object 
* 
* <br>https://cloud.google.com/appengine/docs/flexible/java/writing-application-logs 
* 
* <br>From https://cloud.google.com/appengine/articles/logging 
* <quote> 
* Applications using the flexible environment should write custom log files to the VM's log directory at 
* /var/log/app_engine/custom_logs. These files are automatically collected and made available in the Logs Viewer. 
* Custom log files must have the suffix .log or .log.json. If the suffix is .log.json, the logs must be in JSON 
* format with one JSON object per line. If the suffix is .log, log entries are treated as plain text. 
* </quote> 
* 
* Nathan: I can't find a reference to this format on the google pages but I do remember getting the format from some 
* GO code that a googler on the community slack channel referred me to. 
*/ 
public class GCPCloudLoggingJSONLayout extends PatternLayout { 

    @Override 
    public String doLayout(ILoggingEvent event) { 
     String formattedMessage = super.doLayout(event); 
     return doLayout_internal(formattedMessage, event); 
    } 

    /* for testing without having to deal wth the complexity of super.doLayout() 
    * Uses formattedMessage instead of event.getMessage() */ 
    String doLayout_internal(String formattedMessage, ILoggingEvent event) { 
     GCPCloudLoggingEvent gcpLogEvent = new GCPCloudLoggingEvent(formattedMessage 
                    , convertTimestampToGCPLogTimestamp(event.getTimeStamp()) 
                    , mapLevelToGCPLevel(event.getLevel()) 
                    , null); 
     JSONObject jsonObj = new JSONObject(gcpLogEvent); 
     /* Add a newline so that each JSON log entry is on its own line. 
     * Note that it is also important that the JSON log entry does not span multiple lines. 
     */ 
     return jsonObj.toString() + "\n"; 
    } 

    static GCPCloudLoggingTimestamp convertTimestampToGCPLogTimestamp(long millisSinceEpoch) { 
     int nanos = ((int) (millisSinceEpoch % 1000)) * 1_000_000; // strip out just the milliseconds and convert to nanoseconds 
     long seconds = millisSinceEpoch/1000L; // remove the milliseconds 
     return new GCPCloudLoggingTimestamp(seconds, nanos); 
    } 

    static String mapLevelToGCPLevel(Level level) { 
     switch (level.toInt()) { 
     case TRACE_INT: 
      return "TRACE"; 
     case DEBUG_INT: 
      return "DEBUG"; 
     case INFO_INT: 
      return "INFO"; 
     case WARN_INT: 
      return "WARN"; 
     case ERROR_INT: 
      return "ERROR"; 
     default: 
      return null; /* This should map to no level in GCP Cloud Logging */ 
     } 
    } 

    /* Must be public for JSON marshalling logic */ 
    public static class GCPCloudLoggingEvent { 
     private String message; 
     private GCPCloudLoggingTimestamp timestamp; 
     private String traceId; 
     private String severity; 

     public GCPCloudLoggingEvent(String message, GCPCloudLoggingTimestamp timestamp, String severity, 
       String traceId) { 
      super(); 
      this.message = message; 
      this.timestamp = timestamp; 
      this.traceId = traceId; 
      this.severity = severity; 
     } 

     public String getMessage() { 
      return message; 
     } 

     public void setMessage(String message) { 
      this.message = message; 
     } 

     public GCPCloudLoggingTimestamp getTimestamp() { 
      return timestamp; 
     } 

     public void setTimestamp(GCPCloudLoggingTimestamp timestamp) { 
      this.timestamp = timestamp; 
     } 

     public String getTraceId() { 
      return traceId; 
     } 

     public void setTraceId(String traceId) { 
      this.traceId = traceId; 
     } 

     public String getSeverity() { 
      return severity; 
     } 

     public void setSeverity(String severity) { 
      this.severity = severity; 
     } 

     /* Must be public for JSON marshalling logic */ 
     public static class GCPCloudLoggingTimestamp { 
      private long seconds; 
      private int nanos; 

      public GCPCloudLoggingTimestamp(long seconds, int nanos) { 
       super(); 
       this.seconds = seconds; 
       this.nanos = nanos; 
      } 

      public long getSeconds() { 
       return seconds; 
      } 

      public void setSeconds(long seconds) { 
       this.seconds = seconds; 
      } 

      public int getNanos() { 
       return nanos; 
      } 

      public void setNanos(int nanos) { 
       this.nanos = nanos; 
      } 

     }  
    } 

    @Override 
    public Map<String, String> getDefaultConverterMap() { 
     return PatternLayout.defaultConverterMap; 
    } 
} 
+1

इसे पोस्ट करने के लिए धन्यवाद - मेरे लिए एक बड़ी समस्या हल हो गई। गिटहब पर डालने का कोई विचार है ताकि हम इसे बेहतर बना सकें? एक चीज जो काम नहीं करती है, एक ही समूह में एक ही अनुरोध के लिए सभी लॉग को ध्वस्त कर रहा है, जिस तरह से जीएई क्लासिक काम करता है। – sappenin

0

java.util.logging द्वारा प्रदान किए गए लॉग स्तर क्लाउड लॉगिंग में उचित लॉग स्तर पर मानचित्रित होंगे। फ्लेक्सिबल रनटाइम पर लॉगिंग अनिवार्य रूप से वही काम करता है जैसे यह मानक पर करता है।

संपादित: ऐसा लगता है 'Writing Application Logs' पृष्ठ के लिए तर्क यह है कि बादल लॉगिंग मैपिंग runtimes के सभी के लिए काम नहीं करते है। हालांकि, वे वर्तमान में कम से कम '-compat' रनटाइम और जावा कस्टम रनटाइम के लिए काम करते हैं। अन्य लोगों के लिए वर्कअराउंड डॉक्स में कहीं और प्रदान किए जाते हैं (नीचे देखें):

जावा एप्लिकेशन में लॉगिंग की अनुशंसित डिफ़ॉल्ट विधि java.util.logging (पायथन के लिए 'लॉगिंग' मॉड्यूल का उपयोग करना है, और गो के लिए यह 'लॉग' है पैकेज, जिनमें से सभी लॉग स्तर प्रदान करते हैं जो क्लाउड लॉगिंग स्तर पर मैप करते हैं)। मैं अनुरोध करूंगा कि ये पृष्ठ अपडेट हो जाएंगे।

आपके द्वारा लिंक किए गए अन्य दस्तावेज़ जावा के लिए लॉगिंग के बारे में सटीक जानकारी प्रदान करते हैं। आपके द्वारा उद्धृत अनुभाग के संबंध में, full paragraph it was pulled from संदर्भ प्रदान करता है। यह कह रहा है कि कोई भी लॉगिंग फ्रेमवर्क जो स्टडर या स्टडआउट को लिखता है, काम करेगा, लेकिन अगर आपको 'INFO' या 'चेतावनी' के अलावा अधिक बढ़िया लॉग स्तर चाहिए तो इसे 'java.util.logging' का उपयोग करने की आवश्यकता है। 'Java.util.logging' का उपयोग करने के लिए एक पूर्ण कोड नमूना सीधे उद्धृत अनुभाग के नीचे प्रदान किया जाता है, और अन्य आपके द्वारा उल्लेखित अन्य दस्तावेज़ पर प्रदान किए जाते हैं, 'Logging Application Events with Java'।

अद्यतन:

जावा
https://cloud.google.com/java/getting-started/logging-application-events#understanding_the_code

अजगर
https://cloud.google.com/python/getting-started/logging-application-events#understanding_the_code

: 'प्रारंभ करना' गाइड कैसे प्रत्येक क्रम के लिए लॉगिंग को कॉन्फ़िगर करने पर विशिष्ट विवरण शामिल जाओ
https://cloud.google.com/go/getting-started/logging-application-events

NodeJS
https://cloud.google.com/nodejs/getting-started/logging-application-events#understanding_the_code

रूबी
https://cloud.google.com/ruby/getting-started/logging-application-events#application_structure

पीएचपी
https://cloud.google.com/php/getting-started/logging-application-events

+1

क्या आपने यह कोशिश की है? मेरा मानना ​​है कि मैंने किया और यह मेरे लिए काम नहीं किया। आईआईआरसी, लॉग स्तर बिल्कुल मैप नहीं किए गए थे और बहु-लाइन लॉग इवेंट एक साथ नहीं रखे गए थे। मैं एक लॉग इवेंट फॉर्मेटर (मैंने SLF4J का उपयोग किया) को एक लॉग लाइन JSON दस्तावेज़ के रूप में प्रारूपित करने के लिए समाप्त किया, जिसे औपचारिक रूप से निर्दिष्ट नहीं किया गया था। मुझे कुछ जीओ कोड में प्रारूप मिला कि जीसीपी स्लैक समुदाय के किसी ने मुझे बताया। – successhawk

+0

मैंने जावा-कॉम्पैट, जेट्टी 9-कॉम्पैट, और पायथन-कॉम्पैट-मल्टीकोर रनटाइम्स पर 'रनटाइम: कस्टम' का उपयोग करके ऐप.यामल में इसका परीक्षण किया है। App.yaml में डिफ़ॉल्ट 'रनटाइम: जावा' रनटाइम '[जावा 8/जेटी 9.3 रनटाइम] का चयन करता है (https://cloud.google.com/appengine/docs/flexible/java/configuring-your-app-with- ऐप-यमल) 'जिसकी क्लाउड लॉगिंग कनेक्टर नहीं है। – Adam

+0

धन्यवाद, एडम। मैंने अपने प्रश्न को स्पष्ट करने के लिए स्पष्ट किया कि मैं "संगत" रनटाइम का उपयोग नहीं कर रहा हूं। मुझे एहसास नहीं हुआ कि मैंने देखा है कि सभी दस्तावेजों के आधार पर लॉगिंग से संबंधित एक अंतर होगा। – successhawk

संबंधित मुद्दे