{"id":2414,"date":"2022-07-02T18:42:34","date_gmt":"2022-07-02T16:42:34","guid":{"rendered":"https:\/\/guven.atbakan.com\/blog\/?p=2414"},"modified":"2022-09-04T15:15:29","modified_gmt":"2022-09-04T12:15:29","slug":"komut-satiri-uygulamasi-pratikleri-part-1-ciktilari-loglayin","status":"publish","type":"post","link":"https:\/\/guven.atbakan.com\/blog\/tr\/komut-satiri-uygulamasi-pratikleri-part-1-ciktilari-loglayin\/","title":{"rendered":"Komut Sat\u0131r\u0131 Uygulamas\u0131 Pratikleri &#8211; Part 1 &#8211; \u00c7\u0131kt\u0131lar\u0131 Loglay\u0131n"},"content":{"rendered":"<p>Sizlere bu seride, komut sat\u0131r\u0131 uygulamalar\u0131 yazarken uygulad\u0131\u011f\u0131m y\u00f6ntemlerden ve &quot;best practice&quot; olarak ge\u00e7en kavramlardan bahsedece\u011fim. Bu yazd\u0131klar\u0131m elbette olmazsa olmaz de\u011fil, fakat size daha iyi komut sat\u0131r\u0131 uygulamalar\u0131 yazman\u0131za yard\u0131mc\u0131 olaca\u011f\u0131na eminim.<\/p>\n<h2>\u00c7\u0131kt\u0131lar\u0131 loglay\u0131n, yoksa kan\u0131tlayamazs\u0131n\u0131z!<\/h2>\n<p>Loglama herhangi bir uygulaman\u0131n temel yap\u0131 ta\u015f\u0131d\u0131r. Komut sat\u0131r\u0131 uygulamalar\u0131 i\u00e7in, yap\u0131lan i\u015fin ve sonucunun detaylar\u0131yla loglanmas\u0131 bana kal\u0131rsa hayatidir.<\/p>\n<p>Ben bunun i\u00e7in genel olarak \u00e7ok basit bir y\u00f6ntem kullan\u0131yorum. <\/p>\n<pre><code class=\"language-bash\">\/var\/www\/artisan some:command &gt;  $HOME\/logs\/some-command\/`date +%Y-%m-%d-%H-%M-%S`.log 2&gt;&amp;1<\/code><\/pre>\n<p>\u00c7al\u0131\u015fan komut sat\u0131r\u0131 uygulamas\u0131 ile ilgili \u00e7\u0131kt\u0131y\u0131, onunla ilgili olan bir klas\u00f6r i\u00e7erisine \u00e7al\u0131\u015fma saatiyle yazd\u0131r\u0131yorum. Bunu crontab i\u00e7erisine de yazabilirsiniz. B\u00f6ylece basit\u00e7e bir <code>ls<\/code> komutu yard\u0131m\u0131yla, o uygulaman\u0131n \u00e7al\u0131\u015ft\u0131\u011f\u0131 zamanlar\u0131 h\u0131zl\u0131ca g\u00f6rebilirsiniz.<\/p>\n<p>Peki bu \u00e7\u0131kt\u0131 neler i\u00e7ermeli? Tabi ki uygulaman\u0131n ne yapt\u0131\u011f\u0131na ba\u011fl\u0131 olarak de\u011fi\u015fir bu. Uygulaman\u0131n ne yapaca\u011f\u0131, \u00e7al\u0131\u015ft\u0131rman\u0131n neleri etkileyece\u011fi ve \u00e7al\u0131\u015ft\u0131ktan sonra nelerin etkinlendi\u011fini yazmak en temel konulard\u0131r. Ama a\u00e7\u0131k\u00e7as\u0131 akl\u0131n\u0131za ne gelirse yazabilirsiniz. Yazmaktan da \u00e7ekinmeyin. <\/p>\n<h2>\u00d6rnek bir uygulama<\/h2>\n<p>Biraz daha realize etmeye \u00e7al\u0131\u015fal\u0131m. Varsayal\u0131m ki kullan\u0131c\u0131lar\u0131n g\u00fcncel \u00fcyelik(subscription) durumlar\u0131n\u0131 kontrol eden ve e\u011fer para \u00f6demiyorlarsa onlar\u0131 pasifle\u015ftiren bir uygulama yazd\u0131n\u0131z. <\/p>\n<p>Evet bu i\u015fi normalde webhook ile yapmam\u0131z daha mant\u0131kl\u0131. \u00d6zellikle Stripe \u00e7ok g\u00fczel webhook g\u00f6nderimi yap\u0131yor ve birka\u00e7 kez deniyor. Ama webhooklara her zaman g\u00fcvenebilir miyiz? Bazen uygulamam\u0131zda bir problem olabilir, uygulama kapal\u0131 kalabilir. Ya da yazd\u0131\u011f\u0131m\u0131z bir logic do\u011fru sonu\u00e7 vermiyor olabilir. Her zaman ikinci bir kontrol yapmakta fayda var. <\/p>\n<pre><code class=\"language-php\">&lt;?php\n\n$users = User::where(&#039;is_active&#039;, true)-&gt;get(); \/\/ TODO: use cursors instead of getting whole data. This will be fixed in the next chapters!\n\n$this-&gt;output-&gt;writeln(&#039;There are &#039;.$users-&gt;count().&#039; users to be checked for subscription control.&#039;);\n\nforeach ($users as $user) {\n    if (!$this-&gt;stripeService-&gt;isUserActive($user)) {\n        $this-&gt;userService-&gt;disableUser($user);\n        $this-&gt;output-&gt;writeln(&#039;User have been disabled: user_id_&#039;.$user-&gt;id);\n    }\n}\n\n$this-&gt;output-&gt;writeln(&#039;Done&#039;);\n\nreturn 0;<\/code><\/pre>\n<p>Yukar\u0131daki basit komut sat\u0131r\u0131 uygulamas\u0131n\u0131n \u00e7\u0131kt\u0131s\u0131 a\u015fa\u011f\u0131daki gibi olacak:<\/p>\n<pre><code>There are 1989 users to be checked for subscription control. \nUser have been disabled: user_id_100\nUser have been disabled: user_id_157\nDone.<\/code><\/pre>\n<p>G\u00f6rd\u00fc\u011f\u00fcn\u00fcz gibi uygulama ne yapaca\u011f\u0131n\u0131n bilgisini veriyor. Daha sonra 2 kullan\u0131c\u0131ya i\u015flem yapt\u0131\u011f\u0131n\u0131 bildiriyor. Ve en sonunda basit\u00e7e &quot;Done.&quot; yazarak \u00e7al\u0131\u015fman\u0131n sonland\u0131\u011f\u0131n\u0131 bildiriyor.<\/p>\n<p>Bu \u00e7\u0131kt\u0131 dosyas\u0131n\u0131 art\u0131k isterseniz bash kullanarak inceleyebilirsiniz, isterseniz basit scriptler yazabilir ya da ELK, Datadog, Coralogix, Graylog, Papertrail gibi sistemlere kolayca atabilirsiniz. <\/p>\n<h3>\u00c7\u0131kt\u0131lar \u00fczerinde bilgiyi bulun<\/h3>\n<p>\u00c7o\u011funlukla, bir log y\u00f6netim sistemi kullanmayaca\u011f\u0131n\u0131z\u0131 tahmin ediyorum. Genelde bu durum atlan\u0131r. Bu durumda da loglarda bir arama yapman\u0131z gerekiyor olabilir. Bu i\u015f i\u00e7in <code>grep<\/code> kullanabilirsiniz. (Daha bir\u00e7ok y\u00f6ntem var ayn\u0131 i\u015fi yapan.)<\/p>\n<p><code>grep -Ril -e &#039;user_id_100&#039; $HOME\/logs\/some-command\/<\/code><\/p>\n<p>Bu basit komut sonras\u0131nda kullan\u0131c\u0131n\u0131n pasifle\u015ftirildi\u011fini g\u00f6receksiniz. E\u011fer bunu loglamasayd\u0131n\u0131z, neden pasifle\u015ftirildi\u011fini anlamayabilirdiniz. <\/p>\n<h3>Formatl\u0131 yazd\u0131rma<\/h3>\n<p>Dosyaya \u00e7\u0131kt\u0131 verdi\u011fimizde, datay\u0131 search edilebilir vermek olduk\u00e7a \u00f6nemli. Ben \u00f6rne\u011fimde <code>user_id_XXXX<\/code> olarak verdim. T\u00fcm komut sat\u0131r\u0131 uygulamalar\u0131ndan ayn\u0131 formatta verdi\u011fimde, &quot;<code>user_id_XXXX<\/code> ile ilgili komut sat\u0131r\u0131nda yap\u0131lan i\u015flemler&quot; listesine kolayca ula\u015fabilece\u011fim. <\/p>\n<h2>Laravel&#8217;de cronjob \u00e7\u0131kt\u0131s\u0131n\u0131 yazd\u0131rma<\/h2>\n<p>Laravel&#8217;e \u00f6zel bir ba\u015fl\u0131k a\u00e7\u0131yorum. S\u0131kl\u0131kla <a href=\"https:\/\/laravel.com\/docs\/8.x\/scheduling#task-output\">Scheduler<\/a> \u00f6zelli\u011fini kullan\u0131yorum. \u0130\u015fleri bence olduk\u00e7a kolayla\u015ft\u0131ran ve takip edilebilmesini sa\u011flayan bir y\u00f6ntem. <\/p>\n<p>Laravel bu noktada bize bir kolayl\u0131k sa\u011fl\u0131yor ve \u00e7\u0131kt\u0131lar\u0131 dosya sistemine yazabilmemize olanak tan\u0131yor.<\/p>\n<pre><code class=\"language-php\">$schedule-&gt;command(&#039;emails:send&#039;)\n         -&gt;daily()\n         -&gt;appendOutputTo(storage_path(&#039;cronjob-logs\/emails_send_&#039;.date(&#039;YmdHis&#039;));<\/code><\/pre>\n<p>G\u00fcnl\u00fck \u00e7al\u0131\u015ft\u0131rd\u0131\u011f\u0131m ve belirlenen emailleri g\u00f6nderen bir uygulamam\u0131z olsun. Bunun \u00e7\u0131kt\u0131s\u0131n\u0131 storage klas\u00f6r\u00fc alt\u0131na yazabiliriz. <\/p>\n<h2>Sonu\u00e7<\/h2>\n<p>Loglamak bir uygulamadaki en kritik konu bence. \u00c7\u0131kt\u0131lar\u0131 kaydetmek olduk\u00e7a basit. Sizin i\u00e7in neyin de\u011ferli oldu\u011funa karar vermeniz ve kendiniz i\u00e7in bir log yap\u0131s\u0131 kurman\u0131z gerekiyor. Bir kez log yap\u0131s\u0131 kurduktan sonra, bir daha bir\u015fey yapman\u0131za gerek kalm\u0131yor. Tabi debug gerekmedik\u00e7e :) Umar\u0131m gerekmez, ama her zaman haz\u0131rl\u0131kl\u0131 olmakta fayda var.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Sizlere bu seride, komut sat\u0131r\u0131 uygulamalar\u0131 yazarken uygulad\u0131\u011f\u0131m y\u00f6ntemlerden ve &quot;best practice&quot; olarak ge\u00e7en kavramlardan bahsedece\u011fim. Bu yazd\u0131klar\u0131m elbette olmazsa olmaz de\u011fil, fakat size daha iyi komut sat\u0131r\u0131 uygulamalar\u0131 yazman\u0131za yard\u0131mc\u0131 olaca\u011f\u0131na eminim. \u00c7\u0131kt\u0131lar\u0131 loglay\u0131n, yoksa kan\u0131tlayamazs\u0131n\u0131z! Loglama herhangi bir uygulaman\u0131n temel yap\u0131 ta\u015f\u0131d\u0131r. Komut sat\u0131r\u0131 uygulamalar\u0131 i\u00e7in, yap\u0131lan i\u015fin ve sonucunun detaylar\u0131yla loglanmas\u0131 bana [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":2479,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"jetpack_post_was_ever_published":false,"_jetpack_newsletter_access":"","_jetpack_dont_email_post_to_subs":false,"_jetpack_newsletter_tier_id":0,"_jetpack_memberships_contains_paywalled_content":false,"_jetpack_memberships_contains_paid_content":false,"footnotes":"","jetpack_publicize_message":"","jetpack_publicize_feature_enabled":true,"jetpack_social_post_already_shared":false,"jetpack_social_options":{"image_generator_settings":{"template":"highway","default_image_id":0,"font":"","enabled":false},"version":2}},"categories":[4],"tags":[],"class_list":["post-2414","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-yazilim"],"blocksy_meta":{"styles_descriptor":{"styles":{"desktop":"","tablet":"","mobile":""},"google_fonts":[],"version":6}},"jetpack_publicize_connections":[],"jetpack_featured_media_url":"https:\/\/guven.atbakan.com\/blog\/wp-content\/uploads\/2022\/07\/carbon1.png","jetpack_likes_enabled":true,"jetpack-related-posts":[],"jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/guven.atbakan.com\/blog\/wp-json\/wp\/v2\/posts\/2414","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/guven.atbakan.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/guven.atbakan.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/guven.atbakan.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/guven.atbakan.com\/blog\/wp-json\/wp\/v2\/comments?post=2414"}],"version-history":[{"count":2,"href":"https:\/\/guven.atbakan.com\/blog\/wp-json\/wp\/v2\/posts\/2414\/revisions"}],"predecessor-version":[{"id":2464,"href":"https:\/\/guven.atbakan.com\/blog\/wp-json\/wp\/v2\/posts\/2414\/revisions\/2464"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/guven.atbakan.com\/blog\/wp-json\/wp\/v2\/media\/2479"}],"wp:attachment":[{"href":"https:\/\/guven.atbakan.com\/blog\/wp-json\/wp\/v2\/media?parent=2414"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/guven.atbakan.com\/blog\/wp-json\/wp\/v2\/categories?post=2414"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/guven.atbakan.com\/blog\/wp-json\/wp\/v2\/tags?post=2414"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}