Я слышал о Timber и читал github README , но это немного сбивает меня с толку.
Поведение добавляется через экземпляры дерева. Вы можете установить экземпляр, позвонив на Timber.plant. Установку деревьев следует производить как можно раньше. OnCreate вашего приложения — наиболее логичный выбор.
Это регистратор с небольшим расширяемым API, который предоставляет утилиту поверх обычного класса Log в Android.
Что еще он предоставляет поверх журнала Android?
Реализация DebugTree автоматически определит, из какого класса он вызывается, и будет использовать это имя класса в качестве своего тега. Поскольку теги различаются, он отлично работает в сочетании с программой чтения журналов, такой как Pidcat.
Что такое DebugTree?
По умолчанию реализации Tree не устанавливаются, потому что каждый раз, когда вы входите в производственную среду, щенок умирает.
Опять же, что такое реализация дерева? Что оно делает? И как мне перестать убивать щенков?
Smart Timber — приложение для подсчета запасов леса
Два простых шага:
Установите любые экземпляры Tree, которые вы хотите, в onCreate вашего класса приложения.
Вызов статических методов Timber повсюду в вашем приложении.
Что за два простых шага?
Ничего из этого не было объяснено в Readme. Это в значительной степени описание для тех, кто уже знает, что это такое: /
Источник: question-it.com
Передаем Android логи через интернет с Timber и Node.JS
Многабукаф, не читал: я напилил очень простую реализацию удаленного логгинга. Может быть полезно, когда у вашего клиента (или, например, тестировщика) выскакивает непонятная ошибка, а вам хочется видеть сиюсекундно, что происходит в приложении. Заинтересованных прошу ниже.
Часть 1. Проблема
Вообще проблема появилась так: у тестировщика баг воспроизводился, а у меня — нет. Надо было глянуть логи, по adb подключиться было нельзя (потому что тестировщик в другмо городе и доступа к админке роутера не имел), а перекидываться файликами — это какой-то отстой.
Часть 2. Описываем проблему
Есть такая штука — Timber. Для тех — кто не знает: это библиотека, которая расширяет стандартные возможности Android’овского класса Log. При логгинге библиотека автоматически добавляет в качестве TAG название класса и название метода. Но что для нас еще важнее — там можно оверрайднуть метод логгинга и что-то сделать еще внутри.
План такой: пишем отправку сообщения на сервер со стороны Android, а потом пишем сервер для приемки сообщений.
Часть 3. Пишем для Android
В build.gradle кладем вещи: одна — что у нас DEBUG режим, вторая — SERVER_LOGGING.
Подключение логгера будет выглядеть вот так (этот код надо вызвать в Application):
private fun plantTimberTree() < if (BuildConfig.DEBUG) < if (BuildConfig.SERVER_LOGGING) < val logsSource = Injection.provideLogsDataSource() Timber.plant(ServerLoggingTree(logsSource)) >else < Timber.plant(Timber.DebugTree()) >> >
Как у нас вообще выглядит отправка лога? У лога есть приоритет, сообщение, тэг, дата. И урл, куда его отправлять, в случае удаленного логгинга. Все это дело возвращает Completable.
interface LogsDataSource
Нам надо отправлять это все на сервер с помощью, например, Retrofit’a:
Теперь давайте напишем саму отправку.
class LogsRepository( val rxSchedulers: RxSchedulers ) : LogsDataSource < private val logsService = RestApi.createService(LogsService::class.java) override fun sendLog( priority: Int, tag: String?, message: String, date: Date, url: String ): Completable < val request = logsService.sendLog( url, priority, tag, message, date ) .subscribeOn(rxSchedulers.io) return Completable.fromSingle(request) >>
Теперь давайте посмотрим на наш класс ServerLoggingTree. Там мы оверрайдим метод логгинга и вызываем в нем метод отправки на сервер.
class ServerLoggingTree( private val logsDataSource: LogsDataSource ) : Timber.DebugTree() < companion object < private const val LOG_HOST = «abcdef.ddns.net» private const val LOG_PORT = 8443 private const val LOG_PATH = «api/v1/logs.send» const val LOG_URL = «https://$LOG_HOST:$LOG_PORT/$LOG_PATH» >override fun log( priority: Int, tag: String?, message: String, t: Throwable? ) < val disposable = logsDataSource .sendLog(priority, tag, message, Date(), LOG_URL) .subscribe(<>, < Log.e(«ServerLoggingTree», «Failed to send log») >) super.log(priority, tag, message, t) > >
На этом, собственно, часть для Android закончена.
Часть 4. Пишем сервер
Писать будем на Node.JS, но вообще можно на чем угодно.
Для логгинга мы используем библиотеку Bunyan, потому что она, во-первых, поддерживает запись в файл, а во-вторых, она позволяет выводить сообщения красиво раскрашенными.
Давайте напишем штуку, которая отвечает за логгинг. Пишем, что у нас под каждый тип послания свой файлик.
let bunyan = require(‘bunyan’); let bformat = require(‘bunyan-format’); let formatOut = bformat(< outputMode: ‘short’ >); let fs = require(‘fs’); let path = process.cwd(); module.exports = function(name) < return bunyan.createLogger( < name: name, streams: [ < level: ‘error’, stream: getStream(‘error.json’) >, < level: ‘trace’, stream: getStream(‘trace.json’) >, < level: ‘debug’, stream: getStream(‘debug.json’) >, < level: ‘info’, stream: getStream(‘info.json’) >, < level: ‘warn’, stream: getStream(‘warn.json’) >, < stream: formatOut >] >); >; function getStream(file) < return fs.createWriteStream(path + ‘/logs/’ + file); >
Теперь напишем метод для приема логов от Android’a. Константы, отвечающие за приорити, были определены опытным путем.
const logger = require(‘../../../utils/Bunyan’)(«logs.send»); const PRIORITY_INFO = «4»; const PRIORITY_WARN = «5»; const PRIORITY_VERBOSE = «2»; const PRIORITY_DEBUG = «3»; const PRIORITY_ERROR = «6»; module.exports = async function(req, res) < const priority = req.body.priority; const line = getLogLine(req); if (priority === PRIORITY_INFO) < logger.info(line) >else if (priority === PRIORITY_WARN) < logger.warn(line) >else if (priority === PRIORITY_VERBOSE) < logger.trace(line) >else if (priority === PRIORITY_DEBUG) < logger.debug(line) >else if (priority === PRIORITY_ERROR) < logger.error(line) >res.send() >; function getLogLine(req)
Вот это мы примерно пишем в app.js, дабы подключить нашу штучку для логгинга.
const express = require(‘express’); const helmet = require(‘helmet’); const bodyParser = require(‘body-parser’); const logs_send = require(‘./routes/v1/logs/send’); const fs = require(‘fs’); const https = require(‘https’); const constants = require(‘./config’); const app = express(); app.set(‘view engine’, ‘jade’); app.use(helmet()); app.use(bodyParser.json()); app.use(bodyParser.urlencoded(< extended: false >)); app.use(‘/api/v1/logs.send’, logs_send); app.listen(3600); module.exports = app;
Но вообще тут два пути: если сделать так, как описано выше (без https), то в Android придется вкатывать network_security_config, разрешающий CLEARTEXT коммуникацию. Поэтому по-хорошему надо сделать вот что: на своем роутере сделать DDNS, потом получить для этого домена сертификат (через letsencrypt), ну и поднимать сервак уже с сертификатом.
Часть 5. Заключение
Всем спасибо за прочтение, надеюсь, я кому-то помог.
Источник: habr.com
Что за программа тимбер
Timbeter Log Counter
Запросите демо наших решений
Пообщайтесь с нашим отделом продаж, получите персональную демонстрацию наших решений и узнайте, что Timbeter может сделать для вашей компании.
Запросите демо наших решений
Пообщайтесь с нашим отделом продаж, получите персональную демонстрацию наших решений и узнайте, что Timbeter может сделать для вашей компании.
Источник: timbeter.com