এই দু-भাগের সিরিজের প্রথম অংশে, আমরা কভার করেছিলাম কীভাবে একটি রুবি অন রেইল্স অ্যাপ্লিকেশনে AppSignal সেট আপ করবেন যাতে আউট-অফ-দ্য-বক্স অনেক গভীর ইনসাইট পাওয়া যায়। AppSignal স্বয়ংক্রিয়ভাবে এরর ট্র্যাক করে, পারফরম্যান্স মনিটর করে, এবং কিছু ডিপেনডেন্সি সম্পর্কে মেট্রিক্স রিপোর্ট করে।
তবে, অনেক কেসে আমাদের প্রতিটি অ্যাপ্লিকেশন ভিন্ন ভাবে বিহেভ করে, তাই জেনেরিক মনিটরিং-এর চেয়ে আরও কিছু দরকার।
এই পোস্টে, আমরা একটি রুবি অন রেইল্স অ্যাপ্লিকেশনে কাস্টম ইনস্ট্রুমেন্টেশন এবং মনিটরিং যোগ করার প্রসেস দেখব। এটি আপনাকে আপনার অ্যাপ্লিকেশন কীভাবে বিহেভ করছে সে সম্পর্কে গভীর ইনসাইট দেবে।
কোড ফলো করতে চাইলে প্রি-রিকোয়েজিট:
- www.appsignal.com-এ একাউন্ট
- Docker ইনস্টলড ও রানিং (
docker-composeব্যবহারের জন্য)
এই পোস্ট ফলো করতে, স্যাম্পল অ্যাপ্লিকেশনে আপনার নিজস্ব AppSignal একাউন্ট দিয়ে AppSignal সেট আপ করতে হবে।
কাস্টম ইনস্ট্রুমেন্টেশন ও মনিটরিং
যখন আউট-অফ-দ্য-বক্স AppSignal ইনস্ট্রুমেন্ট করে তার চেয়ে বেশি দরকার, AppSignal জেম আপনাকে আপনার রেইল্স অ্যাপ্লিকেশনে কাস্টম ইনস্ট্রুমেন্টেশন যোগ করার সুবিধা দেয়।
কোডের অংশ ইনস্ট্রুমেন্ট করা
মান लीজিয়ে আপনি একটি অ্যাপ্লিকেশনে নতুন ফিচার যোগ করতে চান। যখন ইউজার /posts ভিজিট করে সব পোস্ট দেখার জন্য, তারা নির্দিষ্ট অক্ষর দিয়ে শুরু হওয়া পোস্ট ফিল্টার করতে পারবে (অথবা আরও কমপ্লেক্স কিছু)।
এই নতুন সার্চ ফাংশনালিটি ইতিমধ্যে Post মডেলে Post.where_title_starts_with মেথড দিয়ে ইমপ্লিমেন্ট করা আছে। PostsController#index আপডেট করি যাতে নির্দিষ্ট কোয়েরি প্যারামিটার থাকলে নতুন মেথডটি ব্যবহার হয়:
# app/controllers/posts_controller.rb
def index
starts_with = params[:starts_with]
@posts = if starts_with.present?
Post.where_title_starts_with(starts_with)
else
Post.all
end
end
এটি আপনার অ্যাপ্লিকেশনের এতটা কোর অংশ যে, আপনি জানতে চাবেন এটি কীভাবে পারফর্ম করছে এবং পারফরম্যান্স কখন পরিবর্তন হচ্ছে। AppSignal এর জন্য কয়েকটি পথ দিয়েছে।
প্রথমে, Post.where_title_starts_with মেথডের কন্টেন্ট ইনস্ট্রুমেন্ট করব। যেকোনো কোড ব্লকের ইনসাইট পেতে চাইলে, ইনস্ট্রুমেন্টেশন ব্লক দিয়ে কোড ব্লক র্যাপ করুন। মেথডটি এইভাবে আপডেট করুন:
# app/models/post.rb
def self.where_title_starts_with(letter)
Appsignal.instrument('Post.where_title_starts_with', "Fetch posts that start with letter") do
Analytics.track_post_title_search(letter.downcase)
select('*, pg_sleep(0.01)').where("title ILIKE :letter", letter: "#{letter.downcase}%").load
end
end
দ্বিতীয়ভাবে, Analytics.track_post_title_search মেথডটিও ইনস্ট্রুমেন্ট করতে চাই কারণ app/services/analytics.rb কিছু হеви প্রসেসিং করছে। এই কেসে, পুরো মেথডটি আরও সঠিকভাবে ইনস্ট্রুমেন্ট করার জন্য মেথড ইনস্ট্রুমেন্টেশন ব্যবহার করব:
# app/services/analytics.rb
require 'appsignal/integrations/object'
class Analytics
def self.track_post_title_search(letter, sleep = sleep(1))
# Some heavy processing
sleep 1
end
appsignal_instrument_class_method :track_post_title_search
end
ইনসাইট
উপরোক্ত কোড সেভ করার কিছু মিনিট পর, আপনার AppSignal ড্যাশবোর্ডে যেনে নিন কী নতুন ইনফরমেশন উপলব্ধ (যদি না দেখেন, ডকার কন্টেইনার রিস্টার্ট করতে হতে পারে)। নতুন ফিচার কাজ করছে কিনা ভেরিফাই করতে পোস্টস ইন্ডেক্স পেজে সার্চ প্যারাম দিয়ে ভিজিট করুন: https://localhost:3000/posts?starts_with=f
ডাটাবেসে কতগুলো পোস্ট তৈরি করা আছে তার ওপর নির্ভর করে, /posts এন্ডপয়েন্টে খুব স্লো হয়ে যেতে পারে।
AppSignal-এ পারফরম্যান্স ইস্যু খুললে (Performance → Issue list) এবং PostsController#index একশন ভিউ করলে, নিচের দিকে Event Timeline দেখতে পাবেন। এটি সপেসিফিক কোড রান করতে কতটুকু টাইম খরচ হচ্ছে সে সম্পর্কে ব্রেকডাউন দেয়:
এই টাইমলাইন সকল পারফরম্যান্স ইভেন্টের জন্য আছে, কিন্তু এখানে কাস্টম ইনস্ট্রুমেন্টেশন ইভেন্টও দেখতে পাচ্ছি। এটি দেখাচ্ছে Post.where_title_starts_with কল করতে ৮.৮৪ সেকেন্ড লেগেছে, যার মধ্যে ২.০১ সেকেন্ড Analytics.track_post_title_search মেথডে খরচ হয়েছে, এবং বাকি টাইম এক্টিভ রেকর্ড কোয়েরিতে। আপনি ইন্ডিভিজুয়াল ইভেন্টে ক্লিক করে আরও ডিটেইলড ইনফরমেশন পেতে পারেন — যেমন sql.active_record ইভেন্ট।
AppSignal-এর ইনস্ট্রুমেন্টেশন হেল্পার আপনাকে অ্যাপ্লিকেশন কোডের আরও ডিটেইলড ব্রেকডাউন দেয়, যাতে পারফরম্যান্সে প্রভাব ফেলতে পারে এমন কোডের টুকরো সম্পর্কে ইনসাইট পাওয়া সহজ হয়। AppSignal-এর ইনস্ট্রুমেন্টেশন গাইডে এর ওপর আরও জানতে পারেন।
এক্সেপশন হ্যান্ডলিং
কোডের পারফরম্যান্স মনিটর করার পাশাপাশি, আপনাকে জানতে হবে যখন অ্যাপ্লিকেশন প্রত্যাশা অনুযায়ী বিহেভ না করছে এবং কোথায় সমস্যা হচ্ছে। আমরা ইতিমধ্যে দেখেছি AppSignal কীভাবে আমাদের কোড দ্বারা হ্যান্ডেল না হওয়া এক্সেপশন রিপোর্ট করে। কিন্তু বক্সের বাইরেও কিছু আছে।
শুরু করি ইন্টারমিটেন্ট এরর সৃষ্টি করার কোডটি রিমুভ করে। ড্যাশবোর্ডে এরর দেখলে ব্যাকট্রেস থেকে জানা যায় এটি কোথায় হচ্ছে। app/controllers/pages_controller.rb-এর ভিতরে if স্টেটমেন্টটি রিমুভ করুন:
class PagesController < ApplicationController
def home
CreateRandomPostsJob.perform_later
end
end
এখন, ওভারভিউ ড্যাশবোর্ডে অ্যাপ্লিকেশনের এরর রেট ন*{০}*-এ চলে যাবে।
এখন, যখন একজন ইউজার অস্তিত্বহীন একটি পোস্ট দেখতে চায়, অ্যাপ্লিকেশন ক্র্যাশ করে — যেমন, https://localhost:3000/posts/doesnotexist। বদলে, আপনি একটা মেসেজ দেখাতে চাইতে পারেন। PostsController-এ যেখানে এটি হতে পারে সেখানে রেস্কিউ যোগ করুন। #set_post মেথড আপডেট করুন:
# app/controllers/posts_controller.rb
class PostsController < ApplicationController
...
private
def set_post
@post = Post.find(params[:id])
rescue ActiveRecord::RecordNotFound => e
render json: { error: "Oops. That post isn't here" }, status: :not_found
end
...
end
যেহেতু আমরা ম্যানুয়ালি এক্সেপশন হ্যান্ডেল করছি, এটি অটোমেটিক্যালি AppSignal-এ রিপোর্ট হবে না। আপনি Appsignal.set_error ব্যবহার করে এখনও ম্যানুয়ালি এরর ট্র্যাক করতে পারেন।
এরর ট্র্যাক করার সবচেয়ে সহজ পথ হলো সেটি ফাংশনের একমাত্র আর্গুমেন্ট হিসেবে পাস করা: Appsignal.set_error(e)। আমরা রিকোয়েস্টে আরও কনটেক্সট যোগ করার সুবিধাও নিতে চাই। AppSignal আপনাকে Appsignal.tag_request ব্যবহার করে ইভেন্টে আপনার আربিট্রারি ইনফরমেশন ট্যাগ করার অনুমতি দেয়:
def set_post
Appsignal.tag_request(user_id: 'user-from-params', post_id: params[:id])
@post = Post.find(params[:id])
rescue ActiveRecord::RecordNotFound => e
Appsignal.set_error(e)
render json: { error: "Oops. That post isn't here" }, status: :not_found
end
এখন https://localhost:3000/posts/doesnotexist ভিজিট করুন যাতে অ্যাপ্লিকেশন ক্র্যাশ না করে JSON রেসপন্স ফেরত দিচ্ছে কিনা ভেরিফাই করতে পারেন।
ইনসাইট
অস্তিত্বহীন পোস্ট দেখতে চেষ্টা করার পর, অ্যাড করা আপডেটগুলো নিশ্চিত করে এররগুলো AppSignal-এ রিপোর্ট হচ্ছে। AppSignal ড্যাশবোর্ডে, Errors → Issue list-এ, নতুন রিপোর্ট করা এরর (ActiveRecord::RecordNotFound) খুঁজে বের করুন।
এরর ডিটেইল পেজ আমাদের এরর সম্পর্কে উপকারী কনটেক্সট দেয়, যা ডিফল্টভাবে রিকোয়েস্ট সম্পর্কে ইনফরমেশন অন্তর্ভুক্ত করে যেমন HTTP মেথড, প্যারামিটার, এবং সেশন ডেটা। আপনি দেখবেন কাস্টম ট্যাগগুলোও অন্তর্ভুক্ত, যা আপনাকে ম্যাচিং ট্যাগ সহ সকল এরর ফিল্টার করার ক্ষমতা দেয়।
যেহেতু আমরা রিকোয়েস্ট ট্যাগ করেছি, এই ইনফরমেশন এরর এবং অন্যান্য ইনস্ট্রুমেন্টেড ইভেন্টে যোগ হয়। যদি আপনি একাধিকবার একটি পোস্ট ভিজিট করেন, যেমন https://localhost:3000/posts/1, আপনি লক্ষ্য করবেন ট্যাগগুলো পারফরম্যান্স মেজারমেন্টেও অন্তর্ভুক্ত (Performance → Issue list → PostsController#show)। ট্রানজ্যাকশন ট্যাগিং-র ওপর আরও পড়ুন গাইডে।
ট্রানজ্যাকশনে কাস্টম মেটাডেটা যোগ করার এই ক্ষমতা প্রোডাকশনে ইস্যু ডায়াগনোস করতে অনেক সুযোগ খুলে দেয়। এর একটি চমৎকার উদাহরণ হলো কুবারনেটিস মেটাডেটা আপনার এররগুলোর সাথে যোগ করা।
মেট্রিক্স
এখন কিছু কাস্টম ইনস্ট্রুমেন্টেশন এবং এরর মনিটরিং সেট আপ হয়ে গেছে, আপনি বুঝতে পারেন কখনও কখনও পোস্টস সার্চে বড় স্পাইক আসছে। যখনই কোনো ইউজার সার্চ করে, Analytics#track_post_title_search কল হয়, যা কিছু ক্যালকুলেশন করে এবং থার্ড-পার্টি সার্ভিসে API কল করে। এই থার্ড পার্টির API-তে রেট লিমিট আছে। আমরা চাই এটি কতবার কল হচ্ছে ট্র্যাক করতে, যাতে অ্যাপ্লিকেশন কতটুকু লিমিটের কাছে সেটি মনিটর করা যায়।
AppSignal আপনাকে অ্যাপ্লিকেশনের যেকোনো জায়গায় কাস্টম মেট্রিক্স ট্র্যাক করার সুবিধা দেয়।
প্রথমে, আমরা আমাদের অ্যানালিটিক্স সার্ভিস কতবার কল হচ্ছে এবং কী ডেটা দিয়ে, সেটি একটি কাউন্টার এবং ট্যাগ দিয়ে ট্র্যাক করব:
#app/services/analytics.rb
require 'appsignal/integrations/object'
class Analytics
def self.track_post_title_search(letter, sleep = sleep(1))
Appsignal.increment_counter("track_post_search", 1, { letter: letter })
# Some heavy processing
sleep 1
end
appsignal_instrument_class_method :track_post_title_search
end
দ্বিতীয়ভাবে, PostsController#index-এ রিটার্ন হওয়া পোস্টের সংখ্যাও ট্র্যাক করব, কারণ এটি অ্যাপ্লিকেশনের কোর বিহেভিয়র এবং আমরা জানি এটি বৃদ্ধি পাচ্ছে:
#app/controllers/posts_controller.rb
class PostsController < ApplicationController
...
def index
...
Appsignal.set_gauge("posts_index", @posts.size, starts_with: params[:starts_with])
end
end
ফেক ট্রাফিক স্ক্রিপ্ট এখনও অ্যাপ্লিকেশনে চলছে যেটি কিছু ডেটা জেনারেট করবে, কিন্তু ভেরিয়েশন বাড়াতে f, l, এবং v দিয়ে সার্চ করেও দেখি।
ইনসাইট
কাস্টম মেট্রিক্স দেখতে, AppSignal-এ কাস্টম গ্রাফ সহ একটি ড্যাশবোর্ড তৈরি করতে হবে। এটি UI-তে করা যায়, কিন্তু উদাহরণের জন্য আমরা একটি ইম্পোর্ট করব। Dashboard সেকশনে, Add dashboard-এ ক্লিক করুন এবং নিচের JSON দিয়ে একটি ড্যাশবোর্ড ইম্পোর্ট করুন:
{
"title": "Post Search",
"description": "Sample dashboard about posts search activity",
"visuals": [
{
"title": "Analytics",
"line_label": "%name% %letter%",
"display": "LINE",
"format": "number",
"draw_null_as_zero": true,
"metrics": [
{
"name": "track_post_search",
"fields": [ { "field": "COUNTER" } ],
"tags": [ { "key": "letter", "value": "*" } ]
}
],
"type": "timeseries"
},
{
"title": "Search",
"line_label": "%name% %starts_with%",
"display": "LINE",
"format": "number",
"draw_null_as_zero": true,
"metrics": [
{
"name": "posts_index",
"fields": [ { "field": "GAUGE" } ],
"tags": [ { "key": "starts_with", "value": "*" } ]
}
],
"type": "timeseries"
}
]
}
কয়েক মিনিটের মধ্যে আপনার গ্রাফে ডেটা দেখতে পাবেন। লাইনের ওপর হোভার করলে আপনি যে টাইমফ্রেম দেখছেন সেটির মেট্রিক্স লেজেন্ড দেখাবে।
লক্ষ্য করুন এটি প্রতিটি ট্যাগ ভ্যালুর জন্য আলাদা লাইন দেখাচ্ছে। বর্তমানে আমাদের ফেক ট্রাফিক শুধু 'e' অক্ষর সার্চ করছে, কিন্তু আমরা ম্যানুয়ালি অন্যান্য অক্ষর সার্চ করলাম, তাই প্রতিটি নতুন ডেটা পয়েন্টের জন্য গ্রাফে নতুন লাইন দেখতে পাচ্ছেন।
এটো দিয়ে কি? AppSignal-এ আরও কাস্টম ইনস্ট্রুমেন্টেশন সলিউশন আছে যা এখানে কভার করা হয়নি। একটু দিয়ে শুনাতে লायक — ব্রেডক্রাম্বস। ব্রেডক্রাম্বস আপনাকে অ্যাপ্লিকেশনে অ্যাকশনের একটি লিস্ট ট্র্যাক করতে দেয়, যা এররে রিপোর্ট হবে। আপনাকে আরো স্পেসিফিক ও অর্ডার্ড ইনফরমেশন মিলবে এরর ঘটার আগে কী কী ঘটেছিল সে সম্পর্কে।
কাস্টম ইনস্ট্রুমেন্টেশন সম্পর্কে সবকিছু পড়ুন গাইডে।
র্যাপ-আপ: AppSignal দিয়ে রুবি অ্যাপের কাস্টম ইনস্ট্রুমেন্টেশন ও মনিটরিং
এই সিরিজের পার্ট ১-এ আপনার রুবি অ্যাপ্লিকেশনে AppSignal বেসিক সেটআপ ও ব্যবহার কভার করা হয়েছিল।
এই পার্টে, আমরা একটি অ্যাপ্লিকেশন নিলাম যাতে ইতিমধ্যে আউট-অফ-দ্য-বক্স গরেট মনিটরিং আছে, এবং AppSignal জেম ব্যবহার করে সেটিকে আরও উন্নত করলাম।
AppSignal-এর কাস্টম ইনস্ট্রুমেন্টেশন, এরর ট্র্যাকিং, এবং পারফরম্যান্স মনিটরিং ফিচার আপনাকে আপনার অ্যাপ্লিকেশন কীভাবে বিহেভ করছে সে সম্পর্কে যে ইনসাইট দরকার সেটি দেয়। এটি আউট-অফ-দ্য-বক্স অনেক কিছু দেয় যোক সময় আপনি কন্ট্রোল নিতে পারেন।
এখন আপনার কোডকে বাঘে ছেড়ে দিন, যতক্ষণ না আপনি তার পারফরম্যান্সের ওপর নজর রাখেন। হ্যাপি কোডিং!
P.S. Ruby Magic পোস্টগুলো প্রেস থেকে বের होते ही পেতে চাইলে, আমাদের Ruby Magic নিউজলেটার সাবস্ক্রাইব করুন এবং কোনো পোস্ট মিস করবেন না!