Skip to content

Commit be3947f

Browse files
committed
Documentation
1 parent 7614fa0 commit be3947f

File tree

4 files changed

+160
-0
lines changed

4 files changed

+160
-0
lines changed

README.md

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ Yet another one. But this one works.
88
* Separate configurations for Debug, Release, JUnit tests, and Android tests
99
* Extension for JUnit 5
1010
* Rule for JUnit 4
11+
* Easy migration from Android Log
1112

1213
The example section shows the usage of SLF4J facade on the lib side and the log control using Log4J2 on the app side.
1314

@@ -192,6 +193,19 @@ class MyClass {
192193
```
193194

194195

196+
# Migrating from Android's Log
197+
198+
Package `android-log4j2-migration` offers the replacement class for Android's `Log` for quick migration.
199+
200+
```groovy
201+
dependencies {
202+
implementation 'io.github.neboskreb:android-log4j2-migration:2.0'
203+
}
204+
```
205+
206+
See article [Migration](doc/migration/README.md) for more details.
207+
208+
195209

196210
# Pinning the Log4J version
197211

doc/migration/README.md

Lines changed: 146 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,146 @@
1+
# Migrating from Android's Log to SLF4J
2+
3+
This article describes how to migrate an existing library/app to the proper SLF4J logging with the minimal impact to
4+
your development process. It assumes that a team of developers is working on the code while the migration is performed.
5+
In case of a solo developer, the steps can be merged.
6+
7+
--------
8+
9+
Migration is a three-step process:
10+
1) Add the migration package to switch from Android's `Log` to SLF4J, thus gaining control over the logging.
11+
Note that though this step allows for quick results, it comes with performance hit. Therefore, proceed to step 2
12+
as soon as your workload permits.
13+
14+
---- at this point the log control works ----
15+
16+
2) Once the logging works well, replace all `Log.x(...)` calls with proper SLF4J logging.
17+
18+
3) Once all sources are treated, remove the migration package.
19+
20+
21+
# 1. Applying the migration package
22+
23+
The migration package provides class `Log` which is a wrapper for SLF4J facade. Once employed, it redirects your used-to-be Android logs to SLF4J.
24+
Hence, you can now control the logging using `log4j2.properties` configuration.
25+
26+
The contract and signature of class `Log` is identical to Android's `Log`. Therefore, you need to replace only
27+
the `import` statement without changing any lines in the code - it will recompile without any errors.
28+
![compare-import.png](compare-import.png)
29+
30+
Such a minimal footprint allows the migration to be performed as a non-blocking task while the team continues working on
31+
other features. In the unlikely event of a merge conflict, the imports are trivial to resolve.
32+
33+
34+
## For a library
35+
36+
> See commit [How to migrate a library](https://github.com/neboskreb/android-log4j2/commit/3ddb6f67a91eee53658d2b2c655daa0fc22e40b8) for the detailed changes.
37+
38+
* Add the SLF4J dependency and the migration package:
39+
```groovy
40+
dependencies {
41+
implementation 'org.slf4j:slf4j-api:[2.0.17, 3.0)'
42+
implementation 'io.github.neboskreb:android-log4j2-migration:2.0'
43+
}
44+
```
45+
46+
* Replace `import android.util.Log` with `import com.github.neboskreb.log4j2.migration.Log` in all source files.
47+
48+
### Tests (optional)
49+
50+
Normally, you don't need to change anything because by default SLF4J prints nothing, which is the desired behaviour in tests.
51+
52+
However, if you _do_ need to see test logs, you have the control now. Add `android-log4j2` library as test dependency:
53+
```groovy
54+
dependencies {
55+
testImplementation 'io.github.neboskreb:android-log4j2:2.24'
56+
57+
androidTestImplementation 'io.github.neboskreb:android-log4j2-junit5:2.24'
58+
}
59+
```
60+
61+
Create configuration files `log4j2.properties` in the [proper folders](/README.md#location-of-config-files) for JUnit and Android tests.
62+
63+
JUnit tests will work without changes in code. For Android tests, add `@ExtendWith` [if you use JUnit 5](/README.md#junit-5) or `@Rule` [in case of JUnit 4](/README.md#junit-4).
64+
65+
66+
## For an app
67+
68+
> See commit [How to migrate an app](https://github.com/neboskreb/android-log4j2/commit/7614fa008022a5cf62b9ef338d4adb49ae9556e4) for the detailed changes.
69+
70+
* Add the SLF4J library and the migration package:
71+
```groovy
72+
dependencies {
73+
implementation 'io.github.neboskreb:android-log4j2-migration:2.0'
74+
implementation 'io.github.neboskreb:android-log4j2:2.24'
75+
// Though android-log4j2 brings Log4J2 in as a transitive dependency,
76+
// it is always a good idea to pin the exact version:
77+
implementation 'org.apache.logging.log4j:log4j-core:2.24.3'
78+
implementation 'org.apache.logging.log4j:log4j-slf4j2-impl:2.24.3'
79+
}
80+
```
81+
82+
* Replace `import android.util.Log` with `import com.github.neboskreb.log4j2.migration.Log` in all source files.
83+
84+
* Add initialization to your `App` class:
85+
```kotlin
86+
import net.loune.log4j2android.AndroidLog4jHelper
87+
88+
class App : Application() {
89+
override fun onCreate() {
90+
super.onCreate()
91+
92+
AndroidLog4jHelper.initialize(applicationContext)
93+
}
94+
}
95+
```
96+
97+
### Tests (optional)
98+
99+
Normally, you don't need to change anything because by default SLF4J prints nothing, which is the desired behaviour in tests.
100+
101+
However, if you _do_ need to see test logs, follow the same instructions as in [library](#tests-optional).
102+
103+
104+
### Bypassing the SLF4J (optional)
105+
106+
By default, `Log` wrapper redirects your logs to SLF4J facade, from whence they are sent to Log4j engine.
107+
If you want, `Log` can send the logs directly to Log4j bypassing the SLF4J. This will give a performance improvement
108+
(though very small, frankly). It is worth applying only if your app logs _heavily_.
109+
110+
This option is activated as follows:
111+
```kotlin
112+
class App : Application() {
113+
init {
114+
// Force Log to invoke the Log4j calls directly, bypassing the SLF4J facade.
115+
Log.useLog4j2()
116+
}
117+
...
118+
}
119+
```
120+
121+
122+
# 2. Replacing the Log calls
123+
124+
Add creating the logger with `log = getLogger(...)`, and replace all `Log.x(...)` calls with corresponding `log.xxx(...)`:
125+
126+
![replace-log-calls.png](replace-log-calls.png)
127+
128+
This footprint is bigger. It might result in conflicts if the module which is being migrated is under active
129+
development. In such case, postpone the replacement until the module is stabilised. Calls `Log.x(...)` and `log.xxx(...)`
130+
can co-exist in the same code without problems.
131+
132+
# 3. Removing the migration package
133+
134+
Run a global search for `import android.util.Log` and make sure it returns no results.
135+
136+
Delete dependency `io.github.neboskreb:android-log4j2-migration:2.0` from your Gradle script. Rebuild the project.
137+
You should get no compiler errors; otherwise make sure you didn't miss a `Log.x(...)` call somewhere.
138+
139+
140+
# Performance considerations
141+
142+
The `Log` wrapper internally calls `getLogger(...)` every time a line `Log.x(...)` is executed. This is by far less
143+
optimal than having the logger created once in the beginning, which is the standard approach.
144+
145+
However, the decision to replace or to keep it should be based on your business priorities and performance targets.
146+
In some cases steps 2 and 3 might be not economically worth of executing.

doc/migration/compare-import.png

123 KB
Loading
122 KB
Loading

0 commit comments

Comments
 (0)