হ্যালো সবাই! আমি Dmitriy Apanasevich, MY.GAMES এ জাভা ডেভেলপার, Rush Royale গেমে কাজ করছি, এবং আমি আমাদের Java ব্যাকএন্ডে OpenTelemetry ফ্রেমওয়ার্ককে একীভূত করার অভিজ্ঞতা শেয়ার করতে চাই। এখানে কভার করার জন্য বেশ কিছু আছে: আমরা এটি বাস্তবায়নের জন্য প্রয়োজনীয় কোড পরিবর্তনগুলি কভার করব, সেইসাথে আমাদের ইনস্টল এবং কনফিগার করার জন্য প্রয়োজনীয় নতুন উপাদানগুলি কভার করব - এবং অবশ্যই, আমরা আমাদের কিছু ফলাফল শেয়ার করব৷
আমাদের লক্ষ্য: সিস্টেম পর্যবেক্ষণযোগ্যতা অর্জন
আমাদের ক্ষেত্রে আরও কিছু প্রসঙ্গ দেওয়া যাক। বিকাশকারী হিসাবে, আমরা এমন সফ্টওয়্যার তৈরি করতে চাই যা নিরীক্ষণ করা, মূল্যায়ন করা এবং বোঝা সহজ (এবং এটিই সঠিকভাবে OpenTelemetry প্রয়োগ করার উদ্দেশ্য — সিস্টেমকে সর্বাধিক করার জন্য
অ্যাপ্লিকেশন পারফরম্যান্সের অন্তর্দৃষ্টি সংগ্রহের জন্য প্রথাগত পদ্ধতিগুলি প্রায়ই ম্যানুয়ালি লগিং ইভেন্ট, মেট্রিক্স এবং ত্রুটি জড়িত:
অবশ্যই, অনেকগুলি ফ্রেমওয়ার্ক রয়েছে যা আমাদের লগগুলির সাথে কাজ করার অনুমতি দেয় এবং আমি নিশ্চিত যে এই নিবন্ধটি যারা পড়ছে তাদের প্রত্যেকের লগ সংগ্রহ, সংরক্ষণ এবং বিশ্লেষণের জন্য একটি কনফিগার করা সিস্টেম রয়েছে৷
লগিং আমাদের জন্য সম্পূর্ণরূপে কনফিগার করা হয়েছিল, তাই আমরা লগগুলির সাথে কাজ করার জন্য OpenTelemetry দ্বারা প্রদত্ত ক্ষমতাগুলি ব্যবহার করিনি।
সিস্টেম নিরীক্ষণ করার আরেকটি সাধারণ উপায় হল মেট্রিক্স ব্যবহার করে:
আমাদের মেট্রিক্স সংগ্রহ এবং ভিজ্যুয়ালাইজ করার জন্য একটি সম্পূর্ণ কনফিগার করা সিস্টেমও ছিল, তাই এখানেও আমরা মেট্রিক্সের সাথে কাজ করার ক্ষেত্রে OpenTelemetry-এর ক্ষমতাগুলিকে উপেক্ষা করেছি।
কিন্তু এই ধরনের সিস্টেম ডেটা প্রাপ্তি এবং বিশ্লেষণ করার জন্য একটি কম সাধারণ টুল
একটি ট্রেস তার জীবদ্দশায় আমাদের সিস্টেমের মাধ্যমে একটি অনুরোধ যে পথটি গ্রহণ করে তা উপস্থাপন করে এবং এটি সাধারণত শুরু হয় যখন সিস্টেম একটি অনুরোধ পায় এবং প্রতিক্রিয়া দিয়ে শেষ হয়। ট্রেস একাধিক গঠিত
এই আলোচনার জন্য, আমরা ওপেনটেলিমেট্রির ট্রেসিং দিকটিতে মনোনিবেশ করব।
ওপেনটেলিমেট্রিতে আরও কিছু পটভূমি
এর ওপেনটেলিমেট্রি প্রকল্পের উপরও কিছু আলোকপাত করা যাক, যা মার্জ করার মাধ্যমে এসেছে
OpenTelemetry এখন একটি স্ট্যান্ডার্ডের উপর ভিত্তি করে উপাদানগুলির একটি বিস্তৃত পরিসর সরবরাহ করে যা বিভিন্ন প্রোগ্রামিং ভাষার জন্য API, SDK এবং সরঞ্জামগুলির একটি সেট সংজ্ঞায়িত করে এবং প্রকল্পের প্রাথমিক লক্ষ্য হল ডেটা তৈরি করা, সংগ্রহ করা, পরিচালনা করা এবং রপ্তানি করা।
এটি বলেছে, OpenTelemetry ডেটা স্টোরেজ বা ভিজ্যুয়ালাইজেশন সরঞ্জামগুলির জন্য একটি ব্যাকএন্ড অফার করে না।
যেহেতু আমরা শুধুমাত্র ট্রেসিং করতে আগ্রহী ছিলাম, তাই আমরা ট্রেসগুলি সংরক্ষণ এবং ভিজ্যুয়ালাইজ করার জন্য সবচেয়ে জনপ্রিয় ওপেন সোর্স সমাধানগুলি অন্বেষণ করেছি:
- জাইগার
- জিপকিন
- গ্রাফানা টেম্পো
পরিশেষে, আমরা Grafana Tempo এর চিত্তাকর্ষক ভিজ্যুয়ালাইজেশন ক্ষমতা, দ্রুত বিকাশের গতি এবং মেট্রিক্স ভিজ্যুয়ালাইজেশনের জন্য আমাদের বিদ্যমান Grafana সেটআপের সাথে একীকরণের কারণে বেছে নিয়েছি। একটি একক, ইউনিফাইড টুল থাকাও একটি উল্লেখযোগ্য সুবিধা ছিল।
OpenTelemetry উপাদান
ওপেনটেলিমেট্রির উপাদানগুলিকেও একটু ব্যবচ্ছেদ করা যাক।
স্পেসিফিকেশন:
API - ডেটার প্রকার, অপারেশন, enums
SDK — স্পেসিফিকেশন বাস্তবায়ন, বিভিন্ন প্রোগ্রামিং ভাষায় APIs। একটি ভিন্ন ভাষা মানে একটি ভিন্ন SDK অবস্থা, আলফা থেকে স্থিতিশীল।
ডেটা প্রোটোকল (OTLP) এবং
শব্দার্থিক নিয়মাবলী
জাভা এপিআই এসডিকে:
- কোড ইনস্ট্রুমেন্টেশন লাইব্রেরি
- রপ্তানিকারক - ব্যাকএন্ডে জেনারেটেড ট্রেস রপ্তানির জন্য সরঞ্জাম
- ক্রস সার্ভিস প্রোপাগেটরস - প্রক্রিয়ার বাইরে এক্সিকিউশন প্রসঙ্গ স্থানান্তর করার জন্য একটি টুল (JVM)
OpenTelemetry সংগ্রাহক হল একটি গুরুত্বপূর্ণ উপাদান, একটি প্রক্সি যা ডেটা গ্রহণ করে, এটি প্রক্রিয়া করে এবং এটিকে পাস করে – আসুন আরও ঘনিষ্ঠভাবে দেখা যাক।
ওপেনটেলিমেট্রি কালেক্টর
প্রতি সেকেন্ডে হাজার হাজার অনুরোধ পরিচালনা করার জন্য উচ্চ-লোড সিস্টেমের জন্য, ডেটা ভলিউম পরিচালনা করা অত্যন্ত গুরুত্বপূর্ণ। ট্রেস ডেটা প্রায়শই আয়তনে ব্যবসায়িক ডেটাকে ছাড়িয়ে যায়, কোন ডেটা সংগ্রহ এবং সংরক্ষণ করতে হবে তা অগ্রাধিকার দেওয়া অপরিহার্য করে তোলে। এখানেই আমাদের ডেটা প্রসেসিং এবং ফিল্টারিং টুল আসে এবং আপনাকে কোন ডেটা সংরক্ষণের যোগ্য তা নির্ধারণ করতে সক্ষম করে৷ সাধারণত, দলগুলি নির্দিষ্ট মানদণ্ড পূরণ করে এমন ট্রেস সংরক্ষণ করতে চায়, যেমন:
- একটি নির্দিষ্ট থ্রেশহোল্ড অতিক্রম করে প্রতিক্রিয়া সময় সহ ট্রেস।
- ট্রেস যেগুলি প্রক্রিয়াকরণের সময় ত্রুটির সম্মুখীন হয়েছে৷
- যে ট্রেসগুলিতে নির্দিষ্ট বৈশিষ্ট্য রয়েছে, যেমন একটি নির্দিষ্ট মাইক্রোসার্ভিসের মধ্য দিয়ে যাওয়া বা কোডে সন্দেহজনক হিসাবে ফ্ল্যাগ করা হয়েছে।
- নিয়মিত ট্রেসগুলির একটি এলোমেলো নির্বাচন যা সিস্টেমের স্বাভাবিক ক্রিয়াকলাপের একটি পরিসংখ্যানগত স্ন্যাপশট প্রদান করে, আপনাকে সাধারণ আচরণ বুঝতে এবং প্রবণতা সনাক্ত করতে সহায়তা করে।
কোন ট্রেস সংরক্ষণ করতে হবে এবং কোনটি বাতিল করতে হবে তা নির্ধারণ করতে এখানে দুটি প্রধান নমুনা পদ্ধতি ব্যবহার করা হয়েছে:
- হেড স্যাম্পলিং — ট্রেসের শুরুতে সিদ্ধান্ত নেয় এটা রাখা হবে কি না
- লেজের নমুনা - সম্পূর্ণ ট্রেস উপলব্ধ হওয়ার পরেই সিদ্ধান্ত নেয়। এটি প্রয়োজনীয় যখন সিদ্ধান্তটি ট্রেসে পরে প্রদর্শিত ডেটার উপর নির্ভর করে। উদাহরণস্বরূপ, ত্রুটি স্প্যান সহ ডেটা। এই কেসগুলি হেড স্যাম্পলিং দ্বারা পরিচালনা করা যায় না কারণ তাদের প্রথমে পুরো ট্রেস বিশ্লেষণ করতে হবে
OpenTelemetry সংগ্রাহক ডেটা সংগ্রহের সিস্টেমকে কনফিগার করতে সাহায্য করে যাতে এটি শুধুমাত্র প্রয়োজনীয় ডেটা সংরক্ষণ করে। আমরা পরে এর কনফিগারেশন নিয়ে আলোচনা করব, কিন্তু আপাতত, কোডে কী পরিবর্তন করতে হবে সেই প্রশ্নের দিকে এগিয়ে যাওয়া যাক যাতে এটি ট্রেস তৈরি করা শুরু করে।
জিরো-কোড ইন্সট্রুমেন্টেশন
ট্রেস জেনারেশন পাওয়ার জন্য সত্যিই ন্যূনতম কোডিং প্রয়োজন - জাভা-এজেন্টের সাথে আমাদের অ্যাপ্লিকেশনগুলি চালু করা প্রয়োজন ছিল, নির্দিষ্ট করে
-javaagent:/opentelemetry-javaagent-1.29.0.jar
-Dotel.javaagent.configuration-file=/otel-config.properties
OpenTelemetry বিপুল সংখ্যক সমর্থন করে
আমাদের এজেন্ট কনফিগারেশনে, আমরা যে লাইব্রেরিগুলি ব্যবহার করছি সেগুলিকে অক্ষম করে দিয়েছি যার স্প্যানগুলি আমরা ট্রেসে দেখতে চাই না এবং আমাদের কোড কীভাবে কাজ করে সে সম্পর্কে ডেটা পেতে, আমরা এটি দিয়ে চিহ্নিত করেছি
@WithSpan("acquire locks") public CompletableFuture<Lock> acquire(SortedSet<Object> source) { var traceLocks = source.stream().map(Object::toString).collect(joining(", ")); Span.current().setAttribute("locks", traceLocks); return CompletableFuture.supplyAsync(() -> /* async job */); }
এই উদাহরণে, @WithSpan
টীকাটি পদ্ধতিটির জন্য ব্যবহার করা হয়, যা " acquire locks
" নামে একটি নতুন স্প্যান তৈরি করার প্রয়োজনীয়তার সংকেত দেয় এবং " locks
" বৈশিষ্ট্যটি মেথড বডিতে তৈরি স্প্যানে যোগ করা হয়।
যখন পদ্ধতিটি কাজ শেষ করে, স্প্যানটি বন্ধ হয়ে যায়, এবং অ্যাসিঙ্ক্রোনাস কোডের জন্য এই বিশদটির দিকে মনোযোগ দেওয়া গুরুত্বপূর্ণ। আপনি যদি একটি টীকাযুক্ত পদ্ধতি থেকে কল করা ল্যাম্বডা ফাংশনে অ্যাসিঙ্ক্রোনাস কোডের কাজের সাথে সম্পর্কিত ডেটা পেতে চান তবে আপনাকে এই ল্যাম্বডাগুলিকে পৃথক পদ্ধতিতে আলাদা করতে হবে এবং একটি অতিরিক্ত টীকা দিয়ে চিহ্নিত করতে হবে।
আমাদের ট্রেস সংগ্রহ সেটআপ
এখন, পুরো ট্রেস সংগ্রহ সিস্টেমটি কীভাবে কনফিগার করবেন সে সম্পর্কে কথা বলা যাক। আমাদের সমস্ত JVM অ্যাপ্লিকেশনগুলি একটি জাভা এজেন্টের সাথে চালু করা হয়েছে যা OpenTelemetry সংগ্রাহকের কাছে ডেটা পাঠায়।
যাইহোক, একটি একক সংগ্রাহক একটি বড় ডেটা প্রবাহ পরিচালনা করতে পারে না এবং সিস্টেমের এই অংশটি অবশ্যই স্কেল করা উচিত। আপনি যদি প্রতিটি JVM অ্যাপ্লিকেশনের জন্য একটি পৃথক সংগ্রাহক চালু করেন, তাহলে টেইল স্যাম্পলিং ভেঙে যাবে, কারণ ট্রেস বিশ্লেষণ অবশ্যই একটি সংগ্রাহকের উপর ঘটতে হবে, এবং যদি অনুরোধটি একাধিক JVM-এর মাধ্যমে যায়, তবে একটি ট্রেসের স্প্যান বিভিন্ন সংগ্রাহকের উপর শেষ হবে এবং তাদের বিশ্লেষণ হবে অসম্ভব
এখানে, ক
ফলস্বরূপ, আমরা নিম্নলিখিত সিস্টেমটি পাই: প্রতিটি JVM অ্যাপ্লিকেশন একই ব্যালেন্সার সংগ্রাহকের কাছে ডেটা পাঠায়, যার একমাত্র কাজ হল বিভিন্ন অ্যাপ্লিকেশন থেকে প্রাপ্ত ডেটা বিতরণ করা, তবে একটি প্রদত্ত ট্রেসের সাথে সম্পর্কিত, একই সংগ্রাহক-প্রসেসরে। তারপর, সংগ্রাহক-প্রসেসর গ্রাফানা টেম্পোতে ডেটা পাঠায়।
আসুন এই সিস্টেমের উপাদানগুলির কনফিগারেশনটি ঘনিষ্ঠভাবে দেখে নেওয়া যাক।
লোড ব্যালেন্সিং সংগ্রাহক
সংগ্রাহক-ব্যালেন্সার কনফিগারেশনে, আমরা নিম্নলিখিত প্রধান অংশগুলি কনফিগার করেছি:
receivers: otlp: protocols: grpc: exporters: loadbalancing: protocol: otlp: tls: insecure: true resolver: static: hostnames: - collector-1.example.com:4317 - collector-2.example.com:4317 - collector-3.example.com:4317 service: pipelines: traces: receivers: [otlp] exporters: [loadbalancing]
- রিসিভারগুলি — যেখানে পদ্ধতিগুলি (যার মাধ্যমে সংগ্রাহক ডেটা গ্রহণ করতে পারে) কনফিগার করা হয়। আমরা শুধুমাত্র OTLP ফর্ম্যাটে ডেটা রিসেপশন কনফিগার করেছি। (এর মাধ্যমে ডেটার অভ্যর্থনা কনফিগার করা সম্ভব
অন্যান্য অনেক প্রোটোকল , উদাহরণস্বরূপ Zipkin, Jaeger।) - রপ্তানিকারক - কনফিগারেশনের অংশ যেখানে ডেটা ব্যালেন্সিং কনফিগার করা হয়। এই বিভাগে নির্দিষ্ট করা সংগ্রাহক-প্রসেসরগুলির মধ্যে, ট্রেস শনাক্তকারী থেকে গণনা করা হ্যাশের উপর নির্ভর করে ডেটা বিতরণ করা হয়।
- পরিষেবা বিভাগটি কীভাবে পরিষেবাটি কাজ করবে তার কনফিগারেশনটি নির্দিষ্ট করে: শুধুমাত্র ট্রেস সহ, উপরে কনফিগার করা OTLP রিসিভার ব্যবহার করা এবং ব্যালেন্সার হিসাবে ডেটা প্রেরণ করা, যেমন প্রক্রিয়াকরণ ছাড়াই।
তথ্য প্রক্রিয়াকরণ সঙ্গে সংগ্রাহক
সংগ্রাহক-প্রসেসরগুলির কনফিগারেশন আরও জটিল, তাই আসুন সেখানে একবার দেখে নেওয়া যাক:
receivers: otlp: protocols: grpc: endpoint: 0.0.0.0:14317 processors: tail_sampling: decision_wait: 10s num_traces: 100 expected_new_traces_per_sec: 10 policies: [ { name: latency500-policy, type: latency, latency: {threshold_ms: 500} }, { name: error-policy, type: string_attribute, string_attribute: {key: error, values: [true, True]} }, { name: probabilistic10-policy, type: probabilistic, probabilistic: {sampling_percentage: 10} } ] resource/delete: attributes: - key: process.command_line action: delete - key: process.executable.path action: delete - key: process.pid action: delete - key: process.runtime.description action: delete - key: process.runtime.name action: delete - key: process.runtime.version action: delete exporters: otlp: endpoint: tempo:4317 tls: insecure: true service: pipelines: traces: receivers: [otlp] exporters: [otlp]
সংগ্রাহক-ব্যালেন্সার কনফিগারেশনের মতো, প্রসেসিং কনফিগারেশন রিসিভার, রপ্তানিকারক এবং পরিষেবা বিভাগগুলি নিয়ে গঠিত। যাইহোক, আমরা প্রসেসর বিভাগে ফোকাস করব, যা ব্যাখ্যা করে কিভাবে ডেটা প্রক্রিয়া করা হয়।
প্রথমত, tail_sampling বিভাগটি প্রদর্শন করে a
latency500-নীতি : এই নিয়মটি 500 মিলিসেকেন্ডের বেশি লেটেন্সি সহ ট্রেস নির্বাচন করে।
error-policy : এই নিয়মটি এমন ট্রেস নির্বাচন করে যা প্রক্রিয়াকরণের সময় ত্রুটির সম্মুখীন হয়। এটি ট্রেস স্প্যানগুলিতে "সত্য" বা "সত্য" মান সহ "ত্রুটি" নামে একটি স্ট্রিং বৈশিষ্ট্য অনুসন্ধান করে।
সম্ভাব্য 10-নীতি : এই নিয়মটি এলোমেলোভাবে সমস্ত চিহ্নের 10% নির্বাচন করে যাতে সাধারণ অ্যাপ্লিকেশন অপারেশন, ত্রুটি এবং দীর্ঘ অনুরোধ প্রক্রিয়াকরণের অন্তর্দৃষ্টি প্রদান করা যায়।
tail_sampling ছাড়াও, এই উদাহরণটি তথ্য বিশ্লেষণ এবং স্টোরেজের জন্য প্রয়োজনীয় নয় এমন অপ্রয়োজনীয় বৈশিষ্ট্যগুলি মুছে ফেলার জন্য সম্পদ/মুছুন বিভাগটি দেখায়।
ফলাফল
ফলস্বরূপ Grafana ট্রেস অনুসন্ধান উইন্ডো আপনাকে বিভিন্ন মানদণ্ড দ্বারা ডেটা ফিল্টার করতে সক্ষম করে। এই উদাহরণে, আমরা কেবল লবি পরিষেবা থেকে প্রাপ্ত ট্রেসগুলির একটি তালিকা প্রদর্শন করি, যা গেম মেটাডেটা প্রক্রিয়া করে। কনফিগারেশনটি লেটেন্সি, ত্রুটি এবং র্যান্ডম স্যাম্পলিং এর মতো বৈশিষ্ট্যগুলির দ্বারা ভবিষ্যতে ফিল্টার করার অনুমতি দেয়।
ট্রেস ভিউ উইন্ডো লবি পরিষেবার এক্সিকিউশন টাইমলাইন প্রদর্শন করে, যার মধ্যে অনুরোধ করা বিভিন্ন স্প্যান রয়েছে।
আপনি ছবিটি থেকে দেখতে পাচ্ছেন, ইভেন্টগুলির ক্রমটি নিম্নরূপ - লকগুলি অর্জিত হয়, তারপরে ক্যাশে থেকে বস্তুগুলি পুনরুদ্ধার করা হয়, তারপরে একটি লেনদেন সম্পাদন করা হয় যা অনুরোধগুলি প্রক্রিয়া করে, তারপরে বস্তুগুলি আবার ক্যাশে সংরক্ষণ করা হয় এবং তালা মুক্তি হয়.
স্ট্যান্ডার্ড লাইব্রেরির ইনস্ট্রুমেন্টেশনের কারণে ডাটাবেস অনুরোধের সাথে সম্পর্কিত স্প্যানগুলি স্বয়ংক্রিয়ভাবে তৈরি হয়েছিল। বিপরীতে, লক ম্যানেজমেন্ট, ক্যাশে অপারেশন, এবং লেনদেন শুরুর সাথে সম্পর্কিত স্প্যানগুলি উপরে উল্লিখিত টীকাগুলি ব্যবহার করে ব্যবসায়িক কোডে ম্যানুয়ালি যুক্ত করা হয়েছিল।
একটি স্প্যান দেখার সময়, আপনি বৈশিষ্ট্যগুলি দেখতে পারেন যা আপনাকে প্রক্রিয়াকরণের সময় কী ঘটেছে তা আরও ভালভাবে বুঝতে দেয়, উদাহরণস্বরূপ, ডাটাবেসে একটি প্রশ্ন দেখুন৷
Grafana Tempo এর একটি আকর্ষণীয় বৈশিষ্ট্য হল
মোড়ানো
আমরা যেমন দেখেছি, OpenTelemetry ট্রেসিংয়ের সাথে কাজ করা আমাদের পর্যবেক্ষণ ক্ষমতাকে বেশ সুন্দরভাবে উন্নত করেছে। ন্যূনতম কোড পরিবর্তন এবং একটি সুগঠিত সংগ্রাহক সেটআপের সাথে, আমরা গভীর অন্তর্দৃষ্টি পেয়েছি – এছাড়াও, আমরা দেখেছি কিভাবে Grafana Tempo-এর ভিজ্যুয়ালাইজেশন ক্ষমতা আমাদের সেটআপকে আরও পরিপূরক করেছে। পড়ার জন্য ধন্যবাদ!