Periodical log collector framework.
Photo Licensed under CC BY-NC 2.0 by jbdodane
In your Application, initialize TimberLorry with configuration on your preference.
After this, you can schedule periodical log collection.
publicclassTimberLorryApplicationextendsApplication {
@OverridepublicvoidonCreate() {
super.onCreate();
TimberLorry.initialize(newConfig.Builder()
.collectIn(10) // collect log data every 10 seconds.
.serializeWith(newGsonSerializer())
.addOutlet(newLogcatOutlet()).build(this));
TimberLorry.getInstance().schedule();
}
}TimberLorry is a log collector without data loss for some reasons(e.g. reboot, exit application). TimberLorry will store logs in the buffer(internal database by default), and periodically send it to an endpoint. If no internet connection available, the periodical work will not executed.
TimberLorry has some gateways to customize payloads, serialization logic, and buffer storage, and log endpoint.
All customization will be injected with Config object.
Payload is an entity object containing log data. The following snippet shows an example code.
publicclassButtonClickimplementsPayload {
privatefinallongtimeInMillis;
publicButtonClick(longtimeInMillis) {
this.timeInMillis = timeInMillis;
}
}Payloads will be serialized by Serializer in the buffer.
You can add your own serializer.
Here is an example using Gson.
publicclassGsonSerializerimplementsSerializer {
@OverridepublicStringserialize(Payloadpayload) {
returnnewGson().toJson(payload);
}
}We have this GsonSerializer in plug project.
If you would like to use another log data storage(e.g. internal storage, shared preferences), you can
implement your own BufferResolver.
publicclassSharedPrefBufferResolverextendsAbstractBufferResolver {
privatefinalApplicationapplication;
publicSharedPrefBufferResolver(Applicationapplication, @NonNullAccountManageraccountManager, @NonNullContentResolverresolver, Accountaccount) {
super(accountManager, resolver, account);
this.application = application;
}
@Overridepublicvoidsave(Serializerserializer, Payloadpayload) {
Recordrecord = newRecord(payload.getClass(), serializer.serialize(payload));
// ... write record on the preference.
}
@Overridepublicvoidsave(Serializerserializer, Payload... payloads) {
for (Payloadpayload : payloads) {
Recordrecord = newRecord(payload.getClass(), serializer.serialize(payload));
SharedPreferencespref = SharedPreferences.getDefaultSharedPreferences(application);
// ... write record on the preference.
}
}
@OverridepublicList<Record> fetch() {
List<Record> records = newArrayList<>();
SharedPreferencespref = SharedPreferences.getDefaultSharedPreferences(application);
// ... find records on the preference and convert them to Record.returnrecords;
}
@Overridepublicvoidremove(Recordrecord) {
SharedPreferencespref = SharedPreferences.getDefaultSharedPreferences(application);
// ... find record on the preference and remove it.
}
@Overridepublicvoidclear() {
SharedPreferencespref = SharedPreferences.getDefaultSharedPreferences(application);
pref.edit().clear().apply();
}
}You can add log endpoint with custom Outlet.
If you want to filter Payload in your Outlet, check the Payload class information in Outlet#accept(Class<?>) and return true if you accept the Payload in this Outlet.
publicclassLogcatOutletimplementsOutlet {
publicstaticfinalStringTAG = LogcatOutlet.class.getSimpleName();
/** * {@inheritDoc} */@Overridepublicbooleanaccept(Class<?> payload) {
returntrue; // every payload is logged with this outlet
}
/** * {@inheritDoc} */@OverridepublicResultdispatch(Stringpayload) {
// do thread blocking work here :)// if something went wrong here, catch the exception here and envelope it into Result object to return.Utils.logV(payload);
returnResult.success();
}
@OverridepublicStringname() {
return"LogCat";
}
}We have some customizations in "plug" project as plugin by default. Currently in "plug" project, following plugins are provided.
Via Gradle
dependencies {
compile 'com.drivemode:TimberLorry:1.0.0@aar'
compile 'com.drivemode:TimberLorry-Plug:1.0.0@aar'// this is an optional
}Copyright (C) 2015 Drivemode, Inc. All rights reserved.
Licensed under the Apache License, Version 2.0 (the "License"); you may not use
this file except in compliance with the License. You may obtain a copy of the
License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software distributed
under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
CONDITIONS OF ANY KIND, either express or implied. See the License for the
specific language governing permissions and limitations under the License.
