tambah html log 18/12/2024

This commit is contained in:
2024-12-18 12:10:18 +07:00
parent fd17185398
commit 8047155417
10 changed files with 289 additions and 15 deletions

View File

@@ -1,4 +1,11 @@
exception=unpack, strip: jdk.internal
writer=console
writer.exception=drop cause
writer.format={date:dd-MM-yyyy HH:mm:ss} {class}.{method}() : {message}
writerConsole=console
writerConsole.level=info
writerConsole.format={date:dd-MM-yyyy HH:mm:ss} {class}.{method}() :\n{message}
writerFile=rolling file
writerFile.file=logs/{date:dd-MM-yyyy}.{count}.log
writerFile.level=info
writerFile.charset=UTF-8
writerFile.append=true
writerFile.policies=daily
writerFile.format={date:dd-MM-yyyy HH:mm:ss}\t{class}.{method}() :\t{message}

View File

@@ -167,4 +167,60 @@ function loginload(){
if (socket && socket.connected) {
socket.disconnect();
}
}
function logload(){
console.log("Log loaded");
if (socket && socket.connected) {
socket.disconnect();
}
getLogFiles();
$('#logfiles').change(function(){
let logname = $('#logfiles').val();
if (logname && logname.length>0){
getLogData(logname);
}
});
}
function getLogFiles(){
fetch('/logfiles', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
}
}).then((response)=>{
response.json().then((data)=>{
let logList = $('#logfiles');
logList.empty();
logList.append('<option value="">Select Logfile</option>');
data.forEach((log)=>{
logList.append('<option value="'+log+'">'+log+'</option>');
});
});
});
}
function getLogData(logname){
fetch('/logdata', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: logname
}).then((response)=>{
response.json().then((data)=>{
let tablebody = $('#tablebody');
tablebody.empty();
data.forEach((log)=>{
let str = '<tr>';
str += '<td>'+log.Date+'</td>';
str += '<td>'+log.Time+'</td>';
str += '<td>'+log.Method+'</td>';
str += '<td>'+log.Message+'</td>';
str += '</tr>';
tablebody.append(str);
});
});
});
}

View File

@@ -27,6 +27,7 @@
<ul class="navbar-nav me-auto">
<li class="nav-item"><a class="nav-link active" href="#">Overview</a></li>
<li class="nav-item"><a class="nav-link" href="setting.html">Setting</a></li>
<li class="nav-item"><a class="nav-link" href="log.html">Log</a></li>
</ul>
<div class="d-md-none my-2"><button class="btn btn-light me-2" type="button">Button</button><button class="btn btn-primary" type="button">Button</button></div>
</div>
@@ -85,8 +86,8 @@
<div class="col"><input type="text" id="dialNumber" name="dialNumber"></div>
<div class="col">
<div class="row">
<div class="col"><button class="btn btn-primary btn-lg" id="dialButton" type="button" onclick="dialClick()">Dial</button></div>
<div class="col"><button class="btn btn-primary btn-lg" id="hangupButton" type="button" onclick="hangupClick()">Hangup</button></div>
<div class="col"><button class="btn btn-primary btn-lg" id="dialButton" type="button">Dial</button></div>
<div class="col"><button class="btn btn-primary btn-lg" id="hangupButton" type="button">Hangup</button></div>
</div>
</div>
</div>

View File

@@ -0,0 +1,87 @@
<!DOCTYPE html>
<html data-bs-theme="light" lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, shrink-to-fit=no">
<title>SIPIntercom</title>
<link rel="stylesheet" href="assets/bootstrap/css/bootstrap.min.css">
<link rel="stylesheet" href="assets/css/Font%20Awesome%205%20Brands.css">
<link rel="stylesheet" href="assets/css/Font%20Awesome%205%20Duotone.css">
<link rel="stylesheet" href="assets/css/Font%20Awesome%205%20Pro.css">
<link rel="stylesheet" href="assets/css/Font%20Awesome%206%20Brands.css">
<link rel="stylesheet" href="assets/css/Font%20Awesome%206%20Duotone.css">
<link rel="stylesheet" href="assets/css/Font%20Awesome%206%20Pro.css">
<link rel="stylesheet" href="assets/css/FontAwesome.css">
<link rel="stylesheet" href="assets/css/all.min.css">
<link rel="stylesheet" href="assets/css/Navbar-Centered-Brand-icons.css">
</head>
<body onload="logload()">
<nav class="navbar navbar-expand-md bg-body py-3">
<div class="container"><a class="navbar-brand d-flex align-items-center" href="#"><span class="bs-icon-sm bs-icon-rounded bs-icon-primary d-flex justify-content-center align-items-center me-2 bs-icon"><svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" fill="currentColor" viewBox="0 0 16 16" class="bi bi-bezier">
<path fill-rule="evenodd" d="M0 10.5A1.5 1.5 0 0 1 1.5 9h1A1.5 1.5 0 0 1 4 10.5v1A1.5 1.5 0 0 1 2.5 13h-1A1.5 1.5 0 0 1 0 11.5zm1.5-.5a.5.5 0 0 0-.5.5v1a.5.5 0 0 0 .5.5h1a.5.5 0 0 0 .5-.5v-1a.5.5 0 0 0-.5-.5zm10.5.5A1.5 1.5 0 0 1 13.5 9h1a1.5 1.5 0 0 1 1.5 1.5v1a1.5 1.5 0 0 1-1.5 1.5h-1a1.5 1.5 0 0 1-1.5-1.5zm1.5-.5a.5.5 0 0 0-.5.5v1a.5.5 0 0 0 .5.5h1a.5.5 0 0 0 .5-.5v-1a.5.5 0 0 0-.5-.5zM6 4.5A1.5 1.5 0 0 1 7.5 3h1A1.5 1.5 0 0 1 10 4.5v1A1.5 1.5 0 0 1 8.5 7h-1A1.5 1.5 0 0 1 6 5.5zM7.5 4a.5.5 0 0 0-.5.5v1a.5.5 0 0 0 .5.5h1a.5.5 0 0 0 .5-.5v-1a.5.5 0 0 0-.5-.5z"></path>
<path d="M6 4.5H1.866a1 1 0 1 0 0 1h2.668A6.517 6.517 0 0 0 1.814 9H2.5c.123 0 .244.015.358.043a5.517 5.517 0 0 1 3.185-3.185A1.503 1.503 0 0 1 6 5.5zm3.957 1.358A1.5 1.5 0 0 0 10 5.5v-1h4.134a1 1 0 1 1 0 1h-2.668a6.517 6.517 0 0 1 2.72 3.5H13.5c-.123 0-.243.015-.358.043a5.517 5.517 0 0 0-3.185-3.185z"></path>
</svg></span><span>SIP Intercom</span></a><button data-bs-toggle="collapse" class="navbar-toggler" data-bs-target="#navcol-4"><span class="visually-hidden">Toggle navigation</span><span class="navbar-toggler-icon"></span></button>
<div class="collapse navbar-collapse flex-grow-0 order-md-first" id="navcol-4">
<ul class="navbar-nav me-auto">
<li class="nav-item"><a class="nav-link" href="index.html">Overview</a></li>
<li class="nav-item"><a class="nav-link" href="setting.html">Setting</a></li>
<li class="nav-item"><a class="nav-link active" href="#">Log</a></li>
</ul>
<div class="d-md-none my-2"><button class="btn btn-light me-2" type="button">Button</button><button class="btn btn-primary" type="button">Button</button></div>
</div>
<div class="d-none d-md-block">
<form method="GET" action="/logout"><button class="btn btn-light me-2" type="submit">Log Off</button></form>
</div>
</div>
</nav>
<div class="container">
<div class="row">
<div class="col-lg-6">
<p>Log File</p>
</div>
<div class="col-lg-6"><select id="logfiles">
<optgroup label="This is a group">
<option value="12" selected="">This is item 1</option>
<option value="13">This is item 2</option>
<option value="14">This is item 3</option>
</optgroup>
</select></div>
</div>
<div class="row">
<div class="table-responsive">
<table class="table" id="logtable">
<thead>
<tr>
<th>Date</th>
<th>Time</th>
<th>Method</th>
<th>Message</th>
</tr>
</thead>
<tbody id="tablebody">
<tr>
<td>Cell 1</td>
<td>Cell 2</td>
<td>Cell 3</td>
<td>Cell 4</td>
</tr>
<tr>
<td>Cell 3</td>
<td>Cell 4</td>
<td>Cell 3</td>
<td>Cell 4</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
<script src="assets/bootstrap/js/bootstrap.min.js"></script>
<script src="assets/js/jquery-3.7.1.js"></script>
<script src="assets/js/socket.io.js"></script>
<script src="assets/js/app.js"></script>
</body>
</html>

View File

@@ -27,6 +27,7 @@
<ul class="navbar-nav me-auto">
<li class="nav-item"><a class="nav-link" href="index.html">Overview</a></li>
<li class="nav-item"><a class="nav-link active" href="#">Setting</a></li>
<li class="nav-item"><a class="nav-link" href="log.html">Log</a></li>
</ul>
<div class="d-md-none my-2"><button class="btn btn-light me-2" type="button">Button</button><button class="btn btn-primary" type="button">Button</button></div>
</div>
@@ -49,7 +50,7 @@
</div>
<div class="col">
<div class="row">
<div class="col"><button class="btn btn-primary btn-lg" type="button" onclick="sendLoginData()">Save&nbsp;&nbsp;<svg xmlns="http://www.w3.org/2000/svg" viewBox="-32 0 512 512" width="1em" height="1em" fill="currentColor">
<div class="col"><button class="btn btn-primary btn-lg" type="submit">Save&nbsp;&nbsp;<svg xmlns="http://www.w3.org/2000/svg" viewBox="-32 0 512 512" width="1em" height="1em" fill="currentColor">
<!--! Font Awesome Free 6.4.2 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2023 Fonticons, Inc. -->
<path d="M48 96V416c0 8.8 7.2 16 16 16H384c8.8 0 16-7.2 16-16V170.5c0-4.2-1.7-8.3-4.7-11.3l33.9-33.9c12 12 18.7 28.3 18.7 45.3V416c0 35.3-28.7 64-64 64H64c-35.3 0-64-28.7-64-64V96C0 60.7 28.7 32 64 32H309.5c17 0 33.3 6.7 45.3 18.7l74.5 74.5-33.9 33.9L320.8 84.7c-.3-.3-.5-.5-.8-.8V184c0 13.3-10.7 24-24 24H104c-13.3 0-24-10.7-24-24V80H64c-8.8 0-16 7.2-16 16zm80-16v80H272V80H128zm32 240a64 64 0 1 1 128 0 64 64 0 1 1 -128 0z"></path>
</svg></button></div>
@@ -76,7 +77,7 @@
<div class="col"><input class="form-control" type="text" id="sipPassword" name="sipPassword" placeholder="SIP Password"></div>
</div>
<div class="row">
<div class="col"><button class="btn btn-primary btn-lg" type="button" onclick="sendSipData()">Save&nbsp;&nbsp;<svg xmlns="http://www.w3.org/2000/svg" viewBox="-32 0 512 512" width="1em" height="1em" fill="currentColor">
<div class="col"><button class="btn btn-primary btn-lg" type="submit">Save&nbsp;&nbsp;<svg xmlns="http://www.w3.org/2000/svg" viewBox="-32 0 512 512" width="1em" height="1em" fill="currentColor">
<!--! Font Awesome Free 6.4.2 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2023 Fonticons, Inc. -->
<path d="M48 96V416c0 8.8 7.2 16 16 16H384c8.8 0 16-7.2 16-16V170.5c0-4.2-1.7-8.3-4.7-11.3l33.9-33.9c12 12 18.7 28.3 18.7 45.3V416c0 35.3-28.7 64-64 64H64c-35.3 0-64-28.7-64-64V96C0 60.7 28.7 32 64 32H309.5c17 0 33.3 6.7 45.3 18.7l74.5 74.5-33.9 33.9L320.8 84.7c-.3-.3-.5-.5-.8-.8V184c0 13.3-10.7 24-24 24H104c-13.3 0-24-10.7-24-24V80H64c-8.8 0-16 7.2-16 16zm80-16v80H272V80H128zm32 240a64 64 0 1 1 128 0 64 64 0 1 1 -128 0z"></path>
</svg></button></div>

64
src/Log/Log.java Normal file
View File

@@ -0,0 +1,64 @@
package Log;
import org.tinylog.Logger;
import java.io.File;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class Log {
private Path logpath;
final String regex = "(\\d{2}-\\d{2}-\\d{4}) (\\d{2}:\\d{2}:\\d{2})\\s+(\\S+)\\s:\\s+(.*)";
final Pattern pattern = Pattern.compile(regex, Pattern.UNIX_LINES);
public Log(){
String currentDirectory = System.getProperty("user.dir");
logpath = Paths.get(currentDirectory,"logs");
}
/**
* Get the log files in the logs directory
* @return List of log files
*/
public List<String> getLogFiles(){
List<String> logFiles = new ArrayList<>();
File[] files = logpath.toFile().listFiles();
for(File file : files){
if(file.isFile()){
String shortName = file.getName();
if (shortName.endsWith(".log")){
if (file.length()>0){
logFiles.add(shortName);
}
}
}
}
return logFiles;
}
public List<LogData> ReadLog(String logFile){
List<LogData> logData = new ArrayList<>();
try{
Path ff = logpath.resolve(logFile);
byte[] bytes = Files.readAllBytes(ff);
String content = new String(bytes);
Matcher matcher = pattern.matcher(content);
while(matcher.find()){
LogData log = new LogData();
log.Date = matcher.group(1);
log.Time = matcher.group(2);
log.Method = matcher.group(3);
log.Message = matcher.group(4);
logData.add(log);
}
} catch (Exception e){
Logger.error("Failed reading log {}, Message: {}", logFile, e.getMessage());
}
return logData;
}
}

24
src/Log/LogData.java Normal file
View File

@@ -0,0 +1,24 @@
package Log;
import com.google.gson.JsonObject;
public class LogData {
public String Date;
public String Time;
public String Method;
public String Message;
@Override
public String toString(){
return Date + " " + Time + " " + Method + " " + Message;
}
public static JsonObject toJson(LogData log){
JsonObject jo = new JsonObject();
jo.addProperty("Date", log.Date);
jo.addProperty("Time", log.Time);
jo.addProperty("Method", log.Method);
jo.addProperty("Message", log.Message);
return jo;
}
}

View File

@@ -17,6 +17,7 @@ import java.util.*;
import static code.common.*;
public class Main {
private static jSIPClient client;
private static WebServer webserver;
@@ -47,11 +48,10 @@ public class Main {
public static Properties config;
private static Thread sipThread;
public static void main(String[] args) {
common.ExtractProperties(currentDir,"config.properties", false);
config = common.LoadProperties(currentDir,"config.properties");
common.ExtractProperties(currentDir,"tinylog.properties", false);
//common.ExtractProperties(currentDir,"tinylog.properties", false);
// Timer Section
timer = new Timer();
@@ -68,6 +68,7 @@ public class Main {
// Start System monitoring
init_system_monitoring();
// Shutdown Hook
Runtime.getRuntime().addShutdownHook(new Thread(() -> {
Logger.info("Shutting down SIPIntercom");
@@ -404,7 +405,7 @@ public class Main {
*/
private static void pickupCall() {
if (incomingRequest!=null || incomingResponse!=null){
Logger.info("Pickup incoming call from {}",incomingRequest.From);
Logger.info("Pickup incoming call from {}",incomingRequest!=null ? incomingRequest.From:"Unknown");
client.AcceptIncomingCall(incomingRequest);
callLight_OnCall();
Buzzer_OnCall();

View File

@@ -1,5 +1,8 @@
package Webpage;
import Log.Log;
import Log.LogData;
import com.google.gson.JsonArray;
import io.javalin.Javalin;
import io.javalin.http.HttpCode;
import io.javalin.http.staticfiles.Location;
@@ -7,6 +10,7 @@ import lombok.Getter;
import lombok.Setter;
import org.tinylog.Logger;
import java.util.List;
import java.util.Objects;
import java.util.Properties;
import java.util.function.Consumer;
@@ -21,12 +25,15 @@ public class WebServer {
private @Setter Consumer<LoginSetting> onLoginSettingChanged;
private @Setter Consumer<SipSetting> onSipSettingChanged;
private @Getter int ProcessID;
private final Log logworker;
public WebServer(Properties prop) {
listenport = GetProperties_IntValue(prop,"WebListenPort", 8080);
webusername = GetProperties_StringValue(prop,"WebUsername", "admin");
webpassword = GetProperties_StringValue(prop,"WebPassword", "admin");
logworker = new Log();
int PID = GetPID(listenport);
if (PID!=0) killPID(PID);
@@ -49,6 +56,11 @@ public class WebServer {
ctx.redirect("/login.html");
}
});
app.before("/log.html", ctx -> {
if (!Objects.equals(ctx.sessionAttribute("username"), webusername)){
ctx.redirect("/login.html");
}
});
app.get("/logout", ctx -> {
ctx.sessionAttribute("username", null);
ctx.redirect("/login.html");
@@ -133,6 +145,27 @@ public class WebServer {
}
});
app.post("/logfiles", ctx -> {
List<String> logfiles = logworker.getLogFiles();
JsonArray jsonArray = new JsonArray();
for (String logfile : logfiles) {
jsonArray.add(logfile);
}
ctx.result(jsonArray.toString());
});
app.post("/logdata", ctx -> {
String logfile = ctx.body();
if (ValidString(logfile)){
List<LogData> logdata = logworker.ReadLog(logfile);
JsonArray jsonArray = new JsonArray();
for (LogData log : logdata) {
jsonArray.add(LogData.toJson(log));
}
ctx.result(jsonArray.toString());
} else ctx.result("Invalid Log File").status(HttpCode.BAD_REQUEST);
});
}
/**

View File

@@ -39,7 +39,7 @@ public class common {
Matcher matcher = pattern.matcher(line);
if (matcher.find()) {
PID = Integer.parseInt(matcher.group(1));
System.out.println("PID: "+PID);
//System.out.println("PID: "+PID);
break;
}
}
@@ -123,7 +123,7 @@ public class common {
try{
File dest = new File(directory,filename);
if (dest.isFile() && !overwrite){
Logger.info("Properties file already exists: {}",filename);
//Logger.info("Properties file already exists: {}",filename);
return;
}
// delete existing file
@@ -156,8 +156,8 @@ public class common {
InputStream is = new FileInputStream(file);
prop.load(is);
is.close();
Logger.info("Loaded properties file: {}",filename);
} else Logger.info("Properties file not found: {}",filename);
//Logger.info("Loaded properties file: {}",filename);
} else Logger.error("Properties file not found: {}",filename);
} catch (Exception e) {
Logger.error("Failed to load properties file: {}",filename);