অ্যান্ড্রয়েড লগিং সিস্টেমের লক্ষ্য সার্বজনীন অ্যাক্সেসযোগ্যতা এবং সহজে ব্যবহারের জন্য, অনুমান করে যে সমস্ত লগ ডেটা অক্ষরের ক্রম হিসাবে উপস্থাপন করা যেতে পারে। এই অনুমানটি বেশিরভাগ ব্যবহারের ক্ষেত্রে সারিবদ্ধ হয়, বিশেষ করে যখন লগ পঠনযোগ্যতা বিশেষ সরঞ্জাম ছাড়াই গুরুত্বপূর্ণ। যাইহোক, উচ্চ লগিং কর্মক্ষমতা এবং সীমাবদ্ধ লগ আকারের দাবি পরিবেশে, পাঠ্য-ভিত্তিক লগিং সর্বোত্তম নাও হতে পারে। এরকম একটি দৃশ্য হল WindowManager, যা একটি শক্তিশালী লগিং সিস্টেমের প্রয়োজন যা ন্যূনতম সিস্টেম প্রভাব সহ রিয়েল-টাইম উইন্ডো ট্রানজিশন লগগুলি পরিচালনা করতে সক্ষম।
ProtoLog হল WindowManager এবং অনুরূপ পরিষেবার লগিং চাহিদা পূরণের বিকল্প। logcat এর উপর ProtoLog এর প্রধান সুবিধা হল:
- লগিং এর জন্য ব্যবহৃত সম্পদের পরিমাণ কম।
- বিকাশকারীর দৃষ্টিকোণ থেকে, এটি ডিফল্ট অ্যান্ড্রয়েড লগিং ফ্রেমওয়ার্ক ব্যবহার করার মতোই।
- রানটাইমে সক্রিয় বা নিষ্ক্রিয় করা লগ স্টেটমেন্ট সমর্থন করে।
- প্রয়োজনে এখনও লগক্যাটে লগ করতে পারেন।
মেমরির ব্যবহার অপ্টিমাইজ করার জন্য, ProtoLog একটি স্ট্রিং ইন্টারনিং মেকানিজম নিযুক্ত করে যার মধ্যে বার্তার একটি সংকলিত হ্যাশ গণনা করা এবং সংরক্ষণ করা জড়িত। উন্নত কর্মক্ষমতার জন্য, ProtoLog সংকলনের সময় (সিস্টেম পরিষেবার জন্য) স্ট্রিং ইন্টারনিং সঞ্চালন করে, রানটাইমে শুধুমাত্র বার্তা শনাক্তকারী এবং আর্গুমেন্ট রেকর্ড করে। উপরন্তু, একটি ProtoLog ট্রেস তৈরি করার সময় বা একটি বাগ রিপোর্ট প্রাপ্ত করার সময়, ProtoLog স্বয়ংক্রিয়ভাবে কম্পাইলের সময়ে তৈরি করা বার্তা অভিধানকে অন্তর্ভুক্ত করে, যেকোনো বিল্ড থেকে বার্তা ডিকোডিং সক্ষম করে।
প্রোটোলগ ব্যবহার করে, বার্তাটি পারফেটো ট্রেসের মধ্যে একটি বাইনারি বিন্যাসে (প্রোটো) সংরক্ষণ করা হয়। বার্তা ডিকোডিং Perfetto এর trace_processor
ভিতরে ঘটে। প্রক্রিয়াটির মধ্যে রয়েছে বাইনারি প্রোটো বার্তাগুলির ডিকোডিং, এমবেডেড বার্তা অভিধান ব্যবহার করে বার্তা সনাক্তকারীকে স্ট্রিংগুলিতে অনুবাদ করা এবং গতিশীল আর্গুমেন্ট ব্যবহার করে স্ট্রিং ফর্ম্যাট করা।
ProtoLog android.utils.Log
মতো একই লগ লেভেল সমর্থন করে, যথা: d
, v
, i
, w
, e
, wtf
।
ক্লায়েন্ট-সাইড প্রোটোলগ
প্রাথমিকভাবে, ProtoLog শুধুমাত্র WindowManager-এর সার্ভার সাইডের উদ্দেশ্যে ছিল, একটি একক প্রক্রিয়া এবং উপাদানের মধ্যে কাজ করে। পরবর্তীকালে, সিস্টেম UI প্রক্রিয়াতে উইন্ডো ম্যানেজার শেল কোডকে অন্তর্ভুক্ত করার জন্য এটিকে প্রসারিত করা হয়েছিল, কিন্তু প্রোটোলগ ব্যবহারের জন্য একটি জটিল বয়লারপ্লেট সেটআপ কোড প্রয়োজন। তদ্ব্যতীত, প্রোটো লগিং সিস্টেম সার্ভার এবং সিস্টেম UI প্রসেসের মধ্যে সীমাবদ্ধ ছিল, এটিকে অন্যান্য প্রসেসে অন্তর্ভুক্ত করা শ্রমসাধ্য এবং প্রতিটির জন্য একটি পৃথক মেমরি বাফার সেটআপের প্রয়োজন ছিল। যাইহোক, প্রোটোলগ এখন ক্লায়েন্ট-সাইড কোডের জন্য উপলব্ধ করা হয়েছে, অতিরিক্ত বয়লারপ্লেট কোডের প্রয়োজনীয়তা দূর করে।
সিস্টেম সার্ভিস কোডের বিপরীতে, ক্লায়েন্ট-সাইড কোড সাধারণত কম্পাইল-টাইম স্ট্রিং ইন্টারনিং এড়িয়ে যায়। পরিবর্তে, স্ট্রিং ইন্টারনিং একটি ব্যাকগ্রাউন্ড থ্রেডে গতিশীলভাবে ঘটে। ফলস্বরূপ, যখন ক্লায়েন্ট-সাইডে প্রোটোলগ সিস্টেম পরিষেবাগুলিতে প্রোটোলগ-এর সাথে তুলনামূলক মেমরি ব্যবহারের সুবিধা প্রদান করে, এটি একটি প্রান্তিকভাবে উচ্চ কার্যকারিতা ওভারহেড বহন করে এবং এর সার্ভার-সাইড কাউন্টারপার্টের পিন করা মেমরির মেমরি হ্রাস সুবিধার অভাব রয়েছে।
প্রোটোলগ গ্রুপ
ProtoLog বার্তাগুলিকে ProtoLogGroups
নামক গোষ্ঠীতে সংগঠিত করা হয়, যেভাবে লগক্যাট বার্তাগুলি TAG
দ্বারা সংগঠিত হয়। এই ProtoLogGroups
বার্তাগুলির ক্লাস্টার হিসাবে কাজ করে যা রানটাইমে সম্মিলিতভাবে সক্ষম বা অক্ষম করা যেতে পারে। উপরন্তু, তারা নিয়ন্ত্রণ করে যে বার্তাগুলি সংকলনের সময় ছিনতাই করা উচিত এবং কোথায় সেগুলি লগ করা উচিত (প্রোটো, লগক্যাট বা উভয়ই)। প্রতিটি ProtoLogGroup
নিম্নলিখিত বৈশিষ্ট্যগুলি নিয়ে গঠিত:
-
enabled
:false
সেট করা হলে, এই গ্রুপের বার্তাগুলি সংকলনের সময় বাদ দেওয়া হয় এবং রানটাইমে উপলব্ধ থাকে না। -
logToProto
: এই গ্রুপটি বাইনারি বিন্যাসে লগ করলে তা নির্ধারণ করে। -
logToLogcat
: এই গ্রুপটি লগক্যাটে লগ করলে তা নির্ধারণ করে। -
tag
: লগ করা বার্তার উৎসের নাম।
ProtoLog ব্যবহার করে প্রতিটি প্রক্রিয়ার একটি ProtoLogGroup
দৃষ্টান্ত কনফিগার করা আবশ্যক।
সমর্থিত যুক্তি প্রকার
অভ্যন্তরীণভাবে, প্রোটোলগ ফর্ম্যাট স্ট্রিংগুলি android.text.TextUtils#formatSimple(String, Object...)
ব্যবহার করে, তাই এর সিনট্যাক্স একই।
ProtoLog নিম্নলিখিত আর্গুমেন্ট প্রকার সমর্থন করে:
-
%b
- বুলিয়ান -
%d
,%x
- অবিচ্ছেদ্য প্রকার (ছোট, পূর্ণসংখ্যা বা দীর্ঘ) -
%f
- ফ্লোটিং পয়েন্ট টাইপ (ফ্লোট বা ডবল) -
%s
- স্ট্রিং -
%%
- একটি আক্ষরিক শতাংশ চরিত্র
%04d
এবং %10b
মতো প্রস্থ এবং নির্ভুলতা সংশোধনকারী সমর্থিত, কিন্তু argument_index
এবং flags
সমর্থিত নয়।
একটি নতুন পরিষেবাতে প্রোটোলগ ব্যবহার করুন
একটি নতুন প্রক্রিয়ায় ProtoLog ব্যবহার করতে:
এই পরিষেবার জন্য একটি
ProtoLogGroup
সংজ্ঞা তৈরি করুন।প্রথম ব্যবহারের আগে সংজ্ঞাটি শুরু করুন (উদাহরণস্বরূপ, প্রক্রিয়া তৈরিতে):
Protolog.init(ProtologGroup.values());
android.util.Log
এর মতো একই পদ্ধতিতেProtolog
ব্যবহার করুন:ProtoLog.v(WM_SHELL_STARTING_WINDOW, "create taskSnapshot surface for task: %d", taskId);
কম্পাইল-টাইম অপ্টিমাইজেশান সক্ষম করুন
একটি প্রক্রিয়ায় কম্পাইল টাইম ProtoLog সক্ষম করতে, আপনাকে অবশ্যই এর বিল্ড নিয়ম পরিবর্তন করতে হবে এবং protologtool
বাইনারী চালু করতে হবে।
ProtoLogTool
হল একটি কোড ট্রান্সফরমেশন বাইনারি যা স্ট্রিং ইন্টারনিং সঞ্চালন করে এবং প্রোটোলগ ইনভোকেশন আপডেট করে। এই বাইনারিটি এই উদাহরণে দেখানো প্রতিটি ProtoLog
লগিং কলকে রূপান্তরিত করে:
ProtoLog.x(ProtoLogGroup.GROUP_NAME, "Format string %d %s", value1, value2);
মধ্যে:
if (ProtoLogImpl.isEnabled(GROUP_NAME)) {
int protoLogParam0 = value1;
String protoLogParam1 = String.valueOf(value2);
ProtoLogImpl.x(ProtoLogGroup.GROUP_NAME, 1234560b0100, protoLogParam0, protoLogParam1);
}
এই উদাহরণে, ProtoLog
, ProtoLogImpl
, এবং ProtoLogGroup
হল আর্গুমেন্ট হিসাবে প্রদত্ত ক্লাস (আমদানি করা যেতে পারে, স্ট্যাটিক আমদানি করা, বা সম্পূর্ণ পথ, ওয়াইল্ডকার্ড আমদানি অনুমোদিত নয়) এবং, x
হল লগিং পদ্ধতি।
রূপান্তর উৎস স্তরে সম্পন্ন করা হয়. ফরম্যাট স্ট্রিং, লগ লেভেল এবং লগ গ্রুপের নাম থেকে একটি হ্যাশ তৈরি করা হয় এবং ProtoLogGroup আর্গুমেন্টের পরে ঢোকানো হয়। প্রকৃত জেনারেট করা কোডটি ইনলাইন করা হয় এবং ফাইলে লাইন নম্বর সংরক্ষণের জন্য বেশ কিছু নতুন লাইন অক্ষর যোগ করা হয়।
উদাহরণ:
genrule {
name: "wm_shell_protolog_src",
srcs: [
":protolog-impl", // protolog lib
":wm_shell_protolog-groups", // protolog groups declaration
":wm_shell-sources", // source code
],
tools: ["protologtool"],
cmd: "$(location protologtool) transform-protolog-calls " +
"--protolog-class com.android.internal.protolog.ProtoLog " +
"--loggroups-class com.android.wm.shell.protolog.ShellProtoLogGroup " +
"--loggroups-jar $(location :wm_shell_protolog-groups) " +
"--viewer-config-file-path /system_ext/etc/wmshell.protolog.pb " +
"--legacy-viewer-config-file-path /system_ext/etc/wmshell.protolog.json.gz " +
"--legacy-output-file-path /data/misc/wmtrace/shell_log.winscope " +
"--output-srcjar $(out) " +
"$(locations :wm_shell-sources)",
out: ["wm_shell_protolog.srcjar"],
}
কমান্ড লাইন বিকল্প
প্রোটোলগের একটি প্রধান সুবিধা হল যে আপনি রানটাইমে এটি সক্ষম বা নিষ্ক্রিয় করতে পারেন। উদাহরণস্বরূপ, একটি নির্দিষ্ট সমস্যা ডিবাগ করার জন্য, আপনি একটি বিল্ডে আরও ভার্বোস লগিং করতে পারেন, ডিফল্টরূপে অক্ষম এবং স্থানীয় বিকাশের সময় এটি সক্রিয় করতে পারেন। এই প্যাটার্নটি ব্যবহার করা হয়, উদাহরণস্বরূপ, WindowManager-এ WM_DEBUG_WINDOW_TRANSITIONS
এবং WM_DEBUG_WINDOW_TRANSITIONS_MIN
গ্রুপগুলির সাথে বিভিন্ন ধরনের ট্রানজিশন লগিং সক্ষম করে, আগেরটি ডিফল্টরূপে সক্রিয় করা হয়।
একটি ট্রেস শুরু করার সময় আপনি Perfetto ব্যবহার করে ProtoLog কনফিগার করতে পারেন। এছাড়াও আপনি adb
কমান্ড লাইন ব্যবহার করে স্থানীয়ভাবে ProtoLog কনফিগার করতে পারেন।
adb shell cmd protolog_configuration
কমান্ড নিম্নলিখিত আর্গুমেন্ট সমর্থন করে:
help
Print this help text.
groups (list | status)
list - lists all ProtoLog groups registered with ProtoLog service"
status <group> - print the status of a ProtoLog group"
logcat (enable | disable) <group>"
enable or disable ProtoLog to logcat
কার্যকর ব্যবহারের জন্য টিপস
ProtoLog বার্তা এবং পাস করা যেকোনো স্ট্রিং আর্গুমেন্ট উভয়ের জন্য স্ট্রিং ইন্টারনিং ব্যবহার করে। এর মানে হল যে, প্রোটোলগ থেকে আরও সুবিধা পেতে, বার্তাগুলিকে ভেরিয়েবলে বারবার মানগুলিকে আলাদা করা উচিত।
উদাহরণস্বরূপ, নিম্নলিখিত বিবৃতি বিবেচনা করুন:
Protolog.v(MY_GROUP, "%s", "The argument value is " + argument);
কম্পাইলের সময় অপ্টিমাইজ করা হলে, এটি এতে অনুবাদ করে:
ProtologImpl.v(MY_GROUP, 0x123, "The argument value is " + argument);
যদি প্রোটোলগ কোডে আর্গুমেন্ট A,B,C
সহ ব্যবহার করা হয়:
Protolog.v(MY_GROUP, "%s", "The argument value is A");
Protolog.v(MY_GROUP, "%s", "The argument value is B");
Protolog.v(MY_GROUP, "%s", "The argument value is C");
Protolog.v(MY_GROUP, "%s", "The argument value is A");
এটি মেমরিতে নিম্নলিখিত বার্তাগুলির ফলাফল দেয়:
Dict:
0x123: "%s"
0x111: "The argument value is A"
0x222: "The argument value is B"
0x333: "The argument value is C"
Message1 (Hash: 0x123, Arg1: 0x111)
Message2 (Hash: 0x123, Arg2: 0x222)
Message3 (Hash: 0x123, Arg3: 0x333)
Message4 (Hash: 0x123, Arg1: 0x111)
যদি, পরিবর্তে, প্রোটোলগ বিবৃতিটি এইভাবে লেখা হয়েছিল:
Protolog.v(MY_GROUP, "The argument value is %s", argument);
মেমরির বাফারটি এইভাবে শেষ হবে:
Dict:
0x123: "The argument value is %s" (24 b)
0x111: "A" (1 b)
0x222: "B" (1 b)
0x333: "C" (1 b)
Message1 (Hash: 0x123, Arg1: 0x111)
Message2 (Hash: 0x123, Arg2: 0x222)
Message3 (Hash: 0x123, Arg3: 0x333)
Message4 (Hash: 0x123, Arg1: 0x111)
এই ক্রমটির ফলে একটি মেমরির পদচিহ্ন পাওয়া যায় যা 35% ছোট।
উইনস্কোপ দর্শক
উইনস্কোপের প্রোটোলগ ভিউয়ার ট্যাবটি একটি সারণী বিন্যাসে সংগঠিত প্রোটোলগ ট্রেস দেখায়। আপনি লগ লেভেল, ট্যাগ, সোর্স ফাইল (যেখানে প্রোটোলগ স্টেটমেন্ট থাকে) এবং মেসেজ কন্টেন্ট দ্বারা ট্রেস ফিল্টার করতে পারেন। সমস্ত কলাম ফিল্টারযোগ্য। প্রথম কলামে টাইমস্ট্যাম্পে ক্লিক করা টাইমলাইনকে বার্তা টাইমস্ট্যাম্পে নিয়ে যায়। উপরন্তু, বর্তমান সময়ে যান ক্লিক করলে প্রোটোলগ টেবিলটি টাইমলাইনে নির্বাচিত টাইমস্ট্যাম্পে ফিরে যায়:
চিত্র 1. প্রোটোলগ ভিউয়ার