viberadar 0.3.205 → 0.3.206
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/server/index.d.ts.map +1 -1
- package/dist/server/index.js +19 -15
- package/dist/server/index.js.map +1 -1
- package/dist/ui/dashboard.html +73 -95
- package/package.json +1 -1
package/dist/ui/dashboard.html
CHANGED
|
@@ -815,10 +815,6 @@
|
|
|
815
815
|
.obs-copy-btn:disabled { opacity:0.35; cursor:not-allowed; }
|
|
816
816
|
.obs-select-all { font-size:12px; color:var(--dim); cursor:pointer; background:none; border:none; padding:4px 8px; }
|
|
817
817
|
.obs-select-all:hover { color:var(--accent); }
|
|
818
|
-
.obs-tier-badge { display:inline-block; padding:3px 8px; border-radius:3px; font-size:11px; font-weight:700; letter-spacing:0.5px; }
|
|
819
|
-
.obs-tier-critical { background:rgba(248,81,73,0.2); color:var(--red); }
|
|
820
|
-
.obs-tier-important { background:rgba(227,179,65,0.2); color:var(--yellow); }
|
|
821
|
-
.obs-tier-normal { background:rgba(139,148,158,0.15); color:var(--muted); }
|
|
822
818
|
.obs-fp-list { font-size:11px; color:var(--muted); margin:4px 0 0 18px; }
|
|
823
819
|
.obs-fp-item { display:flex; gap:6px; padding:1px 0; align-items:baseline; }
|
|
824
820
|
.obs-noisy-detail { display:none; padding:6px 0 2px 0; border-top:1px dashed var(--border); margin-top:4px; }
|
|
@@ -4581,18 +4577,11 @@ function renderObsGlobalDetail(c, filterFeatureKey) {
|
|
|
4581
4577
|
const _blCurrFPs = missingV2.reduce((s, m) => s + (m.failurePoints || []).length, 0);
|
|
4582
4578
|
const _blCurrNoise = topNoisy.length;
|
|
4583
4579
|
const _blCurrEnrich = Object.entries(fieldGapsData).filter(([, v]) => v > 0).length;
|
|
4584
|
-
|
|
4585
|
-
|
|
4586
|
-
|
|
4587
|
-
|
|
4588
|
-
}
|
|
4589
|
-
|
|
4590
|
-
if (!_bl) {
|
|
4591
|
-
_bl = { ts: Date.now(), noiseRatio, structPct, actionPct, coveragePct,
|
|
4592
|
-
missing: _blCurrMissing, fps: _blCurrFPs, noise: _blCurrNoise, enrich: _blCurrEnrich,
|
|
4593
|
-
tiers: _blCurrTiers };
|
|
4594
|
-
try { localStorage.setItem('vr_obs_bl_' + _bsKey, JSON.stringify(_bl)); } catch(e) {}
|
|
4595
|
-
}
|
|
4580
|
+
if (!_bl) {
|
|
4581
|
+
_bl = { ts: Date.now(), noiseRatio, structPct, actionPct, coveragePct,
|
|
4582
|
+
missing: _blCurrMissing, fps: _blCurrFPs, noise: _blCurrNoise, enrich: _blCurrEnrich };
|
|
4583
|
+
try { localStorage.setItem('vr_obs_bl_' + _bsKey, JSON.stringify(_bl)); } catch(e) {}
|
|
4584
|
+
}
|
|
4596
4585
|
|
|
4597
4586
|
// Delta badge helpers
|
|
4598
4587
|
const _d = (curr, base, invert = false) => {
|
|
@@ -4706,7 +4695,7 @@ function renderObsGlobalDetail(c, filterFeatureKey) {
|
|
|
4706
4695
|
</div>`;
|
|
4707
4696
|
}).join('') || '<div class="obs-sub">Шумных паттернов не обнаружено</div>';
|
|
4708
4697
|
|
|
4709
|
-
// ── Missing
|
|
4698
|
+
// ── Missing failure logs (V2: flat list; no heuristic risk tiers in UI) ──
|
|
4710
4699
|
const v2Data = missingV2.filter(m => m.failurePoints.length > 0);
|
|
4711
4700
|
window.__obsMissingV2 = v2Data;
|
|
4712
4701
|
window.__obsMissingGroupMeta = {};
|
|
@@ -4714,66 +4703,56 @@ function renderObsGlobalDetail(c, filterFeatureKey) {
|
|
|
4714
4703
|
'empty-catch':'пустой catch','catch-no-log':'catch без лога','promise-catch-no-log':'.catch без лога',
|
|
4715
4704
|
'http-no-error-handling':'HTTP без обработки','db-no-error-handling':'DB без обработки',
|
|
4716
4705
|
'throw-no-log':'throw без лога','error-check-no-log':'if(err) без лога',
|
|
4717
|
-
};
|
|
4718
|
-
let missingSection = '';
|
|
4719
|
-
if (v2Data.length > 0) {
|
|
4720
|
-
const
|
|
4721
|
-
const
|
|
4722
|
-
|
|
4723
|
-
|
|
4724
|
-
|
|
4725
|
-
|
|
4726
|
-
|
|
4727
|
-
|
|
4728
|
-
|
|
4729
|
-
|
|
4730
|
-
|
|
4731
|
-
|
|
4732
|
-
|
|
4733
|
-
const
|
|
4734
|
-
const
|
|
4735
|
-
|
|
4736
|
-
|
|
4737
|
-
|
|
4738
|
-
|
|
4739
|
-
|
|
4740
|
-
|
|
4741
|
-
).join('')
|
|
4742
|
-
|
|
4743
|
-
|
|
4744
|
-
|
|
4745
|
-
|
|
4746
|
-
|
|
4747
|
-
|
|
4748
|
-
|
|
4749
|
-
|
|
4750
|
-
|
|
4751
|
-
|
|
4752
|
-
}).join('');
|
|
4753
|
-
const addBtn = hasAgent ? `<button class="obs-run-selected" disabled onclick="obsMissingRunSelected('${groupId}')">добавить логи выбранным</button><button class="obs-copy-btn obs-copy-selected" disabled title="Скопировать промпт" onclick="obsCopyMissingSelected('${groupId}')">📋</button>` : '';
|
|
4754
|
-
const detail = hasAgent ? `
|
|
4755
|
-
<div id="obs-detail-${groupId}" class="obs-detail" data-obs-action="missing" data-obs-label="${tierLabels[tier]}">
|
|
4756
|
-
<div class="obs-detail-bar" style="border-top:none;padding-top:0;margin-bottom:4px">
|
|
4757
|
-
<button class="obs-select-all" onclick="obsToggleAll('${groupId}')">выбрать все / снять</button>
|
|
4758
|
-
</div>
|
|
4759
|
-
<div class="obs-detail-list">${detailItems}</div>
|
|
4760
|
-
<div class="obs-detail-bar">${addBtn}</div>
|
|
4761
|
-
</div>` : '';
|
|
4762
|
-
const _blTier = _bl?.tiers?.[tier];
|
|
4763
|
-
return `<div class="obs-tier-group">
|
|
4764
|
-
<div class="obs-tier-group-header">
|
|
4765
|
-
<span class="obs-tier-badge obs-tier-${tier}">${tierLabels[tier]}</span>
|
|
4766
|
-
<span>${items.length}${_d(items.length, _blTier?.modules)} модулей, ${totalFPs}${_d(totalFPs, _blTier?.fps)} точек отказа</span>
|
|
4767
|
-
${copyGroupBtn}
|
|
4768
|
-
${expandBtn}
|
|
4706
|
+
};
|
|
4707
|
+
let missingSection = '';
|
|
4708
|
+
if (v2Data.length > 0) {
|
|
4709
|
+
const groupId = 'missing-all';
|
|
4710
|
+
const groupIndices = v2Data
|
|
4711
|
+
.map(m => (o.missingCriticalLogsV2 || []).indexOf(m))
|
|
4712
|
+
.filter(idx => idx >= 0);
|
|
4713
|
+
window.__obsMissingGroupMeta[groupId] = {
|
|
4714
|
+
missingLogIndices: groupIndices,
|
|
4715
|
+
recommendationType: 'add event',
|
|
4716
|
+
};
|
|
4717
|
+
const expandBtn = hasAgent ? `<button class="obs-expand-btn" onclick="event.stopPropagation();toggleObsDetail('${groupId}')">▼</button>` : '';
|
|
4718
|
+
const copyGroupBtn = `<button class="obs-copy-btn" title="Скопировать prompt по всем точкам отказа" onclick="event.stopPropagation();obsCopyPrompt('obs-fix-selected',window.__obsMissingGroupMeta['${groupId}'])">📋 Промпт</button>`;
|
|
4719
|
+
const totalFPs = v2Data.reduce((s,m) => s + m.failurePoints.length, 0);
|
|
4720
|
+
const detailItems = v2Data.map(m => {
|
|
4721
|
+
const globalIdx = (o.missingCriticalLogsV2 || []).indexOf(m);
|
|
4722
|
+
const fpCount = m.failurePoints.length;
|
|
4723
|
+
const fpPreview = m.failurePoints.slice(0,3).map(fp =>
|
|
4724
|
+
`<div class="obs-fp-item"><span class="obs-fp-type">${fpTypeLabels[fp.type]||fp.type}</span><span class="obs-fp-line">~${fp.lineApprox}</span></div>`
|
|
4725
|
+
).join('');
|
|
4726
|
+
const moreCount = fpCount > 3 ? `<div class="obs-fp-item" style="color:var(--dim)">...и ещё ${fpCount-3}</div>` : '';
|
|
4727
|
+
const covBadge = m.hasAnyWarnError ? '<span style="font-size:10px;color:var(--dim)" title="Есть warn/error, но не все точки покрыты">частично</span>' : '';
|
|
4728
|
+
return `<label class="obs-detail-item" style="flex-wrap:wrap">
|
|
4729
|
+
<input type="checkbox" data-missing-idx="${globalIdx}" onchange="obsUpdateSelectedCount('${groupId}')">
|
|
4730
|
+
<span title="${escapeHtml(m.modulePath)}" style="flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap">${escapeHtml(m.modulePath.split('/').slice(-2).join('/'))}</span>
|
|
4731
|
+
<span style="color:var(--yellow);flex-shrink:0">${fpCount} точек</span>
|
|
4732
|
+
${covBadge}
|
|
4733
|
+
${fpPreview || moreCount ? `<div class="obs-fp-list" style="width:100%">${fpPreview}${moreCount}</div>` : ''}
|
|
4734
|
+
</label>`;
|
|
4735
|
+
}).join('');
|
|
4736
|
+
const addBtn = hasAgent ? `<button class="obs-run-selected" disabled onclick="obsMissingRunSelected('${groupId}')">prompt по выбранным</button><button class="obs-copy-btn obs-copy-selected" disabled title="Скопировать промпт" onclick="obsCopyMissingSelected('${groupId}')">📋</button>` : '';
|
|
4737
|
+
const detail = hasAgent ? `
|
|
4738
|
+
<div id="obs-detail-${groupId}" class="obs-detail" data-obs-action="missing" data-obs-label="точки отказа">
|
|
4739
|
+
<div class="obs-detail-bar" style="border-top:none;padding-top:0;margin-bottom:4px">
|
|
4740
|
+
<button class="obs-select-all" onclick="obsToggleAll('${groupId}')">выбрать все / снять</button>
|
|
4769
4741
|
</div>
|
|
4770
|
-
|
|
4771
|
-
|
|
4772
|
-
|
|
4773
|
-
missingSection =
|
|
4774
|
-
|
|
4775
|
-
|
|
4776
|
-
|
|
4742
|
+
<div class="obs-detail-list">${detailItems}</div>
|
|
4743
|
+
<div class="obs-detail-bar">${addBtn}</div>
|
|
4744
|
+
</div>` : '';
|
|
4745
|
+
missingSection = `<div class="obs-tier-group">
|
|
4746
|
+
<div class="obs-tier-group-header">
|
|
4747
|
+
<span>Точки отказа без достаточного логирования: ${v2Data.length}${_d(v2Data.length, _bl?.missing)} модулей, ${totalFPs}${_d(totalFPs, _bl?.fps)} точек</span>
|
|
4748
|
+
${copyGroupBtn}
|
|
4749
|
+
${expandBtn}
|
|
4750
|
+
</div>
|
|
4751
|
+
${detail}
|
|
4752
|
+
</div>`;
|
|
4753
|
+
} else {
|
|
4754
|
+
missingSection = '<div class="obs-sub" style="color:var(--green)">Точки отказа покрыты</div>';
|
|
4755
|
+
}
|
|
4777
4756
|
|
|
4778
4757
|
const fieldGaps = fieldGapsData;
|
|
4779
4758
|
window.__obsFieldGroupMeta = {};
|
|
@@ -4967,7 +4946,7 @@ function renderObsGlobalDetail(c, filterFeatureKey) {
|
|
|
4967
4946
|
<div class="obs-list">
|
|
4968
4947
|
<div class="obs-list-item"><span style="color:var(--red)">Мусор (убрать)</span><strong>${o.classification.trash}</strong></div>
|
|
4969
4948
|
<div class="obs-list-item"><span style="color:var(--green)">Полезные</span><strong>${o.classification.useful}</strong></div>
|
|
4970
|
-
<div class="obs-list-item"><span style="color:var(--blue)"
|
|
4949
|
+
<div class="obs-list-item"><span style="color:var(--blue)">Actionable warn/error</span><strong>${o.classification.critical}</strong></div>
|
|
4971
4950
|
</div>
|
|
4972
4951
|
</div>
|
|
4973
4952
|
<div class="obs-card">
|
|
@@ -5094,12 +5073,12 @@ function renderObsGlobalDetail(c, filterFeatureKey) {
|
|
|
5094
5073
|
</div>
|
|
5095
5074
|
<div class="obs-hint-section">
|
|
5096
5075
|
<div class="obs-hint-section-title">Как использовать</div>
|
|
5097
|
-
<p
|
|
5076
|
+
<p>Это не шкала критичности и не команда “логировать всё”. VibeRadar показывает найденные точки отказа: скопируй промпт, дай агенту прочитать контекст и добавлять warn/error только там, где это реально operational-сбой.</p>
|
|
5098
5077
|
</div>
|
|
5099
5078
|
</div>
|
|
5100
5079
|
</div>
|
|
5101
5080
|
<div class="obs-card">
|
|
5102
|
-
<div class="obs-title"
|
|
5081
|
+
<div class="obs-title">Точки отказа без достаточного логирования</div>
|
|
5103
5082
|
<div class="obs-list" style="gap:4px">${missingSection}</div>
|
|
5104
5083
|
</div>
|
|
5105
5084
|
</div>
|
|
@@ -5180,7 +5159,7 @@ function renderObsGlobalDetail(c, filterFeatureKey) {
|
|
|
5180
5159
|
|
|
5181
5160
|
<span class="hl-dim">действие</span> suppress — модуль генерирует шум, логи нужно убрать/понизить.
|
|
5182
5161
|
enrich fields — логи есть, но без нужных полей.
|
|
5183
|
-
add event —
|
|
5162
|
+
add event — найдены точки отказа без достаточного warn/error покрытия.
|
|
5184
5163
|
downgrade level— используется INFO там, где достаточно DEBUG.</div>
|
|
5185
5164
|
</div>
|
|
5186
5165
|
<div class="obs-hint-section">
|
|
@@ -5355,19 +5334,18 @@ function renderObservabilityOverview(c) {
|
|
|
5355
5334
|
`<div class="obs-row"><span class="obs-priority-${i.priority}">[${i.priority}]</span> ${escapeHtml(i.pattern)} · x${i.count} → <b>${i.recommendation}</b></div>`
|
|
5356
5335
|
).join('') || '<div class="obs-row">Нет шумных паттернов</div>';
|
|
5357
5336
|
|
|
5358
|
-
const v2Missing = o.missingCriticalLogsV2 || [];
|
|
5359
|
-
let missing;
|
|
5360
|
-
if (v2Missing.length) {
|
|
5361
|
-
|
|
5362
|
-
|
|
5363
|
-
|
|
5364
|
-
)
|
|
5365
|
-
|
|
5366
|
-
|
|
5367
|
-
|
|
5368
|
-
|
|
5369
|
-
|
|
5370
|
-
}
|
|
5337
|
+
const v2Missing = o.missingCriticalLogsV2 || [];
|
|
5338
|
+
let missing;
|
|
5339
|
+
if (v2Missing.length) {
|
|
5340
|
+
missing = v2Missing.slice(0, 8).map(m =>
|
|
5341
|
+
`<div class="obs-row">${escapeHtml(m.modulePath)} · ${m.failurePoints.length} точек отказа${m.hasAnyWarnError ? ' · частично покрыто' : ''}</div>`
|
|
5342
|
+
).join('');
|
|
5343
|
+
if (v2Missing.length > 8) missing += `<div class="obs-row" style="color:var(--dim)">...и ещё ${v2Missing.length - 8}</div>`;
|
|
5344
|
+
} else {
|
|
5345
|
+
missing = (o.missingCriticalLogs || []).slice(0, 5).map(i =>
|
|
5346
|
+
`<div class="obs-row"><span class="obs-priority-${i.priority}">[${i.priority}]</span> ${escapeHtml(i.pattern)} → <b>${i.recommendation}</b></div>`
|
|
5347
|
+
).join('') || '<div class="obs-row">Точки отказа покрыты</div>';
|
|
5348
|
+
}
|
|
5371
5349
|
|
|
5372
5350
|
const catalogRows = (o.catalog || []).slice(0, 10).map(i =>
|
|
5373
5351
|
`<div class="obs-cat-row"><span>${escapeHtml(i.modulePath)}</span><span>${i.level}</span><span>${i.format}</span><span>${i.frequency}</span><span>${escapeHtml(i.owner)}</span><span>${i.recommendation}</span></div>`
|
|
@@ -5385,7 +5363,7 @@ function renderObservabilityOverview(c) {
|
|
|
5385
5363
|
${noisy}
|
|
5386
5364
|
</div>
|
|
5387
5365
|
<div class="obs-list">
|
|
5388
|
-
<h4
|
|
5366
|
+
<h4>Точки отказа без логов</h4>
|
|
5389
5367
|
${missing}
|
|
5390
5368
|
</div>
|
|
5391
5369
|
</div>
|
|
@@ -5395,7 +5373,7 @@ function renderObservabilityOverview(c) {
|
|
|
5395
5373
|
${catalogRows || '<div class="obs-row">Логи не найдены</div>'}
|
|
5396
5374
|
</div>
|
|
5397
5375
|
<div class="obs-row" style="margin-top:8px">
|
|
5398
|
-
|
|
5376
|
+
Классификация логов: шум ${o.classification.trash} · полезно ${o.classification.useful} · actionable warn/error ${o.classification.critical}
|
|
5399
5377
|
</div>
|
|
5400
5378
|
</div>`;
|
|
5401
5379
|
}
|