Раскрашиваем логи

Раскрашиваем логи

Обо мне

Алексей, разработчик ClickHouse.

О чём доклад?

— не про ClickHouse?

— не про базы данных??

— не про бэкенд???

— не про разработку????

— не про технологии?????

О чём доклад?

— про одну маленькую задачу...

Запускаем сервер в терминале

Он выводит логи:

Полезные вещи в логах

— уровень логгирования;

— имя логера;

— идентификатор запроса;

— номер потока;

Скучные серые логи

Нескучные логи

Как раскрасить логи?

Использовать управляющие последовательности терминала.

ANSI escape sequences:

ESC — \x1b (hex), \033 (octal).

Пример: \x1b[31mкрасный цвет.

Как раскрасить логи?

echo -e "\033[1;41m Fatal \033[0m" \
        "\033[7;31m Critical \033[0m" \
        "\033[1;31m Error \033[0m" \
        "\033[0;31m Warning \033[0m" \
        "\033[0;33m Notice \033[0m" \
        "\033[1m Information \033[0m" \
        " Debug " \
        "\033[2m Trace \033[0m"

Классические 8/16 цветов

for i in {0..1};
do
  for j in {0..7};
  do
    echo -e "\033[${i};3${j}m ☻☺☻☺☻☺☻☺☻☺☻☺☻☺☻☺☻☺☻☺ \033[0m";
  done;
  echo;
done
    

Классические 8/16 цветов

— зависят от эмулятора терминала;

— зависят от настроек отображения.

Как раскрасить id запроса?

— псевдослучайно: каждому запросу свой цвет;

— вычислим хэш-функцию, отобразим её в цвет.

Псевдослучайные цвета

COLORS=("\033[0;31m" "\033[0;32m" "\033[0;33m" "\033[0;34m"
        "\033[0;35m" "\033[0;36m" "\033[0;37m" "\033[1;30m"
        "\033[1;31m" "\033[1;32m" "\033[1;34m" "\033[1;35m"
        "\033[1;36m");
NOCOLOR="\033[0m";

for i in {0..1000};
do
    COLOR=${COLORS[$(($RANDOM % ${#COLORS[*]}))]};
    echo -n -e $COLOR test $NOCOLOR;
done

Псевдослучайные цвета

Псевдослучайные цвета

24 bit «true color»

ESC[ 38;2;⟨r⟩;⟨g⟩;⟨b⟩ m

— поддерживается не всеми терминалами;

— например, не поддерживается screen.

Source: https://commons.wikimedia.org/wiki/File:RGB_color_cube.svg

Задача: сгенерировать псевдослучайный цвет

Вариант 1:

— генерируем каждый компонент R, G, B
  равномерно случайно в диапазоне 0..255.

for i in {0..1000}; do echo -e -n
  "\033[38;2;$((RANDOM % 256));$((RANDOM % 256));$((RANDOM % 256))m" \
  "test" \
  "\033[0m";
done

Псевдослучайные цвета

Псевдослучайные цвета

Задача: сгенерировать псевдослучайный цвет

Вариант 1:

— генерируем каждый компонент R, G, B
  равномерно случайно в диапазоне 0..255.

Недостаток:

— часто попадаются цвета, которые сливаются с фоном.

Задача: сгенерировать псевдослучайный цвет

Случайный оттенок цвета, но примерно
одинаковой яркости и насыщенности.

Очевидное решение: перейти в пространство HSV?

PS. HSV? HSL? HSB? HSI?

Source: https://commons.wikimedia.org/wiki/File:HSL-HSV_hue_and_chroma.svg

Source: https://commons.wikimedia.org/wiki/File:HSV-RGB-comparison.svg

Задача: сгенерировать псевдослучайный цвет

for (let i = 0; i < 200; ++i) {
  document.write('<span style="color: hsl('
    + Math.random() * 360
    + ', 100%, 50%)">test<\/span> ');
}

HSV, случайный компонент Hue

HSV, случайный компонент Hue

HSV, случайный компонент Hue

Недостатки:

— почему-то мало цветов;

— почему-то цвета всё-равно разной яркости.

Можно ли сделать лучше?

Можно ли сделать лучше?

Как люди воспринимают цвета?

Как описать множество всевозможных цветов?

Как выглядит цветовое пространство?

Как численно описать это пространство?

Какие цвета могут быть воспроизведены?

Можно ли сделать лучше?

Как люди воспринимают цвета?

— под каким освещением смотреть?

— под каким углом смотреть?

— кто именно смотрит?

— как наблюдатель понимает цвета?

Можно ли сделать лучше?

   
 
   

Как посчитать яркость цвета, заданного в RGB*?

1. Brightness = max(r, g, b)

2. Brightness = (r + g + b) / 3

3. Brightness = 0.299 * r + 0.587 * g + 0.114 * b

4. Brightness = 0.2126 * r + 0.7152 * g + 0.0722 * b

На самом деле все способы выше неверны без контекста.

Какое именно пространство RGB имеется ввиду? Gamma?

Яркость каждой из компонент может зависить от монитора (впрочем, мониторы калибруются) и наблюдателя (а они не калибруются).

Задача: сгенерировать псевдослучайный цвет

Случайный оттенок цвета, но примерно
одинаковой яркости и насыщенности.

Очевидное решение: перейти в пространство HSV?

Не подходит, потому что в HSV, V (value) — не яркость, а что-то другое.

И ещё мы не использовали S (saturation).

Перейдём в цветовое пространство YCbCr!

Задача: сгенерировать псевдослучайный цвет

for (let i = 0; i < 200; ++i) {
  let y = 128;
  let cb = Math.random() * 256;
  let cr = Math.random() * 256;

  let r = Math.max(0.0, Math.min(255.0,
    y + 1.402 * (cr - 128)));
  let g = Math.max(0.0, Math.min(255.0,
    y - 0.344136 * (cb - 128) - 0.714136 * (cr - 128)));
  let b = Math.max(0.0, Math.min(255.0,
    y + 1.772 * (cb - 128)));

  document.write('<span style="color: rgb('
    + r + ',' + g + ',' + b + ')">test<\/span> ');
}

YCbCr, случайные Cb, Cr

YCbCr, случайные Cb, Cr

Задача: сгенерировать псевдослучайный цвет,

Перейдём в цветовое пространство YCbCr
фиксируем Y и генерируем Cb, Cr.

Идеально? Но есть нюанс...

В YCbCr, YPbPr, YUV, компонента Y — это тоже не совсем яркость!

Гамма-коррекция

В YCbCr, YPbPr, YUV, компонента Y — это «Luma»
— нелинейно закодированная яркость с помощью gamma-compression.

sRGB #888888 на типичном мониторе - 20% от яркости, а не 50%.

Баг: изображения становятся темнее при уменьшении: http://www.ericbrasseur.org/gamma.html

Задача: сгенерировать псевдослучайный цвет,

Как сделать ещё лучше?

L*a*b*, XYZ?

Но мне надоело.

Выводы

Хотите сделать что-нибудь действительно хорошо?
— придётся изучить тонну деталей.

Внимание к деталям — важное качество разработчика.

Примечание: этот доклад очень поверхностный!

Литература: https://www.handprint.com/HP/WCL/color1.html

Спасибо!