1. परिचय
पिछला अपडेट: 15-07-2022
ऐप्लिकेशन को मॉनिटर करना
निगरानी और OpenTelemetry
निगरानी, किसी सिस्टम के एट्रिब्यूट के बारे में बताने के लिए इस्तेमाल किया जाने वाला शब्द है. मॉनिटर किए जा सकने वाले सिस्टम की मदद से, टीमें अपने सिस्टम को लगातार डीबग कर सकती हैं. इस संदर्भ में, निगरानी के तीन पिलर; लॉग, मेट्रिक, और ट्रेस, सिस्टम के लिए निगरानी करने के बुनियादी इंस्ट्रूमेंट हैं.
OpenTelemetry, खास जानकारी, लाइब्रेरी, और एजेंट का एक सेट है. यह मेज़रमेंट के लिए ज़रूरी टेलीमेट्री डेटा (लॉग, मेट्रिक, और ट्रेस) को इंस्ट्रूमेंट करने और एक्सपोर्ट करने की प्रोसेस को तेज़ करता है. OpenTelemetry, CNCF के तहत एक ओपन स्टैंडर्ड और कम्यूनिटी से चलने वाला प्रोजेक्ट है. प्रोजेक्ट और उसके इकोसिस्टम में मौजूद लाइब्रेरी का इस्तेमाल करके, डेवलपर अपने ऐप्लिकेशन को वेंडर के हिसाब से और कई आर्किटेक्चर के हिसाब से इंस्ट्रूमेंट कर सकते हैं.
निगरानी के तीन मुख्य पहलुओं के अलावा, निगरानी के लिए एक और अहम कॉम्पोनेंट है, लगातार प्रोफ़ाइल बनाना. इससे इंडस्ट्री में उपयोगकर्ताओं की संख्या बढ़ रही है. Cloud Profiler, इस सुविधा को शुरू करने वाले टूल में से एक है. यह ऐप्लिकेशन कॉल स्टैक में परफ़ॉर्मेंस मेट्रिक को ड्रिल-डाउन करने के लिए, आसान इंटरफ़ेस उपलब्ध कराता है.
यह कोडलैब, सीरीज़ का पहला हिस्सा है. इसमें OpenTelemetry और Cloud Trace की मदद से, माइक्रोसर्विस में डिस्ट्रिब्यूट किए गए ट्रेस को इंस्ट्रूमेंट करने के बारे में बताया गया है. दूसरे भाग में, Cloud Profiler की मदद से प्रोफ़ाइल बनाने की प्रोसेस के बारे में बताया जाएगा.
डिस्ट्रिब्यूटेड ट्रेस
लॉग, मेट्रिक, और ट्रेस में से, ट्रेस एक ऐसा टेलीमेट्री है जो सिस्टम में प्रोसेस के किसी खास हिस्से के इंतज़ार का समय बताता है. खास तौर पर, माइक्रोसर्विस के दौर में, डिस्ट्रिब्यूटेड ट्रेस, पूरे डिस्ट्रिब्यूटेड सिस्टम में इंतज़ार का समय कम करने में मदद करता है.
डिस्ट्रिब्यूट किए गए ट्रेस का विश्लेषण करते समय, ट्रेस डेटा विज़ुअलाइज़ेशन की मदद से, सिस्टम के इंतज़ार का कुल समय एक नज़र में समझा जा सकता है. डिस्ट्रिब्यूटेड ट्रेस में, हम सिस्टम के एंट्रीपॉइंट पर एक अनुरोध को प्रोसेस करने के लिए, कॉल के एक सेट को हैंडल करते हैं. यह अनुरोध, कई स्पैन वाले ट्रेस के तौर पर होता है.
स्पैन, डिस्ट्रिब्यूटेड सिस्टम में किए गए काम की अलग-अलग यूनिट को दिखाता है. इसमें काम शुरू और खत्म होने का समय रिकॉर्ड किया जाता है. स्पैन के बीच अक्सर हैरारकी वाला संबंध होता है - नीचे दी गई इमेज में, सभी छोटे स्पैन, बड़े /messages स्पैन के चाइल्ड स्पैन हैं. साथ ही, इन्हें एक ट्रेस में इकट्ठा किया जाता है, जो सिस्टम के ज़रिए काम के पाथ को दिखाता है.
Google Cloud Trace, डिस्ट्रिब्यूटेड ट्रेस बैकएंड के विकल्पों में से एक है. यह Google Cloud के अन्य प्रॉडक्ट के साथ अच्छी तरह से इंटिग्रेट है.
आपको क्या बनाना है
इस कोडलैब में, आपको "शेक्सपियर ऐप्लिकेशन" (जिसे Shakesapp भी कहा जाता है) नाम की सेवाओं में, ट्रैक की गई जानकारी को इंस्ट्रूमेंट करना है. यह सेवा, Google Kubernetes Engine क्लस्टर पर चलती है. Shakesapp का आर्किटेक्चर नीचे बताया गया है:
- Loadgen, एचटीटीपी में क्लाइंट को क्वेरी स्ट्रिंग भेजता है
- क्लाइंट, gRPC में loadgen से सर्वर तक क्वेरी भेजते हैं
- सर्वर, क्लाइंट से क्वेरी स्वीकार करता है. इसके बाद, Google Cloud Storage से शेक्सपियर के सभी कामों को टेक्स्ट फ़ॉर्मैट में फ़ेच करता है. साथ ही, क्वेरी वाली लाइनें खोजता है और क्लाइंट से मैच होने वाली लाइन की संख्या दिखाता है
आपको अनुरोध के दौरान, ट्रैक की जानकारी को इंस्ट्रूमेंट करना होगा. इसके बाद, आपको सर्वर में प्रोफ़ाइलर एजेंट जोड़ना होगा और समस्या की जांच करनी होगी.
आपको इनके बारे में जानकारी मिलेगी
- Go प्रोजेक्ट में OpenTelemetry ट्रैक लाइब्रेरी का इस्तेमाल शुरू करने का तरीका
- लाइब्रेरी की मदद से स्पैन बनाने का तरीका
- ऐप्लिकेशन कॉम्पोनेंट के बीच, स्पैन कॉन्टेक्स्ट को वायर पर भेजने का तरीका
- Cloud Trace को ट्रैक डेटा भेजने का तरीका
- Cloud Trace पर ट्रैक का विश्लेषण करने का तरीका
इस कोडलैब में, माइक्रोसर्विस को इंस्ट्रूमेंट करने का तरीका बताया गया है. इसे आसानी से समझने के लिए, इस उदाहरण में सिर्फ़ तीन कॉम्पोनेंट (लोड जनरेटर, क्लाइंट, और सर्वर) शामिल किए गए हैं. हालांकि, इस कोडलैब में बताई गई प्रोसेस को ज़्यादा जटिल और बड़े सिस्टम पर भी लागू किया जा सकता है.
आपको इन चीज़ों की ज़रूरत होगी
- Go की बुनियादी जानकारी
- Kubernetes के बारे में बुनियादी जानकारी
2. सेटअप और ज़रूरी शर्तें
अपने हिसाब से एनवायरमेंट सेट अप करना
अगर आपके पास पहले से कोई Google खाता (Gmail या Google Apps) नहीं है, तो आपको एक खाता बनाना होगा. Google Cloud Platform Console ( console.cloud.google.com) में साइन इन करें और नया प्रोजेक्ट बनाएं.
अगर आपके पास पहले से कोई प्रोजेक्ट है, तो कंसोल के ऊपर बाईं ओर मौजूद, प्रोजेक्ट चुनने के लिए उपलब्ध पुल-डाउन मेन्यू पर क्लिक करें:
नया प्रोजेक्ट बनाने के लिए, इसके बाद दिखने वाले डायलॉग में ‘नया प्रोजेक्ट' बटन पर क्लिक करें:
अगर आपके पास पहले से कोई प्रोजेक्ट नहीं है, तो आपको अपना पहला प्रोजेक्ट बनाने के लिए, ऐसा डायलॉग दिखेगा:
प्रोजेक्ट बनाने के बाद दिखने वाले डायलॉग बॉक्स में, अपने नए प्रोजेक्ट की जानकारी डाली जा सकती है:
प्रोजेक्ट आईडी याद रखें. यह Google Cloud के सभी प्रोजेक्ट के लिए यूनीक नाम होता है. ऊपर दिया गया नाम पहले से ही ले लिया गया है और यह आपके लिए काम नहीं करेगा. माफ़ करें! इस कोडलैब में बाद में, इसे PROJECT_ID के तौर पर इस्तेमाल किया जाएगा.
इसके बाद, अगर आपने अब तक ऐसा नहीं किया है, तो आपको Google Cloud के संसाधनों का इस्तेमाल करने और Cloud Trace API को चालू करने के लिए, Developers Console में बिलिंग की सुविधा चालू करनी होगी.
इस कोडलैब को चलाने में आपको कुछ डॉलर से ज़्यादा खर्च नहीं करने पड़ेंगे. हालांकि, ज़्यादा संसाधनों का इस्तेमाल करने या उन्हें चालू रहने देने पर, खर्च ज़्यादा हो सकता है. इस दस्तावेज़ के आखिर में मौजूद "क्लीनअप" सेक्शन देखें. Google Cloud Trace, Google Kubernetes Engine, और Google Artifact Registry की कीमतें, आधिकारिक दस्तावेज़ में दी गई हैं.
- Google Cloud के ऑपरेशंस सुइट की कीमत | ऑपरेशंस सुइट
- कीमत | Kubernetes Engine के दस्तावेज़
- Artifact Registry की कीमत | Artifact Registry के दस्तावेज़
Google Cloud Platform के नए उपयोगकर्ता, 300 डॉलर के मुफ़्त ट्रायल की सुविधा का फ़ायदा ले सकते हैं. इस वजह से, यह कोडलैब पूरी तरह से बिना किसी शुल्क के उपलब्ध है.
Google Cloud Shell सेटअप करना
Google Cloud और Google Cloud Trace को आपके लैपटॉप से रिमोट तौर पर ऑपरेट किया जा सकता है. हालांकि, इस कोडलैब में हम Google Cloud Shell का इस्तेमाल करेंगे. यह क्लाउड में चलने वाला कमांड-लाइन एनवायरमेंट है.
इस डेबियन-आधारित वर्चुअल मशीन में, डेवलपमेंट के लिए ज़रूरी सभी टूल लोड होते हैं. यह 5 जीबी की होम डायरेक्ट्री उपलब्ध कराती है और Google Cloud में काम करती है. इससे नेटवर्क की परफ़ॉर्मेंस और पुष्टि करने की प्रोसेस बेहतर होती है. इसका मतलब है कि इस कोडलैब के लिए, आपको सिर्फ़ एक ब्राउज़र की ज़रूरत होगी. हां, यह Chromebook पर काम करता है.
Cloud Console से Cloud Shell को चालू करने के लिए, बस Cloud Shell चालू करें पर क्लिक करें. इसे एनवायरमेंट से कनेक्ट और प्रोवाइड करने में कुछ ही मिनट लगेंगे.
Cloud Shell से कनेक्ट होने के बाद, आपको दिखेगा कि आपने पहले ही पुष्टि कर ली है और प्रोजेक्ट पहले से ही आपके PROJECT_ID
पर सेट है.
gcloud auth list
कमांड आउटपुट
Credentialed accounts: - <myaccount>@<mydomain>.com (active)
gcloud config list project
कमांड आउटपुट
[core] project = <PROJECT_ID>
अगर किसी वजह से प्रोजेक्ट सेट नहीं है, तो बस यह कमांड दें:
gcloud config set project <PROJECT_ID>
क्या आपको PROJECT_ID
खोजना है? देखें कि सेटअप के दौरान किस आईडी का इस्तेमाल किया गया था या Cloud Console के डैशबोर्ड में जाकर यह पता लगाएं:
Cloud Shell, कुछ एनवायरमेंट वैरिएबल को डिफ़ॉल्ट रूप से भी सेट करता है. आने वाले समय में कमांड चलाते समय, ये वैरिएबल आपके काम आ सकते हैं.
echo $GOOGLE_CLOUD_PROJECT
कमांड आउटपुट
<PROJECT_ID>
आखिर में, डिफ़ॉल्ट ज़ोन और प्रोजेक्ट कॉन्फ़िगरेशन सेट करें.
gcloud config set compute/zone us-central1-f
आपके पास कई तरह के ज़ोन चुनने का विकल्प होता है. ज़्यादा जानकारी के लिए, इलाके और ज़ोन देखें.
भाषा सेटअप करने के लिए
इस कोडलैब में, हम सभी सोर्स कोड के लिए Go का इस्तेमाल करते हैं. Cloud Shell पर यह कमांड चलाएं और पुष्टि करें कि Go का वर्शन 1.17 या उसके बाद का है
go version
कमांड आउटपुट
go version go1.18.3 linux/amd64
Google Kubernetes क्लस्टर सेट अप करना
इस कोडलैब में, आपको Google Kubernetes Engine (GKE) पर माइक्रोसर्विस का क्लस्टर चलाना होगा. इस कोडलैब की प्रोसेस इस तरह की है:
- Cloud Shell में बेसलाइन प्रोजेक्ट डाउनलोड करना
- कंटेनर में माइक्रोसर्विस बनाना
- Google Artifact Registry (GAR) पर कंटेनर अपलोड करना
- GKE पर कंटेनर डिप्लॉय करना
- ट्रैक इंस्ट्रूमेंटेशन के लिए, सेवाओं के सोर्स कोड में बदलाव करना
- दूसरे चरण पर जाएं
Kubernetes Engine चालू करना
सबसे पहले, हमने एक Kubernetes क्लस्टर सेट अप किया, जहां Shakesapp, GKE पर चलता है. इसलिए, हमें GKE चालू करना होगा. "Kubernetes Engine" मेन्यू पर जाएं और चालू करें बटन दबाएं.
अब आप Kubernetes क्लस्टर बनाने के लिए तैयार हैं.
Kubernetes क्लस्टर बनाना
Kubernetes क्लस्टर बनाने के लिए, Cloud Shell में यह कमांड चलाएं. कृपया पुष्टि करें कि ज़ोन की वैल्यू उस क्षेत्र में है जिसका इस्तेमाल आर्टफ़ैक्ट रजिस्ट्री रिपॉज़िटरी बनाने के लिए किया जाएगा. अगर आपका रिपॉज़िटरी क्षेत्र ज़ोन को कवर नहीं कर रहा है, तो ज़ोन की वैल्यू us-central1-f
बदलें.
gcloud container clusters create otel-trace-codelab2 \ --zone us-central1-f \ --release-channel rapid \ --preemptible \ --enable-autoscaling \ --max-nodes 8 \ --no-enable-ip-alias \ --scopes cloud-platform
कमांड आउटपुट
Note: Your Pod address range (`--cluster-ipv4-cidr`) can accommodate at most 1008 node(s). Creating cluster otel-trace-codelab2 in us-central1-f... Cluster is being health-checked (master is healthy)...done. Created [https://container.googleapis.com/v1/projects/development-215403/zones/us-central1-f/clusters/otel-trace-codelab2]. To inspect the contents of your cluster, go to: https://console.cloud.google.com/kubernetes/workload_/gcloud/us-central1-f/otel-trace-codelab2?project=development-215403 kubeconfig entry generated for otel-trace-codelab2. NAME: otel-trace-codelab2 LOCATION: us-central1-f MASTER_VERSION: 1.23.6-gke.1501 MASTER_IP: 104.154.76.89 MACHINE_TYPE: e2-medium NODE_VERSION: 1.23.6-gke.1501 NUM_NODES: 3 STATUS: RUNNING
Artifact Registry और skaffold सेटअप करना
अब हमारे पास डिप्लॉयमेंट के लिए Kubernetes क्लस्टर तैयार है. इसके बाद, हम कंटेनर को पुश और डिप्लॉय करने के लिए, कंटेनर रजिस्ट्री तैयार करते हैं. इन चरणों के लिए, हमें आर्टफ़ैक्ट रजिस्ट्री (GAR) सेट अप करना होगा. साथ ही, इसका इस्तेमाल करने के लिए skaffold भी सेट अप करना होगा.
Artifact Registry का सेटअप
"आर्टफ़ैक्ट रजिस्ट्री" के मेन्यू पर जाएं और 'चालू करें' बटन दबाएं.
कुछ देर बाद, आपको GAR का रिपॉज़िटरी ब्राउज़र दिखेगा. "रिपॉज़िटरी बनाएं" बटन पर क्लिक करें और रिपॉज़िटरी का नाम डालें.
इस कोडलैब में, मैंने नए रिपॉज़िटरी का नाम trace-codelab
रखा है. आर्टफ़ैक्ट का फ़ॉर्मैट "Docker" है और जगह का टाइप "क्षेत्र" है. Google Compute Engine के डिफ़ॉल्ट ज़ोन के लिए सेट किए गए ज़ोन के आस-पास का कोई क्षेत्र चुनें. उदाहरण के लिए, इस उदाहरण में ऊपर "us-central1-f" चुना गया है. इसलिए, यहां हम "us-central1 (Iowa)" चुनते हैं. इसके बाद, "बनाएं" बटन पर क्लिक करें.
अब आपको रिपॉज़िटरी ब्राउज़र पर "trace-codelab" दिखेगा.
हम रजिस्ट्री पाथ की जांच करने के लिए, बाद में यहां वापस आएंगे.
Skaffold सेटअप करना
Kubernetes पर चलने वाली माइक्रोसर्विस बनाने के लिए, Skaffold एक आसान टूल है. यह कमांड के छोटे से सेट की मदद से, ऐप्लिकेशन के कंटेनर बनाने, उन्हें पुश करने, और डिप्लॉय करने के वर्कफ़्लो को मैनेज करता है. Skaffold, डिफ़ॉल्ट रूप से कंटेनर रजिस्ट्री के तौर पर Docker रजिस्ट्री का इस्तेमाल करता है. इसलिए, आपको कंटेनर को पुश करने पर GAR को पहचानने के लिए, skaffold को कॉन्फ़िगर करना होगा.
Cloud Shell को फिर से खोलें और पुष्टि करें कि skaffold इंस्टॉल है या नहीं. (Cloud Shell, skaffold को एनवायरमेंट में डिफ़ॉल्ट रूप से इंस्टॉल करता है.) यह कमांड चलाकर, skaffold का वर्शन देखें.
skaffold version
कमांड आउटपुट
v1.38.0
अब, skaffold का इस्तेमाल करने के लिए डिफ़ॉल्ट रिपॉज़िटरी रजिस्टर किया जा सकता है. रजिस्ट्री पाथ पाने के लिए, Artifact Registry के डैशबोर्ड पर जाएं और उस रिपॉज़िटरी के नाम पर क्लिक करें जिसे आपने पिछले चरण में सेट अप किया था.
इसके बाद, आपको पेज पर सबसे ऊपर ब्रेडक्रंब ट्रेल दिखेंगे. रजिस्ट्री पाथ को क्लिपबोर्ड पर कॉपी करने के लिए, आइकॉन पर क्लिक करें.
'कॉपी करें' बटन पर क्लिक करने पर, आपको ब्राउज़र में सबसे नीचे यह डायलॉग दिखेगा:
"us-central1-docker.pkg.dev/psychic-order-307806/trace-codelab" को कॉपी किया गया
Cloud Shell पर वापस जाएं. डैशबोर्ड से कॉपी की गई वैल्यू के साथ skaffold config set default-repo
कमांड चलाएं.
skaffold config set default-repo us-central1-docker.pkg.dev/psychic-order-307806/trace-codelab
कमांड आउटपुट
set value default-repo to us-central1-docker.pkg.dev/psychic-order-307806/trace-codelab for context gke_stackdriver-sandbox-3438851889_us-central1-b_stackdriver-sandbox
साथ ही, आपको रजिस्ट्री को Docker कॉन्फ़िगरेशन के हिसाब से कॉन्फ़िगर करना होगा. यह कमांड चलाएं:
gcloud auth configure-docker us-central1-docker.pkg.dev --quiet
कमांड आउटपुट
{ "credHelpers": { "gcr.io": "gcloud", "us.gcr.io": "gcloud", "eu.gcr.io": "gcloud", "asia.gcr.io": "gcloud", "staging-k8s.gcr.io": "gcloud", "marketplace.gcr.io": "gcloud", "us-central1-docker.pkg.dev": "gcloud" } } Adding credentials for: us-central1-docker.pkg.dev
अब GKE पर Kubernetes कंटेनर सेट अप करने के अगले चरण पर जाएं.
खास जानकारी
इस चरण में, आपको अपना कोडलैब एनवायरमेंट सेट अप करना होगा:
- Cloud Shell सेट अप करना
- कंटेनर रजिस्ट्री के लिए Artifact Registry का डेटा स्टोर करने की जगह बनाई गई
- कंटेनर रजिस्ट्री का इस्तेमाल करने के लिए, skaffold सेट अप करना
- कोडलैब की माइक्रोसर्विस चलाने के लिए Kubernetes क्लस्टर बनाया
अगला चरण
अगले चरण में, आपको क्लस्टर पर अपनी माइक्रोसर्विस बनानी होंगी, उन्हें पुश करना होगा, और उन्हें डिप्लॉय करना होगा
3. माइक्रोसर्विस बनाना, उन्हें पुश करना, और डिप्लॉय करना
कोडलैब का मटीरियल डाउनलोड करना
पिछले चरण में, हमने इस कोडलैब के लिए सभी ज़रूरी शर्तें सेट अप कर दी हैं. अब आपके पास उन पर पूरी माइक्रोसर्विस चलाने का विकल्प है. कोडलैब का कॉन्टेंट GitHub पर होस्ट किया जाता है. इसलिए, यहां दिए गए git कमांड का इस्तेमाल करके, उसे Cloud Shell के एनवायरमेंट में डाउनलोड करें.
cd ~ git clone https://github.com/ymotongpoo/opentelemetry-trace-codelab-go.git cd opentelemetry-trace-codelab-go
प्रोजेक्ट का डायरेक्ट्री स्ट्रक्चर इस तरह का है:
. ├── README.md ├── step0 │ ├── manifests │ ├── proto │ ├── skaffold.yaml │ └── src ├── step1 │ ├── manifests │ ├── proto │ ├── skaffold.yaml │ └── src ├── step2 │ ├── manifests │ ├── proto │ ├── skaffold.yaml │ └── src ├── step3 │ ├── manifests │ ├── proto │ ├── skaffold.yaml │ └── src ├── step4 │ ├── manifests │ ├── proto │ ├── skaffold.yaml │ └── src ├── step5 │ ├── manifests │ ├── proto │ ├── skaffold.yaml │ └── src └── step6 ├── manifests ├── proto ├── skaffold.yaml └── src
- मेनिफ़ेस्ट: Kubernetes मेनिफ़ेस्ट फ़ाइलें
- proto: क्लाइंट और सर्वर के बीच कम्यूनिकेशन के लिए प्रोटो की परिभाषा
- src: हर सेवा के सोर्स कोड के लिए डायरेक्ट्री
- skaffold.yaml: skaffold के लिए कॉन्फ़िगरेशन फ़ाइल
इस कोडलैब में, आपको step0
फ़ोल्डर में मौजूद सोर्स कोड को अपडेट करना होगा. जवाब पाने के लिए, step[1-6]
फ़ोल्डर में मौजूद सोर्स कोड को भी देखा जा सकता है. इसके लिए, यहां दिया गया तरीका अपनाएं. (पहले हिस्से में पहला से चौथा चरण और दूसरे हिस्से में पांचवां और छठा चरण शामिल है)
skaffold कमांड चलाना
आखिर में, आपने जो Kubernetes क्लस्टर बनाया है उस पर पूरा कॉन्टेंट बनाने, पुश करने, और डिप्लॉय करने के लिए तैयार हैं. ऐसा लगता है कि इसमें कई चरण शामिल हैं, लेकिन असल में skaffold आपके लिए सब कुछ करता है. आइए, इस निर्देश की मदद से ऐसा करके देखते हैं:
cd step0 skaffold dev
निर्देश चलाने के तुरंत बाद, आपको docker build
का लॉग आउट दिखता है. साथ ही, यह पुष्टि की जा सकती है कि उन्हें रजिस्ट्री में पुश कर दिया गया है.
कमांड आउटपुट
... ---> Running in c39b3ea8692b ---> 90932a583ab6 Successfully built 90932a583ab6 Successfully tagged us-central1-docker.pkg.dev/psychic-order-307806/trace-codelab/serverservice:step1 The push refers to repository [us-central1-docker.pkg.dev/psychic-order-307806/trace-codelab/serverservice] cc8f5a05df4a: Preparing 5bf719419ee2: Preparing 2901929ad341: Preparing 88d9943798ba: Preparing b0fdf826a39a: Preparing 3c9c1e0b1647: Preparing f3427ce9393d: Preparing 14a1ca976738: Preparing f3427ce9393d: Waiting 14a1ca976738: Waiting 3c9c1e0b1647: Waiting b0fdf826a39a: Layer already exists 88d9943798ba: Layer already exists f3427ce9393d: Layer already exists 3c9c1e0b1647: Layer already exists 14a1ca976738: Layer already exists 2901929ad341: Pushed 5bf719419ee2: Pushed cc8f5a05df4a: Pushed step1: digest: sha256:8acdbe3a453001f120fb22c11c4f6d64c2451347732f4f271d746c2e4d193bbe size: 2001
सभी सेवा कंटेनर को पुश करने के बाद, Kubernetes डिप्लॉयमेंट अपने-आप शुरू हो जाते हैं.
कमांड आउटपुट
sha256:b71fce0a96cea08075dc20758ae561cf78c83ff656b04d211ffa00cedb77edf8 size: 1997 Tags used in deployment: - serverservice -> us-central1-docker.pkg.dev/psychic-order-307806/trace-codelab/serverservice:step4@sha256:8acdbe3a453001f120fb22c11c4f6d64c2451347732f4f271d746c2e4d193bbe - clientservice -> us-central1-docker.pkg.dev/psychic-order-307806/trace-codelab/clientservice:step4@sha256:b71fce0a96cea08075dc20758ae561cf78c83ff656b04d211ffa00cedb77edf8 - loadgen -> us-central1-docker.pkg.dev/psychic-order-307806/trace-codelab/loadgen:step4@sha256:eea2e5bc8463ecf886f958a86906cab896e9e2e380a0eb143deaeaca40f7888a Starting deploy... - deployment.apps/clientservice created - service/clientservice created - deployment.apps/loadgen created - deployment.apps/serverservice created - service/serverservice created
डिप्लॉयमेंट के बाद, आपको हर कंटेनर में स्टैंडर्ड आउटपुट (stdout) में, ऐप्लिकेशन के असल लॉग दिखेंगे. जैसे:
कमांड आउटपुट
[client] 2022/07/14 06:33:15 {"match_count":3040} [loadgen] 2022/07/14 06:33:15 query 'love': matched 3040 [client] 2022/07/14 06:33:15 {"match_count":3040} [loadgen] 2022/07/14 06:33:15 query 'love': matched 3040 [client] 2022/07/14 06:33:16 {"match_count":3040} [loadgen] 2022/07/14 06:33:16 query 'love': matched 3040 [client] 2022/07/14 06:33:19 {"match_count":463} [loadgen] 2022/07/14 06:33:19 query 'tear': matched 463 [loadgen] 2022/07/14 06:33:20 query 'world': matched 728 [client] 2022/07/14 06:33:20 {"match_count":728} [client] 2022/07/14 06:33:22 {"match_count":463} [loadgen] 2022/07/14 06:33:22 query 'tear': matched 463
ध्यान दें कि इस समय, आपको सर्वर से कोई भी मैसेज देखना है. ठीक है, अब आपके पास सेवाओं की डिस्ट्रिब्यूटेड ट्रैकिंग के लिए, OpenTelemetry की मदद से अपने ऐप्लिकेशन को इंस्ट्रूमेंट करने का विकल्प है.
सेवा को इंस्ट्रूमेंट करने से पहले, कृपया Ctrl-C का इस्तेमाल करके अपना क्लस्टर बंद कर दें.
कमांड आउटपुट
... [client] 2022/07/14 06:34:57 {"match_count":1} [loadgen] 2022/07/14 06:34:57 query 'what's past is prologue': matched 1 ^CCleaning up... - W0714 06:34:58.464305 28078 gcp.go:120] WARNING: the gcp auth plugin is deprecated in v1.22+, unavailable in v1.25+; use gcloud instead. - To learn more, consult https://cloud.google.com/blog/products/containers-kubernetes/kubectl-auth-changes-in-gke - deployment.apps "clientservice" deleted - service "clientservice" deleted - deployment.apps "loadgen" deleted - deployment.apps "serverservice" deleted - service "serverservice" deleted
खास जानकारी
इस चरण में, आपने अपने एनवायरमेंट में कोडलैब का कॉन्टेंट तैयार कर लिया है और यह पुष्टि कर ली है कि skaffold उम्मीद के मुताबिक काम कर रहा है.
अगला चरण
अगले चरण में, आपको ट्रैक की गई जानकारी को इंस्ट्रूमेंट करने के लिए, loadgen सेवा के सोर्स कोड में बदलाव करना होगा.
4. एचटीटीपी के लिए इंस्ट्रूमेंटेशन
ट्रेस इंस्ट्रूमेंटेशन और प्रॉपेगेशन का कॉन्सेप्ट
सोर्स कोड में बदलाव करने से पहले, हम आपको एक आसान डायग्राम की मदद से बताते हैं कि डिस्ट्रिब्यूटेड ट्रेस कैसे काम करते हैं.
इस उदाहरण में, हम Cloud Trace में ट्रैक और स्पैन की जानकारी एक्सपोर्ट करने के लिए कोड को इंस्ट्रूमेंट करते हैं. साथ ही, loadgen सेवा से सर्वर सेवा के अनुरोध में ट्रैक कॉन्टेक्स्ट को प्रॉपेगेट करते हैं.
Cloud Trace, एक ही ट्रैक आईडी वाले सभी स्पैन को एक ट्रैक में इकट्ठा कर सके, इसके लिए ऐप्लिकेशन को ट्रैक आईडी और स्पैन आईडी जैसे ट्रैक मेटाडेटा भेजने होंगे. साथ ही, ऐप्लिकेशन को डाउनस्ट्रीम सेवाओं का अनुरोध करने पर, ट्रेस कॉन्टेक्स्ट (पैरंट स्पैन के ट्रेस आईडी और स्पैन आईडी का कॉम्बिनेशन) को प्रॉग्रेस करना होगा, ताकि उन्हें पता चल सके कि वे किस ट्रेस कॉन्टेक्स्ट को हैंडल कर रहे हैं.
OpenTelemetry से आपको इन कामों में मदद मिलती है:
- यूनीक ट्रेस आईडी और स्पैन आईडी जनरेट करने के लिए
- बैकएंड में ट्रस आईडी और स्पैन आईडी एक्सपोर्ट करने के लिए
- अन्य सेवाओं पर ट्रेस कॉन्टेक्स्ट भेजने के लिए
- , ताकि अतिरिक्त मेटाडेटा जोड़ा जा सके. इससे ट्रेस का विश्लेषण करने में मदद मिलती है
OpenTelemetry ट्रेस में कॉम्पोनेंट
OpenTelemetry की मदद से ऐप्लिकेशन ट्रेस को इंस्ट्रूमेंट करने की प्रोसेस इस तरह की है:
- एक्सपोर्टर बनाना
- एक्सपोर्टर को 1 में बांधने वाला TracerProvider बनाएं और उसे ग्लोबल के तौर पर सेट करें.
- प्रॉपेगेशन का तरीका सेट करने के लिए, TextMapPropagaror सेट करें
- TracerProvider से ट्रैसर पाना
- ट्रैसर से स्पैन जनरेट करना
फ़िलहाल, आपको हर कॉम्पोनेंट की ज़्यादा जानकारी वाली प्रॉपर्टी को समझने की ज़रूरत नहीं है. हालांकि, आपको ये बातें याद रखनी चाहिए:
- यहां एक्सपोर्टर, TracerProvider में प्लग इन किया जा सकता है
- TracerProvider में, ट्रेस सैंपलिंग और एक्सपोर्ट से जुड़ा पूरा कॉन्फ़िगरेशन होता है
- सभी ट्रेस, Tracer ऑब्जेक्ट में बंडल किए जाते हैं
इस बारे में जानने के बाद, आइए कोडिंग के असली काम पर चलते हैं.
इंस्ट्रूमेंट का पहला स्पैन
इंस्ट्रूमेंट लोड जनरेटर सेवा
Cloud Shell के सबसे ऊपर दाईं ओर मौजूद बटन को दबाकर, Cloud Shell एडिटर खोलें. बाएं पैनल में एक्सप्लोरर से
step0/src/loadgen/main.go
खोलें और मुख्य फ़ंक्शन ढूंढें.
step0/src/loadgen/main.go
func main() { ... for range t.C { log.Printf("simulating client requests, round %d", i) if err := run(numWorkers, numConcurrency); err != nil { log.Printf("aborted round with error: %v", err) } log.Printf("simulated %d requests", numWorkers) if numRounds != 0 && i > numRounds { break } i++ } }
मुख्य फ़ंक्शन में, आपको फ़ंक्शन run
को कॉल करने वाला लूप दिखता है. फ़िलहाल, सेक्शन में दो लॉग लाइन हैं, जो फ़ंक्शन कॉल की शुरुआत और खत्म होने की जानकारी रिकॉर्ड करती हैं. अब फ़ंक्शन कॉल के इंतज़ार का समय ट्रैक करने के लिए, स्पैन की जानकारी को इंस्ट्रूमेंट करते हैं.
सबसे पहले, पिछले सेक्शन में बताए गए तरीके से, OpenTelemetry के लिए पूरे कॉन्फ़िगरेशन सेट अप करें. OpenTelemetry पैकेज इस तरह जोड़ें:
step0/src/loadgen/main.go
import ( "context" // step1. add packages "encoding/json" "fmt" "io" "log" "math/rand" "net/http" "net/url" "time" // step1. add packages "go.opentelemetry.io/otel" "go.opentelemetry.io/otel/attribute" stdout "go.opentelemetry.io/otel/exporters/stdout/stdouttrace" "go.opentelemetry.io/otel/propagation" sdktrace "go.opentelemetry.io/otel/sdk/trace" semconv "go.opentelemetry.io/otel/semconv/v1.10.0" "go.opentelemetry.io/otel/trace" // step1. end add packages )
आसानी से पढ़ने के लिए, हमने initTracer
नाम का एक सेटअप फ़ंक्शन बनाया है और उसे main
फ़ंक्शन में कॉल किया है.
step0/src/loadgen/main.go
// step1. add OpenTelemetry initialization function func initTracer() (*sdktrace.TracerProvider, error) { // create a stdout exporter to show collected spans out to stdout. exporter, err := stdout.New(stdout.WithPrettyPrint()) if err != nil { return nil, err } // for the demonstration, we use AlwaysSmaple sampler to take all spans. // do not use this option in production. tp := sdktrace.NewTracerProvider( sdktrace.WithSampler(sdktrace.AlwaysSample()), sdktrace.WithBatcher(exporter), ) otel.SetTracerProvider(tp) otel.SetTextMapPropagator(propagation.TraceContext{}) return tp, nil }
आपको पता चल सकता है कि OpenTelemetry को सेट अप करने का तरीका, पिछले सेक्शन में बताए गए तरीके से मिलता-जुलता है. इस तरीके को लागू करने के लिए, हम stdout
एक्सपोर्टर का इस्तेमाल करते हैं. यह एक्सपोर्टर, सभी ट्रेस की जानकारी को स्ट्रक्चर्ड फ़ॉर्मैट में स्टडआउट में एक्सपोर्ट करता है.
इसके बाद, इसे मुख्य फ़ंक्शन से कॉल किया जाता है. initTracer()
को कॉल करें और ऐप्लिकेशन बंद करते समय, TracerProvider.Shutdown()
को कॉल करना न भूलें.
step0/src/loadgen/main.go
func main() { // step1. setup OpenTelemetry tp, err := initTracer() if err != nil { log.Fatalf("failed to initialize TracerProvider: %v", err) } defer func() { if err := tp.Shutdown(context.Background()); err != nil { log.Fatalf("error shutting down TracerProvider: %v", err) } }() // step1. end setup log.Printf("starting worder with %d workers in %d concurrency", numWorkers, numConcurrency) log.Printf("number of rounds: %d (0 is inifinite)", numRounds) ...
सेट अप पूरा करने के बाद, आपको यूनीक ट्रैक आईडी और स्पैन आईडी के साथ एक स्पैन बनाना होगा. OpenTelemetry, इसके लिए एक आसान लाइब्रेरी उपलब्ध कराता है. इंस्ट्रूमेंट के एचटीटीपी क्लाइंट में नए पैकेज जोड़ें.
step0/src/loadgen/main.go
import ( "context" "encoding/json" "fmt" "io" "log" "math/rand" "net/http" "net/http/httptrace" // step1. add packages "net/url" "time" // step1. add packages "go.opentelemetry.io/contrib/instrumentation/net/http/httptrace/otelhttptrace" "go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp" // step1. end add packages "go.opentelemetry.io/otel" "go.opentelemetry.io/otel/attribute" stdout "go.opentelemetry.io/otel/exporters/stdout/stdouttrace" "go.opentelemetry.io/otel/propagation" sdktrace "go.opentelemetry.io/otel/sdk/trace" semconv "go.opentelemetry.io/otel/semconv/v1.10.0" "go.opentelemetry.io/otel/trace" )
लोड जनरेटर, runQuery
फ़ंक्शन में net/http
के साथ HTTP में क्लाइंट सेवा को कॉल कर रहा है. इसलिए, हम net/http
के लिए contrib पैकेज का इस्तेमाल करते हैं और httptrace
और otelhttp
पैकेज के एक्सटेंशन के साथ इंस्ट्रूमेंटेशन को चालू करते हैं.
सबसे पहले, पैकेज के ग्लोबल वैरिएबल httpClient को जोड़ें, ताकि इंस्ट्रूमेंट किए गए क्लाइंट के ज़रिए एचटीटीपी अनुरोधों को कॉल किया जा सके.
step0/src/loadgen/main.go
var httpClient = http.Client{ Transport: otelhttp.NewTransport(http.DefaultTransport) }
इसके बाद, runQuery
फ़ंक्शन में इंस्ट्रूमेंटेशन जोड़ें, ताकि OpenTelemetry और कस्टम एचटीटीपी क्लाइंट से अपने-आप जनरेट हुए स्पैन का इस्तेमाल करके कस्टम स्पैन बनाया जा सके. आपको ये काम करने होंगे:
otel.Tracer()
की मदद से, ग्लोबलTracerProvider
से ट्रैसर पानाTracer.Start()
तरीके से रूट स्पैन बनाना- रूट स्पैन को किसी भी समय खत्म किया जा सकता है. इस मामले में,
runQuery
फ़ंक्शन के आखिर में
step0/src/loadgen/main.go
reqURL.RawQuery = v.Encode() // step1. replace http.Get() with custom client call // resp, err := http.Get(reqURL.String()) // step1. instrument trace ctx := context.Background() tr := otel.Tracer("loadgen") ctx, span := tr.Start(ctx, "query.request", trace.WithAttributes( semconv.TelemetrySDKLanguageGo, semconv.ServiceNameKey.String("loadgen.runQuery"), attribute.Key("query").String(s), )) defer span.End() ctx = httptrace.WithClientTrace(ctx, otelhttptrace.NewClientTrace(ctx)) req, err := http.NewRequestWithContext(ctx, "GET", reqURL.String(), nil) if err != nil { return -1, fmt.Errorf("error creating HTTP request object: %v", err) } resp, err := httpClient.Do(req) // step1. end instrumentation if err != nil { return -1, fmt.Errorf("error sending request to %v: %v", reqURL.String(), err) }
अब loadgen (एचटीटीपी क्लाइंट ऐप्लिकेशन) में इंस्ट्रूमेंटेशन पूरा हो गया है. कृपया go mod
कमांड की मदद से, अपने go.mod
और go.sum
को अपडेट करना न भूलें.
go mod tidy
इंस्ट्रूमेंट क्लाइंट सेवा
पिछले सेक्शन में, हमने नीचे दी गई ड्रॉइंग में लाल रंग के रेक्टैंगल में मौजूद हिस्से को इंस्ट्रूमेंट किया है. हमने लोड जनरेटर सेवा में स्पैन की जानकारी को इंस्ट्रूमेंट किया है. लोड जनरेटर सेवा की तरह ही, अब हमें क्लाइंट सेवा को इंस्ट्रूमेंट करना होगा. क्लाइंट सेवा और लोड जनरेटर सेवा में अंतर यह है कि क्लाइंट सेवा को एचटीटीपी हेडर में लोड जनरेटर सेवा से भेजे गए ट्रैक आईडी की जानकारी निकालनी होती है. साथ ही, स्पैन जनरेट करने के लिए आईडी का इस्तेमाल करना होता है.
Cloud Shell Editor खोलें और ज़रूरी पैकेज जोड़ें, जैसा कि हमने लोड जनरेटर सेवा के लिए किया था.
step0/src/client/main.go
import ( "context" "encoding/json" "fmt" "io" "log" "net/http" "net/url" "os" "time" "opentelemetry-trace-codelab-go/client/shakesapp" // step1. add new import "go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp" "go.opentelemetry.io/otel" "go.opentelemetry.io/otel/attribute" stdout "go.opentelemetry.io/otel/exporters/stdout/stdouttrace" "go.opentelemetry.io/otel/propagation" sdktrace "go.opentelemetry.io/otel/sdk/trace" "go.opentelemetry.io/otel/trace" "google.golang.org/grpc" "google.golang.org/grpc/credentials/insecure" // step1. end new import )
हमें फिर से OpenTelemtry सेट अप करना होगा. loadgen से initTracer
फ़ंक्शन को कॉपी करके चिपकाएं और क्लाइंट सेवा के main
फ़ंक्शन में भी इसे कॉल करें.
step0/src/client/main.go
// step1. add OpenTelemetry initialization function func initTracer() (*sdktrace.TracerProvider, error) { // create a stdout exporter to show collected spans out to stdout. exporter, err := stdout.New(stdout.WithPrettyPrint()) if err != nil { return nil, err } // for the demonstration, we use AlwaysSmaple sampler to take all spans. // do not use this option in production. tp := sdktrace.NewTracerProvider( sdktrace.WithSampler(sdktrace.AlwaysSample()), sdktrace.WithBatcher(exporter), ) otel.SetTracerProvider(tp) otel.SetTextMapPropagator(propagation.TraceContext{}) return tp, nil }
अब स्पैन को इंस्ट्रूमेंट करने का समय आ गया है. क्लाइंट सेवा को loadgen सेवा से एचटीटीपी अनुरोध स्वीकार करने की ज़रूरत होती है. इसलिए, उसे हैंडलर को इंस्ट्रूमेंट करना होगा. क्लाइंट सेवा में एचटीटीपी सर्वर, net/http के साथ लागू किया जाता है. साथ ही, loadgen में किए गए तरीके की तरह otelhttp
पैकेज का इस्तेमाल किया जा सकता है.
सबसे पहले, हम हैंडलर रजिस्ट्रेशन को otelhttp
हैंडलर से बदल देते हैं. main
फ़ंक्शन में, वे लाइनें ढूंढें जहां एचटीटीपी हैंडलर को http.HandleFunc()
के साथ रजिस्टर किया गया है.
step0/src/client/main.go
// step1. change handler to intercept OpenTelemetry related headers // http.HandleFunc("/", svc.handler) otelHandler := otelhttp.NewHandler(http.HandlerFunc(svc.handler), "client.handler") http.Handle("/", otelHandler) // step1. end intercepter setting http.HandleFunc("/_genki", svc.health)
इसके बाद, हम हैंडलर के अंदर असल स्पैन को इंस्ट्रूमेंट करते हैं. func (*clientService) handler() ढूंढें और trace.SpanFromContext()
के साथ स्पैन इंस्ट्रूमेंटेशन जोड़ें.
step0/src/client/main.go
func (cs *clientService) handler(w http.ResponseWriter, r *http.Request) { ... ctx := r.Context() ctx, cancel := context.WithCancel(ctx) defer cancel() // step1. instrument trace span := trace.SpanFromContext(ctx) defer span.End() // step1. end instrument ...
इस इंस्ट्रूमेंटेशन की मदद से, आपको handler
तरीके की शुरुआत से लेकर आखिर तक के स्पैन मिलते हैं. स्पैन का आसानी से विश्लेषण करने के लिए, एक और एट्रिब्यूट जोड़ें. यह एट्रिब्यूट, क्वेरी से मैच होने वाली वैल्यू की संख्या को सेव करता है. लॉग लाइन से ठीक पहले, यह कोड जोड़ें.
func (cs *clientService) handler(w http.ResponseWriter, r *http.Request) { ... // step1. add span specific attribute span.SetAttributes(attribute.Key("matched").Int64(resp.MatchCount)) // step1. end adding attribute log.Println(string(ret)) ...
ऊपर दिए गए सभी इंस्ट्रूमेंटेशन की मदद से, loadgen और क्लाइंट के बीच ट्रैक इंस्ट्रूमेंटेशन पूरा हो गया है. आइए, देखते हैं कि यह सुविधा कैसे काम करती है. skaffold की मदद से कोड को फिर से चलाएं.
skaffold dev
GKE क्लस्टर पर सेवाएं चलाने के कुछ समय बाद, आपको इस तरह के बहुत सारे लॉग मैसेज दिखेंगे:
कमांड आउटपुट
[loadgen] { [loadgen] "Name": "query.request", [loadgen] "SpanContext": { [loadgen] "TraceID": "cfa22247a542beeb55a3434392d46b89", [loadgen] "SpanID": "18b06404b10c418b", [loadgen] "TraceFlags": "01", [loadgen] "TraceState": "", [loadgen] "Remote": false [loadgen] }, [loadgen] "Parent": { [loadgen] "TraceID": "00000000000000000000000000000000", [loadgen] "SpanID": "0000000000000000", [loadgen] "TraceFlags": "00", [loadgen] "TraceState": "", [loadgen] "Remote": false [loadgen] }, [loadgen] "SpanKind": 1, [loadgen] "StartTime": "2022-07-14T13:13:36.686751087Z", [loadgen] "EndTime": "2022-07-14T13:14:31.849601964Z", [loadgen] "Attributes": [ [loadgen] { [loadgen] "Key": "telemetry.sdk.language", [loadgen] "Value": { [loadgen] "Type": "STRING", [loadgen] "Value": "go" [loadgen] } [loadgen] }, [loadgen] { [loadgen] "Key": "service.name", [loadgen] "Value": { [loadgen] "Type": "STRING", [loadgen] "Value": "loadgen.runQuery" [loadgen] } [loadgen] }, [loadgen] { [loadgen] "Key": "query", [loadgen] "Value": { [loadgen] "Type": "STRING", [loadgen] "Value": "faith" [loadgen] } [loadgen] } [loadgen] ], [loadgen] "Events": null, [loadgen] "Links": null, [loadgen] "Status": { [loadgen] "Code": "Unset", [loadgen] "Description": "" [loadgen] }, [loadgen] "DroppedAttributes": 0, [loadgen] "DroppedEvents": 0, [loadgen] "DroppedLinks": 0, [loadgen] "ChildSpanCount": 5, [loadgen] "Resource": [ [loadgen] { [loadgen] "Key": "service.name", [loadgen] "Value": { [loadgen] "Type": "STRING", [loadgen] "Value": "unknown_service:loadgen" ...
stdout
एक्सपोर्टर, ये मैसेज भेजता है. आपको पता चलेगा कि loadgen के सभी स्पैन के पैरंट में TraceID: 00000000000000000000000000000000
है, क्योंकि यह रूट स्पैन है. इसका मतलब है कि यह ट्रैक में पहला स्पैन है. आपको यह भी पता चलता है कि एम्बेड एट्रिब्यूट "query"
में क्वेरी स्ट्रिंग है, जिसे क्लाइंट सेवा को पास किया जाता है.
खास जानकारी
इस चरण में, आपने एचटीटीपी में कम्यूनिकेट करने वाली लोड जनरेटर सेवा और क्लाइंट सेवा को इंस्ट्रुमेंट किया है. साथ ही, यह पुष्टि की है कि आपने सभी सेवाओं में ट्रेस कॉन्टेक्स्ट को सही तरीके से प्रॉपेगेट किया है और दोनों सेवाओं से स्टैंडआउट में स्पैन की जानकारी एक्सपोर्ट की है.
आगे क्या करना है
अगले चरण में, आपको क्लाइंट सेवा और सर्वर सेवा को इंस्ट्रूमेंट करना होगा, ताकि यह पुष्टि की जा सके कि gRPC के ज़रिए ट्रेस कॉन्टेक्स्ट को कैसे प्रसारित किया जाए.
5. gRPC के लिए इंस्ट्रूमेंटेशन
पिछले चरण में, हमने इस माइक्रोसर्विस में अनुरोध के पहले आधे हिस्से को इंस्ट्रूमेंट किया था. इस चरण में, हम क्लाइंट सेवा और सर्वर सेवा के बीच gRPC कम्यूनिकेशन को इंस्ट्रूमेंट करने की कोशिश करते हैं. (नीचे दी गई इमेज में हरा और बैंगनी रंग का रेक्टैंगल)
gRPC क्लाइंट के लिए, पहले से इंस्ट्रूमेंटेशन बनाना
OpenTelemetry के नेटवर्क में कई काम की लाइब्रेरी उपलब्ध हैं. इनकी मदद से, डेवलपर ऐप्लिकेशन को इंस्ट्रूमेंट कर सकते हैं. पिछले चरण में, हमने net/http
पैकेज के लिए, पहले से बने इंस्ट्रूमेंटेशन का इस्तेमाल किया था. इस चरण में, हम gRPC के ज़रिए ट्रेस कॉन्टेक्स्ट को प्रसारित करने की कोशिश कर रहे हैं. इसके लिए, हम लाइब्रेरी का इस्तेमाल करते हैं.
सबसे पहले, otelgrpc
नाम का पहले से बना gRPC पैकेज इंपोर्ट करें.
step0/src/client/main.go
import ( "context" "encoding/json" "fmt" "io" "log" "net/http" "net/url" "os" "time" "opentelemetry-trace-codelab-go/client/shakesapp" // step2. add prebuilt gRPC package (otelgrpc) "go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc" "go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp" "go.opentelemetry.io/otel" "go.opentelemetry.io/otel/attribute" stdout "go.opentelemetry.io/otel/exporters/stdout/stdouttrace" "go.opentelemetry.io/otel/propagation" sdktrace "go.opentelemetry.io/otel/sdk/trace" "go.opentelemetry.io/otel/trace" "google.golang.org/grpc" "google.golang.org/grpc/credentials/insecure" )
इस बार, क्लाइंट सेवा, सर्वर सेवा के मुकाबले gRPC क्लाइंट है. इसलिए, आपको gRPC क्लाइंट को इंस्ट्रूमेंट करना होगा. mustConnGRPC
फ़ंक्शन ढूंढें और gRPC इंटरसेप्टर्स जोड़ें, जो हर बार क्लाइंट के सर्वर से अनुरोध करने पर नए स्पैन को इंस्ट्रूमेंट करते हैं.
step0/src/client/main.go
// Helper function for gRPC connections: Dial and create client once, reuse. func mustConnGRPC(ctx context.Context, conn **grpc.ClientConn, addr string) { var err error // step2. add gRPC interceptor interceptorOpt := otelgrpc.WithTracerProvider(otel.GetTracerProvider()) *conn, err = grpc.DialContext(ctx, addr, grpc.WithTransportCredentials(insecure.NewCredentials()), grpc.WithUnaryInterceptor(otelgrpc.UnaryClientInterceptor(interceptorOpt)), grpc.WithStreamInterceptor(otelgrpc.StreamClientInterceptor(interceptorOpt)), grpc.WithTimeout(time.Second*3), ) // step2: end adding interceptor if err != nil { panic(fmt.Sprintf("Error %s grpc: failed to connect %s", err, addr)) } }
आपने पिछले सेक्शन में OpenTelemetry को पहले ही सेट अप कर लिया है. इसलिए, आपको इसे फिर से सेट अप करने की ज़रूरत नहीं है.
gRPC सर्वर के लिए पहले से मौजूद इंस्ट्रूमेंटेशन
gRPC क्लाइंट के लिए हमने जो किया था उसी तरह, हम gRPC सर्वर के लिए पहले से बने इंस्ट्रूमेंटेशन को कॉल करते हैं. इंपोर्ट सेक्शन में नया पैकेज जोड़ें, जैसे:
step0/src/server/main.go
import ( "context" "fmt" "io/ioutil" "log" "net" "os" "regexp" "strings" "opentelemetry-trace-codelab-go/server/shakesapp" "cloud.google.com/go/storage" // step2. add OpenTelemetry packages including otelgrpc "go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc" "go.opentelemetry.io/otel" stdout "go.opentelemetry.io/otel/exporters/stdout/stdouttrace" "go.opentelemetry.io/otel/propagation" sdktrace "go.opentelemetry.io/otel/sdk/trace" "google.golang.org/api/iterator" "google.golang.org/api/option" "google.golang.org/grpc" healthpb "google.golang.org/grpc/health/grpc_health_v1" )
सर्वर को पहली बार इंस्ट्रूमेंट किया जा रहा है. इसलिए, आपको पहले OpenTelemetry सेट अप करना होगा. यह उसी तरह से किया जाता है जिस तरह हमने loadgen और क्लाइंट सेवाओं के लिए किया था.
step0/src/server/main.go
// step2. add OpenTelemetry initialization function func initTracer() (*sdktrace.TracerProvider, error) { // create a stdout exporter to show collected spans out to stdout. exporter, err := stdout.New(stdout.WithPrettyPrint()) if err != nil { return nil, err } // for the demonstration, we use AlwaysSmaple sampler to take all spans. // do not use this option in production. tp := sdktrace.NewTracerProvider( sdktrace.WithSampler(sdktrace.AlwaysSample()), sdktrace.WithBatcher(exporter), ) otel.SetTracerProvider(tp) otel.SetTextMapPropagator(propagation.TraceContext{}) return tp, nil } func main() { ... // step2. setup OpenTelemetry tp, err := initTracer() if err != nil { log.Fatalf("failed to initialize TracerProvider: %v", err) } defer func() { if err := tp.Shutdown(context.Background()); err != nil { log.Fatalf("error shutting down TracerProvider: %v", err) } }() // step2. end setup ...
इसके बाद, आपको सर्वर इंटरसेप्टर्स जोड़ने होंगे. main
फ़ंक्शन में, वह जगह ढूंढें जहां grpc.NewServer()
को कॉल किया जाता है और फ़ंक्शन में इंटरसेप्टर्स जोड़ें.
step0/src/server/main.go
func main() { ... svc := NewServerService() // step2: add interceptor interceptorOpt := otelgrpc.WithTracerProvider(otel.GetTracerProvider()) srv := grpc.NewServer( grpc.UnaryInterceptor(otelgrpc.UnaryServerInterceptor(interceptorOpt)), grpc.StreamInterceptor(otelgrpc.StreamServerInterceptor(interceptorOpt)), ) // step2: end adding interceptor shakesapp.RegisterShakespeareServiceServer(srv, svc) ...
माइक्रोसर्विस चलाना और ट्रैक की पुष्टि करना
इसके बाद, बदले गए कोड को skaffold कमांड की मदद से चलाएं.
skaffold dev
अब आपको स्टैंडर्ड आउटपुट पर, स्पैन की जानकारी फिर से दिखेगी.
कमांड आउटपुट
... [server] { [server] "Name": "shakesapp.ShakespeareService/GetMatchCount", [server] "SpanContext": { [server] "TraceID": "89b472f213a400cf975e0a0041649667", [server] "SpanID": "96030dbad0061b3f", [server] "TraceFlags": "01", [server] "TraceState": "", [server] "Remote": false [server] }, [server] "Parent": { [server] "TraceID": "89b472f213a400cf975e0a0041649667", [server] "SpanID": "cd90cc3859b73890", [server] "TraceFlags": "01", [server] "TraceState": "", [server] "Remote": true [server] }, [server] "SpanKind": 2, [server] "StartTime": "2022-07-14T14:05:55.74822525Z", [server] "EndTime": "2022-07-14T14:06:03.449258891Z", [server] "Attributes": [ ... [server] ], [server] "Events": [ [server] { [server] "Name": "message", [server] "Attributes": [ ... [server] ], [server] "DroppedAttributeCount": 0, [server] "Time": "2022-07-14T14:05:55.748235489Z" [server] }, [server] { [server] "Name": "message", [server] "Attributes": [ ... [server] ], [server] "DroppedAttributeCount": 0, [server] "Time": "2022-07-14T14:06:03.449255889Z" [server] } [server] ], [server] "Links": null, [server] "Status": { [server] "Code": "Unset", [server] "Description": "" [server] }, [server] "DroppedAttributes": 0, [server] "DroppedEvents": 0, [server] "DroppedLinks": 0, [server] "ChildSpanCount": 0, [server] "Resource": [ [server] { ... [server] ], [server] "InstrumentationLibrary": { [server] "Name": "go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc", [server] "Version": "semver:0.33.0", [server] "SchemaURL": "" [server] } [server] } ...
आपको पता चलता है कि आपने कोई स्पैन नाम एम्बेड नहीं किया है और trace.Start()
या span.SpanFromContext()
की मदद से मैन्युअल तरीके से स्पैन बनाए हैं. हालांकि, आपको बड़ी संख्या में स्पैन मिलते हैं, क्योंकि gRPC इंटरसेप्टर्स ने उन्हें जनरेट किया है.
खास जानकारी
इस चरण में, आपने OpenTelemetry नेटवर्क लाइब्रेरी की मदद से, gRPC पर आधारित कम्यूनिकेशन को इंस्ट्रूमेंट किया है.
अगला चरण
अगले चरण में, आपको Cloud Trace की मदद से ट्रैक को विज़ुअलाइज़ करने का तरीका पता चलेगा. साथ ही, इकट्ठा किए गए स्पैन का विश्लेषण करने का तरीका भी पता चलेगा.
6. Cloud Trace की मदद से ट्रेस को विज़ुअलाइज़ करना
आपने OpenTelemetry की मदद से, पूरे सिस्टम में ट्रैस को इंस्ट्रूमेंट किया है. अब तक, आपने एचटीटीपी और gRPC सेवाओं को इंस्ट्रूमेंट करने का तरीका जाना है. आपने इन्हें इंस्ट्रूमेंट करने का तरीका तो सीख लिया है, लेकिन इनका विश्लेषण करने का तरीका नहीं. इस सेक्शन में, स्टैंडर्ड आउटपुट एक्सपोर्टर को Cloud Trace एक्सपोर्टर से बदला जाएगा. साथ ही, अपने ट्रेस का विश्लेषण करने का तरीका भी सीखा जाएगा.
Cloud Trace एक्सपोर्टर का इस्तेमाल करना
OpenTelemetry की सबसे खास सुविधाओं में से एक है, प्लग इन करने की सुविधा. अपने इंस्ट्रूमेंटेशन से इकट्ठा किए गए सभी स्पैन को विज़ुअलाइज़ करने के लिए, आपको स्टैंडआउट एक्सपोर्टर को Cloud Trace एक्सपोर्टर से बदलना होगा.
हर सेवा की main.go
फ़ाइलें खोलें और initTracer()
फ़ंक्शन ढूंढें. स्टैंडआउट एक्सपोर्टर जनरेट करने के लिए लाइन मिटाएं और इसके बजाय Cloud Trace एक्सपोर्टर बनाएं.
step0/src/loadgen/main.go
import ( ... // step3. add OpenTelemetry for Cloud Trace package cloudtrace "github.com/GoogleCloudPlatform/opentelemetry-operations-go/exporter/trace" ) // step1. add OpenTelemetry initialization function func initTracer() (*sdktrace.TracerProvider, error) { // step3. replace stdout exporter with Cloud Trace exporter // cloudtrace.New() finds the credentials to Cloud Trace automatically following the // rules defined by golang.org/x/oauth2/google.findDefaultCredentailsWithParams. // https://pkg.go.dev/golang.org/x/oauth2/google#FindDefaultCredentialsWithParams exporter, err := cloudtrace.New() // step3. end replacing exporter if err != nil { return nil, err } // for the demonstration, we use AlwaysSmaple sampler to take all spans. // do not use this option in production. tp := sdktrace.NewTracerProvider( sdktrace.WithSampler(sdktrace.AlwaysSample()), sdktrace.WithBatcher(exporter), ) otel.SetTracerProvider(tp) otel.SetTextMapPropagator(propagation.TraceContext{}) return tp, nil }
आपको क्लाइंट और सर्वर सेवा में भी उसी फ़ंक्शन में बदलाव करना होगा.
माइक्रोसर्विस चलाना और ट्रैक की पुष्टि करना
बदलाव करने के बाद, skaffold कमांड की मदद से क्लस्टर को हमेशा की तरह चलाएं.
skaffold dev
इसके बाद, आपको स्टैंडर्ड आउटपुट (stdout) पर, स्ट्रक्चर्ड लॉग फ़ॉर्मैट में स्पैन की ज़्यादा जानकारी नहीं दिखेगी, क्योंकि आपने एक्सपोर्टर को Cloud Trace से बदल दिया है.
कमांड आउटपुट
[loadgen] 2022/07/14 15:01:07 simulated 20 requests [loadgen] 2022/07/14 15:01:07 simulating client requests, round 37 [loadgen] 2022/07/14 15:01:14 query 'sweet': matched 958 [client] 2022/07/14 15:01:14 {"match_count":958} [client] 2022/07/14 15:01:14 {"match_count":3040} [loadgen] 2022/07/14 15:01:14 query 'love': matched 3040 [client] 2022/07/14 15:01:15 {"match_count":349} [loadgen] 2022/07/14 15:01:15 query 'hello': matched 349 [client] 2022/07/14 15:01:15 {"match_count":484} [loadgen] 2022/07/14 15:01:15 query 'faith': matched 484 [loadgen] 2022/07/14 15:01:15 query 'insolence': matched 14 [client] 2022/07/14 15:01:15 {"match_count":14} [client] 2022/07/14 15:01:21 {"match_count":484} [loadgen] 2022/07/14 15:01:21 query 'faith': matched 484 [client] 2022/07/14 15:01:21 {"match_count":728} [loadgen] 2022/07/14 15:01:21 query 'world': matched 728 [client] 2022/07/14 15:01:22 {"match_count":484} [loadgen] 2022/07/14 15:01:22 query 'faith': matched 484 [loadgen] 2022/07/14 15:01:22 query 'hello': matched 349 [client] 2022/07/14 15:01:22 {"match_count":349} [client] 2022/07/14 15:01:23 {"match_count":1036} [loadgen] 2022/07/14 15:01:23 query 'friend': matched 1036 [loadgen] 2022/07/14 15:01:28 query 'tear': matched 463 ...
अब यह पुष्टि करें कि सभी स्पैन, Cloud Trace को सही तरीके से भेजे गए हैं या नहीं. Cloud Console को ऐक्सेस करें और "ट्रैक की गई गतिविधि की सूची" पर जाएं. इसे खोज बॉक्स से आसानी से ऐक्सेस किया जा सकता है. इसके अलावा, बाईं ओर मौजूद पैनल में मेन्यू पर क्लिक किया जा सकता है.
इसके बाद, आपको इंतज़ार का समय दिखाने वाले ग्राफ़ में कई नीले रंग के स्पॉट दिखेंगे. हर स्पॉट एक ट्रेस दिखाता है.
इनमें से किसी एक पर क्लिक करें. इसके बाद, आपको ट्रैस में जानकारी दिखेगी.
इस आसान और तेज़ नज़र से भी, आपको काफ़ी अहम जानकारी मिल जाती है. उदाहरण के लिए, वॉटरफ़ॉल ग्राफ़ से यह देखा जा सकता है कि shakesapp.ShakespeareService/GetMatchCount
नाम के स्पैन की वजह से, इंतज़ार का समय ज़्यादा हो रहा है. (ऊपर दी गई इमेज में 1 देखें) खास जानकारी वाली टेबल से इसकी पुष्टि की जा सकती है. (सबसे दाईं ओर मौजूद कॉलम में, हर स्पैन की अवधि दिखती है.) साथ ही, यह ट्रेस "friend" क्वेरी के लिए था. (ऊपर दी गई इमेज में 2 देखें)
इन छोटे विश्लेषणों से, आपको यह पता चल सकता है कि आपको GetMatchCount
तरीके के अंदर ज़्यादा जानकारी वाले स्पैन के बारे में जानना होगा. स्टैंडर्ड आउटपुट (stdout) की जानकारी की तुलना में, विज़ुअलाइज़ेशन बेहतर होता है. Cloud Trace की जानकारी के बारे में ज़्यादा जानने के लिए, कृपया हमारा आधिकारिक दस्तावेज़ पढ़ें.
खास जानकारी
इस चरण में, आपने स्टैंडआउट एक्सपोर्टर को Cloud Trace वाले एक्सपोर्टर से बदल दिया है और Cloud Trace पर ट्रैक को विज़ुअलाइज़ किया है. साथ ही, आपने ट्रेस का विश्लेषण करने का तरीका भी जाना.
आगे क्या करना है
अगले चरण में, आपको GetMatchCount में सब स्पैन जोड़ने के लिए, सर्वर सेवा के सोर्स कोड में बदलाव करना होगा.
7. बेहतर विश्लेषण के लिए सब स्पैन जोड़ना
पिछले चरण में, आपको पता चला था कि loadgen से रिकॉर्ड किए गए राउंड ट्रिप टाइम की वजह, ज़्यादातर सर्वर सेवा में GetMatchCount तरीके और gRPC हैंडलर की प्रोसेस है. हालांकि, हमने हैंडलर के अलावा किसी और चीज़ को इंस्ट्रूमेंट नहीं किया है. इसलिए, हमें वॉटरफ़ॉल ग्राफ़ से ज़्यादा अहम जानकारी नहीं मिल पा रही है. जब हम माइक्रोसर्विस को इंस्ट्रूमेंट करना शुरू करते हैं, तो आम तौर पर ऐसा होता है.
इस सेक्शन में, हम उस सब स्पैन को इंस्ट्रूमेंट करने जा रहे हैं जहां सर्वर, Google Cloud Storage को कॉल करता है. ऐसा इसलिए, क्योंकि आम तौर पर कुछ बाहरी नेटवर्क I/O प्रोसेस में काफ़ी समय लेते हैं. इसलिए, यह पता लगाना ज़रूरी है कि कॉल की वजह से ऐसा हो रहा है या नहीं.
सर्वर में किसी सब स्पैन को इंस्ट्रूमेंट करना
सर्वर में main.go
खोलें और फ़ंक्शन readFiles
ढूंढें. यह फ़ंक्शन, Google Cloud Storage से शेक्सपियर के कामों की सभी टेक्स्ट फ़ाइलें फ़ेच करने के लिए अनुरोध कर रहा है. इस फ़ंक्शन में, क्लाइंट सेवा में एचटीटीपी सर्वर इंस्ट्रूमेंटेशन के लिए किया गया काम करने जैसा सब स्पैन बनाया जा सकता है.
step0/src/server/main.go
func readFiles(ctx context.Context, bucketName, prefix string) ([]string, error) { type resp struct { s string err error } // step4: add an extra span span := trace.SpanFromContext(ctx) span.SetName("server.readFiles") span.SetAttributes(attribute.Key("bucketname").String(bucketName)) defer span.End() // step4: end add span ...
नया स्पैन जोड़ने के लिए, यही तरीका अपनाएं. आइए, ऐप्लिकेशन चलाकर देखते हैं कि यह कैसे काम करता है.
माइक्रोसर्विस चलाना और ट्रैक की पुष्टि करना
बदलाव करने के बाद, skaffold कमांड की मदद से क्लस्टर को हमेशा की तरह चलाएं.
skaffold dev
इसके बाद, ट्रेस की सूची से query.request
नाम का कोई एक ट्रेस चुनें. आपको shakesapp.ShakespeareService/GetMatchCount
के नीचे एक नया स्पैन के अलावा, ट्रैस वॉटरफ़ॉल ग्राफ़ दिखेगा. (नीचे लाल रंग के आयत में दिखाया गया स्पैन)
इस ग्राफ़ से पता चलता है कि Google Cloud Storage के बाहरी कॉल में ज़्यादा देरी होती है. हालांकि, ज़्यादातर देरी दूसरी चीज़ों की वजह से होती है.
ट्रेस वॉटरफ़ॉल ग्राफ़ में सिर्फ़ कुछ नज़र डालने से ही, आपको कई अहम जानकारी मिल गई है. अपने ऐप्लिकेशन की परफ़ॉर्मेंस के बारे में ज़्यादा जानकारी कैसे पाई जा सकती है? यहां प्रोफ़ाइलर की मदद ली जाती है. हालांकि, फ़िलहाल इस कोडलैब को यहीं खत्म कर दें और प्रोफ़ाइलर के सभी ट्यूटोरियल को दूसरे चरण में देखें.
खास जानकारी
इस चरण में, आपने सर्वर सेवा में एक और स्पैन इंस्ट्रूमेंट किया और सिस्टम के इंतज़ार का समय जानने के बारे में ज़्यादा जानकारी हासिल की.
8. बधाई हो
आपने OpenTelemery की मदद से डिस्ट्रिब्यूटेड ट्रेस बनाए हैं और Google Cloud Trace पर, माइक्रोसर्विस के लिए अनुरोध में लगने वाले समय की पुष्टि की है.
ज़्यादा समय तक कसरत करने के लिए, नीचे दिए गए विषयों को खुद आज़माएं.
- फ़िलहाल, सेहत की जांच से जनरेट होने वाले सभी स्पैन भेजे जाते हैं. (
grpc.health.v1.Health/Check
) Cloud Traces से उन स्पैन को कैसे फ़िल्टर किया जाता है? इसके लिए, यहां दिया गया संकेत देखें. - इवेंट लॉग को स्पैन से जोड़ें और देखें कि यह Google Cloud Trace और Google Cloud Logging पर कैसे काम करता है. इसके लिए, यहां दिया गया संकेत देखें.
- किसी सेवा को किसी दूसरी भाषा में बदलें और उस भाषा के लिए, OpenTelemetry की मदद से उसे इंस्ट्रूमेंट करने की कोशिश करें.
इसके बाद, अगर आपको प्रोफ़ाइलर के बारे में जानना है, तो कृपया दूसरे चरण पर जाएं. ऐसे में, नीचे दिए गए 'साफ़ करें' सेक्शन को छोड़ा जा सकता है.
खाली करने के लिए जगह
इस कोडलैब के बाद, कृपया Kubernetes क्लस्टर को बंद कर दें और प्रोजेक्ट मिटाना न भूलें. इससे, आपको Google Kubernetes Engine, Google Cloud Trace, और Google Artifact Registry पर अनचाहे शुल्क नहीं चुकाने पड़ेंगे.
सबसे पहले, क्लस्टर मिटाएं. अगर क्लस्टर को skaffold dev
के साथ चलाया जा रहा है, तो आपको सिर्फ़ Ctrl-C दबाना होगा. अगर क्लस्टर को skaffold run
के साथ चलाया जा रहा है, तो यह कमांड चलाएं:
skaffold delete
कमांड आउटपुट
Cleaning up... - deployment.apps "clientservice" deleted - service "clientservice" deleted - deployment.apps "loadgen" deleted - deployment.apps "serverservice" deleted - service "serverservice" deleted
क्लस्टर मिटाने के बाद, मेन्यू पैनल में "IAM और एडमिन" > "सेटिंग" चुनें. इसके बाद, "बंद करें" बटन पर क्लिक करें.
इसके बाद, डायलॉग बॉक्स में मौजूद फ़ॉर्म में प्रोजेक्ट आईडी (न कि प्रोजेक्ट का नाम) डालें और बंद करने की पुष्टि करें.