之前看网站日志什么的都得连接服务器输入命令才能查看,非常麻烦,今天利用websocket来进行日志实时查看。
maven依赖:
<!-- springboot整合websocket -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-websocket</artifactId>
</dependency>
后端代码:
1、注入serverEndpointExporter
@Configuration
public class WebSocketConfig {
@Bean
public ServerEndpointExporter serverEndpointExporter() {
return new ServerEndpointExporter();
}
}
2、TailLogThread类
import javax.websocket.Session;
import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
/**
* @className: TailLogThread
* @description: TailLogThread
* @author: xiaofei
* @create: 2020年01月04日
*/
public class TailLogThread extends Thread {
private BufferedReader reader;
private Session session;
public TailLogThread(InputStream in, Session session) {
this.reader = new BufferedReader(new InputStreamReader(in));
this.session = session;
}
@Override
public void run() {
String line;
try {
while ((line = reader.readLine()) != null) {
if (session.isOpen()) {
// 将实时日志通过WebSocket发送给客户端,给每一行添加一个Html换行
session.getBasicRemote().sendText(line + "<br>");
try {
// 每0.5秒执行一次
Thread.sleep(500);
} catch (Exception e) {
e.printStackTrace();
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
3、注入serverEndpointExporter
@Component
@ServerEndpoint("xxxxxx")
public class TailLogWebSocket {
private final static Logger logger = LoggerFactory.getLogger(TailLogWebSocket.class);
private Process process;
private InputStream inputStream;
@OnOpen
public void onOpen(Session session) {
logger.info("连接建立成功");
logger.debug("debug日志测试");
logger.warn("warn日志测试");
logger.error("warn日志测试");
try {
// 这个是日志存放路径,我写在了yml里面
String logPath = "";
logPath = logPath.split("&")[0];
String temp = "local";
// 获取项目运行yml的后缀,如 pro test..
String activeProfile = "";
// 我这里只有两个环境,一个测试环境一个生产环境
if (temp.equals(activeProfile)) {
// 这里是windows读取方法
File file = new File(logPath);
FileInputStream fileInputStream = new FileInputStream(file);
TailLogThread thread = new TailLogThread(fileInputStream, session);
thread.start();
} else {
// 这里是Linux读取方法
process = Runtime.getRuntime().exec(logPath);
inputStream = process.getInputStream();
TailLogThread thread = new TailLogThread(inputStream, session);
thread.start();
}
} catch (IOException e) {
logger.error("WebSocket读取日志出错:", e);
e.printStackTrace();
}
}
@OnMessage
public void OnMessage(String msg) {
logger.info("发送消息:{}", msg);
}
@OnClose
public void onClose() {
logger.info("连接关闭");
try {
if (inputStream != null) {
inputStream.close();
}
} catch (Exception e) {
e.printStackTrace();
}
if (process != null) {
process.destroy();
}
}
@OnError
public void onError(Throwable thr) {
logger.error("WebSocket发生错误:", thr);
}
}
这里说一下logPath,由于我的生产环境是在linux所以需要弄两份。&后面的我下面会讲怎么填写。
如果你是本地运行只需要填写 127.0.0.1:项目端口号 即可。
linux查看日志: tail -90f /java/xxxx.out&xxxxx/wss
windows查看日志:E:\IdeaProjects\aliyun\logs\xxxxx.log&127.0.0.1
前端html
前端页面,根据自己需求进行设置样式。里面我用了一个th标签用来回显WebSocket地址用的。
<div class="container-div">
<div class="col-sm-12 search-collapse">
<div class="select-list">
<ul>
<li>
监控地址:<input type="text" style="width: 350px;" id="wsServerUrl" name="wsServerUrl"
th:value="${wsServerUrl}"/>
</li>
<li>
<a class="btn btn-primary btn-rounded btn-sm" onclick="addWebSocket();" id="openLog"><i
class="fa fa-refresh"></i> 开始监控</a>
</li>
<li>
<a class="btn btn-warning btn-rounded btn-sm" onclick="closeWebSocket();" id="stopLog"><i
class="fa fa-remove"></i> 停止监控</a>
</li>
<li>
<a class="btn btn-danger btn-rounded btn-sm" onclick="emptyWebScoket();" id="cleanLog"><i
class="fa fa-trash"></i> 清空日志</a>
</li>
</ul>
</div>
</div>
<div class="container-div ui-layout-center">
<div class="row">
<div class="col-sm-12 select-table table-striped">
<div id="log-container">
<div>
</div>
</div>
</div>
</div>
</div>
</div>
前端js
<script>
var websocket;
var wsaddr;
/**
* 开启
*/
function addWebSocket() {
var wsaddr = $("#wsServerUrl").val();
if (wsaddr == '') {
$.modal.msgWarning("请填写WebSocket的地址");
return false;
}
StartWebSocket(wsaddr);
}
/**
* 关闭
*/
function closeWebSocket() {
if (websocket) {
if (websocket.readyState === 3) {
$.modal.msgWarning("已断开");
return
}
if (websocket.readyState === 0) {
$.modal.msgWarning("连接中...");
return
}
websocket.close();
} else {
$.modal.msgWarning("还未建立连接");
}
}
/**
* 缓存
*/
$(function () {
var ws_adr = window.localStorage.getItem("bejson_ws_adr");
if (ws_adr != null && ws_adr != "") {
wsaddr.value = ws_adr;
}
})
/**
* 清空
*/
function emptyWebScoket() {
$("#log-container div").empty();
window.localStorage.removeItem('bejson_ws_adr')
}
function StartWebSocket(wsUri) {
if (websocket && websocket.readyState === 2) {
$.modal.msgWarning("断开中...");
return
}
try {
websocket = new WebSocket(wsUri);
websocket.onopen = function (evt) {
onOpen(evt);
};
websocket.onclose = function (evt) {
onClose(evt);
};
websocket.onmessage = function (evt) {
onMessage(evt)
};
websocket.onerror = function (evt) {
onError(evt)
};
} catch (e) {
$.modal.msgWarning("错误的WebSocket链接");
}
}
function onOpen(evt) {
writeToScreen("<span style='color:#14ff00;'>连接成功建立!!!</span></br>");
}
function onClose(evt) {
writeToScreen("<span style='color:red;'>WebSocket连接已断开!!!</span></br>");
websocket.close();
}
function onMessage(evt) {
let msg = evt.data;
if (msg.indexOf('INFO') > 0) {
msg = '<p style="color: #aaa;">' + msg + '</p>';
} else if (msg.indexOf('WARN') > 0) {
msg = '<p style="color: #FFB800;">' + msg + '</p>';
} else if (msg.indexOf('ERROR') > 0) {
msg = '<p style="color: #ff3a00;">' + msg + '</p>';
} else if (msg.indexOf('DEBUG') > 0) {
msg = '<p style="color: #09ff02;">' + msg + '</p>';
}
writeToScreen(msg);
}
function onError(evt) {
writeToScreen('<span style="color: red;">发生错误:</span> ' + evt.data);
}
/**
* 打印输输出
*/
function writeToScreen(message) {
$("#log-container div").append(message);
// 滚动条滚动到最低部
$("#log-container").scrollTop($("#log-container div").height() - $("#log-container").height());
}
</script>
Nginx配置
如果你网站的域名是Https,WebSocket也必须配置证书。
linux查看日志: tail -90f /java/xxxx.out&xxxxx/wss
说一下上面&后面配置:
项目不是https协议,直接用服务器ip+项目端口号即可。
xxxx.out&127.0.0.1:8080/wss
项目是https协议,WebSocket域名 + wss。域名不要加前缀 https://
xxxx.out&域名/wss
server{
listen 80;
listen 443 ssl http2;
server_name 自己的域名;
# 强制跳转https
if ($server_port !~ 443){
rewrite ^(/.*)$ https://$host$1 permanent;
}
#HTTP_TO_HTTPS_END
# 证书pem
ssl_certificate /1.pem;
# 证书key
ssl_certificate_key /1.key;
ssl_protocols TLSv1.1 TLSv1.2 TLSv1.3;
ssl_ciphers EECDH+CHACHA20:EECDH+CHACHA20-draft:EECDH+AES128:RSA+AES128:EECDH+AES256:RSA+AES256:EECDH+3DES:RSA+3DES:!MD5;
ssl_prefer_server_ciphers on;
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 10m;
add_header Strict-Transport-Security "max-age=31536000";
error_page 497 https://$host$request_uri;
# 访问就是 xxx.com/wss
location /wss/ {
proxy_pass http://127.0.0.1:8080/;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "Upgrade";
proxy_set_header X-real-ip $remote_addr;
proxy_set_header X-Forwarded-For $remote_addr;
}
# 禁止访问的文件或目录
location ~ ^/(\.user.ini|\.htaccess|\.git|\.svn|\.project|LICENSE|README.md)
{
return 404;
}
#一键申请SSL证书验证目录相关设置
location ~ \.well-known{
allow all;
}
}
效果
上面页面监控地址填写配置:
后面的wss就是下面nginx里面的配置wss,可以自行更改,只要保持一致即可。
不是https:ws://ip地址:项目端口号/wss
是https:wss://域名/wss
如果你的项目域名用了CDN,则就不能作为WebSocket的连接地址。
如果项目用了CDN解决办法: 在开一个二级域名。
打赏
当前共有 0 条评论