сделал страницу для разработчиков, добавил примитивный сбор журнала статистики
This commit is contained in:
163
static/dev.html
163
static/dev.html
@@ -22,9 +22,6 @@
|
||||
padding-top: var(--header-height);
|
||||
}
|
||||
|
||||
.l3-proto-label {
|
||||
margin: 0 0 0 0.5em;
|
||||
}
|
||||
.l3-proto-label > * {
|
||||
display: inline-block;
|
||||
}
|
||||
@@ -36,64 +33,164 @@
|
||||
<body>
|
||||
<div id="app" hidden>
|
||||
<header>
|
||||
<span class="nav-bar-element">Прием: <span :class="{ indicator_bad: stat_rx.state === false, indicator_good: stat_rx.state === true, indicator: true }"></span></span>
|
||||
<span :class="{ value_bad: initState !== 'Успешная инициализация системы' }">{{ initState }}</span>
|
||||
<div class="tabs-header">
|
||||
<span style="font-weight:bold">RSCM-101</span>
|
||||
<a href="#monitoring" class="tabs-btn" @click="activeTab = 'monitoring'" :class="{ active: activeTab === 'monitoring' }">Мониторинг</a>
|
||||
<a href="#setup" class="tabs-btn" @click="activeTab = 'setup'" :class="{ active: activeTab === 'setup' }">Настройки</a>
|
||||
<a href="#qos" class="tabs-btn" @click="activeTab = 'qos'" :class="{ active: activeTab === 'qos' }">QoS</a>
|
||||
<a href="#admin" class="tabs-btn" @click="activeTab = 'admin'" :class="{ active: activeTab === 'admin' }">Администрирование</a>
|
||||
<a href="/#monitoring" class="tabs-btn">Мониторинг</a>
|
||||
<a href="/#setup" class="tabs-btn">Настройки</a>
|
||||
<a href="/#qos" class="tabs-btn">QoS</a>
|
||||
<a href="/#admin" class="tabs-btn">Администрирование</a>
|
||||
<a class="tabs-btn active">Разработчикам</a>
|
||||
<a href="/logout" class="tabs-btn">Выход</a>
|
||||
</div>
|
||||
</header>
|
||||
<div id="content">
|
||||
<p>Прием: <span :class="{ indicator_bad: stat_rx.state === false, indicator_good: stat_rx.state === true, indicator: true }"></span></p>
|
||||
<p>Скорость: <span>{{ stat_rx.speedOnRxKbit }}</span></p>
|
||||
|
||||
<h2>Настройки</h2>
|
||||
<div class="settings-set-container">
|
||||
<h2>Настройки записи пакетов в IPS</h2>
|
||||
<label>
|
||||
<span>Режим работы</span>
|
||||
<select v-model="param.general.isCinC">
|
||||
<option :value="false">SCPC</option>
|
||||
<option :value="true">CinC</option>
|
||||
<span>Активировать запись</span>
|
||||
<span class="toggle-input"><input type="checkbox" v-model="params.loggingIps" /><span class="slider"></span></span>
|
||||
</label>
|
||||
<button class="action-button" @click="settingsSubmitLoggingIps()">Сохранить <span class="submit-spinner" v-show="submitStatus.loggingIps"></span></button>
|
||||
</div>
|
||||
<div class="settings-set-container" v-if="settingFetchComplete">
|
||||
<h2>Настройки журналирования статистики</h2>
|
||||
<label>
|
||||
<span>Активировать запись</span>
|
||||
<span class="toggle-input"><input type="checkbox" v-model="params.loggingStatistics.en" /><span class="slider"></span></span>
|
||||
</label>
|
||||
<label>
|
||||
<span>Период сбора статистики</span>
|
||||
<select v-model="params.loggingStatistics.logPeriodMs">
|
||||
<option :value="30000">30s</option>
|
||||
<option :value="10000">10s</option>
|
||||
<option :value="5000">5s</option>
|
||||
<option :value="2000">2s</option>
|
||||
<option :value="1000">1s</option>
|
||||
<option :value="500">500ms</option>
|
||||
<option :value="250">250ms (!)</option>
|
||||
<option :value="50">FULL SPEED (!)</option>
|
||||
</select>
|
||||
</label>
|
||||
<label>
|
||||
<span>Полоса поиска, кгц ±</span>
|
||||
<input v-model="param.num" type="number" min="0" max="100" step="1"/>
|
||||
<span>Время хранения</span>
|
||||
<select v-model="params.loggingStatistics.maxAgeMs">
|
||||
<option :value="60000">1 мин</option>
|
||||
<option :value="300000">5 мин</option>
|
||||
<option :value="900000">15 мин</option>
|
||||
<option :value="1800000">30 мин</option>
|
||||
<option :value="3600000">1 час</option>
|
||||
<option :value="7200000">2 часа</option>
|
||||
<option :value="21600000">6 часов</option>
|
||||
<option :value="43200000">12 часов</option>
|
||||
<option :value="86400000">24 часа</option>
|
||||
<option :value="172800000">48 часов</option>
|
||||
<option :value="604800000">7 суток</option>
|
||||
</select>
|
||||
</label>
|
||||
<button class="action-button" @click="settingsSubmitLoggingStatistics()">Сохранить <span class="submit-spinner" v-show="submitStatus.loggingIps"></span></button>
|
||||
</div>
|
||||
<div class="settings-set-container">
|
||||
<h2>Просмотр логов</h2>
|
||||
<button class="action-button" @click="logView()">Обновить <span class="submit-spinner" v-show="submitStatus.logView"></span></button>
|
||||
<a href="/dev/logs.csv" class="action-button">Скачать</a>
|
||||
<pre style="overflow-x: auto">{{ logfileContent }}</pre>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script src="/js/vue.js"></script>
|
||||
<script src="/js/vue.js?v=3.5.13"></script>
|
||||
<script>
|
||||
// для обновления высоты хидера
|
||||
function updateHeaderHeight() { const header = document.querySelector('header'); document.body.style.setProperty('--header-height', `${header.offsetHeight}px`); }
|
||||
window.addEventListener('load', updateHeaderHeight); window.addEventListener('resize', updateHeaderHeight);
|
||||
|
||||
const app = Vue.createApp({
|
||||
data() {
|
||||
return {
|
||||
stat_rx: {
|
||||
state: false,
|
||||
// false - означает что статистика не отправляется, true - отправляется
|
||||
submitStatus: {
|
||||
loggingIps: false,
|
||||
loggingStatistics: false,
|
||||
logView: false
|
||||
},
|
||||
param: {
|
||||
general: {
|
||||
isCinC: true,
|
||||
isTestInputData: false,
|
||||
modulatorMode: 'test'
|
||||
},
|
||||
num: 1
|
||||
params: {
|
||||
loggingIps: false,
|
||||
loggingStatistics: {
|
||||
en: false,
|
||||
logPeriodMs: 1000,
|
||||
maxAgeMs: 0
|
||||
}
|
||||
},
|
||||
logfileContent: "",
|
||||
|
||||
initState: '?',
|
||||
activeTab: 'setup'
|
||||
settingFetchComplete: false
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
settingsSubmitLoggingIps() {
|
||||
if (this.submitStatus.loggingIps) { return }
|
||||
|
||||
this.submitStatus.loggingIps = true
|
||||
fetch(`/dev/cpapicall?f=SetDmaDebug¶m=log_bool&value=${this.params.loggingIps}`, {method: 'POST', headers: {'Content-Type': 'application/json'}, credentials: 'same-origin' })
|
||||
.then(async (resp) => { let vals = await resp.json(); if (vals['status'] !== 'ok') { throw new Error(vals['error'] ? vals['error'] : "Server returns undefined error") } })
|
||||
.catch((reason) => { alert(`Ошибка при применении настроек: ${reason}`) })
|
||||
.finally(() => { this.submitStatus.loggingIps = false })
|
||||
},
|
||||
settingsSubmitLoggingStatistics() {
|
||||
function modcodToStr(modcod) {
|
||||
// модкоды из раздела 5.5.2.2 https://www.etsi.org/deliver/etsi_en/302300_302399/302307/01.01.02_60/en_302307v010102p.pdf
|
||||
const modcods = [
|
||||
"DUMMY",
|
||||
"QPSK 1/4", "QPSK 1/3", "QPSK 2/5", "QPSK 1/2", "QPSK 3/5", "QPSK 2/3", "QPSK 3/4", "QPSK 4/5", "QPSK 5/6", "QPSK 8/9", "QPSK 9/10",
|
||||
"8PSK 3/5", "8PSK 2/3", "8PSK 3/4", "8PSK 5/6", "8PSK 8/9", "8PSK 9/10",
|
||||
"16APSK 2/3", "16APSK 3/4", "16APSK 4/5", "16APSK 5/6", "16APSK 8/9", "16APSK 9/10",
|
||||
"32APSK 3/4", "32APSK 4/5", "32APSK 5/6", "32APSK 8/9", "32APSK 9/10",
|
||||
]
|
||||
if (typeof modcod != "number") {
|
||||
return "?";
|
||||
}
|
||||
if (modcod < 0 || modcod >= modcods.length) {
|
||||
return `? (${modcod})`
|
||||
}
|
||||
return modcods[modcod]
|
||||
}
|
||||
|
||||
if (this.submitStatus.loggingStatistics) { return }
|
||||
|
||||
let query = {
|
||||
"en": this.params.loggingStatistics.en,
|
||||
"logPeriodMs": this.params.loggingStatistics.logPeriodMs,
|
||||
"maxAgeMs": this.params.loggingStatistics.maxAgeMs,
|
||||
}
|
||||
|
||||
this.submitStatus.loggingStatistics = true
|
||||
fetch('/dev/settings', {method: 'POST', headers: {'Content-Type': 'application/json'}, body: JSON.stringify(query), credentials: 'same-origin' })
|
||||
.then(async (resp) => { let vals = await resp.json(); if (vals['status'] !== 'ok') { throw new Error(vals['error'] ? vals['error'] : "Server returns undefined error") } this.updateLoggingStatisticsSettings(vals) })
|
||||
.catch((reason) => { alert(`Ошибка при применении настроек: ${reason}`) })
|
||||
.finally(() => { this.submitStatus.loggingStatistics = false })
|
||||
},
|
||||
logView() {
|
||||
if (this.submitStatus.logView) { return }
|
||||
|
||||
this.submitStatus.logView = true
|
||||
fetch(`/dev/logs.csv`, {method: 'GET', credentials: 'same-origin' })
|
||||
.then(async (resp) => { this.logfileContent = await resp.text() })
|
||||
.catch((reason) => { alert(`Ошибка при чтении логов: ${reason}`) })
|
||||
.finally(() => { this.submitStatus.logView = false })
|
||||
},
|
||||
updateLoggingStatisticsSettings(vals) {
|
||||
this.params.loggingStatistics.en = vals['logstat']['en']
|
||||
this.params.loggingStatistics.logPeriodMs = vals['logstat']['logPeriodMs']
|
||||
this.params.loggingStatistics.maxAgeMs = vals['logstat']['maxAgeMs']
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
const doFetchSettings = async () => {
|
||||
let d = await fetch("/dev/settings")
|
||||
let vals = await d.json()
|
||||
this.settingFetchComplete = true
|
||||
this.updateLoggingStatisticsSettings(vals)
|
||||
}
|
||||
doFetchSettings().then(() => {})
|
||||
document.getElementById("app").removeAttribute("hidden")
|
||||
}
|
||||
});
|
||||
|
Reference in New Issue
Block a user