PHP Günlük Dosyalarınızdan En İyi Şekilde Yararlanma: Pratik Bir Kılavuz

Yayınlanan: 2022-03-11

Haklı olarak, günlüklerin serbest çalışan bir php geliştiricisinin emrindeki en hafife alınan ve yeterince kullanılmayan araçlardan biri olduğu söylenebilir. Sunabilecekleri bilgi zenginliğine rağmen, günlüklerin bir geliştiricinin bir sorunu çözmeye çalışırken baktığı son yer olması nadir değildir.

Gerçekte, PHP günlük dosyaları birçok durumda sorunlar ortaya çıktığında ipuçlarını arayan ilk yer olmalıdır. Çoğu zaman, içerdikleri bilgiler, budaklı bir böceğin izini sürmek için saçınızı çekmeye harcanan süreyi önemli ölçüde azaltabilir.

Ancak belki de daha da önemlisi, biraz yaratıcılık ve öngörü ile günlük dosyalarınız, değerli bir kullanım bilgisi ve analitik kaynağı olarak hizmet etmek için kullanılabilir. Günlük dosyalarının yaratıcı kullanımı aşağıdaki gibi soruların yanıtlanmasına yardımcı olabilir: Sitemi ziyaret etmek için en yaygın olarak hangi tarayıcılar kullanılıyor? Sunucumdan ortalama yanıt süresi nedir? Site köküne yapılan isteklerin yüzdesi neydi? En son güncellemeleri dağıttığımızdan beri kullanım nasıl değişti? Ve çok daha fazlası.

PHP günlük dosyaları

Bu makale, sağladıkları faydayı en üst düzeye çıkarmak için günlük dosyalarınızı nasıl yapılandıracağınıza ve içerdikleri bilgileri nasıl işleyeceğinize ilişkin bir dizi ipucu sağlar.

Bu makale teknik olarak PHP geliştiricileri için günlüğe kaydetmeye odaklansa da, burada sunulan bilgilerin çoğu oldukça teknolojiden bağımsızdır ve diğer diller ve teknoloji yığınlarıyla da ilgilidir.

Not: Bu makalede, Unix kabuğuna temel düzeyde aşina olunduğu varsayılmaktadır. Bu bilgiye sahip olmayanlar için, bir Unix sisteminde günlük dosyalarına erişmek ve bunları okumak için gereken bazı komutları tanıtan bir Ek sağlanmıştır.

PHP Log Dosyası Örnek Projemiz

Bu yazıda tartışma amaçlı örnek bir proje olarak, Symfony Standard'ı çalışan bir proje olarak alacağız ve onu Debian 7 Wheezy üzerinde rsyslogd , nginx ve PHP-FPM ile kuracağız.

 composer create-project symfony/framework-standard-edition my "2.6.*"

Bu bize hızlı bir şekilde güzel bir kullanıcı arayüzü ile çalışan bir test projesi verir.

Günlük Dosyalarınızı Yapılandırmak İçin İpuçları

Değerlerini en üst düzeye çıkarmaya yardımcı olmak için günlük dosyalarınızı nasıl yapılandıracağınıza ilişkin bazı ipuçları.

Hata Günlüğü Yapılandırması

Hata günlükleri, günlük kaydının en temel biçimini temsil eder; yani, sorunlar oluştuğunda ek bilgi ve ayrıntı yakalamak. Yani ideal bir dünyada hata olmamasını ve hata günlüklerinizin boş olmasını istersiniz. Ancak sorunlar ortaya çıktığında (her zaman olduğu gibi), hata günlükleriniz hata ayıklama izinizde yaptığınız ilk duraklardan biri olmalıdır.

Hata günlüklerini yapılandırmak genellikle oldukça kolaydır.

Birincisi, tüm hata ve kilitlenme mesajları, aksi takdirde bir kullanıcıya sunulacakları biçimde hata günlüğüne tam olarak aynı biçimde kaydedilebilir. Bazı basit yapılandırmalarla, son kullanıcının sitenizdeki bu çirkin hata izlerini asla görmesine gerek kalmayacak, devops ise sistemi izleyebilecek ve bu hata mesajlarını tüm kanlı ayrıntılarıyla gözden geçirebilecek. PHP'de bu tür bir oturum açmanın nasıl kurulacağı aşağıda açıklanmıştır:

 log_errors = On error_reporting = E_ALL error_log = /path/to/my/error/log

Canlı bir site için bir günlük dosyasına dahil edilmesi, kanlı hata ayrıntı düzeylerinin kullanıcılara sunulmasını önlemek için önemli olan diğer iki satır şunlardır:

 display_errors = Off display_startup_errors = Off

Sistem Günlüğü ( syslog ) Yapılandırması

Açık kaynak dünyasında syslog arka plan programının genel olarak uyumlu birçok uygulaması vardır:

  • syslogd ve sysklogd – en sık BSD ailesi sistemlerinde, CentOS, Mac OS X ve diğerlerinde görülür
  • syslog-ng – modern Gentoo ve SuSE yapıları için varsayılan
  • rsyslogd – Debian ve Fedora işletim sistemleri ailelerinde yaygın olarak kullanılır

(Not: Bu makalede, örneklerimiz için rsyslogd .)

Temel sistem günlüğü yapılandırması, günlük mesajlarınızı sistem çapında bir günlük dosyasında yakalamak için genellikle yeterlidir (normalde /var/log/syslog ; dağıtıma bağlı olarak /var/log/messages veya /var/log/system.log da olabilir) kullanıyorsun).

Sistem günlüğü, sekizi ( LOG_LOCAL0 ila LOG_LOCAL7 ) kullanıcı tarafından dağıtılan projeler için ayrılmış birkaç günlük olanağı sağlar. Örneğin, LOG_LOCAL0 , günlük düzeyine göre (yani, hata, uyarı, bilgi, hata ayıklama) 4 ayrı günlük dosyasına yazacak şekilde nasıl kurabileceğiniz aşağıda açıklanmıştır:

 # /etc/rsyslog.d/my.conf local0.err /var/log/my/err.log local0.warning /var/log/my/warning.log local0.info -/var/log/my/info.log local0.debug -/var/log/my/debug.log

Şimdi, LOG_LOCAL0 tesisine ne zaman bir günlük mesajı yazsanız, hata mesajları /var/log/my/warning.log /var/log/my/err.log a gidecek ve bu şekilde devam edecek. Yine de, syslog arka plan programının her dosya için iletileri "bu düzey ve üstü" kuralına göre filtrelediğini unutmayın. Bu nedenle, yukarıdaki örnekte, tüm hata mesajları yapılandırılmış dört dosyanın hepsinde görünecek, uyarı mesajları hata günlüğü dışında tümünde görünecek, bilgi mesajları bilgi ve hata ayıklama günlüklerinde görünecek ve hata ayıklama mesajları yalnızca debug.log gidecek .

Bir önemli not daha; Yukarıdaki yapılandırma dosyası örneğinde bilgi ve hata ayıklama düzeyindeki dosyalardan önceki - işaretleri, bu dosyalara yazma işlemlerinin eşzamansız olarak gerçekleştirilmesi gerektiğini belirtir (çünkü bu işlemler bloke edici değildir). Bu, bilgi ve hata ayıklama günlükleri için genellikle iyidir (ve hatta çoğu durumda önerilir), ancak hata günlüğüne (ve muhtemelen uyarı günlüğüne de) yazmaların eşzamanlı olması en iyisidir.

Daha az önemli bir günlük kaydını kapatmak için (örneğin, bir üretim sunucusunda), ilgili mesajları /dev/null (yani, hiçbir yere) yönlendirmeniz yeterlidir:

 local0.debug /dev/null # -/var/log/my/debug.log

Özellikle bu makalenin ilerleyen kısımlarında tartışacağımız bazı PHP günlük dosyası ayrıştırmalarını desteklemek için yararlı olan özel bir özelleştirme, günlük mesajlarında sınırlayıcı karakter olarak sekmeyi kullanmaktır. Bu, aşağıdaki dosyayı /etc/rsyslog.d ekleyerek kolayca yapılabilir:

 # /etc/rsyslog.d/fixtab.conf $EscapeControlCharactersOnReceive off

Son olarak, geçerli olmaları için herhangi bir yapılandırma değişikliği yaptıktan sonra syslog arka plan programını yeniden başlatmayı unutmayın:

 service rsyslog restart

Sunucu Günlüğü Yapılandırması

Yazabileceğiniz uygulama günlükleri ve hata günlüklerinden farklı olarak, sunucu günlükleri her istekte ilgili sunucu arka plan programları (örn. web sunucusu, veritabanı sunucusu vb.) tarafından özel olarak yazılır. Bu günlükler üzerinde sahip olduğunuz tek "kontrol", sunucunun günlük tutma işlevini yapılandırmanıza izin verdiği ölçüdedir. Bu dosyalarda gözden geçirilecek çok şey olsa da, genellikle sunucunuzda "kaputun altında" neler olup bittiğine dair net bir fikir edinmenin tek yolu bunlardır.

Symfony Standard örnek uygulamamızı MySQL depolama arka ucu ile nginx ortamında dağıtalım. İşte kullanacağımız nginx ana bilgisayar yapılandırması:

 server { server_name my.log-sandbox; root /var/www/my/web; location / { # try to serve file directly, fallback to app.php try_files $uri /app.php$is_args$args; } # DEV # This rule should only be placed on your development environment # In production, don't include this and don't deploy app_dev.php or config.php location ~ ^/(app_dev|config)\.php(/|$) { fastcgi_pass unix:/var/run/php5-fpm.sock; fastcgi_split_path_info ^(.+\.php)(/.*)$; include fastcgi_params; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; fastcgi_param HTTPS off; } # PROD location ~ ^/app\.php(/|$) { fastcgi_pass unix:/var/run/php5-fpm.sock; fastcgi_split_path_info ^(.+\.php)(/.*)$; include fastcgi_params; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; fastcgi_param HTTPS off; # Prevents URIs that include the front controller. This will 404: # http://domain.tld/app.php/some-path # Remove the internal directive to allow URIs like this internal; } error_log /var/log/nginx/my_error.log; access_log /var/log/nginx/my_access.log; }

Yukarıdaki son iki yönergeyle ilgili olarak: access_log genel istekler günlüğünü temsil ederken error_log hatalar içindir ve uygulama hata günlüklerinde olduğu gibi, hızlı tepki verebilmeniz için sorunlara karşı uyarılmak üzere ek izleme ayarlamaya değer.

Not: Bu, yalnızca örnek amaçlı sağlanan, kasıtlı olarak basitleştirilmiş bir nginx yapılandırma dosyasıdır. Güvenlik ve performansa neredeyse hiç dikkat etmez ve herhangi bir "gerçek" ortamda olduğu gibi kullanılmamalıdır.

Tarayıcıya http://my.log-sandbox/app_dev.php/ yazıp Enter bastıktan sonra /var/log/nginx/my_access.log dosyasına şunu alıyoruz.

 192.168.56.1 - - [26/Apr/2015:16:13:28 +0300] "GET /app_dev.php/ HTTP/1.1" 200 6715 "-" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/42.0.2311.90 Safari/537.36" 192.168.56.1 - - [26/Apr/2015:16:13:28 +0300] "GET /bundles/framework/css/body.css HTTP/1.1" 200 6657 "http://my.log-sandbox/app_dev.php/" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/42.0.2311.90 Safari/537.36" 192.168.56.1 - - [26/Apr/2015:16:13:28 +0300] "GET /bundles/framework/css/structure.css HTTP/1.1" 200 1191 "http://my.log-sandbox/app_dev.php/" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/42.0.2311.90 Safari/537.36" 192.168.56.1 - - [26/Apr/2015:16:13:28 +0300] "GET /bundles/acmedemo/css/demo.css HTTP/1.1" 200 2204 "http://my.log-sandbox/app_dev.php/" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/42.0.2311.90 Safari/537.36" 192.168.56.1 - - [26/Apr/2015:16:13:28 +0300] "GET /bundles/acmedemo/images/welcome-quick-tour.gif HTTP/1.1" 200 4770 "http://my.log-sandbox/app_dev.php/" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/42.0.2311.90 Safari/537.36" 192.168.56.1 - - [26/Apr/2015:16:13:28 +0300] "GET /bundles/acmedemo/images/welcome-demo.gif HTTP/1.1" 200 4053 "http://my.log-sandbox/app_dev.php/" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/42.0.2311.90 Safari/537.36" 192.168.56.1 - - [26/Apr/2015:16:13:28 +0300] "GET /bundles/acmedemo/images/welcome-configure.gif HTTP/1.1" 200 3530 "http://my.log-sandbox/app_dev.php/" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/42.0.2311.90 Safari/537.36" 192.168.56.1 - - [26/Apr/2015:16:13:28 +0300] "GET /favicon.ico HTTP/1.1" 200 6518 "http://my.log-sandbox/app_dev.php/" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/42.0.2311.90 Safari/537.36" 192.168.56.1 - - [26/Apr/2015:16:13:30 +0300] "GET /app_dev.php/_wdt/e50d73 HTTP/1.1" 200 13265 "http://my.log-sandbox/app_dev.php/" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/42.0.2311.90 Safari/537.36"

Bu, bir sayfa sunmak için tarayıcının aslında 9 HTTP çağrısı gerçekleştirdiğini gösterir. Ancak bunlardan 7'si sade ve hafif olan statik içerik istekleridir. Ancak, yine de ağ kaynaklarını alırlar ve bu, çeşitli sprite ve küçültme teknikleri kullanılarak optimize edilebilir.

Bu optimizasyonlar başka bir makalede tartışılacak olsa da, burada önemli olan, statik içeriklere istekleri, onlar için başka bir location yönergesi kullanarak ayrı ayrı kaydedebilmemizdir:

 location ~ \.(jpg|jpeg|gif|png|ico|css|zip|tgz|gz|rar|bz2|pdf|txt|tar|wav|bmp|rtf|js)$ { access_log /var/log/nginx/my_access-static.log; }

nginx location basit normal ifade eşleştirmesi gerçekleştirdiğini unutmayın, böylece sitenize göndermeyi beklediğiniz kadar statik içerik uzantısı ekleyebilirsiniz.

Bu tür günlükleri ayrıştırmak, uygulama günlüklerini ayrıştırmaktan farklı değildir.

Bahsetmeye Değer Diğer Günlükler

Bahsetmeye değer diğer iki PHP günlüğü, hata ayıklama günlüğü ve veri depolama günlüğüdür.

Hata Ayıklama Günlüğü

Nginx günlükleriyle ilgili bir başka kullanışlı şey de hata ayıklama günlüğüdür. Yapılandırmanın error_log satırını aşağıdaki ile değiştirerek açabiliriz (nginx hata ayıklama modülünün kurulmasını gerektirir):

 error_log /var/log/nginx/my_error.log debug;

Aynı ayar Apache veya kullandığınız diğer web sunucuları için de geçerlidir.

Ve tesadüfen, hata ayıklama günlükleri, error_log yönergesinde yapılandırılmış olsalar bile, hata günlükleriyle ilgili değildir .

Hata ayıklama günlüğü gerçekten ayrıntılı olabilse de (örneğin, tek bir nginx isteği, 127 KB günlük verisi oluşturdu!), yine de çok yararlı olabilir. Bir günlük dosyasında gezinme hantal ve sıkıcı olabilir, ancak genellikle hata ayıklama sürecini hızlandırmaya büyük ölçüde yardımcı olan ipuçlarını ve bilgileri hızlı bir şekilde sağlayabilir.

Özellikle, hata ayıklama günlüğü, özellikle location eşleştirme ve rewrite zincirleri gibi en karmaşık parçalar olmak üzere nginx yapılandırmalarında hata ayıklamaya gerçekten yardımcı olabilir.

Elbette, hata ayıklama günlükleri bir üretim ortamında hiçbir zaman etkinleştirilmemelidir. Ayrıca kullandıkları alan miktarı ve depoladıkları bilgi miktarı, sunucunuz üzerinde çok fazla G/Ç yükü anlamına gelir ve bu da tüm sistemin performansını önemli ölçüde düşürebilir.

Veri Depolama Günlükleri

Başka bir sunucu günlüğü türü (hata ayıklama için kullanışlıdır) veri depolama günlükleridir. MySQL'de şu satırları ekleyerek bunları açabilirsiniz:

 [mysqld] general_log = 1 general_log_file = /var/log/mysql/query.log

Bu günlükler, çeşitli hata ayıklama ve izleme ihtiyaçları için yardımcı olabilecek, kronolojik sırayla veritabanı isteklerini sunarken sistem tarafından yürütülen sorguların bir listesini içerir. Ancak, performansı etkileyen fazladan gereksiz G/Ç yükü oluşturacaklarından üretim sistemlerinde etkin kalmamalıdırlar.

Günlük Dosyalarınıza Yazma

PHP'nin kendisi, günlük dosyalarını açmak, yazmak ve kapatmak için işlevler sağlar ( openlog() , syslog() ve closelog() ).

Ayrıca, Monolog (Symfony ve Laravel kullanıcıları arasında popüler) gibi PHP geliştiricisi için çok sayıda günlük kitaplığı ve CakePHP'ye dahil edilen günlük tutma yetenekleri gibi çeşitli çerçeveye özel uygulamalar vardır. Genel olarak, Monolog gibi kitaplıklar yalnızca syslog() çağrılarını sarmakla kalmaz, aynı zamanda diğer arka uç işlevlerinin ve araçlarının kullanılmasına da izin verir.

Günlüğe nasıl yazılacağına dair basit bir örnek:

 <?php openlog(uniqid(), LOG_ODELAY, LOG_LOCAL0); syslog(LOG_INFO, 'It works!');

Burada openlog için çağrımız:

  • PHP'yi, betiğin ömrü boyunca her sistem günlüğü mesajına benzersiz bir tanımlayıcı ekleyecek şekilde yapılandırır
  • ilk syslog() çağrısı gerçekleşene kadar syslog bağlantısının açılmasını geciktirecek şekilde ayarlar
  • LOG_LOCAL0 varsayılan günlük kaydı tesisi olarak ayarlar

Yukarıdaki kodu çalıştırdıktan sonra günlük dosyasının içeriği şöyle görünür:

 # cat /var/log/my/info.log Mar 2 00:23:29 log-sandbox 54f39161a2e55: It works!

PHP Günlük Dosyalarınızın Değerini En Üst Düzeye Çıkarma

Artık teori ve temel bilgilerde iyi olduğumuza göre, örnek Symfony Standard projemizde mümkün olduğunca az değişiklik yaparak günlüklerden ne kadar elde edebileceğimizi görelim.

İlk olarak, src/log-begin.php (günlüklerimizi düzgün bir şekilde açmak ve yapılandırmak için) ve src/log-end.php (başarılı tamamlama hakkında bilgileri günlüğe kaydetmek için) komut dosyalarını oluşturalım. Basit olması için tüm mesajları bilgi günlüğüne yazacağımızı unutmayın.

 # src/log-begin.php <?php define('START_TIME', microtime(true)); openlog(uniqid(), LOG_ODELAY, LOG_LOCAL0); syslog(LOG_INFO, 'BEGIN'); syslog(LOG_INFO, "URI\t{$_SERVER['REQUEST_URI']}"); $browserHash = substr(md5($_SERVER['HTTP_USER_AGENT']), 0, 7); syslog(LOG_INFO, "CLIENT\t{$_SERVER['REMOTE_ADDR']}\t{$browserHash}"); <br /> # src/log-end.php <?php syslog(LOG_INFO, "DISPATCH TIME\t" . round(microtime(true) - START_TIME, 2)); syslog(LOG_INFO, 'END');

Ve şu komut dosyalarını app.php :

 <?php require_once(dirname(__DIR__) . '/src/log-begin.php'); syslog(LOG_INFO, "MODE\tPROD"); # original app.php contents require_once(dirname(__DIR__) . '/src/log-end.php');

Geliştirme ortamı için bu betikleri app_dev.php içinde de gerekli kılmak istiyoruz. Bunu yapacak kod, MODE PROD yerine DEV olarak ayarlamamız dışında yukarıdakiyle aynı olacaktır.

Hangi denetleyicilerin çağrıldığını da izlemek istiyoruz, bu yüzden Acme\DemoBundle\EventListener\ControllerListener içinde ControllerListener::onKernelController() yönteminin hemen başına bir satır daha ekleyelim:

 syslog(LOG_INFO, "CONTROLLER\t" . get_class($event->getController()[0]));

Bu değişikliklerin toplamda yalnızca 15 ekstra kod satırı olduğunu, ancak toplu olarak çok sayıda bilgi sağlayabileceğini unutmayın.

Günlük Dosyalarınızdaki Verileri Analiz Etme

Yeni başlayanlar için, her sayfa yüklemesini sunmak için kaç HTTP isteğinin gerekli olduğunu görelim.

Günlük kaydımızı yapılandırma şeklimize bağlı olarak, bir istek için günlüklerdeki bilgiler:

 Mar 3 12:04:20 log-sandbox 54f58724b1ccc: BEGIN Mar 3 12:04:20 log-sandbox 54f58724b1ccc: URI /app_dev.php/ Mar 3 12:04:20 log-sandbox 54f58724b1ccc: CLIENT 192.168.56.1 1b101cd Mar 3 12:04:20 log-sandbox 54f58724b1ccc: MODE DEV Mar 3 12:04:23 log-sandbox 54f58724b1ccc: CONTROLLER Acme\DemoBundle\Controller\WelcomeController Mar 3 12:04:25 log-sandbox 54f58724b1ccc: DISPATCH TIME 4.51 Mar 3 12:04:25 log-sandbox 54f58724b1ccc: END Mar 3 12:04:25 log-sandbox 54f5872967dea: BEGIN Mar 3 12:04:25 log-sandbox 54f5872967dea: URI /app_dev.php/_wdt/59b8b6 Mar 3 12:04:25 log-sandbox 54f5872967dea: CLIENT 192.168.56.1 1b101cd Mar 3 12:04:25 log-sandbox 54f5872967dea: MODE DEV Mar 3 12:04:28 log-sandbox 54f5872967dea: CONTROLLER Symfony\Bundle\WebProfilerBundle\Controller\ProfilerController Mar 3 12:04:29 log-sandbox 54f5872967dea: DISPATCH TIME 4.17 Mar 3 12:04:29 log-sandbox 54f5872967dea: END

Artık her sayfa yüklemesinin aslında iki HTTP isteğiyle sunulduğunu biliyoruz.

Aslında burada bahsetmeye değer iki nokta var. İlk olarak, sayfa yüklemesi başına iki istek Symfony'yi geliştirme modunda kullanmak içindir (ki bunu bu makale boyunca yaptım). /app-dev.php/ URL parçalarını arayarak geliştirme modu çağrılarını tanımlayabilirsiniz. İkinci olarak, her sayfa yüklemesinin Symfony uygulamasına iki ardışık istekle sunulduğunu varsayalım. Daha önce nginx erişim günlüklerinde gördüğümüz gibi, aslında bazıları statik içerik için olan daha fazla HTTP çağrısı var.

Tamam, şimdi demo sitesinde biraz gezinelim (günlük dosyalarındaki verileri oluşturmak için) ve bu günlüklerden başka neler öğrenebileceğimize bir bakalım.

Günlük dosyasının başlangıcından bu yana toplamda kaç istek sunuldu?

 # grep -c BEGIN info.log 10

Bunlardan herhangi biri başarısız oldu mu (senaryo sona ulaşmadan kapandı mı)?

 # grep -c END info.log 10

BEGIN ve END kayıtlarının sayısının eşleştiğini görüyoruz, bu bize tüm çağrıların başarılı olduğunu söylüyor. (PHP betiği başarıyla tamamlanmamış olsaydı, src/log-end.php betiğinin yürütülmesine ulaşamazdı.)

Site köküne yapılan isteklerin yüzdesi neydi?

 # `grep -cE "\s/app_dev.php/$" info.log` 2

Bu bize site kökünden 2 sayfa yüklendiğini söyler. Daha önce (a) sayfa yükleme başına uygulamaya 2 istek olduğunu ve (b) toplam 10 HTTP isteği olduğunu öğrendiğimiz için, site köküne yapılan isteklerin yüzdesi %40'tı (yani 2x2/10).

İstekleri site köküne sunmaktan hangi denetleyici sınıfı sorumludur?

 # grep -E "\s/$|\s/app_dev.php/$" info.log | head -n1 Mar 3 12:04:20 log-sandbox 54f58724b1ccc: URI /app_dev.php/ # grep 54f58724b1ccc info.log | grep CONTROLLER Mar 3 12:04:23 log-sandbox 54f58724b1ccc: CONTROLLER Acme\DemoBundle\Controller\WelcomeController

Burada, o tek istekle ilgili tüm günlük mesajlarını kontrol etmek için bir isteğin benzersiz kimliğini kullandık. Böylece site köküne istek sunmaktan sorumlu denetleyici sınıfının Acme\DemoBundle\Controller\WelcomeController .

192.168.0.0/16 alt ağının IP'lerine sahip hangi istemciler siteye erişti?

 # grep CLIENT info.log | cut -d":" -f4 | cut -f2 | sort | uniq 192.168.56.1

Bu basit test durumunda beklendiği gibi, siteye yalnızca ana bilgisayarım erişti. Bu elbette çok basit bir örnek, ancak gösterdiği yetenek (sitenize gelen trafiğin kaynaklarını analiz edebilme) açıkçası oldukça güçlü ve önemlidir.

Siteme gelen trafiğin ne kadarı FireFox'tan geldi?

Firefox User-Agent'ımın karması olarak 1b101cd sahip olduğum için bu soruyu şu şekilde cevaplayabilirim:

 # grep -c 1b101cd info.log 8 # grep -c CLIENT info.log 10

Cevap: %80 (yani, 8/10)

Yavaş yanıt veren isteklerin yüzdesi nedir?

Bu örneğin amaçları doğrultusunda, "yavaş"ı yanıt vermenin 5 saniyeden uzun sürmesi olarak tanımlayacağız. Buna göre:

 # grep "DISPATCH TIME" info.log | grep -cE "\s[0-9]{2,}\.|\s[5-9]\." 2

Cevap: %20 (yani, 2/10)

Hiç kimse GET parametreleri sağladı mı?

 # grep URI info.log | grep \?

Hayır, Symfony standardı yalnızca URL sümüklü böceklerini kullanır, bu nedenle bu bize burada kimsenin siteyi hacklemeye çalışmadığını da söyler.

Bunlar, günlük dosyalarının değerli kullanım bilgileri ve hatta temel analizler elde etmek için yaratıcı bir şekilde kullanılma yollarının nispeten ilkel örneklerinden sadece birkaçıdır.

Akılda Tutulması Gereken Diğer Şeyler

Eşyaları Güvende Tutmak

Başka bir uyarı güvenlik içindir. Günlüğe kaydetme isteklerinin iyi bir fikir olduğunu düşünebilirsiniz, çoğu durumda gerçekten de öyle. Ancak, potansiyel olarak hassas kullanıcı bilgilerini günlükte saklamadan önce kaldırma konusunda son derece dikkatli olmak önemlidir.

Günlük Dosya Şişkinliğiyle Mücadele

Günlük dosyaları, her zaman bilgi eklediğiniz metin dosyaları olduğundan, sürekli olarak büyürler. Bu iyi bilinen bir sorun olduğundan, günlük dosyası büyümesini denetlemek için oldukça standart bazı yaklaşımlar vardır.

En kolayı günlükleri döndürmektir . Dönen günlükler şu anlama gelir:

  • Daha fazla yazmak için günlüğü düzenli olarak yeni bir boş dosyayla değiştirmek
  • Eski dosyayı tarih için saklamak
  • Disk alanını boşaltmak için yeterince "eski" dosyaları kaldırma
  • Bu dosya değişiklikleri meydana geldiğinde uygulamanın kesintiye uğramadan günlüklere yazabilmesini sağlamak

Bunun için en yaygın çözüm, çoğu *nix dağıtımıyla önceden yüklenmiş olarak gelen logrotate . Günlüklerimizi döndürmek için basit bir yapılandırma dosyası görelim:

 /var/log/my/debug.log /var/log/my/info.log /var/log/my/warning.log /var/log/my/error.log { rotate 7 daily missingok notifempty delaycompress compress sharedscripts postrotate invoke-rc.d rsyslog rotate > /dev/null endscript }

Daha gelişmiş bir başka yaklaşım da, rsyslogd mesajları, geçerli tarih ve saate göre dinamik olarak oluşturulan dosyalara yazmasını sağlamaktır. Bu, eski dosyaların kaldırılması için yine de özel bir çözüm gerektirir, ancak geliştiricilerin her günlük dosyası için zaman dilimlerini tam olarak yönetmesine izin verir. Örneğimiz için:

 $template DynaLocal0Err, "/var/log/my/error-%$NOW%-%$HOUR%.log" $template DynaLocal0Info, "/var/log/my/info-%$NOW%-%$HOUR%.log" $template DynaLocal0Warning, "/var/log/my/warning-%$NOW%-%$HOUR%.log" $template DynaLocal0Debug, "/var/log/my/debug-%$NOW%-%$HOUR%.log" local1.err -?DynaLocal0Err local1.info -?DynaLocal0Info local1.warning -?DynaLocal0Warning local1.debug -?DynaLocal0Debug

Bu şekilde, rsyslog her saat başı ayrı bir günlük dosyası oluşturacak ve bunları döndürmeye ve arka plan programını yeniden başlatmaya gerek kalmayacak. Bu çözümü gerçekleştirmek için 5 günden eski günlük dosyalarının nasıl kaldırılabileceği aşağıda açıklanmıştır:

 find /var/log/my/ -mtime +5 -print0 | xargs -0 rm

Uzak Günlükler

Proje büyüdükçe, günlüklerdeki bilgileri ayrıştırmak giderek daha fazla kaynağa ihtiyaç duyar. Bu yalnızca ekstra sunucu yükü oluşturmak anlamına gelmez; aynı zamanda, günlükleri ayrıştırdığınız zamanlarda, kullanıcılar için sunucu yanıt süresini azaltabilen (veya en kötü durumda siteyi bile çökertebilen) CPU ve disk sürücülerinde en yüksek yük oluşturma anlamına gelir.

Bunu çözmek için merkezi bir günlük kaydı sunucusu kurmayı düşünün. Bunun için tek ihtiyacınız olan UDP bağlantı noktası 514 (varsayılan) açık olan başka bir kutu. rsyslogd bağlantıları dinlemesini sağlamak için yapılandırma dosyasına aşağıdaki satırı ekleyin:

 $UDPServerRun 514

Buna sahip olarak, istemciyi kurmak şu kadar kolaydır:

 *.* @HOSTNAME:514

(burada HOSTNAME , uzak günlük kaydı sunucunuzun ana bilgisayar adıdır).

Çözüm

Bu makale, günlük dosyalarının daha önce hayal ettiğinizden çok daha değerli bilgiler sunabileceği yaratıcı yöntemlerden bazılarını gösterse de, mümkün olanın yalnızca yüzeyini çizdiğimizi vurgulamak önemlidir. Günlüğe kaydedebileceklerinizin kapsamı, kapsamı ve biçimi neredeyse sınırsızdır. Bu, günlüklerinizden çıkarmak istediğiniz kullanım veya analiz verileri varsa, bunları daha sonra ayrıştırmayı ve analiz etmeyi kolaylaştıracak şekilde kaydetmeniz gerektiği anlamına gelir. Ayrıca, bu analiz genellikle grep , sed veya awk gibi standart Linux komut satırı araçlarıyla gerçekleştirilebilir.

Gerçekten de, PHP günlük dosyaları, muazzam fayda sağlayabilecek en güçlü araçlardır.

Kaynaklar

GitHub'daki kod: https://github.com/isanosyan/toptal-blog-logs-post-example


Ek: Unix Kabuğundaki Günlük Dosyalarını Okuma ve Manipüle Etme

Günlük dosyalarınızı okumak ve işlemek için aşina olmak isteyeceğiniz daha yaygın *nix komut satırı araçlarından bazılarına kısa bir giriş.

  • cat belki de en basit olanıdır. Tüm dosyayı çıktı akışına yazdırır. Örneğin, aşağıdaki komut logfile1 konsola yazdıracaktır:

     cat logfile1
  • > karakteri, kullanıcının çıktıyı, örneğin başka bir dosyaya yeniden yönlendirmesine izin verir. Hedef akışı yazma modunda açar (bu, hedef içeriğin silinmesi anlamına gelir). tmpfile içeriğini logfile1 içeriğiyle şu şekilde değiştiriyoruz:

     cat logfile1 > tmpfile
  • >> çıktıyı yeniden yönlendirir ve hedef akışı ekleme modunda açar. Hedef dosyanın mevcut içeriği korunacak, alta yeni satırlar eklenecektir. Bu, logfile1 içeriğini tmpfile öğesine ekleyecektir:

     cat logfile1 >> tmpfile
  • grep , dosyayı bazı desenlere göre filtreler ve yalnızca eşleşen satırları yazdırır. Aşağıdaki komut, yalnızca Bingo mesajını içeren logfile1 satırlarını yazdıracaktır:

     grep Bingo logfile1
  • cut , tek bir sütunun içeriğini yazdırır (1'den başlayarak numaraya göre). Varsayılan olarak, sütunlar arasında sınırlayıcı olarak sekme karakterlerini arar. Örneğin, YYYY-MM-DD HH:MM:SS biçiminde zaman damgalarıyla dolu bir dosyanız varsa, bu yalnızca yılları yazdırmanıza olanak tanır:

     cut -d"-" -f1 logfile1
  • head , bir dosyanın yalnızca ilk satırlarını görüntüler

  • tail bir dosyanın yalnızca son satırlarını görüntüler

  • sort çıktıdaki satırları sıralar

  • uniq yinelenen satırları filtreler

  • wc kelimeleri (veya -l bayrağıyla kullanıldığında satırları) sayar

  • | (yani, "boru" sembolü) bir komuttan diğerine girdi olarak çıktı sağlar. Pipe komutları birleştirmek için çok uygundur. Örneğin, bir dizi zaman damgası içinde gerçekleşen 2014'ün aylarını şu şekilde bulabiliriz:

     grep -E "^2014" logfile1 | cut -d"-" -f2 | sort | uniq

Burada önce satırları “2014 ile başlar” düzenli ifadesiyle eşleştirir, ardından ayları keseriz. Son olarak, oluşumları yalnızca bir kez yazdırmak için sort ve uniq kombinasyonunu kullanırız.