разбор метрик HAE: фикстуры, канонизация, парсер
- tmp/research/fixtures.py собирает фикстуры из архива, вычищая измерения и сохраняя порядок ключей, форму литералов, выравнивание меток и невидимые символы; шесть фикстур в internal/hae/testdata - internal/canon — общий дом канонической формы, полноты и хеша: числа читаются литералом через json.Number, округление до 12 значащих цифр - internal/hae — разбор секции metrics, вывод слоя по метрике, разделение схем сна, координаты интервалом; recover внутри Parse, фаззинг - миграция bucket и docs/database.md
This commit is contained in:
@@ -0,0 +1,78 @@
|
||||
package hae
|
||||
|
||||
// assignLayers проставляет слой каждой группе точек.
|
||||
//
|
||||
// Правило проверено на всей истории (находка 33) и дважды ломалось на живых
|
||||
// данных при более простых формулировках: классификация доставки целиком
|
||||
// сложила минутные точки с посекундными и удвоила сумму за час, а
|
||||
// классификация каждой метрики по отдельности растащила редкие метрики по трём
|
||||
// слоям.
|
||||
//
|
||||
// Работающая формулировка в три шага:
|
||||
//
|
||||
// 1. плотная метрика (не меньше denseThreshold точек) классифицируется по
|
||||
// собственному выравниванию;
|
||||
// 2. редкая наследует самый мелкий слой среди плотных метрик этой доставки —
|
||||
// её собственное выравнивание ничего не значит, одна метка на часе бывает
|
||||
// и у минутного ряда;
|
||||
// 3. доставка без плотных метрик вовсе наследует последний надёжно выведенный
|
||||
// слой той же автоматизации, а если и его нет — берёт слой из НАДЁЖНОГО
|
||||
// заголовка.
|
||||
//
|
||||
// Третий шаг не роскошь: измерено 2 такие доставки из 89, обе с заголовком
|
||||
// `Default`. Заменить его заголовком нельзя — `Default` не означает режима.
|
||||
func assignLayers(groups []group, meta Meta, res *Result) error {
|
||||
delivery := deliveryLayer(groups)
|
||||
|
||||
if delivery == "" {
|
||||
// Плотных метрик нет: наследуем от прошлых доставок этой автоматизации,
|
||||
// иначе — от надёжного заголовка.
|
||||
delivery = meta.FallbackLayer
|
||||
if delivery == "" {
|
||||
delivery = res.HeaderLayer
|
||||
}
|
||||
if delivery == "" {
|
||||
return ErrLayerUnknown
|
||||
}
|
||||
}
|
||||
|
||||
res.Layer = delivery
|
||||
// Расхождение сверяется только с надёжным заголовком: `Default` не
|
||||
// означает режима, и сравнение с ним давало бы WARN на каждой доставке
|
||||
// потока в пять минут — сигнал утонул бы в собственном шуме.
|
||||
res.LayerMismatch = res.HeaderLayer != "" && delivery != res.HeaderLayer
|
||||
|
||||
for i := range groups {
|
||||
g := &groups[i]
|
||||
switch {
|
||||
case g.fixed:
|
||||
// Слой назначен схемой, выводить нечего.
|
||||
case g.dense:
|
||||
g.layer = g.alignment
|
||||
default:
|
||||
g.layer = delivery
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// deliveryLayer — самый мелкий слой среди плотных метрик доставки. Пустой,
|
||||
// если плотных метрик нет.
|
||||
//
|
||||
// Группы с назначенным слоем в голосовании не участвуют: суточных сводок сна
|
||||
// бывает больше порога плотности, и их полуночные метки иначе назначили бы
|
||||
// всей доставке слой hour.
|
||||
func deliveryLayer(groups []group) Layer {
|
||||
var out Layer
|
||||
for _, g := range groups {
|
||||
if g.fixed || !g.dense {
|
||||
continue
|
||||
}
|
||||
if out == "" {
|
||||
out = g.alignment
|
||||
continue
|
||||
}
|
||||
out = finer(out, g.alignment)
|
||||
}
|
||||
return out
|
||||
}
|
||||
Reference in New Issue
Block a user