avaScript一種直譯式腳本語言,是一種動態類型、弱類型、基于原型的語言,內置支持類型。它的解釋器被稱為JavaScript引擎,為瀏覽器的一部分,廣泛用于客戶端的腳本語言,最早是在HTML(標準通用標記語言下的一個應用)網頁上使用,用來給HTML網頁增加動態功能。
JavaScript 顯示數據
JavaScript 可以通過不同的方式來輸出數據:
使用 window.alert() 彈出警告框。
使用 document.write() 方法將內容寫到 HTML 文檔中。
使用 innerHTML 寫入到 HTML 元素。
使用 console.log() 寫入到瀏覽器的控制臺。
使用 window.alert()
你可以彈出警告框來顯示數據:
實例
nbsp;html>
我的第一個頁面
我的第一個段落。
操作 HTML 元素
如需從 JavaScript 訪問某個 HTML 元素,您可以使用 document.getElementById(id) 方法。
請使用 “id” 屬性來標識 HTML 元素,并 innerHTML 來獲取或插入元素內容:
實例
nbsp;html>
我的第一個 Web 頁面
"demo">我的第一個段落
以上 JavaScript 語句(在 標簽中)可以在 web 瀏覽器中執行:
document.getElementById(“demo”) 是使用 id 屬性來查找 HTML 元素的 JavaScript 代碼 。
innerHTML = “段落已修改。” 是用于修改元素的 HTML 內容(innerHTML)的JavaScript 代碼。
在本教程中
在大多數情況下,在本教程中,我們將使用上面描述的方法來輸出:
上面的例子直接把 id=”demo” 的
元素寫到 HTML 文檔輸出中:
寫到 HTML 文檔
出于測試目的,您可以將JavaScript直接寫在HTML 文檔中:
實例
nbsp;html>
我的第一個 Web 頁面
我的第一個段落。
Fri Apr 22 2022 16:20:12 GMT+0800 (中國標準時間)
請使用 document.write() 僅僅向文檔輸出寫內容。
如果在文檔已完成加載后執行 document.write,整個 HTML 頁面將被覆蓋。
實例
nbsp;html>
我的第一個 Web 頁面
我的第一個段落。
"MYFUNCTION()">點我
寫到控制臺
如果您的瀏覽器支持調試,你可以使用 console.log() 方法在瀏覽器中顯示 JavaScript 值。
瀏覽器中使用 F12 來啟用調試模式, 在調試窗口中點擊 “Console” 菜單。
nbsp;html>
我的第一個 Web 頁面
實例 console 截圖:
您知道嗎?
程序中調試是測試,查找及減少bug(錯誤)的過程。
avaScript 輸出
JavaScript 不提供任何內建的打印或顯示函數。
JavaScript 能夠以不同方式“顯示”數據:
如需訪問 HTML 元素,JavaScript 可使用 document.getElementById(id) 方法。
id 屬性定義 HTML 元素。innerHTML 屬性定義 HTML 內容:
<!DOCTYPE html>
<html>
<body>
<h1>我的第一張網頁</h1>
<p>我的第一個段落</p>
<p id="demo"></p>
<script>
document.getElementById("demo").innerHTML = 5 + 6;
</script>
</body>
</html>
出于測試目的,使用 document.write() 比較方便:
<!DOCTYPE html>
<html>
<body>
<h1>我的第一張網頁</h1>
<p>我的第一個段落</p>
<script>
document.write(5 + 6);
</script>
</body>
</html>
注意:在 HTML 文檔完全加載后使用 document.write() 將刪除所有已有的 HTML :
<!DOCTYPE html>
<html>
<body>
<h1>我的第一張網頁</h1>
<p>我的第一個段落</p>
<button onclick="document.write(5 + 6)">試一試</button>
</body>
</html>
提示:document.write() 方法僅用于測試。
您能夠使用警告框來顯示數據:
<!DOCTYPE html>
<html>
<body>
<h1>我的第一張網頁</h1>
<p>我的第一個段落</p>
<script>
window.alert(5 + 6);
</script>
</body>
</html>
在瀏覽器中,您可使用 console.log() 方法來顯示數據。
請通過 F12 來激活瀏覽器控制臺,并在菜單中選擇“控制臺”。
<!DOCTYPE html>
<html>
<body>
<h1>我的第一張網頁</h1>
<p>我的第一個段落</p>
<script>
console.log(5 + 6);
</script>
</body>
</html>
親自試一試
SpringBoot對所有內部日志使用通用日志記錄,但保留底層日志實現。為Java Util Logging、Log4J2和Logback提供了默認配置。在不同的情況下,日志記錄器都預先配置為使用控制臺輸出,同時還提供可選的文件輸出。默認情況下,SpringBoot使用Logback進行日志記錄。
日志級別有(從高到低):FATAL(致命),ERROR(錯誤),WARN(警告),INFO(信息),DEBUG(調試),TRACE(跟蹤)或者 OFF(關閉),默認的日志配置在消息寫入時將消息回顯到控制臺。默認情況下,將記錄錯誤級別、警告級別和信息級別的消息。
PS:Logback does not have a FATAL level. It is mapped to ERROR Logback沒有FATAL致命級別。它被映射到ERROR錯誤級別
詳情請戳官方文檔:https://docs.spring.io/spring-boot/docs/2.1.5.RELEASE/reference/htmlsingle/#boot-features-logging
本文主要記錄Logback日志輸出到文件以及實時輸出到web頁面
我們創建SpringBoot項目時,spring-boot-starter已經包含了spring-boot-starter-logging,不需要再進行引入依賴
2014-03-05 10:57:51.112 INFO 45469 --- [ main] org.apache.catalina.core.StandardEngine : Starting Servlet Engine: Apache Tomcat/7.0.52
2014-03-05 10:57:51.253 INFO 45469 --- [ost-startStop-1] o.a.c.c.C.[Tomcat].[localhost].[/] : Initializing Spring embedded WebApplicationContext
2014-03-05 10:57:51.253 INFO 45469 --- [ost-startStop-1] o.s.web.context.ContextLoader : Root WebApplicationContext: initialization completed in 1358 ms
2014-03-05 10:57:51.698 INFO 45469 --- [ost-startStop-1] o.s.b.c.e.ServletRegistrationBean : Mapping servlet: 'dispatcherServlet' to [/]
2014-03-05 10:57:51.702 INFO 45469 --- [ost-startStop-1] o.s.b.c.embedded.FilterRegistrationBean : Mapping filter: 'hiddenHttpMethodFilter' to: [/*]
如何打印日志?
方法1
/**
* 配置內部類
*/
@Controller
@Configuration
class Config {
/**
* 獲取日志對象,構造函數傳入當前類,查找日志方便定位
*/
private final Logger log = LoggerFactory.getLogger(this.getClass());
@Value("${user.home}")
private String userName;
/**
* 端口
*/
@Value("${server.port}")
private String port;
/**
* 啟動成功
*/
@Bean
public ApplicationRunner applicationRunner() {
return applicationArguments -> {
try {
InetAddress ia = InetAddress.getLocalHost();
//獲取本機內網IP
log.info("啟動成功:" + "http://" + ia.getHostAddress() + ":" + port + "/");
log.info("${user.home} :" + userName);
} catch (UnknownHostException ex) {
ex.printStackTrace();
}
};
}
}
方法2 使用lombok的@Slf4j,幫我們創建Logger對象,效果與方法1一樣
/**
* 配置內部類
*/
@Controller
@Configuration
class Config {
/**
* 獲取日志對象,構造函數傳入當前類,查找日志方便定位
*/
private final Logger log = LoggerFactory.getLogger(this.getClass());
@Value("${user.home}")
private String userName;
/**
* 端口
*/
@Value("${server.port}")
private String port;
/**
* 啟動成功
*/
@Bean
public ApplicationRunner applicationRunner() {
return applicationArguments -> {
try {
InetAddress ia = InetAddress.getLocalHost();
//獲取本機內網IP
log.info("啟動成功:" + "http://" + ia.getHostAddress() + ":" + port + "/");
log.info("${user.home} :" + userName);
} catch (UnknownHostException ex) {
ex.printStackTrace();
}
};
}
}
如果不需要進行復雜的日志配置,則在配置文件中進行簡單的日志配置即可,默認情況下,SpringBoot日志只記錄到控制臺,不寫日志文件。如果希望在控制臺輸出之外編寫日志文件,則需要進行配置
logging:
path: /Users/Administrator/Desktop/雜七雜八/ims #日志文件路徑
file: ims.log #日志文件名稱
level:
root: info #日志級別 root表示所有包,也可以單獨配置具體包 fatal error warn info debug trace off
重新啟動項目
打開ims.log
Spring Boot包含許多Logback擴展,可以幫助進行高級配置。您可以在您的logback-spring.xml配置文件中使用這些擴展。如果需要比較復雜的配置,建議使用擴展配置的方式
PS:SpringBoot推薦我們使用帶-spring后綴的 logback-spring.xml 擴展配置,因為默認的的logback.xml標準配置,Spring無法完全控制日志初始化。(spring擴展對springProfile節點的支持)
以下是項目常見的完整logback-spring.xml,SpringBoot默認掃描classpath下面的logback.xml、logback-spring.xml,所以不需要再指定spring.logging.config,當然,你指定也沒有問題
logging:
config: classpath:logback-spring.xml
<?xml version="1.0" encoding="UTF-8"?>
<configuration debug="false">
<!--日志文件主目錄:這里${user.home}為當前服務器用戶主目錄-->
<property name="LOG_HOME" value="${user.home}/log"/>
<!--日志文件名稱:這里spring.application.name表示工程名稱-->
<springProperty scope="context" name="APP_NAME" source="spring.application.name"/>
<!--默認配置-->
<include resource="org/springframework/boot/logging/logback/defaults.xml"/>
<!--配置控制臺(Console)-->
<include resource="org/springframework/boot/logging/logback/console-appender.xml"/>
<!--配置日志文件(File)-->
<appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<!--設置策略-->
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!--日志文件路徑:這里%d{yyyyMMdd}表示按天分類日志-->
<FileNamePattern>${LOG_HOME}/%d{yyyyMMdd}/${APP_NAME}.log</FileNamePattern>
<!--日志保留天數-->
<MaxHistory>15</MaxHistory>
</rollingPolicy>
<!--設置格式-->
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
<!--格式化輸出:%d表示日期,%thread表示線程名,%-5level:級別從左顯示5個字符寬度%msg:日志消息,%n是換行符-->
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern>
<!-- 或者使用默認配置 -->
<!--<pattern>${FILE_LOG_PATTERN}</pattern>-->
<charset>utf8</charset>
</encoder>
<!--日志文件最大的大小-->
<triggeringPolicy class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy">
<MaxFileSize>100MB</MaxFileSize>
</triggeringPolicy>
</appender>
<!-- 多環境配置 按照active profile選擇分支 -->
<springProfile name="dev">
<!--root節點 全局日志級別,用來指定最基礎的日志輸出級別-->
<root level="INFO">
<appender-ref ref="FILE"/>
<appender-ref ref="CONSOLE"/>
</root>
<!-- 子節點向上級傳遞 局部日志級別-->
<logger level="WARN" name="org.springframework"/>
<logger level="WARN" name="com.netflix"/>
<logger level="DEBUG" name="org.hibernate.SQL"/>
</springProfile>
<springProfile name="prod">
</springProfile>
</configuration>
啟動項目,去到${user.home}當前服務器用戶主目錄,日志按日期進行產生,如果項目產生的日志文件比較大,還可以按照小時進行.log文件的生成
2021-02-24更新:
如果需要按日志級別分別輸出到對應的日志文件,在appender標簽新增filter標簽進行指定
<!-- 時間滾動輸出 level為 【debug / info / warn / error】 日志 -->
<appender name="【DEBUG / INFO / WARN / ERROR】_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<!-- 忽略其他配置 -->
<!-- 此日志文件只記錄 【debug / info / warn / error】 級別的 -->
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<level>【debug / info / warn / error】</level>
<onMatch>ACCEPT</onMatch>
<onMismatch>DENY</onMismatch>
</filter>
</appender>
我們已經有日志文件.log了,為什么還要這個功能呢?(滑稽臉)為了偷懶!
當我們把項目部署到Linux服務器,當你想看日志文件,還得打開xshell連接,定位到log文件夾,麻煩;如果我們把日志輸出到Web頁面,當做超級管理員或者測試賬號下面的一個功能,點擊就開始實時獲取生成的日志并輸出在Web頁面,是不是爽很多呢?
PS:這個功能可得小心使用,因為日志會暴露很多信息
使用WebSocket實現實時獲取,建立WebSocket連接后創建一個線程任務,每秒讀取一次最新的日志文件,第一次只取后面200行,后面取相比上次新增的行,為了在頁面上更加方便的閱讀日志,對日志級別單詞進行著色(PS:如何創建springboot的websocket,請戳:SpringBoot系列——WebSocket)
package cn.huanzi.qch.springbootlogback;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.thymeleaf.util.StringUtils;
import javax.websocket.*;
import javax.websocket.server.ServerEndpoint;
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Date;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
/**
* WebSocket獲取實時日志并輸出到Web頁面
*/
@Slf4j
@Component
@ServerEndpoint(value = "/websocket/logging", configurator = MyEndpointConfigure.class)
public class LoggingWSServer {
@Value("${spring.application.name}")
private String applicationName;
/**
* 連接集合
*/
private static Map<String, Session> sessionMap = new ConcurrentHashMap<String, Session>();
private static Map<String, Integer> lengthMap = new ConcurrentHashMap<String, Integer>();
/**
* 連接建立成功調用的方法
*/
@OnOpen
public void onOpen(Session session) {
//添加到集合中
sessionMap.put(session.getId(), session);
lengthMap.put(session.getId(), 1);//默認從第一行開始
//獲取日志信息
new Thread(() -> {
log.info("LoggingWebSocketServer 任務開始");
boolean first = true;
while (sessionMap.get(session.getId()) != null) {
BufferedReader reader = null;
try {
//日志文件路徑,獲取最新的
String filePath = System.getProperty("user.home") + "/log/" + new SimpleDateFormat("yyyyMMdd").format(new Date()) + "/"+applicationName+".log";
//字符流
reader = new BufferedReader(new FileReader(filePath));
Object[] lines = reader.lines().toArray();
//只取從上次之后產生的日志
Object[] copyOfRange = Arrays.copyOfRange(lines, lengthMap.get(session.getId()), lines.length);
//對日志進行著色,更加美觀 PS:注意,這里要根據日志生成規則來操作
for (int i = 0; i < copyOfRange.length; i++) {
String line = (String) copyOfRange[i];
//先轉義
line = line.replaceAll("&", "&")
.replaceAll("<", "<")
.replaceAll(">", ">")
.replaceAll("\"", """);
//處理等級
line = line.replace("DEBUG", "<span style='color: blue;'>DEBUG</span>");
line = line.replace("INFO", "<span style='color: green;'>INFO</span>");
line = line.replace("WARN", "<span style='color: orange;'>WARN</span>");
line = line.replace("ERROR", "<span style='color: red;'>ERROR</span>");
//處理類名
String[] split = line.split("]");
if (split.length >= 2) {
String[] split1 = split[1].split("-");
if (split1.length >= 2) {
line = split[0] + "]" + "<span style='color: #298a8a;'>" + split1[0] + "</span>" + "-" + split1[1];
}
}
copyOfRange[i] = line;
}
//存儲最新一行開始
lengthMap.put(session.getId(), lines.length);
//第一次如果太大,截取最新的200行就夠了,避免傳輸的數據太大
if(first && copyOfRange.length > 200){
copyOfRange = Arrays.copyOfRange(copyOfRange, copyOfRange.length - 200, copyOfRange.length);
first = false;
}
String result = StringUtils.join(copyOfRange, "<br/>");
//發送
send(session, result);
//休眠一秒
Thread.sleep(1000);
} catch (Exception e) {
//捕獲但不處理
e.printStackTrace();
} finally {
try {
reader.close();
} catch (IOException ignored) {
}
}
}
log.info("LoggingWebSocketServer 任務結束");
}).start();
}
/**
* 連接關閉調用的方法
*/
@OnClose
public void onClose(Session session) {
//從集合中刪除
sessionMap.remove(session.getId());
lengthMap.remove(session.getId());
}
/**
* 發生錯誤時調用
*/
@OnError
public void onError(Session session, Throwable error) {
error.printStackTrace();
}
/**
* 服務器接收到客戶端消息時調用的方法
*/
@OnMessage
public void onMessage(String message, Session session) {
}
/**
* 封裝一個send方法,發送消息到前端
*/
private void send(Session session, String message) {
try {
session.getBasicRemote().sendText(message);
} catch (Exception e) {
e.printStackTrace();
}
}
}
頁面收到數據就追加到div中,為了方便新增了幾個功能:
清屏,清空div內容
滾動至底部、將div的滾動條滑到最下面
開啟/關閉自動滾動,div新增內容后自動將滾動條滑到最下面,點一下開啟,再點關閉,默認關閉
PS:引入公用部分,就是一些jquery等常用靜態資源
<!DOCTYPE>
<!--解決idea thymeleaf 表達式模板報紅波浪線-->
<!--suppress ALL -->
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>IMS實時日志</title>
<!-- 引入公用部分 -->
<script th:replace="head::static"></script>
</head>
<body>
<!-- 標題 -->
<h1 style="text-align: center;">IMS實時日志</h1>
<!-- 顯示區 -->
<div id="loggingText" contenteditable="true"
style="width:100%;height: 600px;background-color: ghostwhite; overflow: auto;"></div>
<!-- 操作欄 -->
<div style="text-align: center;">
<button onclick="$('#loggingText').text('')" style="color: green; height: 35px;">清屏</button>
<button onclick="$('#loggingText').animate({scrollTop:$('#loggingText')[0].scrollHeight});"
style="color: green; height: 35px;">滾動至底部
</button>
<button onclick="if(window.loggingAutoBottom){$(this).text('開啟自動滾動');}else{$(this).text('關閉自動滾動');};window.loggingAutoBottom = !window.loggingAutoBottom"
style="color: green; height: 35px; ">開啟自動滾動
</button>
</div>
</body>
<script th:inline="javascript">
//websocket對象
let websocket = null;
//判斷當前瀏覽器是否支持WebSocket
if ('WebSocket' in window) {
websocket = new WebSocket("ws://localhost:10086/websocket/logging");
} else {
console.error("不支持WebSocket");
}
//連接發生錯誤的回調方法
websocket.onerror = function (e) {
console.error("WebSocket連接發生錯誤");
};
//連接成功建立的回調方法
websocket.onopen = function () {
console.log("WebSocket連接成功")
};
//接收到消息的回調方法
websocket.onmessage = function (event) {
//追加
if (event.data) {
//日志內容
let $loggingText = $("#loggingText");
$loggingText.append(event.data);
//是否開啟自動底部
if (window.loggingAutoBottom) {
//滾動條自動到最底部
$loggingText.scrollTop($loggingText[0].scrollHeight);
}
}
}
//連接關閉的回調方法
websocket.onclose = function () {
console.log("WebSocket連接關閉")
};
</script>
</html>
有了日志記錄,我們以后寫代碼時就要注意了,應使用下面的正確示例
//錯誤示例,這樣寫只會輸出到控制臺,不會輸出到日志中
System.out.println("XXX");
e.printStackTrace();
//正確示例,既輸出到控制臺,又輸出到日志
log.info("XXX");
log.error("XXX報錯",e);
SpringBoot日志暫時先記錄到這里,點擊官網了解更多:https://docs.spring.io/spring-boot/docs/2.1.5.RELEASE/reference/htmlsingle/#boot-features-logging
2019-07-03補充:我們之前只對日志等級關鍵字進行著色,還是覺得不夠,因此又新增了類名著色跟HTML轉義
主要修改:
效果:
2019-08-12補充:我發現有時候顯示的時候,換行不太準確,我們原先是在行末追加<br/>,但有時候讀取出來的一行記錄是自動換行后的數據,頁面顯示效果很丑
因此我改成用正則([\d+][\d+][\d+][\d+]-[\d+][\d+]-[\d+][\d+] [\d+][\d+]:[\d+][\d+]:[\d+][\d+])去匹配日期,然后再對應的起始下標插入<br/>,從而達到與控制臺輸出類似的效果
匹配、插入結果
頁面效果
異步輸出日志
異步輸出日志的方式很簡單,添加一個基于異步寫日志的appender,并指向原先配置的appender即可
<!-- 將文件輸出設置成異步輸出 -->
<appender name="ASYNC-FILE" class="ch.qos.logback.classic.AsyncAppender">
<!-- 不丟失日志.默認的,如果隊列的80%已滿,則會丟棄TRACT、DEBUG、INFO級別的日志 -->
<discardingThreshold>0</discardingThreshold>
<!-- 更改默認的隊列的深度,該值會影響性能.默認值為256 -->
<queueSize>256</queueSize>
<!-- 添加附加的appender,最多只能添加一個 -->
<appender-ref ref="FILE"/>
</appender>
<!-- 將控制臺輸出設置成異步輸出 -->
<appender name="ASYNC-CONSOLE" class="ch.qos.logback.classic.AsyncAppender">
<!-- 不丟失日志.默認的,如果隊列的80%已滿,則會丟棄TRACT、DEBUG、INFO級別的日志 -->
<discardingThreshold>0</discardingThreshold>
<!-- 更改默認的隊列的深度,該值會影響性能.默認值為256 -->
<queueSize>256</queueSize>
<!-- 添加附加的appender,最多只能添加一個 -->
<appender-ref ref="CONSOLE"/>
</appender>
原理很簡單,主線程將日志扔到阻塞隊列中,然后IO操作日志寫入文件是通過新起一個線程去完成的
2020-05-26補充
e.printStackTrace();會打出詳細異常,異常名稱,出錯位置,便于調試用,但直接調用會輸出到std.err,并沒有輸出到日志文件中,因此需要先輸出到流中再轉成字符串
封裝工具類
import java.io.IOException;
import java.io.PrintWriter;
import java.io.StringWriter;
/**
* 捕獲報錯日志處理工具類
*/
public class ErrorUtil {
/**
* Exception出錯的棧信息轉成字符串
* 用于打印到日志中
*/
public static String errorInfoToString(Throwable e) {
StringWriter sw = null;
PrintWriter pw = null;
try {
sw = new StringWriter();
pw = new PrintWriter(sw);
// 將出錯的棧信息輸出到printWriter中
e.printStackTrace(pw);
pw.flush();
sw.flush();
} finally {
if (sw != null) {
try {
sw.close();
} catch (IOException e1) {
e1.printStackTrace();
}
}
if (pw != null) {
pw.close();
}
}
return sw.toString();
}
}
也可以使用騷操作簡化代碼
public static String errorInfoToString(Throwable e) {
//try-with-resource語法糖 處理機制
try(StringWriter sw = new StringWriter();PrintWriter pw = new PrintWriter(sw)){
e.printStackTrace(pw);
pw.flush();
sw.flush();
return sw.toString();
}catch (Exception ignored){
throw new RuntimeException(ignored.getMessage(),ignored);
}
}
使用
try {
//省略其他代碼
} catch (Throwable e) {
//之前的操作,輸出控制臺
e.printStackTrace();
//輸出到日志文件中
log.error(ErrorUtil.errorInfoToString(e));
}
2020-08-04更新
SpringBoot默認使用內置Tomcat,那么我們如何配置Tomcat的Access Logging呢?
詳情可查看官方文檔:
SpringBoot配置介紹:https://docs.spring.io/spring-boot/docs/2.1.0.RELEASE/reference/htmlsingle/#howto-configure-accesslogs
Apache Tomcat配置介紹:https://tomcat.apache.org/tomcat-8.5-doc/config/valve.html#Access_Logging
SpringBoot對Access Log的默認配置
server.tomcat.accesslog.buffered=true # Whether to buffer output such that it is flushed only periodically.
server.tomcat.accesslog.directory=logs # Directory in which log files are created. Can be absolute or relative to the Tomcat base dir.
server.tomcat.accesslog.enabled=false # Enable access log.
server.tomcat.accesslog.file-date-format=.yyyy-MM-dd # Date format to place in the log file name.
server.tomcat.accesslog.pattern=common # Format pattern for access logs.
server.tomcat.accesslog.prefix=access_log # Log file name prefix.
server.tomcat.accesslog.rename-on-rotate=false # Whether to defer inclusion of the date stamp in the file name until rotate time.
server.tomcat.accesslog.request-attributes-enabled=false # Set request attributes for the IP address, Hostname, protocol, and port used for the request.
server.tomcat.accesslog.rotate=true # Whether to enable access log rotation.
server.tomcat.accesslog.suffix=.log # Log file name suffix.
日志格式說明(摘自上方Apache Tomcat配置介紹官方文檔)
Values for the pattern attribute are made up of literal text strings, combined with pattern identifiers prefixed by the "%" character to cause replacement by the corresponding variable value from the current request and response. The following pattern codes are supported:
There is also support to write information incoming or outgoing headers, cookies, session or request attributes and special timestamp formats. It is modeled after the Apache HTTP Server log configuration syntax. Each of them can be used multiple times with different xxx keys:
All formats supported by SimpleDateFormat are allowed in %{xxx}t. In addition the following extensions have been added:
These formats cannot be mixed with SimpleDateFormat formats in the same format token.
Furthermore one can define whether to log the timestamp for the request start time or the response finish time:
By adding multiple %{xxx}t tokens to the pattern, one can also log both timestamps.
The shorthand pattern pattern="common" corresponds to the Common Log Format defined by '%h %l %u %t "%r" %s %b'.
The shorthand pattern pattern="combined" appends the values of the Referer and User-Agent headers, each in double quotes, to the common pattern.
When Tomcat is operating behind a reverse proxy, the client information logged by the Access Log Valve may represent the reverse proxy, the browser or some combination of the two depending on the configuration of Tomcat and the reverse proxy. For Tomcat configuration options see Proxies Support and the Proxy How-To. For reverse proxies that use mod_jk, see the generic proxy documentation. For other reverse proxies, consult their documentation.
我們只需要配置以下幾個簡單配置即可
#開啟內置Tomcat請求日志 access.log
server.tomcat.accesslog.enabled=true
#日志格式
server.tomcat.accesslog.pattern=%h %l %u %t "%r" %s %b
#日志輸出目錄
server.tomcat.accesslog.directory=${user.home}/log/accesslog/${spring.application.name}
#日志文件名
server.tomcat.accesslog.prefix=access_log
server.tomcat.accesslog.file-date-format=_yyyy-MM-dd
server.tomcat.accesslog.suffix=.log
效果
如何接口統計QPS?
如上圖中,logging接口,我們只要統計同一秒中,logging接口的請求次數即是該接口的QPS
代碼已經開源、托管到我的GitHub、碼云:
GitHub:https://github.com/huanzi-qch/springBoot
碼云:https://gitee.com/huanzi-qch/springBoot
作者:huanzi-qch
出處:https://www.cnblogs.com/huanzi-qch
若標題中有“轉載”字樣,則本文版權歸原作者所有。若無轉載字樣,本文版權歸作者所有,歡迎轉載,但未經作者同意必須保留此段聲明,且在文章頁面明顯位置給出原文鏈接,否則保留追究法律責任的權利.
*請認真填寫需求信息,我們會在24小時內與您取得聯系。