315 lines
16 KiB
Plaintext
315 lines
16 KiB
Plaintext
<%- await include('parts/header.ejs', locals) %>
|
|
|
|
|
|
<div class="row justify-content-md-center">
|
|
<div class="col-lg-8 col-xl-5 mw-col6">
|
|
<!-- Environment Card -->
|
|
<div class="card card-accent-danger" style="min-height: 160px;">
|
|
<div class="card-header font-weight-bold">Environment:</div>
|
|
<div class="card-body">
|
|
<% if (host.error) { %>
|
|
<%- host.error %>
|
|
<% } else { %>
|
|
<strong>Node:</strong> <%= host.static.nodeVersion %> <br>
|
|
<strong>OS:</strong> <%= host.static.osDistro %> <br>
|
|
<strong>Username:</strong> <%= host.static.username %> <br>
|
|
|
|
<strong>CPU Model:</strong> <%- host.static.cpu.manufacturer %> <%- host.static.cpu.brand %> <br>
|
|
<strong>CPU Stats:</strong>
|
|
<%- host.static.cpu.physicalCores %>c/<%- host.static.cpu.cores %>t -
|
|
<%- host.static.cpu.speedMin %> GHz
|
|
<%- host.static.cpu.clockWarning %> <br>
|
|
<% if (host.dynamic) { %>
|
|
<strong>CPU Usage:</strong> <%= host.dynamic.cpuUsage %>% <br>
|
|
<strong>Memory:</strong>
|
|
<%= host.dynamic.memory.usage %>%
|
|
(<%= host.dynamic.memory.used.toFixed(2) %>/<%= host.dynamic.memory.total.toFixed(2) %>)
|
|
<% } else { %>
|
|
<i>Dynamic usage data not available.</i>
|
|
<% } %>
|
|
<% } %>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- txAdmin Config Card -->
|
|
<div class="card card-accent-danger" style="min-height: 160px;">
|
|
<div class="card-header font-weight-bold">txAdmin Runtime:</div>
|
|
<div class="card-body">
|
|
<strong>Uptime:</strong> <code><%= txadmin.uptime %></code> <br>
|
|
<strong>Versions:</strong>
|
|
<code>v<%= txAdminVersion %></code> /
|
|
<code>b<%= fxServerVersion %></code> <br>
|
|
<strong>Database File Size:</strong> <code><%= txadmin.databaseFileSize %></code> <br>
|
|
<strong>Env:</strong> <br>
|
|
├─ FXServer: <code><%= txadmin.txEnv.fxsPath %></code> <br>
|
|
├─ Profile: <code><%= txadmin.txEnv.profilePath %></code> <br>
|
|
├─ Defaults: <code><%= txadmin.txHostConfig.defaults.length > 0 ? txadmin.txHostConfig.defaults.join(', ') : '--' %></code> <br>
|
|
├─ Interface: <code><%= txadmin.txHostConfig.netInterface ?? '--' %></code> <br>
|
|
└─ Provider: <code><%= txadmin.txHostConfig.providerName ?? '--' %></code> <br>
|
|
<strong>Monitor:</strong> <br>
|
|
├─ HB Fails:
|
|
<code>HTTP <%= txadmin.monitor.hbFails.http %></code> /
|
|
<code>FD3 <%= txadmin.monitor.hbFails.fd3 %></code> <br>
|
|
└─ Restarts:
|
|
<code>BT <%= txadmin.monitor.restarts.bootTimeout %></code> /
|
|
<code>CL <%= txadmin.monitor.restarts.close %></code> /
|
|
<code>HB <%= txadmin.monitor.restarts.heartBeat %></code> /
|
|
<code>HC <%= txadmin.monitor.restarts.healthCheck %></code> /
|
|
<code>BO <%= txadmin.monitor.restarts.both %></code> <br>
|
|
<strong>Performance Times:</strong> <br>
|
|
├─ BanCheck: <code><%= txadmin.performance.banCheck %></code> <br>
|
|
├─ WhitelistCheck: <code><%= txadmin.performance.whitelistCheck %></code> <br>
|
|
├─ PlayersTable: <code><%= txadmin.performance.playersTableSearch %></code> <br>
|
|
├─ HistoryTable: <code><%= txadmin.performance.historyTableSearch %></code> <br>
|
|
├─ DatabaseSave: <code><%= txadmin.performance.databaseSave %></code> <br>
|
|
└─ PerfCollection: <code><%= txadmin.performance.perfCollection %></code> <br>
|
|
<strong>Memory:</strong> <br>
|
|
├─ Heap: <code><%= txadmin.memoryUsage.heap_used %> / <%= txadmin.memoryUsage.heap_limit %> (<%= txadmin.memoryUsage.heap_pct %>%)</code> <br>
|
|
├─ Physical: <code><%= txadmin.memoryUsage.physical %></code> <br>
|
|
└─ Peak. Alloc.: <code><%= txadmin.memoryUsage.peak_malloced %></code> <br>
|
|
<strong>Logger Status:</strong> <br>
|
|
├─ Storage Size: <code><%= txadmin.logger.storageSize %></code> <br>
|
|
├─ Admin: <code><%= txadmin.logger.statusAdmin %></code> <br>
|
|
├─ FXServer: <code><%= txadmin.logger.statusFXServer %></code> <br>
|
|
└─ Server: <code><%= txadmin.logger.statusServer %></code> <br>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Execution time -->
|
|
<div class="text-center mb-4">
|
|
<small class="text-muted"><%- message %></small>
|
|
</div>
|
|
|
|
</div>
|
|
<!-- /.col-->
|
|
|
|
|
|
<div class="col-lg-8 col-xl-5 mw-col6">
|
|
<!-- Diagnostics Report -->
|
|
<div class="card card-accent-info">
|
|
<div class="card-header font-weight-bold">Diagnostics Report:</div>
|
|
<div class="card-body text-center">
|
|
<div class="row text-center">
|
|
<div class="col-lg-9 text-lg-left">
|
|
To receive txAdmin Support, it is recommended that you send the diagnostics data directly to the Support Team.
|
|
</div>
|
|
<div class="col-lg-3 text-lg-right">
|
|
<button
|
|
class="btn btn-sm btn-outline-info"
|
|
type="button"
|
|
onclick="showReportModal()"
|
|
>
|
|
Review Details <br>
|
|
& Send Data
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- FXServer Info Card -->
|
|
<div class="card card-accent-info" style="min-height: 160px;">
|
|
<div class="card-header font-weight-bold">FXServer /info.json:</div>
|
|
<div class="card-body">
|
|
<% if (fxserver.versionMismatch) { %>
|
|
<div class="alert alert-danger text-center" role="alert">
|
|
<strong>This version doesn't match txAdmin's version!</strong><br>
|
|
If you just updated FXServer, restart txAdmin. <br>
|
|
Otherwise, it means FXServer was already running before txAdmin started, and nothing is going to work properly.
|
|
</div>
|
|
<% } %>
|
|
<% if (fxserver.error !== false) { %>
|
|
<%- fxserver.error %>
|
|
<% } else { %>
|
|
<strong>Status: <span class="badge badge-<%= fxserver.statusColor %>"><%= fxserver.status %></span></strong> <br>
|
|
<strong>Version:</strong> <%= fxserver.version %> <br>
|
|
<strong>Resources:</strong> <%= fxserver.resources %> <br>
|
|
<strong>OneSync:</strong> <%= fxserver.onesync %> <br>
|
|
<strong>Max Clients:</strong> <%= fxserver.maxClients %> <br>
|
|
<strong>txAdmin Version:</strong> <%= fxserver.txAdminVersion %> <br>
|
|
<% } %>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Proccesses Card -->
|
|
<div class="card card-accent-info">
|
|
<div class="card-header font-weight-bold">Processes:</div>
|
|
<div class="card-body">
|
|
<% if (!proccesses.length) { %>
|
|
Failed to retrieve processed data. <br>
|
|
Check the terminal for more information (if verbosity is enabled)
|
|
<% } else { %>
|
|
<% for (const process of proccesses) { %>
|
|
<strong>Process:</strong> (<%= process.pid %>) <%= process.name %> <br>
|
|
<strong>Parent:</strong> <%= process.ppid %> <br>
|
|
<strong>Memory:</strong> <%= process.memory.toFixed(2) %>MB <br>
|
|
<strong>CPU:</strong> <%= process.cpu.toFixed(2) %>% <br>
|
|
<br>
|
|
<% } %>
|
|
<% } %>
|
|
</div>
|
|
</div>
|
|
|
|
</div>
|
|
<!-- /.col-->
|
|
</div>
|
|
|
|
<%- await include('parts/footer.ejs', locals) %>
|
|
|
|
<!-- Submit Report modal -->
|
|
<div class="modal fade" id="modReport" tabindex="-1" role="dialog" aria-labelledby="modReport-title" aria-hidden="true">
|
|
<div class="modal-dialog modal-dialog-centered" role="document">
|
|
<div class="modal-content">
|
|
<div class="modal-header">
|
|
<h5 class="modal-title" id="modReport-title">Send Diagnostics Data</h5>
|
|
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
|
|
<span aria-hidden="true">×</span>
|
|
</button>
|
|
</div>
|
|
|
|
<div class="modal-body">
|
|
<!-- Spinner -->
|
|
<div class="d-none" id="modReport-spinnerBody">
|
|
<div style="min-height: 125px;">
|
|
<div class="txSpinner">Loading...</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Review -->
|
|
<div class="d-none" id="modReport-infoBody">
|
|
<p>
|
|
This <i>optional</i> feature sends a diagnostics report to the txAdmin/Cfx.re teams, and may be required to diagnose a wide range of server issues. <br>
|
|
After sending the data, you will receive a Report ID you can send in the support channels.
|
|
</p>
|
|
<ul style="padding-inline-start: 1rem;">
|
|
<li>
|
|
<strong>Which data will be sent?</strong>
|
|
<ul style="padding-inline-start: 1rem;">
|
|
<li>All diagnostics page data</li>
|
|
<li>Recent txAdmin (system), live console and server log</li>
|
|
<li>Environment variables</li>
|
|
<li>Server performance (dashboard chart) data</li>
|
|
<li>Player database statistics</li>
|
|
<li>txAdmin settings (no bot token)</li>
|
|
<li>List of admins (no passwords/hashes)</li>
|
|
<li>List of files/folders in server data and monitor folders</li>
|
|
<li>Config files in server data folder</li>
|
|
</ul>
|
|
</li>
|
|
<li>
|
|
<strong>Who can access the data?</strong> <br>
|
|
The data will be available for up to 24 hours to the txAdmin support team, as well as the Cfx.re team.
|
|
</li>
|
|
<li>
|
|
<strong>Sensitive Information Protection:</strong> <br>
|
|
<ul style="padding-inline-start: 1rem;">
|
|
<li><strong>Settings:</strong> the Discord Bot Token will be removed</li>
|
|
<li><strong>Admin List:</strong> the password hashes will not be sent</li>
|
|
<li><strong>Env Vars:</strong> parameters with <code>key, license, pass, private, secret, token</code> in their name will be masked.</li>
|
|
<li><strong>CFG Files:</strong> known secret parameters will be masked (ex license, mysql string, tebex secret, webhooks, etc).</li>
|
|
<li><strong>Logs:</strong> any identifiable IPv4 address in logs will be masked.</li>
|
|
</ul>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
|
|
<!-- Result Success -->
|
|
<div class="d-none" id="modReport-resultSuccessBody">
|
|
<style>
|
|
.reportIdCode {
|
|
font-size: 1.75rem;
|
|
letter-spacing: 0.65rem;
|
|
background-color: rgb(128 128 128 / 20%);
|
|
padding: 0.25rem 0.1rem 0.25rem 0.85rem;
|
|
text-align: center;
|
|
}
|
|
</style>
|
|
<div class="text-center">
|
|
<h2>Report ID: <code class="reportIdCode" id="modReport-reportId">??????</code></h2>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Result Error -->
|
|
<div class="d-none" id="modReport-resultErrorBody">
|
|
<div class="text-center">
|
|
<h4 class="text-danger" id="modReport-resultErrorMessage">sdfsdf sdf sdfsdf</h4>
|
|
</div>
|
|
</div>
|
|
|
|
<p class="lead mb-1 pt-2 text-center" style="font-style: italic;">
|
|
For txAdmin support, join the official Discord:
|
|
<a href="https://discord.gg/uAmsGa2" target="_blank" style="vertical-align: text-bottom;">
|
|
<img src="https://discordapp.com/api/guilds/577993482761928734/widget.png?style=shield"></img>
|
|
</a>
|
|
</p>
|
|
</div>
|
|
|
|
|
|
<div class="modal-footer text-center">
|
|
<div class="mx-auto">
|
|
<button type="button" class="btn btn-secondary" data-dismiss="modal">Close</button>
|
|
|
|
|
|
<button type="button" class="btn btn-success" id="modReport-saveBtn">Agree & Send Data</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
|
|
<script>
|
|
const els = {
|
|
modal: document.getElementById('modReport'),
|
|
infoBody: document.getElementById('modReport-infoBody'),
|
|
spinnerBody: document.getElementById('modReport-spinnerBody'),
|
|
resultSuccessBody: document.getElementById('modReport-resultSuccessBody'),
|
|
resultErrorBody: document.getElementById('modReport-resultErrorBody'),
|
|
resultErrorMessage: document.getElementById('modReport-resultErrorMessage'),
|
|
saveBtn: document.getElementById('modReport-saveBtn'),
|
|
reportId: document.getElementById('modReport-reportId'),
|
|
}
|
|
|
|
function showReportModal() {
|
|
els.infoBody.classList.remove('d-none');
|
|
els.resultSuccessBody.classList.add('d-none');
|
|
els.resultErrorBody.classList.add('d-none');
|
|
els.spinnerBody.classList.add('d-none');
|
|
els.saveBtn.classList.remove('d-none');
|
|
els.saveBtn.classList.remove('disabled');
|
|
$('#modReport').modal('show');
|
|
}
|
|
|
|
els.saveBtn.onclick = () => {
|
|
els.infoBody.classList.add('d-none');
|
|
els.spinnerBody.classList.remove('d-none');
|
|
els.saveBtn.classList.add('disabled');
|
|
|
|
txAdminAPI({
|
|
type: "POST",
|
|
url: `diagnostics/sendReport`,
|
|
timeout: REQ_TIMEOUT_REALLY_LONG,
|
|
//NOTE: in NUI, empty bodies become GET requests even if you specify POST
|
|
data: {bugfix:true},
|
|
success: function (data) {
|
|
els.spinnerBody.classList.add('d-none');
|
|
els.saveBtn.classList.add('d-none');
|
|
if(data.error){
|
|
els.resultErrorBody.classList.remove('d-none');
|
|
els.resultErrorMessage.textContent = data.error;
|
|
}else if(data.reportId){
|
|
els.resultSuccessBody.classList.remove('d-none');
|
|
els.reportId.textContent = data.reportId;
|
|
}else{
|
|
els.resultErrorBody.classList.remove('d-none');
|
|
els.resultErrorMessage.textContent = 'Unknown backend error.';
|
|
}
|
|
},
|
|
error: function (xmlhttprequest, textstatus, message) {
|
|
els.resultErrorBody.classList.remove('d-none');
|
|
els.resultErrorMessage.textContent = `Error: ${message}`;
|
|
}
|
|
});
|
|
}
|
|
</script>
|