Web 開発再入門 #15 ― ログ出力処理

# Web 開発再入門 #15 ― ログ出力処理

fmockup

## はじめに

Web アプリケーションのサーバー・サイドを開発します。

アクセス・ログとアプリケーション・ログをファイルに書き出すようにします。

**アクセス・ログ：**
アカウントに関する操作（ログイン、ログアウト、アカウント追加・変更・削除）のログを出力します。
セキュリティを脅かす攻撃を受けているか否かの分析で使用します。

**アプリケーション・ログ：**
各処理の開始と終了のログを出力します。
アプリケーションの動作に問題があった時の初期切り分けに使用します。

## フォルダー・ファイル構成

D:\\
└ Development\\
&nbsp;&nbsp;&nbsp;&nbsp;└ Workspace\\
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;└ fmockup\\
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;├ build\\
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;├ sql\\
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;├ src\\
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;│&nbsp;└ main\\
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;│&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;├ java\\
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;│&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;│&nbsp;└ cn\\
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;│&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;│&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;└ com\\
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;│&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;│&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;└ xxxx\\
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;│&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;│&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;└ fmockup\\
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;│&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;│&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;├ action\\
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;│&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;│&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;├ controller\\
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;│&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;│&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;├ customizer\\
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;│&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;│&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;├ entity\\
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;│&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;│&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;├ mapper\\
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;│&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;│&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;├ response\\
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;│&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;│&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;├ service\\
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;│&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;│&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;├ util\\
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;│&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;│&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;│&nbsp;└ LogUtil.java ← コレ
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;│&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;│&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;├ validator\\
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;│&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;│&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;└ validator_order\\
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;│&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;└ resources\\
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;│&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;└ logback-spring.xml ← コレ
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;├ vue-vite\\
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;└ WinSW.NET-nnn\\

## ファイルの文字コード

基本的に Eclipse でファイルを作成するので、あまり意識したことがありません。
多分、Unix 改行（LF）なのだと思います。

## ファイルの作成

1. Eclipse で、ファイル “logback-spring.xml”、 “LogUtil.java” を作成する。
    ```xml:logback-spring.xml
    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE logback>
    <configuration>
    
    	<!-- xxxx environment -->
    	<springProfile name="xxxx">
    		<property name="logFilePath" value="d:/systems/fmockup/log/xxxx/" />
    		<property name="logFileName" value="fmockup" />
    　　	<property name="logLevel" value="INFO" />
    	</springProfile>
    
    	<!-- production environent -->
    	<springProfile name="production">
     		<property name="logFilePath" value="${LOG_PATH}/" />
    		<property name="accountLogFileName" value="fmockup-account" />
    		<property name="applicationLogFileName" value="fmockup-application" />
    　　	<property name="logLevel" value="INFO" />
    	</springProfile>
    
    	<!-- console output -->
    	<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
    		<target>System.out</target>
    		<encoder>
    			<charset>UTF-8</charset>
    			<pattern>fmockup stdout %d{yyyy/MM/dd HH:mm:ss} %-5level [%thread] - %msg%n</pattern>
    		</encoder>
    	</appender>
    
    	<!-- account log -->
    	<appender name="ACCESS_LOG" class="ch.qos.logback.core.rolling.RollingFileAppender">
    
    		<!--file name -->
    		<file>${logFilePath}${accountLogFileName}.log</file>
    
    		<!--log lotation -->
    		<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
    			<fileNamePattern>${logFilePath}${accountLogFileName}-%d{yyyy-MM-dd}.log.zip</fileNamePattern>
    <!--		<maxHistory>180</maxHistory>  -->
    			<maxHistory>3</maxHistory>
    			<cleanHistoryOnStart>true</cleanHistoryOnStart>
    		</rollingPolicy>
    
    		<!--log output format -->
    		<encoder>
    			<charset>UTF-8</charset>
    			<pattern>fmockup account %d{yyyy/MM/dd HH:mm:ss} %-5level [%thread] - %msg%n</pattern>
    		</encoder>
    	</appender>
    
    	<!-- application log -->
    	<appender name="APPLICATION_LOG" class="ch.qos.logback.core.rolling.RollingFileAppender">
    
    		<!--file name -->
    		<file>${logFilePath}${applicationLogFileName}.log</file>
    
    		<!--log lotation -->
    		<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
    			<fileNamePattern>${logFilePath}${applicationLogFileName}-%d{yyyy-MM-dd}.log.zip</fileNamePattern>
    <!--		<maxHistory>180</maxHistory>  -->
    			<maxHistory>3</maxHistory>
    			<cleanHistoryOnStart>true</cleanHistoryOnStart>
    		</rollingPolicy>
    
    		<!--log output format -->
    		<encoder>
    			<charset>UTF-8</charset>
    			<pattern>fmockup application %d{yyyy/MM/dd HH:mm:ss} %-5level [%thread] - %msg%n</pattern>
    		</encoder>
    	</appender>
    
    	<!-- root -->
    	<root level="INFO">
    		<appender-ref ref="STDOUT" />
    	</root>
    
    	<root level="INFO">
    		<appender-ref ref="APPLICATION_LOG" />
    	</root>
    
    	<!-- logger -->
    	<logger name="accountLogger" additivity="false" level="INFO">
    		<appender-ref ref="ACCESS_LOG" />
    	</logger>
    	<logger name="applicationLogger" additivity="false" level="INFO">
    		<appender-ref ref="APPLICATION_LOG" />
    	</logger>
    
    </configuration>
    ```
    ```java:LogUtil.java
    ・・・
    
    package cn.com.xxxx.fmockup.util;
    
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    
    /**
     * Log Utility
     *   It writes to log file.
     */
    
    public class LogUtil {
    
    	protected static final Logger accountLogger = LoggerFactory.getLogger("accountLogger");
    	protected static final Logger applicationLogger = LoggerFactory.getLogger("applicationLogger");
    
    	public static void access(String msg) {
    		accountLogger.info(msg);
    		applicationLogger.info(msg);
    	}
    
    	public static void info(String msg) {
    		applicationLogger.info(msg);
    	}
    
    	public static void warn(String msg) {
    		applicationLogger.warn(msg);
    	}
    
    	public static void error(String msg) {
    		applicationLogger.error(msg);
    	}
    
    	public static void debug(String msg) {
    		applicationLogger.debug(msg);
    	}
    
    	public static void trace(String msg) {
    		applicationLogger.trace(msg);
    	}
    
    }
    ```

## 参考

**Logback**

https://qiita.com/t-iguchi/items/94c35818577580310e4b

https://qiita.com/Masahiro_Uemura1234/items/61a25ce4aa815a9922d6