প্রোটোলগ

অ্যান্ড্রয়েড লগিং সিস্টেমের লক্ষ্য হল সর্বজনীন অ্যাক্সেসযোগ্যতা এবং ব্যবহারের সহজলভ্যতা অর্জন করা, ধরে নেওয়া হচ্ছে যে সমস্ত লগ ডেটা অক্ষরের ক্রম হিসাবে উপস্থাপন করা যেতে পারে। এই ধারণাটি বেশিরভাগ ব্যবহারের ক্ষেত্রেই প্রযোজ্য, বিশেষ করে যখন বিশেষ সরঞ্জাম ছাড়াই লগ পঠনযোগ্যতা অত্যন্ত গুরুত্বপূর্ণ। তবে, উচ্চ লগিং কর্মক্ষমতা এবং সীমিত লগ আকারের দাবিদার পরিবেশে, টেক্সট-ভিত্তিক লগিং সর্বোত্তম নয়। এরকম একটি পরিস্থিতি হল WindowManager, যার জন্য একটি শক্তিশালী লগিং সিস্টেম প্রয়োজন যা ন্যূনতম সিস্টেম প্রভাব সহ রিয়েল-টাইম উইন্ডো ট্রানজিশন লগ পরিচালনা করে।

ProtoLog হল WindowManager এবং অনুরূপ পরিষেবাগুলির লগিং চাহিদা পূরণের বিকল্প। ProtoLog logcat-এর তুলনায় নিম্নলিখিত সুবিধাগুলি প্রদান করে:

  • লগিং এর জন্য কম রিসোর্স ব্যবহার করে।
  • একজন ডেভেলপারের দৃষ্টিকোণ থেকে, এটি ডিফল্ট অ্যান্ড্রয়েড লগিং ফ্রেমওয়ার্কের মতোই কাজ করে।
  • রানটাইমে লগ স্টেটমেন্ট সক্রিয় বা নিষ্ক্রিয় করতে দেয়।
  • লগক্যাটেও লগ ইন করতে পারবেন।

মেমোরি ব্যবহার অপ্টিমাইজ করার জন্য, ProtoLog একটি স্ট্রিং ইন্টার্নিং মেকানিজম ব্যবহার করে। এই মেকানিজম বার্তার একটি সংকলিত হ্যাশ গণনা করে এবং সংরক্ষণ করে। কর্মক্ষমতা উন্নত করার জন্য, ProtoLog সিস্টেম পরিষেবাগুলির জন্য সংকলনের সময় স্ট্রিং ইন্টার্নিং সম্পাদন করে। এটি রানটাইমে শুধুমাত্র বার্তা শনাক্তকারী এবং আর্গুমেন্ট রেকর্ড করে। যখন আপনি একটি ProtoLog ট্রেস তৈরি করেন বা একটি বাগ রিপোর্ট পান, তখন ProtoLog স্বয়ংক্রিয়ভাবে কম্পাইলের সময় তৈরি বার্তা অভিধানটি অন্তর্ভুক্ত করে। এটি যেকোনো বিল্ড থেকে বার্তা ডিকোডিং সক্ষম করে।

ProtoLog একটি Perfetto ট্রেসের মধ্যে বাইনারি ফর্ম্যাটে (proto) বার্তা সংরক্ষণ করে। Perfetto এর trace_processor মধ্যে বার্তা ডিকোডিং ঘটে। প্রক্রিয়াটি বাইনারি প্রোটো বার্তাগুলিকে ডিকোড করে, এমবেডেড বার্তা অভিধান ব্যবহার করে বার্তা শনাক্তকারীকে স্ট্রিংয়ে অনুবাদ করে এবং গতিশীল আর্গুমেন্ট ব্যবহার করে স্ট্রিংটিকে ফর্ম্যাট করে।

ProtoLog android.utils.Log এর মতো একই লগ লেভেল সমর্থন করে, যা হল d , v , i , w , e , এবং wtf

ক্লায়েন্ট-সাইড প্রোটোলগ

প্রাথমিকভাবে, ProtoLog শুধুমাত্র WindowManager এর সার্ভার সাইডের জন্য তৈরি করা হয়েছিল, যা একটি একক প্রক্রিয়া এবং উপাদানের মধ্যে কাজ করত। পরবর্তীতে, সিস্টেম UI প্রক্রিয়ায় WindowManager শেল কোড অন্তর্ভুক্ত করার জন্য এটি সম্প্রসারিত করা হয়েছিল। তবে, ProtoLog ব্যবহারের জন্য জটিল বয়লারপ্লেট সেটআপ কোডের প্রয়োজন ছিল। অতিরিক্তভাবে, Proto লগিং সিস্টেম সার্ভার এবং সিস্টেম UI প্রক্রিয়াগুলির মধ্যে সীমাবদ্ধ ছিল। এর ফলে অন্যান্য প্রক্রিয়াগুলিতে অন্তর্ভুক্ত করা কঠিন হয়ে পড়ে এবং প্রতিটি প্রক্রিয়ার জন্য পৃথক মেমরি বাফার সেটআপের প্রয়োজন হয়। ProtoLog এখন ক্লায়েন্ট-সাইড কোডের জন্য উপলব্ধ, অতিরিক্ত বয়লারপ্লেট কোডের প্রয়োজন বাদ দেয়।

সিস্টেম সার্ভিস কোডের বিপরীতে, ক্লায়েন্ট-সাইড কোড সাধারণত কম্পাইল-টাইম স্ট্রিং ইন্টার্নিং এড়িয়ে যায়। পরিবর্তে, স্ট্রিং ইন্টার্নিং একটি ব্যাকগ্রাউন্ড থ্রেডে গতিশীলভাবে ঘটে। ফলস্বরূপ, ক্লায়েন্ট-সাইড প্রোটোলগ সিস্টেম পরিষেবাগুলিতে প্রোটোলগের সাথে তুলনীয় মেমরি ব্যবহারের সুবিধা প্রদান করলেও, এটির পারফরম্যান্স ওভারহেড কিছুটা বেশি এবং এর সার্ভার-সাইড কাউন্টারপার্টের অফার করা পিনড মেমরির মেমরি হ্রাস সুবিধার অভাব রয়েছে।

প্রোটোলগ গ্রুপ

ProtoLog বার্তাগুলিকে ProtoLogGroups নামে পরিচিত গ্রুপে সংগঠিত করা হয়, যেমনটি TAG দ্বারা Logcat বার্তাগুলিকে সংগঠিত করা হয়। এই ProtoLogGroups বার্তা ক্লাস্টার হিসাবে কাজ করে যা আপনি রানটাইমে সক্ষম বা অক্ষম করতে পারেন। তারা সংকলনের সময় বার্তাগুলি স্ট্রিপ করা হবে কিনা এবং কোথায় লগ করা হবে তাও নিয়ন্ত্রণ করে (proto, logcat, অথবা উভয়)। প্রতিটি ProtoLogGroup নিম্নলিখিত বৈশিষ্ট্যগুলি অন্তর্ভুক্ত থাকে:

  • enabled : false তে সেট করা হলে, এই গ্রুপের বার্তাগুলি সংকলনের সময় বাদ দেওয়া হয় এবং রানটাইমে উপলব্ধ থাকে না।
  • logToProto : এই গ্রুপটি বাইনারি ফর্ম্যাটে লগ করে কিনা তা নির্ধারণ করে।
  • logToLogcat : এই গ্রুপটি logcat-এ লগ ইন করে কিনা তা নির্ধারণ করে।
  • tag : লগ করা বার্তার উৎসের নাম।

ProtoLog ব্যবহার করে এমন প্রতিটি প্রক্রিয়ার একটি ProtoLogGroup ইনস্ট্যান্স কনফিগার করা থাকতে হবে।

সমর্থিত যুক্তির ধরণ

ProtoLog অভ্যন্তরীণভাবে android.text.TextUtils#formatSimple(String, Object...) ব্যবহার করে স্ট্রিং ফরম্যাট করে, তাই এর সিনট্যাক্স একই।

ProtoLog নিম্নলিখিত আর্গুমেন্ট প্রকারগুলিকে সমর্থন করে:

  • %b - বুলিয়ান
  • %d , %x - ইন্টিগ্রাল টাইপ (সংক্ষিপ্ত, পূর্ণসংখ্যা, অথবা দীর্ঘ)
  • %f - ভাসমান বিন্দুর ধরণ (ভাসমান বা দ্বিগুণ)
  • %s - স্ট্রিং
  • %% - একটি আক্ষরিক শতাংশ অক্ষর

%04d এবং %10b মতো প্রস্থ এবং নির্ভুলতা পরিবর্তনকারীগুলি সমর্থিত। তবে, argument_index এবং flags সমর্থিত নয়।

একটি নতুন পরিষেবাতে ProtoLog ব্যবহার করুন

নতুন পরিষেবায় ProtoLog ব্যবহার করতে, এই পদক্ষেপগুলি অনুসরণ করুন:

  1. এই পরিষেবার জন্য একটি ProtoLogGroup সংজ্ঞা তৈরি করুন।
  2. প্রথম ব্যবহারের আগে সংজ্ঞাটি শুরু করুন। উদাহরণস্বরূপ, প্রক্রিয়া তৈরির সময় এটি শুরু করুন:

    ProtoLog.init(ProtoLogGroup.values());
    
  3. ProtoLog ব্যবহার করুন ঠিক একইভাবে যেভাবে আপনি android.util.Log ব্যবহার করেন:

    ProtoLog.v(WM_SHELL_STARTING_WINDOW, "create taskSnapshot surface for task: %d", taskId);
    

কম্পাইল-টাইম অপ্টিমাইজেশন সক্ষম করুন

একটি প্রক্রিয়ায় কম্পাইল-টাইম প্রোটোলগ সক্ষম করতে, আপনাকে এর বিল্ড নিয়ম পরিবর্তন করতে হবে এবং protologtool বাইনারি চালু করতে হবে।

ProtoLogTool হল একটি কোড ট্রান্সফর্মেশন বাইনারি যা স্ট্রিং ইন্টার্নিং করে এবং ProtoLog ইনভোকেশন আপডেট করে। এই বাইনারিটি প্রতিটি 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"],
}

কমান্ড লাইন বিকল্পগুলি

ProtoLog এর একটি প্রধান সুবিধা হল আপনি রানটাইমে এটি সক্রিয় বা নিষ্ক্রিয় করতে পারেন। উদাহরণস্বরূপ, আপনি একটি নির্দিষ্ট সমস্যা ডিবাগ করার জন্য একটি বিল্ডে আরও ভার্বোজ লগিং রাখতে পারেন, ডিফল্টরূপে অক্ষম করা এবং স্থানীয় বিকাশের সময় এটি সক্ষম করা। এই প্যাটার্নটি, উদাহরণস্বরূপ, 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 থেকে আরও সুবিধা পেতে, বার্তাগুলিকে ভেরিয়েবলে পুনরাবৃত্ত মানগুলিকে আলাদা করতে হবে।

উদাহরণস্বরূপ, নিম্নলিখিত বিবৃতিটি বিবেচনা করুন:

Protolog.v(MY_GROUP, "%s", "The argument value is " + argument);

কম্পাইলের সময় অপ্টিমাইজ করা হলে, এটি এভাবে অনুবাদ করে:

ProtologImpl.v(MY_GROUP, 0x123, "The argument value is " + argument);

যদি A,B,C আর্গুমেন্ট সহ কোডে ProtoLog ব্যবহার করা হয়:

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 বিবৃতিটি এভাবে লেখা হত:

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)

এই ক্রমটির ফলে মেমরি ফুটপ্রিন্ট ৩৫% ছোট হয়।

উইনস্কোপ ভিউয়ার

Winscope এর ProtoLog ভিউয়ার ট্যাবে ProtoLog ট্রেসগুলি একটি ট্যাবুলার ফর্ম্যাটে সংগঠিত দেখানো হয়েছে। আপনি লগ লেভেল, ট্যাগ, সোর্স ফাইল (যেখানে ProtoLog স্টেটমেন্ট উপস্থিত থাকে) এবং বার্তার বিষয়বস্তু অনুসারে ট্রেসগুলি ফিল্টার করতে পারেন। সমস্ত কলাম ফিল্টারযোগ্য। প্রথম কলামের টাইমস্ট্যাম্পে ক্লিক করলে টাইমলাইনটি বার্তার টাইমস্ট্যাম্পে স্থানান্তরিত হয়। অতিরিক্তভাবে, Go to Current Time এ ক্লিক করলে ProtoLog টেবিলটি টাইমলাইনে নির্বাচিত টাইমস্ট্যাম্পে ফিরে যায়:

ProtoLog viewer

চিত্র ১. প্রোটোলগ ভিউয়ার