viberadar 0.3.77 → 0.3.78
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/ui/dashboard.html +244 -0
- package/package.json +1 -1
package/dist/ui/dashboard.html
CHANGED
|
@@ -739,6 +739,54 @@
|
|
|
739
739
|
.obs-tab-content.active { display:block; }
|
|
740
740
|
@media (max-width:640px) { .obs-kpi-strip { grid-template-columns:repeat(2,1fr); } }
|
|
741
741
|
|
|
742
|
+
/* ── Tab hint panels ── */
|
|
743
|
+
.obs-hint {
|
|
744
|
+
margin-bottom: 12px;
|
|
745
|
+
border: 1px solid var(--border);
|
|
746
|
+
border-radius: 8px;
|
|
747
|
+
overflow: hidden;
|
|
748
|
+
}
|
|
749
|
+
.obs-hint-toggle {
|
|
750
|
+
display: flex; align-items: center; gap: 8px;
|
|
751
|
+
width: 100%; padding: 10px 14px;
|
|
752
|
+
background: none; border: none; cursor: pointer;
|
|
753
|
+
color: var(--muted); font-size: 12px; font-weight: 600;
|
|
754
|
+
text-align: left; transition: background 0.1s, color 0.1s;
|
|
755
|
+
}
|
|
756
|
+
.obs-hint-toggle:hover { background: var(--bg-card); color: var(--text); }
|
|
757
|
+
.obs-hint-icon {
|
|
758
|
+
display: inline-flex; align-items: center; justify-content: center;
|
|
759
|
+
width: 18px; height: 18px; border-radius: 50%;
|
|
760
|
+
border: 1.5px solid currentColor; font-size: 11px; font-weight: 700;
|
|
761
|
+
flex-shrink: 0;
|
|
762
|
+
}
|
|
763
|
+
.obs-hint-chevron { margin-left: auto; font-size: 10px; transition: transform 0.2s; }
|
|
764
|
+
.obs-hint.open .obs-hint-chevron { transform: rotate(180deg); }
|
|
765
|
+
.obs-hint-body {
|
|
766
|
+
display: none;
|
|
767
|
+
padding: 0 16px 16px 16px;
|
|
768
|
+
background: var(--bg-card);
|
|
769
|
+
font-size: 12px; color: var(--muted); line-height: 1.6;
|
|
770
|
+
}
|
|
771
|
+
.obs-hint.open .obs-hint-body { display: block; }
|
|
772
|
+
.obs-hint-section { margin-top: 12px; }
|
|
773
|
+
.obs-hint-section-title { font-size: 11px; font-weight: 700; color: var(--text); text-transform: uppercase; letter-spacing: 0.5px; margin-bottom: 6px; }
|
|
774
|
+
.obs-hint-code {
|
|
775
|
+
font-family: monospace; font-size: 11px;
|
|
776
|
+
background: var(--bg); border: 1px solid var(--border);
|
|
777
|
+
border-radius: 5px; padding: 8px 10px; margin: 4px 0;
|
|
778
|
+
line-height: 1.5; overflow-x: auto; white-space: pre;
|
|
779
|
+
}
|
|
780
|
+
.obs-hint-code .hl-red { color: var(--red); }
|
|
781
|
+
.obs-hint-code .hl-green { color: var(--green); }
|
|
782
|
+
.obs-hint-code .hl-yellow { color: var(--yellow); }
|
|
783
|
+
.obs-hint-code .hl-dim { color: var(--dim); }
|
|
784
|
+
.obs-hint-row { display: flex; gap: 12px; }
|
|
785
|
+
.obs-hint-row > * { flex: 1; min-width: 0; }
|
|
786
|
+
.obs-hint-label { font-size: 10px; font-weight: 700; margin-bottom: 3px; }
|
|
787
|
+
.obs-hint-label.before { color: var(--red); }
|
|
788
|
+
.obs-hint-label.after { color: var(--green); }
|
|
789
|
+
|
|
742
790
|
.file-row-err-badge {
|
|
743
791
|
display: inline-flex; align-items: center;
|
|
744
792
|
font-size: 11px; padding: 1px 6px; border-radius: 10px;
|
|
@@ -1220,6 +1268,10 @@ let e2ePlan = null; // current E2E plan object
|
|
|
1220
1268
|
let e2ePlanLoading = false;
|
|
1221
1269
|
let obsActiveTab = 'overview'; // active observability tab
|
|
1222
1270
|
|
|
1271
|
+
function toggleObsHint(id) {
|
|
1272
|
+
document.getElementById(id).classList.toggle('open');
|
|
1273
|
+
}
|
|
1274
|
+
|
|
1223
1275
|
function switchObsTab(tabId) {
|
|
1224
1276
|
obsActiveTab = tabId;
|
|
1225
1277
|
history.replaceState(null, '', location.pathname + location.search + '#obs-tab=' + tabId);
|
|
@@ -2700,6 +2752,35 @@ function renderObservability(c) {
|
|
|
2700
2752
|
</div>
|
|
2701
2753
|
|
|
2702
2754
|
<div class="obs-tab-content" data-obstab="overview">
|
|
2755
|
+
<div class="obs-hint" id="obs-hint-overview">
|
|
2756
|
+
<button class="obs-hint-toggle" onclick="toggleObsHint('obs-hint-overview')">
|
|
2757
|
+
<span class="obs-hint-icon">?</span>
|
|
2758
|
+
Что такое «Обзор» и как читать эти числа?
|
|
2759
|
+
<span class="obs-hint-chevron">▼</span>
|
|
2760
|
+
</button>
|
|
2761
|
+
<div class="obs-hint-body">
|
|
2762
|
+
<p>Обзор — это «пульс» логирования в проекте. Четыре метрики наверху показывают, насколько логи полезны прямо сейчас.</p>
|
|
2763
|
+
<div class="obs-hint-section">
|
|
2764
|
+
<div class="obs-hint-section-title">Что означает каждая метрика</div>
|
|
2765
|
+
<div class="obs-hint-code"><span class="hl-red">Шум 40%</span> — почти половина логов бесполезны. Они засоряют Kibana/Datadog
|
|
2766
|
+
и скрывают реальные ошибки.
|
|
2767
|
+
|
|
2768
|
+
<span class="hl-yellow">Структурированность 20%</span> — большинство логов — просто строки вроде
|
|
2769
|
+
<span class="hl-dim">"Starting process..."</span>. Их нельзя фильтровать, группировать,
|
|
2770
|
+
строить алерты. Цель — 80%+.
|
|
2771
|
+
|
|
2772
|
+
<span class="hl-yellow">Actionable ошибки 50%</span> — половина ошибок логируется без контекста.
|
|
2773
|
+
Инженер видит <span class="hl-dim">"Error occurred"</span> — и ничего больше.
|
|
2774
|
+
|
|
2775
|
+
<span class="hl-red">Покрытие сценариев 24%</span> — 76% модулей вообще не имеют warn/error логов.
|
|
2776
|
+
Когда они сломаются — узнаешь только от пользователей.</div>
|
|
2777
|
+
</div>
|
|
2778
|
+
<div class="obs-hint-section">
|
|
2779
|
+
<div class="obs-hint-section-title">Блок «Рекомендации»</div>
|
|
2780
|
+
<p>Итоговый план действий по всему проекту: сколько источников нужно <span style="color:var(--red)">убрать</span>, <span style="color:var(--yellow)">обогатить</span>, <span style="color:var(--yellow)">добавить</span>. Каждая строчка раскрывается — можно выбрать файлы и отдать агенту.</p>
|
|
2781
|
+
</div>
|
|
2782
|
+
</div>
|
|
2783
|
+
</div>
|
|
2703
2784
|
<div class="obs-grid" style="grid-template-columns:1fr 1fr 1fr;margin-bottom:12px">
|
|
2704
2785
|
<div class="obs-card">
|
|
2705
2786
|
<div class="obs-title">Источники по формату</div>
|
|
@@ -2753,6 +2834,42 @@ function renderObservability(c) {
|
|
|
2753
2834
|
</div>
|
|
2754
2835
|
|
|
2755
2836
|
<div class="obs-tab-content" data-obstab="remove">
|
|
2837
|
+
<div class="obs-hint" id="obs-hint-remove">
|
|
2838
|
+
<button class="obs-hint-toggle" onclick="toggleObsHint('obs-hint-remove')">
|
|
2839
|
+
<span class="obs-hint-icon">?</span>
|
|
2840
|
+
Зачем убирать эти логи? Разве лишний лог — не лучше, чем ничего?
|
|
2841
|
+
<span class="obs-hint-chevron">▼</span>
|
|
2842
|
+
</button>
|
|
2843
|
+
<div class="obs-hint-body">
|
|
2844
|
+
<p>Шумные логи — это строки, которые пишутся при каждом запросе или в цикле и не несут полезной информации. Они создают три реальные проблемы:</p>
|
|
2845
|
+
<ul style="margin:8px 0 0 16px;display:flex;flex-direction:column;gap:4px">
|
|
2846
|
+
<li><strong style="color:var(--red)">Топят сигнал.</strong> Когда в Kibana 10 000 строк в минуту, реальная ошибка теряется на странице 47.</li>
|
|
2847
|
+
<li><strong style="color:var(--yellow)">Стоят деньги.</strong> Datadog, New Relic, Elastic — тарификация по объёму. Шум = деньги на ветер.</li>
|
|
2848
|
+
<li><strong style="color:var(--muted)">Замедляют дебаг.</strong> Инженер тратит 20 минут, чтобы понять, что «[unknown]» — это просто фоновый краулер.</li>
|
|
2849
|
+
</ul>
|
|
2850
|
+
<div class="obs-hint-section">
|
|
2851
|
+
<div class="obs-hint-section-title">До / После</div>
|
|
2852
|
+
<div class="obs-hint-row">
|
|
2853
|
+
<div>
|
|
2854
|
+
<div class="obs-hint-label before">БЫЛО — шум</div>
|
|
2855
|
+
<div class="obs-hint-code"><span class="hl-red">logger.info('[unknown]') // ×116/день</span>
|
|
2856
|
+
<span class="hl-red">logger.info('Converting WebM to OGG...')// ×200/день</span>
|
|
2857
|
+
<span class="hl-red">logger.info('Using API key from env') // каждый запрос</span></div>
|
|
2858
|
+
</div>
|
|
2859
|
+
<div>
|
|
2860
|
+
<div class="obs-hint-label after">СТАЛО — чисто</div>
|
|
2861
|
+
<div class="obs-hint-code"><span class="hl-green">// строки удалены или понижены до debug</span>
|
|
2862
|
+
<span class="hl-dim">// В production debug-логи выключены</span>
|
|
2863
|
+
<span class="hl-green">// В мониторинге только важные события</span></div>
|
|
2864
|
+
</div>
|
|
2865
|
+
</div>
|
|
2866
|
+
</div>
|
|
2867
|
+
<div class="obs-hint-section">
|
|
2868
|
+
<div class="obs-hint-section-title">Как использовать</div>
|
|
2869
|
+
<p>Нажми <strong>«убрать»</strong> рядом с паттерном — агент найдёт все места в коде и либо удалит строку, либо заменит <code>logger.info</code> на <code>logger.debug</code>. Можно обработать несколько паттернов сразу.</p>
|
|
2870
|
+
</div>
|
|
2871
|
+
</div>
|
|
2872
|
+
</div>
|
|
2756
2873
|
<div class="obs-card">
|
|
2757
2874
|
<div class="obs-title">Шумные паттерны</div>
|
|
2758
2875
|
<div class="obs-list" style="gap:4px">${noisyRows}</div>
|
|
@@ -2760,6 +2877,57 @@ function renderObservability(c) {
|
|
|
2760
2877
|
</div>
|
|
2761
2878
|
|
|
2762
2879
|
<div class="obs-tab-content" data-obstab="add">
|
|
2880
|
+
<div class="obs-hint" id="obs-hint-add">
|
|
2881
|
+
<button class="obs-hint-toggle" onclick="toggleObsHint('obs-hint-add')">
|
|
2882
|
+
<span class="obs-hint-icon">?</span>
|
|
2883
|
+
Почему важно добавлять логи именно в эти места?
|
|
2884
|
+
<span class="obs-hint-chevron">▼</span>
|
|
2885
|
+
</button>
|
|
2886
|
+
<div class="obs-hint-body">
|
|
2887
|
+
<p>Сканер нашёл «точки отказа» — конструкции в коде, где что-то может пойти не так, но лог туда не написан. Если здесь случится ошибка в production — ты узнаешь об этом только от пользователя.</p>
|
|
2888
|
+
<div class="obs-hint-section">
|
|
2889
|
+
<div class="obs-hint-section-title">Типы точек отказа</div>
|
|
2890
|
+
<div class="obs-hint-code"><span class="hl-red">empty-catch</span> — catch(){} без лога. Ошибка молча проглочена.
|
|
2891
|
+
<span class="hl-red">catch-no-log</span> — catch(e){ doSomething() } — ошибка обработана, но не залогирована.
|
|
2892
|
+
<span class="hl-yellow">http-no-error-handling</span> — HTTP-запрос без обработки ошибки (нет .catch или try/catch).
|
|
2893
|
+
<span class="hl-yellow">db-no-error-handling</span> — запрос к БД без обработки ошибки.
|
|
2894
|
+
<span class="hl-yellow">throw-no-log</span> — throw new Error(...) без предварительного лога.
|
|
2895
|
+
<span class="hl-dim">error-check-no-log</span> — if (err) { return } без лога.</div>
|
|
2896
|
+
</div>
|
|
2897
|
+
<div class="obs-hint-section">
|
|
2898
|
+
<div class="obs-hint-section-title">До / После</div>
|
|
2899
|
+
<div class="obs-hint-row">
|
|
2900
|
+
<div>
|
|
2901
|
+
<div class="obs-hint-label before">БЫЛО — немая ошибка</div>
|
|
2902
|
+
<div class="obs-hint-code"><span class="hl-dim">async function processPayment(data) {</span>
|
|
2903
|
+
<span class="hl-dim">try {</span>
|
|
2904
|
+
<span class="hl-dim">await stripe.charge(data);</span>
|
|
2905
|
+
<span class="hl-red">} catch (e) {</span>
|
|
2906
|
+
<span class="hl-red"> // пусто! ошибка проглочена</span>
|
|
2907
|
+
<span class="hl-red">}</span>
|
|
2908
|
+
<span class="hl-dim">}</span></div>
|
|
2909
|
+
</div>
|
|
2910
|
+
<div>
|
|
2911
|
+
<div class="obs-hint-label after">СТАЛО — видимая ошибка</div>
|
|
2912
|
+
<div class="obs-hint-code"><span class="hl-dim">async function processPayment(data) {</span>
|
|
2913
|
+
<span class="hl-dim">try {</span>
|
|
2914
|
+
<span class="hl-dim">await stripe.charge(data);</span>
|
|
2915
|
+
<span class="hl-green">} catch (e) {</span>
|
|
2916
|
+
<span class="hl-green"> logger.error('payment_failed', {</span>
|
|
2917
|
+
<span class="hl-green"> error: e.message, userId: data.userId</span>
|
|
2918
|
+
<span class="hl-green"> });</span>
|
|
2919
|
+
<span class="hl-green"> throw e;</span>
|
|
2920
|
+
<span class="hl-green">}</span>
|
|
2921
|
+
<span class="hl-dim">}</span></div>
|
|
2922
|
+
</div>
|
|
2923
|
+
</div>
|
|
2924
|
+
</div>
|
|
2925
|
+
<div class="obs-hint-section">
|
|
2926
|
+
<div class="obs-hint-section-title">Как использовать</div>
|
|
2927
|
+
<p>Модули разбиты по уровню риска: <span style="color:var(--red)">Критичные</span> — трогать в первую очередь (платежи, авторизация, запись данных). Раскрой группу, выбери модули и нажми <strong>«добавить логи выбранным»</strong>.</p>
|
|
2928
|
+
</div>
|
|
2929
|
+
</div>
|
|
2930
|
+
</div>
|
|
2763
2931
|
<div class="obs-card">
|
|
2764
2932
|
<div class="obs-title">Нет критичных логов</div>
|
|
2765
2933
|
<div class="obs-list" style="gap:4px">${missingSection}</div>
|
|
@@ -2767,6 +2935,54 @@ function renderObservability(c) {
|
|
|
2767
2935
|
</div>
|
|
2768
2936
|
|
|
2769
2937
|
<div class="obs-tab-content" data-obstab="enrich">
|
|
2938
|
+
<div class="obs-hint" id="obs-hint-enrich">
|
|
2939
|
+
<button class="obs-hint-toggle" onclick="toggleObsHint('obs-hint-enrich')">
|
|
2940
|
+
<span class="obs-hint-icon">?</span>
|
|
2941
|
+
Какая разница, есть ли поля в логе? Главное, что сообщение есть.
|
|
2942
|
+
<span class="obs-hint-chevron">▼</span>
|
|
2943
|
+
</button>
|
|
2944
|
+
<div class="obs-hint-body">
|
|
2945
|
+
<p>Лог без полей — это как сигнал пожарной тревоги без адреса. Ты знаешь, что что-то горит, но не знаешь где и что именно. Структурированные поля превращают лог из строки в <em>данные</em>.</p>
|
|
2946
|
+
<div class="obs-hint-section">
|
|
2947
|
+
<div class="obs-hint-section-title">До / После</div>
|
|
2948
|
+
<div class="obs-hint-row">
|
|
2949
|
+
<div>
|
|
2950
|
+
<div class="obs-hint-label before">БЫЛО — бесполезный лог</div>
|
|
2951
|
+
<div class="obs-hint-code"><span class="hl-red">logger.error('Request failed')</span>
|
|
2952
|
+
<span class="hl-dim">// В Kibana: "Request failed"</span>
|
|
2953
|
+
<span class="hl-dim">// Что за запрос? Чей? Когда?</span>
|
|
2954
|
+
<span class="hl-dim">// Какая ошибка? Какой эндпоинт?</span>
|
|
2955
|
+
<span class="hl-dim">// → звонишь разработчику в 2 ночи</span></div>
|
|
2956
|
+
</div>
|
|
2957
|
+
<div>
|
|
2958
|
+
<div class="obs-hint-label after">СТАЛО — actionable лог</div>
|
|
2959
|
+
<div class="obs-hint-code"><span class="hl-green">logger.error('request_failed', {</span>
|
|
2960
|
+
<span class="hl-green">event: 'request_failed',</span>
|
|
2961
|
+
<span class="hl-green">service: 'payment-api',</span>
|
|
2962
|
+
<span class="hl-green">trace_id: req.traceId,</span>
|
|
2963
|
+
<span class="hl-green">user_id: req.userId,</span>
|
|
2964
|
+
<span class="hl-green">error_code: e.code,</span>
|
|
2965
|
+
<span class="hl-green">outcome: 'failure'</span>
|
|
2966
|
+
<span class="hl-green">})</span>
|
|
2967
|
+
<span class="hl-dim">// → фильтр по user_id, алерт по error_code</span></div>
|
|
2968
|
+
</div>
|
|
2969
|
+
</div>
|
|
2970
|
+
</div>
|
|
2971
|
+
<div class="obs-hint-section">
|
|
2972
|
+
<div class="obs-hint-section-title">Обязательные поля и зачем они нужны</div>
|
|
2973
|
+
<div class="obs-hint-code"><span class="hl-green">service</span> — какой сервис логирует (нужен для фильтрации в мульти-сервисе)
|
|
2974
|
+
<span class="hl-green">event_name</span> — машиночитаемое название события (для алертов и дашбордов)
|
|
2975
|
+
<span class="hl-green">trace_id</span> — сквозной ID запроса (связывает логи из разных сервисов)
|
|
2976
|
+
<span class="hl-green">outcome</span> — success/failure (позволяет строить SLO-метрики)
|
|
2977
|
+
<span class="hl-yellow">user_id</span> — чей запрос (обязателен для error/warn)
|
|
2978
|
+
<span class="hl-yellow">error_code</span> — код ошибки (обязателен для error/warn)</div>
|
|
2979
|
+
</div>
|
|
2980
|
+
<div class="obs-hint-section">
|
|
2981
|
+
<div class="obs-hint-section-title">Как использовать</div>
|
|
2982
|
+
<p>Каждая строчка — пропущенное поле и сколько раз оно отсутствует. Раскрой строку, выбери затронутые модули и нажми <strong>«обогатить выбранные»</strong> — агент добавит поля в существующие лог-вызовы.</p>
|
|
2983
|
+
</div>
|
|
2984
|
+
</div>
|
|
2985
|
+
</div>
|
|
2770
2986
|
<div class="obs-card">
|
|
2771
2987
|
<div class="obs-title">Пробелы по полям</div>
|
|
2772
2988
|
<div class="obs-sub" style="margin-bottom:8px">Обязательные поля по стандарту: service, env, trace_id, request_id, event_name, outcome, error_code (warn/error), user_id.</div>
|
|
@@ -2775,6 +2991,34 @@ function renderObservability(c) {
|
|
|
2775
2991
|
</div>
|
|
2776
2992
|
|
|
2777
2993
|
<div class="obs-tab-content" data-obstab="catalog">
|
|
2994
|
+
<div class="obs-hint" id="obs-hint-catalog">
|
|
2995
|
+
<button class="obs-hint-toggle" onclick="toggleObsHint('obs-hint-catalog')">
|
|
2996
|
+
<span class="obs-hint-icon">?</span>
|
|
2997
|
+
Как читать таблицу и что означают колонки?
|
|
2998
|
+
<span class="obs-hint-chevron">▼</span>
|
|
2999
|
+
</button>
|
|
3000
|
+
<div class="obs-hint-body">
|
|
3001
|
+
<p>Каталог — полная карта всех источников логов в проекте. Каждая строка = один файл/модуль. Это отправная точка для ручного аудита или приоритизации задач агента.</p>
|
|
3002
|
+
<div class="obs-hint-section">
|
|
3003
|
+
<div class="obs-hint-section-title">Что означают колонки</div>
|
|
3004
|
+
<div class="obs-hint-code"><span class="hl-green">формат</span> <span class="hl-green">structured</span> — логи в JSON с полями. Можно фильтровать, алертить.
|
|
3005
|
+
<span class="hl-yellow">mixed</span> — часть логов структурированы, часть — нет.
|
|
3006
|
+
<span class="hl-red">unstructured</span> — просто строки. Ни алертов, ни поиска по полям.
|
|
3007
|
+
|
|
3008
|
+
<span class="hl-yellow">пробелы</span> <span class="hl-dim">N/8</span> — сколько из 8 обязательных полей отсутствуют.
|
|
3009
|
+
<span class="hl-green">0/8</span> — отлично. <span class="hl-red">5/8</span> — нужно работать.
|
|
3010
|
+
|
|
3011
|
+
<span class="hl-dim">действие</span> suppress — модуль генерирует шум, логи нужно убрать/понизить.
|
|
3012
|
+
enrich fields — логи есть, но без нужных полей.
|
|
3013
|
+
add event — нет вообще никаких логов в критичных местах.
|
|
3014
|
+
downgrade level— используется INFO там, где достаточно DEBUG.</div>
|
|
3015
|
+
</div>
|
|
3016
|
+
<div class="obs-hint-section">
|
|
3017
|
+
<div class="obs-hint-section-title">Как использовать</div>
|
|
3018
|
+
<p>Нажми <strong>«исправить»</strong> в строке конкретного модуля — агент откроет файл, посмотрит контекст и применит рекомендованное действие. Удобно для точечных правок без выбора целой группы.</p>
|
|
3019
|
+
</div>
|
|
3020
|
+
</div>
|
|
3021
|
+
</div>
|
|
2778
3022
|
<div class="obs-card">
|
|
2779
3023
|
<div class="obs-title">Каталог источников логов</div>
|
|
2780
3024
|
<div class="obs-catalog" style="margin-top:8px;border:none;padding:0">
|