Android günlük kaydı sistemi, tüm günlük verilerinin bir karakter dizisi olarak temsil edilebileceği varsayımıyla evrensel erişilebilirlik ve kullanım kolaylığı sağlamayı amaçlar. Bu varsayım, özellikle günlük okunabilirliğinin özel araçlar olmadan çok önemli olduğu durumlarda çoğu kullanım alanıyla uyumludur. Ancak yüksek günlük kaydı performansı ve kısıtlanmış günlük boyutları gerektiren ortamlarda metin tabanlı günlük kaydı ideal değildir. Bu tür senaryolardan biri, gerçek zamanlı pencere geçiş günlüklerini minimum sistem etkisiyle işleyen sağlam bir günlük kaydı sistemi gerektiren WindowManager'dır.
ProtoLog, WindowManager ve benzer hizmetlerin günlük kaydı ihtiyaçlarını karşılamak için kullanılan alternatif bir yöntemdir. ProtoLog, logcat'e kıyasla aşağıdaki avantajları sunar:
- Günlüğe kaydetme için daha az kaynak kullanır.
- Geliştirici açısından bakıldığında, varsayılan Android günlük kaydı çerçevesiyle aynı şekilde çalışır.
- Günlük ifadelerini çalışma zamanında etkinleştirmenize veya devre dışı bırakmanıza olanak tanır.
- Logcat'e de kaydedilebilir.
ProtoLog, bellek kullanımını optimize etmek için dize yerleştirme mekanizması kullanır. Bu mekanizma, iletinin derlenmiş karma değerini hesaplayıp kaydeder. ProtoLog, performansı artırmak için sistem hizmetleri derlenirken dize yerleştirme işlemi gerçekleştirir. Yalnızca ileti tanımlayıcısını ve bağımsız değişkenleri çalışma zamanında kaydeder. ProtoLog izlemesi oluşturduğunuzda veya hata raporu aldığınızda ProtoLog, derleme süresinde oluşturulan mesaj sözlüğünü otomatik olarak dahil eder. Bu seçenek, herhangi bir derlemeden mesaj kod çözme işlemini etkinleştirir.
ProtoLog, iletileri Perfetto izinde ikili biçimde (proto) depolar.
İleti kod çözme işlemi Perfetto'nun trace_processor içinde gerçekleşir. Bu işlem, ikili proto iletilerin kodunu çözer, yerleştirilmiş ileti sözlüğünü kullanarak ileti tanımlayıcılarını dizelere çevirir ve dizeyi dinamik bağımsız değişkenlerle biçimlendirir.
ProtoLog, android.utils.Log ile aynı günlük seviyelerini (d, v, i, w, e ve wtf) destekler.
İstemci tarafı ProtoLog
Başlangıçta ProtoLog, WindowManager'ın yalnızca sunucu tarafı için tasarlanmış olup tek bir işlem ve bileşen içinde çalışıyordu. Daha sonra, Sistem Arayüzü sürecindeki WindowManager kabuk kodunu kapsayacak şekilde genişletildi. Ancak ProtoLog'un kullanılması için karmaşık bir standart kurulum kodu gerekiyordu. Ayrıca, Proto günlük kaydı sistem sunucusu ve Sistem Arayüzü işlemleriyle sınırlandırıldı. Bu durum, diğer süreçlere dahil etmeyi zorlaştırıyor ve her biri için ayrı bir bellek arabelleği kurulumu gerektiriyordu. ProtoLog artık istemci tarafı kodu için kullanılabilir ve ek ortak metin kodu ihtiyacını ortadan kaldırır.
Sistem hizmetleri kodunun aksine, istemci tarafı kodu genellikle derleme zamanı dize intern işlemini atlar. Bunun yerine, dize havuzu oluşturma işlemi arka plan iş parçacığında dinamik olarak gerçekleşir. Sonuç olarak, istemci tarafı ProtoLog, sistem hizmetlerindeki ProtoLog'a benzer bellek kullanım avantajları sunsa da biraz daha yüksek bir performans ek yüküne neden olur ve sunucu tarafı karşılığının sunduğu sabitlenmiş bellek avantajına sahip değildir.
ProtoLog grupları
ProtoLog mesajları, ProtoLogGroups adı verilen gruplar halinde düzenlenir. Bu gruplar, Logcat mesajlarının TAG'ye göre düzenlenmesine benzer. Bu ProtoLogGroups, çalışma zamanında etkinleştirebileceğiniz veya devre dışı bırakabileceğiniz ileti kümeleri olarak işlev görür. Ayrıca, derleme sırasında iletilerin temizlenip temizlenmeyeceğini ve nereye kaydedileceğini (proto, logcat veya her ikisi) de kontrol ederler. Her ProtoLogGroup aşağıdaki özellikleri içerir:
enabled:falseolarak ayarlandığında, bu gruptaki iletiler derleme sırasında hariç tutulur ve çalışma zamanında kullanılamaz.logToProto: Bu grubun ikili biçimde günlük kaydı oluşturup oluşturmayacağını tanımlar.logToLogcat: Bu grubun logcat'e kaydedilip kaydedilmeyeceğini tanımlar.tag: Kaydedilen mesajın kaynağının adı.
ProtoLog'u kullanan her işlemin yapılandırılmış bir ProtoLogGroup örneği olmalıdır.
Desteklenen bağımsız değişken türleri
ProtoLog, dizeleri dahili olarak android.text.TextUtils#formatSimple(String, Object...) kullanarak biçimlendirdiğinden söz dizimi aynıdır.
ProtoLog aşağıdaki bağımsız değişken türlerini destekler:
%b- boolean%d,%x- integral türü (short, integer veya long)%f- kayan nokta türü (float veya double)%s- dize%%: değişmez yüzde işareti
%04d ve %10b gibi genişlik ve hassasiyet değiştiriciler desteklenir.
Ancak argument_index ve flags desteklenmez.
Yeni bir hizmette ProtoLog'u kullanma
ProtoLog'u yeni bir hizmette kullanmak için aşağıdaki adımları uygulayın:
- Bu hizmet için bir
ProtoLogGrouptanım oluşturun. Tanımı ilk kullanımdan önce başlatın. Örneğin, işlemi oluştururken başlatın:
ProtoLog.init(ProtoLogGroup.values());ProtoLogöğesiniandroid.util.Logöğesini kullandığınız şekilde kullanın:ProtoLog.v(WM_SHELL_STARTING_WINDOW, "create taskSnapshot surface for task: %d", taskId);
Derleme zamanı optimizasyonunu etkinleştirme
Bir süreçte derleme zamanı ProtoLog'u etkinleştirmek için derleme kurallarını değiştirmeniz ve protologtool ikili programını çağırmanız gerekir.
ProtoLogTool, dize yerleştirme işlemi gerçekleştiren ve ProtoLog çağrısını güncelleyen bir kod dönüştürme ikili programıdır. Bu ikili, her ProtoLog günlük kaydı çağrısını aşağıdaki örnekte gösterildiği gibi dönüştürür:
ProtoLog.x(ProtoLogGroup.GROUP_NAME, "Format string %d %s", value1, value2);
şununla:
if (ProtoLogImpl.isEnabled(GROUP_NAME)) {
int protoLogParam0 = value1;
String protoLogParam1 = String.valueOf(value2);
ProtoLogImpl.x(ProtoLogGroup.GROUP_NAME, 1234560b0100, protoLogParam0, protoLogParam1);
}
Bu örnekte ProtoLog, ProtoLogImpl ve ProtoLogGroup, bağımsız değişken olarak sağlanan sınıflardır (içe aktarılabilir, statik olarak içe aktarılabilir veya tam yol olabilir, joker karakterle içe aktarmaya izin verilmez). x ise günlük kaydı yöntemidir.
Dönüştürme işlemi kaynak düzeyinde yapılır. Karma, biçim dizesi, günlük düzeyi ve günlük grubu adından oluşturulur ve ProtoLogGroup bağımsız değişkeninden sonra eklenir. Gerçek oluşturulan kod satır içi olarak eklenir ve satır numaralandırmasını korumak için bir dizi yeni satır karakteri eklenir.
Örnek:
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"],
}
Komut satırı seçenekleri
ProtoLog'un temel avantajlarından biri, çalışma zamanında etkinleştirilip devre dışı bırakılabilmesidir. Örneğin, bir derlemede varsayılan olarak devre dışı bırakılan ve belirli bir sorunda hata ayıklamak için yerel geliştirme sırasında etkinleştirilen daha ayrıntılı günlük kaydı olabilir. Bu kalıp, örneğin WindowManager'da kullanılır. WM_DEBUG_WINDOW_TRANSITIONS ve WM_DEBUG_WINDOW_TRANSITIONS_MIN grupları, farklı türlerde geçiş günlüğü kaydını etkinleştirir. WM_DEBUG_WINDOW_TRANSITIONS grubu varsayılan olarak etkindir.
İzlemeyi başlatırken ProtoLog'u Perfetto'yu kullanarak yapılandırabilirsiniz. ProtoLog'u adb komut satırını kullanarak yerel olarak da yapılandırabilirsiniz.
adb shell cmd protolog_configuration komutu aşağıdaki bağımsız değişkenleri destekler:
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
Etkili kullanım için ipuçları
ProtoLog, hem ileti hem de iletilen tüm dize bağımsız değişkenleri için dize intern'ü kullanır. Bu nedenle, ProtoLog'dan daha fazla yararlanmak için mesajlar, tekrarlanan değerleri değişkenlere ayırmalıdır.
Örneğin, aşağıdaki ifadeyi ele alalım:
Protolog.v(MY_GROUP, "%s", "The argument value is " + argument);
Derleme zamanında optimize edildiğinde şu şekilde çevrilir:
ProtologImpl.v(MY_GROUP, 0x123, "The argument value is " + argument);
ProtoLog, A,B,C bağımsız değişkenleriyle kodda kullanılıyorsa:
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");
Bu işlem, bellekte aşağıdaki iletilerin oluşmasına neden olur:
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)
Bunun yerine ProtoLog ifadesi şu şekilde yazılmışsa:
Protolog.v(MY_GROUP, "The argument value is %s", argument);
Bellekteki arabellek şu şekilde sonuçlanır:
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)
Bu sıra, %35 daha küçük bir bellekte kaplanan yerle sonuçlanır.
Winscope görüntüleyici
Winscope'un ProtoLog görüntüleyici sekmesinde, tablo biçiminde düzenlenmiş ProtoLog izleri gösterilir. İzleri günlük düzeyine, etikete, kaynak dosyaya (ProtoLog ifadesinin bulunduğu yer) ve ileti içeriğine göre filtreleyebilirsiniz. Tüm sütunlar filtrelenebilir. İlk sütundaki zaman damgasını tıkladığınızda zaman çizelgesi, mesajın zaman damgasına yönlendirilir. Ayrıca, Geçerli Zamana Git'i tıkladığınızda ProtoLog tablosu, zaman çizelgesinde seçilen zaman damgasına geri kaydırılır:
Şekil 1. ProtoLog görüntüleyici