1. Preface, the purpose of writing this framework

The android team doesn’t have a unified logging framework. The use of logs varies from developer to developer. As an ambitious programmer, I felt like writing a logging framework to promote within the team. Of course, there are also on-site Log frameworks on the Internet, but due to the particularity of the company’s business and equipment, I decided to write one myself.

Just a few days ago in the study of design pattern related knowledge, can use this framework to practice. (I highly recommend “Beauty of Design Patterns” on Geek Time, step-by-step and easy to understand, gK. link/ A /10iK4)

In addition, make fun of two points for everyone to learn and improve:

  1. Use the log log level correctly. During my work, I read the code written by my colleague and found that my colleague often used the log level inappropriately. For example, he used the error level to print logs when he should not use the error level (for example, to print a list data obtained through the interface). Maybe the user can debug with the error “red” message to observe, it is a bit more obvious, but usually other people looking at the logcat message, a bunch of red font filled the eye ball, it really feels…
  2. Use log tags correctly. Personally, I think the tag is used to classify the logs of the same function, but I found that some students like to use their names as tags.

So we’ve recently incorporated the proper use of logs into our company’s programming specification.

2. Organize requirements from vague to specific

The nature of the framework, or the function that does not have much relevance to the business, the requirements are relatively vague. Writing this kind of code, I think it is best to sort out the requirements first and convert the vague ideas into specific text requirements.

The benefits of organizing requirements into words, each point is important:

  1. It is convenient for you to have specific requirements as a design reference when designing the following classes
  2. It is convenient to review framework functions after a long time
  3. Facilitate the team or new members to quickly understand the framework’s history and requirements. (Don’t underestimate the importance of documentation when you’re a veteran employee with a highly mobile team and have to explain the logic to everyone over and over again.)

Let’s first clarify the role of the log, which can be summarized as two points:

  1. Easy to debug programs during development.
  2. This helps you quickly locate a problem after the product is launched.

In general, the logging framework has two functions: write and read. According to these two points, we carefully think and subdivide. Of course, when thinking about requirements, we can refer to previous project experience or the log function of Android itself. Here’s a rough list of what I need:

3. Design confusing classes, and the responsibilities and relationships between classes

Through the requirements sorting above, we can see that the framework is roughly divided into two parts: reading and writing. So let’s first design the interface between these two parts.

1. Write

First define a write interface LogWriter, we can refer to the Android logcat display, write method parameters should include: time, logVersion, tag, content, threadName.

public interface LogWriter {
    void write(@LogVersion int version, String tag, String content) throws WriteLogErrException;

    void write(@LogVersion int version, long time, String threadName, String tag, String content) throws WriteLogErrException;

    void write(Log log) throws WriteLogErrException;
}
Copy the code

As for the implementation classes, we divide them by where the log is stored:

  1. LogcatLogWriter
  2. CacheLogWriter
  3. DiskLogWriter
  4. CrashLogWriter (Crash logs are stored in separate files)

Performance requirements: As we mentioned earlier when we were sorting out the requirements, when you store logs, you don’t have to affect the performance of your software. Performance is all about space and time, so let’s think about time. If you just write logs to Logcat and memory, it doesn’t take a lot of time. We can initially set up a “log store queue” for storing logs to files. As for the space requirement, we will consider it with the others below.

2. Read (Log extractor)

First, we define a Log extractor interface, LogExtractor. Since reading logs requires asynchronous processing, we also need a read fetch callback, ExtractCallBack

public interface LogExtractor {
    interface ExtractCallBack {
        /** * Succeeded in extracting logs *@paramLogFile the extracted logFile */
        void onSuccess(File logFile);

        void onFail(String errMsg);
    }

    /** * Extract log **@paramExtractCallBack Extracts the log callback */
    void extract(ExtractCallBack extractCallBack);
}
Copy the code

Next are the implementation classes of each Log extractor LogcatExtractor, DateLogExtractor, TimeLogExtractor, CrashLogExtractor

3. Configurability: LogConfig

We need a log configuration class, provided to the user, the user can configure the log framework according to the actual needs of the project. So what can be configured?

  1. Whether to use memory cache
  2. Whether to use disk storage
  3. Whether to store crash logs
  4. Log Maximum capacity of the memory cache
  5. The maximum capacity of the folder for storing logs
  6. The maximum capacity of the folder for storing crash logs
  7. Path to the folder where logs are stored
  8. Path to the folder where crash logs are stored

4. LogWriteLogic — LogWriteLogic class

In the “write” section above we have designed the LogWriter and the implementation classes, but how to call them? We can implement a logic class that executes logic based on the configuration LogConfig passed in by the user. As for its specific implementation details, we will not consider, we will mainly design the responsibilities and relationships of each class.

5. Users invoke the portal in a unified manner

Finally, in order to reduce the difficulty of using the framework, the framework will design an entry class (appearance class) for users to use. The general methods to be provided are:

  1. 1.1 Importing LogConfig
  2. Log Writing Related 2.1 Writing Common Logs 2.2 Writing Crash Logs
  3. Log Extraction 3.1 Extracting Logs from LogCAT 3.2 Extracting Logs by Date 3.3 Extracting Logs by Start date and End Date 3.4 Extracting Routing Logs

4. Source address

With the early design, writing code part is not too difficult, directly put the source code, what problems can be more advice: github.com/chenyugui/T…