John Squirrels
مرحله
San Francisco

ثبت جاوا

در گروه منتشر شد
سلام! هنگام نوشتن دروس، به ویژه تأکید می کنم که آیا موضوع خاصی وجود دارد که در کار واقعی کاملاً ضروری باشد. پس، گوش کن! موضوعی که امروز به آن خواهیم پرداخت قطعا از همان روز اول استخدام در همه پروژه های شما مفید خواهد بود. ما در مورد Java Logging صحبت خواهیم کرد. این موضوع اصلاً پیچیده نیست (حتی می توانم بگویم آسان است). اما در اولین کارتان به اندازه کافی چیزهای واضحی خواهید داشت که باید روی آن تاکید کنید، بنابراین بهتر است همین الان آن را کاملاً درک کنید :) خب، بیایید شروع کنیم.

لاگین کردن در جاوا چیست؟

Logging عمل ثبت اطلاعات در مورد عملکرد یک برنامه است. مکانی که این داده ها را در آن ثبت می کنیم "log" نامیده می شود. بلافاصله دو سوال مطرح می شود: چه داده ای و کجا نوشته شده است؟ بیایید با "کجا" شروع کنیم. شما می توانید داده های مربوط به کار یک برنامه را در مکان های مختلف بنویسید. برای مثال، در طول تحصیل، شما اغلب System.out.println()برای خروجی داده ها به کنسول این در واقع ورود به سیستم است، البته در ساده ترین شکل آن. البته، این برای کاربران یا تیم پشتیبانی محصول خیلی راحت نیست: بدیهی است که آنها نمی‌خواهند یک IDE نصب کنند و کنسول را نظارت کنند :) فرمت مرسوم‌تری برای ضبط اطلاعات وجود دارد: فایل‌های متنی. انسان ها در خواندن داده ها در این قالب بسیار راحت تر هستند و مطمئناً برای ذخیره داده ها بسیار راحت تر است! حالا سوال دوم: داده های چه برنامه ای باید ثبت شود؟ این کاملا به شما بستگی دارد! سیستم لاگ جاوا بسیار منعطف است. می توانید آن را طوری پیکربندی کنید که همه کارهایی که برنامه شما انجام می دهد را ثبت کند. از یک طرف این خوب است. اما از سوی دیگر، تصور کنید که لاگ های فیس بوک یا توییتر چقدر بزرگ می شود اگر همه چیز را در آنها بنویسند. این شرکت‌های بزرگ احتمالاً توانایی ذخیره این مقدار داده را دارند. اما تصور کنید که یافتن اطلاعات مربوط به یک خطای حیاتی در 500 گیگابایت گزارش متن چقدر دشوار خواهد بود؟ این بدتر از جستجوی سوزن در انبار کاه است. بر این اساس، جاوا را می توان طوری پیکربندی کرد که فقط داده های خطا را ثبت کند. یا حتی فقط خطاهای مهم! گفته می‌شود، صحبت از سیستم ورود به سیستم بومی جاوا کاملاً دقیق نیست. واقعیت این است که برنامه نویسان قبل از اینکه این قابلیت به زبان اضافه شود نیاز به ورود به سیستم داشتند. زمانی که جاوا کتابخانه لاگ خود را معرفی کرد، همه از کتابخانه log4j استفاده می کردند. تاریخچه ورود به جاوا در واقع بسیار طولانی و آموزنده است. به طور خلاصه، جاوا کتابخانه لاگ مخصوص به خود را دارد، اما تقریباً هیچ کس از آن استفاده نمی کند :) بعداً، زمانی که چندین کتابخانه گزارش گیری مختلف ظاهر شد و توسط برنامه نویسان شروع به استفاده کرد، مشکلات سازگاری به وجود آمد. برای جلوگیری از اختراع مجدد چرخ در ده ها کتابخانه مختلف با رابط های مختلف، چارچوب انتزاعی SLF4J ("Service Logging Facade For Java") ایجاد شد. به آن انتزاعی می‌گویند، زیرا حتی اگر از متدهای کلاس‌های SLF4J استفاده کنید و آن‌ها را فراخوانی کنید، در زیر هود آن‌ها در واقع از تمام چارچوب‌های گزارش‌گیری که قبلاً آمده‌اند استفاده می‌کنند: log4j، استاندارد java.util.logging، و موارد دیگر. اگر زمانی به ویژگی خاصی از Log4j نیاز دارید که در کتابخانه های دیگر وجود ندارد، اما نمی خواهید پروژه خود را مستقیماً به این کتابخانه پیوند دهید، فقط از SLF4J استفاده کنید. و سپس اجازه دهید متدهای Log4j را فراخوانی کند. اگر نظر خود را تغییر دادید و تصمیم گرفتید که دیگر نیازی به ویژگی های Log4j ندارید، فقط باید "wrapper" (به عنوان مثال SLF4J) را برای استفاده از کتابخانه دیگری پیکربندی مجدد کنید. کد شما از کار نمی افتد، زیرا شما در حال فراخوانی روش های SLF4J هستید، نه یک کتابخانه خاص. یک انحراف کوچک. برای اینکه مثال‌های زیر کار کنند، باید کتابخانه SLF4J را از اینجا و کتابخانه Log4j را از اینجا دانلود کنید. . در مرحله بعد، بایگانی را باز کنید و از IntelliJ IDEA برای اضافه کردن فایل های JAR به مسیر کلاس استفاده کنید. آیتم های منو: فایل -> ساختار پروژه -> کتابخانه ها فایل های JAR لازم را انتخاب کرده و به پروژه اضافه کنید (بایگانی هایی که دانلود کردیم حاوی بسیاری از فایل های JAR هستند — برای دیدن موارد مورد نیاز به تصاویر نگاه کنید) توجه داشته باشید که این دستورالعمل برای آن دانش آموزان است چرا به ورود به سیستم نیاز داریم - 2چرا به ورود به سیستم نیاز داریم - 3. کسانی که نمی دانند چگونه از Maven استفاده کنند. اگر می‌دانید چگونه از Maven استفاده کنید، معمولاً بهتر است (بسیار ساده‌تر) از آنجا شروع کنید. اگر از Maven استفاده می کنید ، این وابستگی را اضافه کنید:
<dependency>
            <groupId>org.apache.logging.log4j</groupId>
            <artifactId>log4j-slf4j-impl</artifactId>
            <version>2.14.0</version>
</dependency>
عالی! ما تنظیمات را فهمیدیم :) بیایید ببینیم SLF4J چگونه کار می کند. چگونه مطمئن شویم که کار برنامه در جایی ضبط شده است؟ برای این کار به دو چیز نیاز داریم: logger و appender. بیایید با اول شروع کنیم. لاگر شی ای است که کنترل کامل ورود به سیستم را فراهم می کند. ایجاد یک لاگر بسیار آسان است: ما این کار را با استفاده از متدهای استاتیک LoggerFactory.getLogger() انجام می دهیم . پارامتر متد کلاسی است که عملیات آن ثبت خواهد شد. بیایید کد خود را اجرا کنیم:
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class MyTestClass {

   public static final Logger LOGGER = LoggerFactory.getLogger(MyTestClass.class);

   public static void main(String[] args) {

       LOGGER.info("Test log entry!!!");
       LOGGER.error("An error occurred!");
   }
}
خروجی کنسول:

ERROR StatusLogger No Log4j 2 configuration file found. Using default configuration (logging only errors to the console), or user programmatically provided configurations. Set system property 'log4j2.debug' to show Log4j 2 internal initialization logging. See https://logging.apache.org/log4j/2.x/manual/configuration.html for instructions on how to configure Log4j 2 15:49:08.907 [main] ERROR MyTestClass - An error occurred!
اینجا چه می بینیم؟ ابتدا یک پیغام خطا می بینیم. این در نتیجه این واقعیت است که اکنون ما فاقد تنظیمات لازم هستیم. بر این اساس، لاگر ما در حال حاضر فقط قادر به خروجی پیام های خطا (ERROR) و فقط به کنسول است. متد logger.info() کار نکرد. اما logger.error() انجام داد! در کنسول، تاریخ فعلی، روشی که خطا رخ داده است ( main )، کلمه "ERROR" و پیام ما را می بینیم! ERROR سطح ورود به سیستم است. به طور کلی، اگر یک ورودی گزارش با کلمه "ERROR" مشخص شده باشد، در این مرحله از برنامه خطایی رخ داده است. اگر ورودی با کلمه "INFO" مشخص شده باشد، پیام به سادگی نشان دهنده اطلاعات فعلی در مورد عملکرد عادی برنامه است. کتابخانه SLF4J دارای سطوح مختلف گزارش گیری است که به شما امکان می دهد ثبت گزارش را به صورت انعطاف پذیر پیکربندی کنید. مدیریت همه اینها بسیار آسان است: تمام منطق لازم از قبل در کلاس Java Logger وجود دارد . فقط باید روش های مربوطه را فراخوانی کنید. اگر می خواهید یک پیام معمولی را ثبت کنید، با متد ()logger.info تماس بگیرید . برای پیغام خطا، از logger.error() استفاده کنید . برای اخطار، از logger.warn() استفاده کنید

حالا بیایید در مورد appender صحبت کنیم

ضمیمه مکانی است که داده های شما در آن جا می رود. به نوعی برعکس یک منبع داده، یعنی «نقطه B». به طور پیش فرض، داده ها به کنسول خروجی می شوند. توجه داشته باشید که در مثال قبلی نیازی به پیکربندی چیزی نبود: متن در کنسول ظاهر می‌شود و لاگر کتابخانه Log4j فقط می‌تواند پیام‌های سطح ERROR را به کنسول ارسال کند. بدیهی است که خواندن و نوشتن گزارش‌ها در یک فایل متنی برای افراد راحت‌تر است. برای تغییر رفتار پیش فرض لاگر، باید ضمیمه فایل خود را پیکربندی کنیم. برای شروع، باید یک فایل log4j.xml را مستقیماً در پوشه src ایجاد کنید. شما قبلاً با فرمت XML آشنا هستید: اخیراً درسی در مورد آن داشتیم :) محتویات فایل در اینجا آمده است:
<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="INFO">
   <Appenders>
       <File name="MyFileAppender" fileName="C:\Users\Username\Desktop\testlog.txt" immediateFlush="false" append="false">
           <PatternLayout pattern="%d{yyy-MM-dd HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n"/>
       </File>
   </Appenders>
   <Loggers>
       <Root level="INFO">
           <AppenderRef ref="MyFileAppender"/>
       </Root>
   </Loggers>
</Configuration>
در اینجا هیچ چیز خاص یا سختی وجود ندارد :) اما با این حال، اجازه دهید از طریق محتوا بگذریم.
<Configuration status="INFO">
این به اصطلاح StatusLogger است. ارتباطی با لاگر ما ندارد و در فرآیندهای داخلی Log4j استفاده می شود. اگر status="TRACE" را به جای status="INFO" تنظیم کنید، تمام اطلاعات مربوط به کارهای داخلی Log4j در کنسول نمایش داده می شود (StatusLogger داده ها را روی کنسول نمایش می دهد، حتی اگر ضمیمه ما یک فایل باشد). ما اکنون به آن نیاز نداریم، پس بیایید آن را همانطور که هست رها کنیم.
<Appenders>
   <File name="MyFileAppender" fileName="C:\Users\Evgeny\Desktop\testlog.txt" append="true">
       <PatternLayout pattern="%d{yyy-MM-dd HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n"/>
   </File>
</Appenders>
در اینجا ما appender خود را ایجاد می کنیم. تگ <File> نشان می دهد که یک ضمیمه فایل خواهد بود. name="MyFileAppender" نام ضمیمه را تنظیم می کند. fileName="C:\Users\Username\Desktop\testlog.txt" مسیر فایل log را نشان می دهد که در آن همه داده ها نوشته می شوند. append="true" نشان می دهد که آیا داده ها باید در انتهای فایل نوشته شوند یا خیر. در مورد ما، این دقیقاً همان کاری است که ما انجام خواهیم داد. اگر مقدار را روی false تنظیم کنید، هر بار که برنامه شروع می شود، محتوای قدیمی فایل log حذف می شود. <PatternLayout pattern="%d{yyy-MM-dd HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n"/> تنظیمات قالب‌بندی را نشان می‌دهد . در اینجا می‌توانیم از عبارات منظم برای سفارشی کردن نحوه قالب‌بندی متن در گزارش خود استفاده کنیم.
<Loggers>
       <Root level="INFO">
           <AppenderRef ref="MyFileAppender"/>
       </Root>
</Loggers>
در اینجا ما سطح ریشه را نشان می دهیم. ما سطح "INFO" را تنظیم کرده ایم، به این معنی که تمام پیام هایی که سطح آنها بالاتر از INFO است (طبق جدولی که در بالا نگاه کردیم) ثبت نمی شود. برنامه ما 3 پیام خواهد داشت: یک INFO، یک WARN و یک ERROR. با پیکربندی فعلی، هر 3 پیام ثبت خواهد شد. اگر سطح ریشه را به ERROR تغییر دهید، فقط آخرین پیام از فراخوانی متد LOGGER.error () در لاگ پایان می یابد. علاوه بر این، اشاره ای به ضمیمه نیز در اینجا آمده است. برای ایجاد چنین مرجعی، باید یک تگ <ApprenderRef> در تگ <Root> ایجاد کنید و ویژگی ref='your appender's name' را به آن اضافه کنید. اگر فراموش کردید، اینجاست که نام ضمیمه را تنظیم می کنیم: <File name="MyFileAppender" . و کد ما اینجاست!
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class MyTestClass {

   public static final Logger LOGGER = LoggerFactory.getLogger(MyTestClass.class);

   public static void main(String[] args) {

       LOGGER.info("The program is starting!!!");

       try {
           LOGGER.warn("Attention! The program is trying to divide a number by another.
           System.out.println(12/0);
       } catch (ArithmeticException x) {

           LOGGER.error("Error! Division by zero!");
       }
   }
}
البته، کمی سخت است (گرفتن RuntimeException یک ایده سوال برانگیز است)، اما برای اهداف ما عالی است :) بیایید متد main() خود را 4 بار پشت سر هم اجرا کنیم و به فایل testlog.txt خود نگاه کنیم. نیازی به ایجاد آن از قبل ندارید: کتابخانه این کار را به صورت خودکار انجام می دهد. همه چیز کار کرد! :) حالا شما یک لاگر پیکربندی شده دارید. می توانید با برخی از برنامه های قدیمی خود بازی کنید و تماس های لاگر را به هر روش اضافه کنید. سپس به لاگ حاصل نگاه کنید :) موضوع ورود به سیستم را عمیقاً در نظر می گیرد. خواندن همه آن در یک جلسه چالش برانگیز خواهد بود. گفته می شود، حاوی اطلاعات مفید اضافی زیادی است. به عنوان مثال، شما یاد خواهید گرفت که چگونه لاگر را به گونه ای پیکربندی کنید که اگر فایل testlog.txt ما به اندازه خاصی برسد، یک فایل متنی جدید ایجاد کند :) و این کلاس ما را به پایان می رساند! امروز با موضوع بسیار مهمی آشنا شدید و این دانش قطعاً در کارهای آینده برای شما مفید خواهد بود. تا دفعه بعد! :)
نظرات
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION