Однажды я писал один проект. Проект выдался большим и писал я его долго.
Там было все что только можно было запихнуть — и retrolambda/java8, и пара десятков
других библиотек (жадность заказчика до новых фич не знала границ, а потому
росло число зависимостей).
Но речь даже не об этом. Настало время делать релиз. И оказалось что в проекте
множество логов и неплохо бы их из релизной сборки убрать. Всем известный
способ с ProGuard не сработал с первого раза. С каждым новым "-keep"
приложение падало в каком-то новом месте. Так что ProGuard пришлось отключить
до лучших времен.
Все это время меня не покидало ощущуение, что управление уровнем логировния c
помощью изменения байт-кода — это нелепо. И тогда за полчаса я написал свой
примитивный логгер.
Обычно я редко довожу свои проекты до конца, но тут он был настолько прост — что теперь он лежит на гитхабе, желающие — пользуйтесь.
Одна из причин почему я не стал использовать Timber — потому что мои пальцы
привыкли печатать Log.d. Свой класс я назвал тоже «Log», а методы сделал совместимыми с «android.util.Log».
Это значит, что если вы захотите соскочить со стандартного логгера — просто
замените импорты. Это можно сделать с помощью sed, или с помощью вашей любимой
IDE.
Ну вот несколько отрывков кода, показывающие основные фичи логгера:
Исходники на гитхабе: github.com/zserge/log
В build.gradle библиотека подключается как обычно:
Вот так можно заменить импорты:
Логгер под лицензией MIT, используйте на здоровье. Там один класс без
зависимостей, всего на 250 строк, так что проект ваш тяжелей/тормозней не станет.
Любые пожелания или багрепорты (особенно с патчами) приветствуются!
UPD: Всем спасибо за код-ревью и конструктивные замечания. Благодаря вам выложил версию 1.1.5.
Там было все что только можно было запихнуть — и retrolambda/java8, и пара десятков
других библиотек (жадность заказчика до новых фич не знала границ, а потому
росло число зависимостей).
Но речь даже не об этом. Настало время делать релиз. И оказалось что в проекте
множество логов и неплохо бы их из релизной сборки убрать. Всем известный
способ с ProGuard не сработал с первого раза. С каждым новым "-keep"
приложение падало в каком-то новом месте. Так что ProGuard пришлось отключить
до лучших времен.
Все это время меня не покидало ощущуение, что управление уровнем логировния c
помощью изменения байт-кода — это нелепо. И тогда за полчаса я написал свой
примитивный логгер.
Обычно я редко довожу свои проекты до конца, но тут он был настолько прост — что теперь он лежит на гитхабе, желающие — пользуйтесь.
Совместимое API — залог простой миграции
Одна из причин почему я не стал использовать Timber — потому что мои пальцы
привыкли печатать Log.d. Свой класс я назвал тоже «Log», а методы сделал совместимыми с «android.util.Log».
Это значит, что если вы захотите соскочить со стандартного логгера — просто
замените импорты. Это можно сделать с помощью sed, или с помощью вашей любимой
IDE.
А в чем преимущество?
Ну вот несколько отрывков кода, показывающие основные фичи логгера:
// Весь ваш старый код останется работать как и прежде
Log.d(tag, "X equals " + x);
// Но теперь можно будет выводить несколько значений через запятую
Log.d(tag, "X", x)
// Можно будет не писать теги, по умолчанию они возьмутся из имени класса
class Foo {
public void foo() {
Log.d("Hello"); // выведет 'D/Foo: Hello'
}
}
// Разве только в классе будет свой атрибут "tag" (или "TAG")
class Foo {
private final static String TAG = "Bar";
public void foo() {
Log.d("Hello"); // выведет 'D/Bar: Hello'
Log.d(TAG, "Hello"); // выведет 'D/Bar: Hello', не 'D/Bar: Bar Hello'
}
}
// Конечно, все это настаиваемо и атрибут тега может называться как угодно
class Foo {
static {
Log.useTags(new String[]{"tag", "TAG", "MYTAG", "_TAG", "iLoveLongFieldName"});
}
private final static String _TAG = "Bar";
...
}
// Можно выводить экспешены, для них будет напечатан стек-трейс
Exception e = new Exception("foo");
Log.d("Something bad happened", someObject, "error:", e);
// Длинные сообщения можно писать через точку
Log
.d("First")
.d("Second")
.d("Third line")
// То с чего все начиналось - контроль за уровнем логирования
Log.level(Log.I);
Log.d("foo"); // ничего не выведет
// Можно использовать форматные стоки, как в String.format()
Log.useFormat(true);
Log.d("X equals %d", x); // выведет 'X equals 42'
// Если в первой строке нет процентов - будет использоваться вывод через запятую
Log.d("Value of X", x); // выведет 'Value of X 42'
// Длинные строки переносятся по '\n'. Непереносимые строки длиннее 4000
// символов будет переноситься по пробелам или пунктуации. Можно смело
// выводить длинные JSON-ы или HTML
Log.d("Hello\nworld"); // выведет 'D/SomeTag: Hello', затем 'D/SomeTag: world'
// Логгер работает как в андроиде, так и в JVM.
// В андроиде логирование ведется через стандартный логгер, в обычной джаве -
// через System.out.println
// Но все это можно настроить вручную
Log.usePrinter(Log.SYSTEM.true).usePrinter(Log.ANDROID, false).d("hello"); // использовать System.out, в том числе и в андроиде
// А еще можно использовать свои "принтеры", например для Crashlytics
Log.usePrinter(mCrashlyricsPrinter, true);
Уговорили, где взять?
Исходники на гитхабе: github.com/zserge/log
В build.gradle библиотека подключается как обычно:
repositories {
jcenter() // или mavenCentral()
}
dependencies {
compile 'co.trikita:log:1.1.5'
}
Вот так можно заменить импорты:
$ find -name "*.java" -type f -exec sed -i 's/import android.util.Log/import trikita.log.Log/g' {} \;
Логгер под лицензией MIT, используйте на здоровье. Там один класс без
зависимостей, всего на 250 строк, так что проект ваш тяжелей/тормозней не станет.
Любые пожелания или багрепорты (особенно с патчами) приветствуются!
UPD: Всем спасибо за код-ревью и конструктивные замечания. Благодаря вам выложил версию 1.1.5.
- Потокобезопасность пришлось сделать в лоб, через synchronized. Померял скорость — практически не замедлилась, зато многострочные сообщения не разрываются если их печатать из разных потоков. Да и так спокойнее если вдруг принтер не многопоточный
- Проверил бенчмарки — да, мой логгер медленнее чем android.util.Log за счет рефлексии. Однако он ничуть не медленнее Timber'а. Вообщем, если вы пишете меньше чем 10000 логов в секунду — проблем с производительностью не будет
- Добавил приватный конструктор, ну и там по мелочам — где названия привел в порядок, где документацию