Log levels and hygiene
Skill almasumdev/awesome-mobile-observability-agent-skills/.github/skills/logs/log-levels-and-hygiene
Agent skills for logging, metrics, tracing, crash reporting, and analytics in mobile apps.
npx -y skills add almasumdev/awesome-mobile-observability-agent-skills --skill log-levels-and-hygieneAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
2 things to look at
- no licenseNo license file was found in the repository. Code published without one is not open source by default, so using it at work is a question for whoever answers licensing questions where you are.
- 1 stars1 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.
What its author says it does
Copied from the file, not written here
Rules for choosing log levels, keeping signal/noise healthy, managing on-device log retention, and avoiding logger abuse on mobile. Use whenever adding or reviewing log statements.
SKILL.md
6.0 KB, as published. Nobody here has run it
Log Levels and Hygiene
Instructions
Mobile loggers double as crash breadcrumbs, support artifacts, and product telemetry. Without discipline they also become the loudest, most expensive channel in the stack. This skill defines the levels, the on-device retention policy, and the review rules.
1. Level Definitions
Use exactly five levels. No custom levels, no verbose vs trace variants.
| Level | Meaning | Ships remote? | Kept after crash? |
|---|---|---|---|
trace | Only during local debugging. Very chatty, per-frame or per-iteration. | Never | No |
debug | Developer-oriented. Off in release builds unless a debug flag is set. | Sampled low | Yes (last 64) |
info | Business events and state transitions worth surfacing in production. | Sampled med | Yes |
warn | Recoverable anomaly; user experience may be degraded. | Always | Yes |
error | Failed operation; requires investigation. Often paired with a non-fatal. | Always | Yes |
fatal is not a log level; it is a crash. Use recordError(fatal=true) / SentrySDK.capture instead.
2. When to Log What
- Every screen transition:
infonav_screen_shown { from, to }. - Every network request outcome:
infoon success,warnon retry,erroron final failure. Includestatus,duration_ms,request_id. - Every auth boundary:
infoon sign-in / sign-out,warnon token refresh retries,erroron auth failure. - Every feature-flag evaluation that changes user experience:
debuglevel with flag name and assignment. - Never log inside
build,render,onDraw,layoutSubviews,scrollViewDidScroll, or any per-frame callback.
3. Anti-Patterns
Log.d("TAG", "user=$user")whereuseris a full object -- leaks PII and blows up allocation. Log specific fields, after redaction.catch (e: Exception) { Log.e("err", e) }with no context. Always include what was being attempted and what is being recovered.- Logging success of every operation at
info. If 99% of calls succeed, one success log per release build is enough; log only failures atinfoor above. - Reusing one logger name for the whole app. Use
feature.subfeatureso filtering works.
4. On-Device Retention
- Crashlytics keeps the last 64 log lines per crash. Do not rely on longer history on the client.
- Write-ahead log for the remote shipper is not a persistent diagnostic log -- it is a transient queue.
- For support-driven diagnostics (opt-in "share logs" button), write a separate rotated file log:
- Rolling file size 2 MB, 3 files max (6 MB ceiling).
- Stored in the app sandbox, never in shared storage.
- Cleared on sign-out and on app uninstall (automatic on both platforms).
- Encrypted at rest if any PII can land in it, which it usually will.
5. Kotlin Example
inline fun <T> traced(logger: String, op: String, block: () -> T): T {
Log.event(logger, "${op}_start")
val start = System.nanoTime()
return try {
val result = block()
Log.event(logger, "${op}_success",
attrs = mapOf("duration_ms" to (System.nanoTime() - start) / 1_000_000))
result
} catch (t: Throwable) {
Log.event(logger, "${op}_error", level = Level.ERROR,
attrs = mapOf("error_class" to (t::class.simpleName ?: "Unknown"),
"duration_ms" to (System.nanoTime() - start) / 1_000_000))
throw t
}
}
6. Swift Example
func traced<T>(_ logger: String, op: String, _ block: () throws -> T) rethrows -> T {
AppLog.event(logger: logger, msg: "\(op)_start")
let start = DispatchTime.now().uptimeNanoseconds
do {
let r = try block()
AppLog.event(logger: logger, msg: "\(op)_success",
attrs: ["duration_ms": (DispatchTime.now().uptimeNanoseconds - start) / 1_000_000])
return r
} catch {
AppLog.event(logger: logger, msg: "\(op)_error", level: .error,
attrs: ["error_class": String(describing: type(of: error)),
"duration_ms": (DispatchTime.now().uptimeNanoseconds - start) / 1_000_000])
throw error
}
}
7. Debug Flags
Do not ship an in-app "verbose logging" toggle that a user can flip without consent implications. Instead:
- Gate verbose logging behind a remote config flag assigned only to internal QA cohorts.
- Require re-consent to ship logs if verbose mode is enabled mid-session.
- Auto-expire verbose mode after 1 hour or at app restart.
8. Review Rules
In code review, reject any new log statement that:
- Does not have a stable
msgevent name. - Logs an object reference or a full stack trace at
infoor below. - Runs inside a hot path (render, scroll, animation tick).
- Leaks PII per the redactor deny-list.
- Adds a new logger name without being listed in the logger registry.
9. Metrics on Your Own Logs
Track log_volume_per_logger_per_release and log_error_rate_per_session. Alert when either doubles release over release -- that's usually a regression, not a new feature.
Checklist
- Exactly five levels are used:
trace,debug,info,warn,error. -
tracenever ships;debugis off in release unless a gated flag is on. - No logs inside per-frame or per-scroll callbacks.
- Support-log file is rotated, capped, encrypted, cleared on sign-out.
- Verbose mode is gated by remote config and auto-expires.
- Logger registry exists and code review enforces it.
- Log-volume and log-error-rate dashboards alert on release-over-release doubling.