Обновить
7
0

Пользователь

Отправить сообщение

Для такого в доке лежит вот такой раздел: https://opentelemetry.io/docs/collector/resiliency/

Если коротко, да, отказ хранилища (Prometheus/Loki/Jaeger) принять телеметрию рано или поздно приведёт к её отбрасыванию, с этим ничего не поделать (падать он при этом не будет), но этот момент можно отсрочить:

  1. Выставляем sending_queue, это спасает нас в случае кратковременных сбоев хранилища и позволяет поделать ретраи, но если падает сам OTelCol, то накопленная в нём телеметрия теряется (т.к. лежит в памяти)

  2. Использовать file_storage extension. Это заставляет sending_queue сбрасывать телеметрию на диск, что спасает при падении OTelCol. Какое-то время (пока ёмкость очереди не переполнится) телеметрия теряться не будет, плюс некоторую телеметрию всё же можно будет посмотреть с помощью ZPages

  3. Всегда можно слегка укрепить схему Application -> OTelCol -> Storage, используя промежуточное хранилище: Application -> OTelCol -> Kafka/RabbitMQ/NATS/.... -> OTelCol -> Storage. Да, это увеличивает число движущихся частей, но если нам оооооочень важно не терять телеметрию, то это вполне рабочий вариант

Далее, чтобы инстансы OTelCol не становились SPF-ами, нужно их запускать по следующей схеме:

  1. Для отдельных Application ставим OTelCol в виде Sidecar. Он может, например, докидывать метаданные о поде в кубере, приложении и т.п., если оно само этого не делает, или, например, писать телеметрию в локальные файлики с logrotate, чтобы всегда можно было "как деды" зайти в контейнер и что-то там почитать-погрепать

  2. Для каждого Host можно ставить OTelCol уровня хост-агента (K8S DaemonSet или Docker Swarm global deployment). Этот агент может докидывать метаданные о хосте, ОС и т.п., ну и, опять же, писать всю телеметрию в файлики (как в первом пункте, но теперь уже для всего хоста). Ну и плюсом может собирать, собственно, телеметрию самого хоста (с тех же cAdvisor, node-exporter, или из собственных receiver-ов)

  3. На предыдущих этапах не надо было заботиться об отказоустойчивости, т.е. если OTelCol падает (и это не просто ошибка конфига и подобные вещи, которые видно сразу), то уже пофиг.

    А вот на уровне Gateway нам уже нужно накидать сочной отказоустойчивости. Как? Правильно -- поднять больше инстансов. И тут самая главная часть -- правильный роутинг при балансировке нагрузки. Например, важно чтобы трейсы с одинаковым trace-id летели на один и тот же OTelCol, на котором будет приниматься решение о tail-sampling. Если же отправить их на два разных, то один может записать трассу, а другой -- нет, и мы получим некрасивые разрывы и невалидные метрики.

Насчёт метки "по ключу были изменения": в Redis имеются keyspace и keyevent pub/sub каналы.
keyspace говорит "на ключе А была применена операция Б"
keyevent говорит "операция Б была применена на ключе А"

Т.е. можно отслеживать все операции над конкретным ключом через keyspace и все ключи, к которым была применена конкретная операция через keyevent


Также имеется система "кеширования на стороне клиента", когда Redis через pubsub отсылает уведомления о том, что "этот ключ был изменён". Подписался, и будет тебе счастье.

(Знаю, капец, как вовремя), но почему, собственно, не подходит?
Сейчас в Redis можно загружать хранимые функции (не скрипты, а именно функции, которые являются объектами Redis, и будут сохраняться и реплицироваться). Так что такой мизер логики спокойно можно написать, добавив всего одну функцию.

К сожалению, не подскажу. Я заходил в параметры (preferences) QtCreator (где настраивается почти вся IDE), открывал CLang и крутил по всяким малоприятным (ну а что мы хотели от CLang) сайтам.

Это я делал для старого ПК, на ноуте (сейчас только с ним хожу, ибо давно не дома) изначально всё ок было.

Manjaro имба.+респект

Можно взять std::numeric_limits<double>::epsilon().

Зашёл в коменты, чтобы как раз это и найти)

std::numeric_limits<T>::epsilon есть в C++ вроде как ещё до C++11

Так это из-за шланг-анализатора. Если настройки под свой ноут покрутить, то всё ок.

Ну так всегда лучше использовать стандартные алгоритмы. Тут человек явно для примера всё пишет.

Тебе ответ о том, были данные или нет, всё-равно придёт (или не придёт, если пакет потерялся, но тогда будет timeout-event). Просто на транспортном уровне это будет несколько дешевле.

Авторизация по токену существует кучу лет. Тот же OAuth2 был опубликован в 2012, а до этого как пример можно привести ключи от игр (продажа диска и была надёжным способом доставки).

И да, библиотек для этого куча, с различными интерфейсами, и даже под плюсы, и даже, думаю, можно что-то хорошее для Qt наковырять.

Тут вопрос скорее, как сделать это на Qt, и чисто повод для меня написать немного прикольного кода.

Если библиотека предоставляет несколько путей решения нетривиальных задач, значит, имея мозг, можно выбрать оптимальный из них в конкретном контексте.

Никто не должен пилить MV поверх Qt. В Qt реализован MVD подход, предполагающий отделение данных от их отображения и обработки.

Типизация позволяет в проекте больше хелловорда не запутаться во всех этих "правильных" либах питона, считающих своим долгом возвращать Any, чтобы ты лез в доку, и смотрел, что конкретно вернула тебе эта хренотень.

Не, ну по сравнению с питоновскими либами на десять функций Qt, конечно, очень сложен. Но этой штуке скоро тридцать лет, и на тех же плюсах можно писать код не беря вообще ничего, кроме стандартной либы и Qt. Но то, что кому-то лень потратить несколько часов и разобраться в объектной модели, не делает Qt плохой либой.

Мы на работе используем как mvd, так и mvc подходы. Но у нас много кастомных виджетов и отрисовки, поэтому специально под mvc ничего допиливать не пришлось.

Лямбду можно использовать. Только надо не забыть несколько пунктов:

  • task — move-only класс. Поэтому просто захватит всё по значению — не вариант.

  • Не забываем про mutable, т.к. handleNextMessage изменяет состояние task (вызывает task.promise().finish()).

Штука с возвращаемым значением — плохой вариант. Причина проста — зачастую непросто определить, когда функция завершит выполнение и вернёт значение. Избежать можно двумя путями:

  • Qt::DirectConnection — вызывать callable сразу из потока, который дёрнул QMetaObject::invokeMethod. Нам не подходит, т.к. Active object предполагает разделение вызова операции, и её выполнения.

  • Qt::BlockingQueuedConnection — callable исполняется в том потоке, который владеет context (указатель this в вызове QMetaObject::invokeMethod), а поток, вызвавший метод будет заблокирован до конца выполнения callable. Крайне отвратительный подход.

Резюмируя, можно создать вот такую конструкцию, которая избавит нас от строковых литералов, избавит нас от макросов, и при этом будет достаточно красивой:

Метод print
QFuture<void> MetaInvokeBasedAsyncQDebugPrinter::print(const QString &message) {
    auto task = PrinterMessage{ message };
    auto future = task.promise().future();

    QMetaObject::invokeMethod(this,
    [task_object = std::move(task), this]() mutable {
        return this->handleNextMessage(task_object);
    }, Qt::QueuedConnection);

    return future;
}

Ну и теперь у нас прекратит собираться. Причина тому — попытка moc обернуть handleNextMessage в метасистему. Поэтому нужен новый подход в передаче данных. Есть два способа исправить это:

  • Пусть handleNextMessage принимает task по ссылке из лямбды.

  • Убрать пометку "slots" с handleNextMessage. Макроса Q_INVOKABLE тоже быть не должно. Но т.к. это приватный метод, и никто, нигде и никогда его вызывать не должен, то это разумно. Ну и можно принимать task хоть по значению (ибо всё равно move-only), хоть по r-value ссылке.

Ну и если возникнет идея обернуть этот callable в какой-нибудь std::bind для красоты — не вариант, потому что std::move_only_function нам пока не дали.

Да. Забыл про эту штуку. Сейчас обновлю статью.

Полагаю, это вопрос к первой части.

QQueue требует, чтобы тип был копируемый, а QPromise у нас некопируемый. Поэтому используется stl-очередь, поддерживающая move-only типы.

В коде явно видно, что сначала задача перемещается (std::move()) в очередь в методе print, а затем также перемещается обратно в методе run().

Зачастую это так. Как минимум, потому что тебе не нужен тест на то, что "результат вот этой функции -- действительно число". Тебе это прямо в сигнатуре функции дано.

Соответственно, остаётся проверять исключительно логику кода, а не его типы.

  1. Прикол с таймером для "отдышаться" лишний. Это точно никому не нужно. Если что, в крайнем случае у тебя ядро процессора будет долбиться в сотку с максимальным фпс. Но лагать ничего не будет.

  2. "Как в Angry Birds" делается тремя событиями (pressed уже обрабатывается в коде): https://www.sfml-dev.org/tutorials/2.5/window-events.php#the-mousebuttonpressed-and-mousebuttonreleased-events и https://www.sfml-dev.org/tutorials/2.5/window-events.php#the-mousemoved-event . На pressed надо запоминать координату нажатия, на moved - рисовать стрелку между координатой нажатия и текущей координатой мыши, а на released -- создавать объект и давать ускорение.

  1. Ну а какая разница, кто ограничил. Вот не пашет, и всё.

  2. Ну вот на моей работе (не могу показать по понятным причинам) использовали qmake. Но, правда сказать, там всё было плохо скорее от расдолбайства разрабов....но вообще, CMake - это унификация. А унификация - это хорошо.

  1. Моё личное мнение

  2. mingw не поддерживает некоторые модули, например, QWebEngine. По крайней мере, так было у меня чуть больше года назад, и я не видел новости, чтобы что-то заработало. Так что тут лучше msvc.

  3. На Cmake собственно перешёл сам Qt. Его активно развивают. Для простых проектов всё ещё можно использовать qmake, но имхо Cmake банально мощнее.

1

Информация

В рейтинге
Не участвует
Зарегистрирован
Активность

Специализация

Десктоп разработчик
Младший
C++
C++ stl
Qt
Linux
Многопоточность