Structured Logging ay isang paraan ng pag-log kung saan ang bawat mensahe ay iniharap sa isang machine-readable na format na may mga key-value pair, sa halip na unstructured na teksto. Hindi tulad ng mga flat string, ang mga structured log ay naglalaman ng metadata: timestamp, antas, modyul, identifier ng kahilingan — at maaaring i-index ng mga sistema ng analitika. Ayon sa datos ng O'Reilly Effective Logging, ang paglipat sa mga structured na format ay nagbabawas ng oras ng paghahanap ng insidente mula oras hanggang minuto dahil sa kakayahang mag-filter ayon sa mga field. Ito ang de facto na pamantayan sa modernong mobile at server development: ang JSON at logfmt ay nagpapahintulot sa pagproseso ng mga log sa pamamagitan ng mga programa, hindi ng mga mata.
Mga Pangunahing Punto
Structured Logging ay isang paraan ng pag-log kung saan ang bawat mensahe ay naglalaman ng mga pinangalanang field na may naka-type na mga halaga. Sa halip na isang string tulad ng User 42 logged in from device ABC ang isang structured log ay mukhang isang set ng mga field: user_id=42, event=login, device_id=ABC, timestamp=2026-07-04T10:30:00Z.
Ang pangunahing bentahe ng mga structured log kumpara sa text log ay ang kakayahang mag-programmatic processing. Ang pag-parse ng mga text log ay nangangailangan ng mga regular na expression at mga palagay tungkol sa format ng string. Ang mga structured log ay nai-parse nang walang pagkawala: bawat field ay may kilalang uri at pangalan, na nagpapahintulot sa pagbuo ng mga query tulad ng hanapin ang lahat ng error sa awtorisasyon sa nakaraang oras para sa gumagamit 42 nang walang karagdagang pagproseso.
Ayon sa datos ng Honeycomb.io (2023), ang mga team na gumagamit ng structured logging sa production ay nakakatuklas ng mga insidente nang average na 4 na beses na mas mabilis kumpara sa mga team na umaasa sa text log at grep.
Structured Logging ay sumusuporta sa maraming format ng serialization. Ang pagpili ng format ay depende sa imprastraktura: JSON ay maginhawa para sa pagsasama sa Elasticsearch at mga cloud system, logfmt — para sa console viewing sa pamamagitan ng tail at grep, Protocol Buffers — para sa high-performance system na may limitasyon sa bandwidth.
| Format | Halimbawa | Kailan gagamitin |
|---|---|---|
| JSON | {"event":"login","user_id":42} | ELK Stack, mga cloud collector, microservices |
| Logfmt | event=login user_id=42 duration_ms=150 | Console, tail, heroku logs |
| MessagePack | Binary na katumbas ng JSON | Mga system na may mataas na karga, IoT |
JSON ay ang pinakakaraniwang format para sa mga structured log. Ito ay native na sinusuportahan ng lahat ng sistema ng pagkolekta: Logstash, Fluentd, Amazon CloudWatch, Google Cloud Logging. Ang mga JSON log ay madaling basahin ng tao at i-parse ng anumang programming language nang walang karagdagang library. Ang pangunahing disbentaha — redundancy: bawat key-value pair ay nangangailangan ng mga panipi at tutuldok, na nagpapataas ng volume ng nakaimbak na data ng 30–50% kumpara sa logfmt.
Logfmt ay binuo sa Heroku para sa console visibility. Ito ay mas compact kaysa JSON, nagpapanatili ng pagiging nababasa ng tao at madaling maputol sa pamamagitan ng cut at awk. Halimbawa: ts=2026-07-04T10:30:00Z level=error module=api status=500. Ang Logfmt ay hindi nangangailangan ng pag-escape ng karamihan ng mga character at angkop para sa stdout-logging sa mga container.
Sa mga mobile application, Structured Logging ay lumulutas ng tatlong pangunahing gawain: paghahanap ng mga sanhi ng crash nang walang reproduksyon sa device, pagsubaybay sa mga sesyon ng gumagamit at pagsusuri ng pagganap ayon sa mga bersyon ng application.
Ang mga text log sa mga mobile device ay halos walang silbi — ang developer ay hindi maaaring mag-grep ng mga log sa device ng gumagamit. Ang mga structured log ay ipinapadala sa mga cloud system (Firebase, Sentry, Datadog) at nai-index doon. Maaaring bumuo ng query: ipakita ang lahat ng crash sa iOS 17.4, bersyon ng app 3.2, sa modyul na checkouts — at makakuha ng eksaktong seleksyon sa ilang segundo.
Ayon sa datos ng Sentry (2024), ang mga application na gumagamit ng structured breadcrumbs ay may 60% na mas maraming konteksto sa bawat ulat ng crash kumpara sa mga application na nagla-log lamang ng text ng error. Ito ay direktang nakakaapekto sa bilis ng pag-aayos ng bug.
ELK Stack — Elasticsearch, Logstash, Kibana — nananatiling standard na imprastraktura para sa pagtatrabaho sa mga structured log. Ang Logstash ay tumatanggap ng mga log sa JSON, nagko-convert at nagpapadala sa Elasticsearch para sa pag-index, ang Kibana ay nagbibigay ng visual na interface para sa mga query at dashboard.
Para sa mga mobile application, popular ang mga cloud solution: Firebase Crashlytics na may custom na log, Sentry na may breadcrumbs, Datadog na may APM tracking. Tumatanggap sila ng mga structured log nang direkta mula sa mobile SDK at hindi nangangailangan ng pag-deploy ng sariling backend. Ang Firebase ay nag-aalok ng libreng pakete para sa pag-uulat ng crash, ang Sentry ay nagdaragdag ng distributed tracing, at ang Datadog ay nagsasama sa APM para sa sabay-sabay na pagsubaybay sa pagganap ng mga kahilingan sa client at server.
Grafana Loki — alternatibo sa Elasticsearch, na-optimize para sa mga log. Ang Loki ay hindi nag-i-index ng nilalaman ng mga mensahe bilang default, sa halip ay gumagamit ng mga label para sa pag-filter. Ito ay makabuluhang mas mura sa pag-iimbak at mas mabilis para sa mga query batay sa isang nakapirming set ng mga field.
// Structured logging sa pamamagitan ng Swift Logger papuntang JSON
struct StructuredLog {
let event: String
let attributes: [String: Any]
let level: String
func serialize() -> String {
var base = "event=\(event) level=\(level)"
for (key, value) in attributes {
base += " \(key)=\(value)"
}
return base
}
}
Ang unang tuntunin ng structured logging: bawat mensahe ay dapat maglaman ng identifier ng kahilingan o sesyon. Nang walang konteksto, ang isang solong log ay walang silbi — hindi posible na maunawaan kung aling gumagamit o kahilingan ito nauukol. Magdagdag ng correlation ID sa simula ng sesyon at ipasa ito sa lahat ng layer ng application.
Ang pangalawang tuntunin: pag-type ng mga field. Ang mga numerical field (duration_ms, status_code, retry_count) ay dapat ipadala bilang mga numero, hindi bilang mga string. Ang Elasticsearch at mga katulad na sistema ay nag-i-index ng mga numero at string nang magkaiba: sa mga numero ay maaaring ilapat ang mga agregasyon (average, median, persentil), sa mga string — full-text na paghahanap. Ang maling pag-type ay nag-aalis ng posibilidad na bumuo ng mga analytical dashboard.
Ang ikatlong tuntunin: iwasan ang mga nested object. Ang mga JSON log na may lalim ng nesting na higit sa 2 antas ay mahirap i-filter at i-visualize. Sa halip na {"user": {"name": "Alice", "role": "admin"}} gumamit ng flat keys: user_name=Alice user_role=admin.
// Structured logging sa Android sa pamamagitan ng Timber + logfmt
class StructuredTree : Timber.Tree() {
override fun log(priority: Int, tag: String?,
message: String?, t: Throwable?) {
val level = priorityToLevel(priority)
val logfmt = "level=$level tag=$tag message=$message"
sendToRemote(logfmt)
}
}
Minimum na set ng field para sa bawat structured na mensahe: timestamp sa ISO 8601, level (debug/info/warn/error/fatal), logger (pangalan ng modyul o klase), message (paglalarawan ng kaganapan na nababasa ng tao). Karagdagan: correlation_id, user_id (kung kilala), version (bersyon ng application), platform (iOS/Android), environment (dev/staging/prod).
Kung walang correlation_id ang mga structured log ay nagiging isang koleksyon ng mga hiwa-hiwalay na tala na hindi maaaring iugnay sa isang solong senaryo ng gumagamit. Bumuo ng UUID sa bawat pagsisimula ng application at idagdag ito sa lahat ng log ng sesyon. Sa praktika, ang correlation_id ay dapat ipasa sa lahat ng layer: mula sa mga UI event hanggang sa mga network request at background task — kung hindi, ang bahagi ng mga log ay mananatiling walang konteksto at hindi makikilahok sa analitika. Sa end-to-end tracking, ang isang UUID ay nagpapahintulot sa pagkolekta ng kumpletong larawan ng landas ng gumagamit.
Sa iOS, ang structured logging ay maaaring ipatupad sa pamamagitan ng isang wrapper sa paligid ng os_log na nagse-serialize ng mga field sa logfmt format. Sa Android — sa pamamagitan ng Timber na may custom na Tree na nagko-convert ng mga mensahe sa JSON o logfmt bago ipadala sa server.
import OSLog
struct StructuredLogger {
let subsystem: String
let category: String
func log(level: OSLogType,
event: String,
context: [String: Any]) {
let oslogger = Logger(
subsystem: subsystem,
category: category
)
let fields = context.map {
"\($0.key)=\($0.value)"
}.joined(separator: " ")
oslogger.log(level: level,
"\(event) \(fields)")
}
}
Ang pagpili sa pagitan ng structured at text log ay depende sa yugto ng proyekto. Sa mga unang yugto ng pag-unlad, ang mga text log ay mas simple at mas mabilis — ang developer ay nagsusulat ng mensahe nang direkta nang walang karagdagang wrapper. Ngunit sa sandaling lumampas ang proyekto sa mga hangganan ng isang team o isang server, ang mga structured log ay nagiging mandatory.
| Kriterion | Text log | Structured log |
|---|---|---|
| Pagiging nababasa | Mataas sa console | Katamtaman (nangangailangan ng pretty-print) |
| Paghahanap | grep sa substring | Query ayon sa mga field at halaga |
| Agregasyon | Hindi sinusuportahan | Average, median, persentil |
| Integrasyon | Nangangailangan ng pag-parse | Native sa ELK/Loki/Datadog |
| Dami ng imbakan | Mas maliit (walang metadata) | Mas malaki (mga field + halaga) |
Mga Madalas Itanong
Para sa pagpapadala sa server gamitin ang JSON — ito ay native na sinusuportahan ng Firebase Crashlytics, Sentry at Datadog. Para sa lokal na pagtingin sa Xcode o Android Studio logs gamitin ang logfmt — ito ay mas compact at nababasa nang walang format.
Oo, ang mga structured log sa client ay nagpapahintulot sa pagdagdag ng konteksto sa bawat ulat ng crash: bersyon ng OS, estado ng network, huling aksyon ng gumagamit. Kung walang structured breadcrumbs, ang ulat ng crash ay naglalaman lamang ng stack ng tawag nang walang senaryo ng gumagamit.
Ang Logfmt ay mas compact (30–50% mas maliit na volume) at mas madaling basahin sa terminal. Ang JSON ay sumusuporta sa nested object at array, ngunit nangangailangan ng pag-escape ng mga panipi. Ang pagpili ay depende sa imprastraktura: para sa ELK — JSON, para sa console viewing — logfmt.
Gumawa ng isang instance ng UUID sa pagsisimula ng application, i-save ito sa singleton o DI container at ipasa ito sa lahat ng logger sa pamamagitan ng constructor. Alternatibo — paggamit ng threading-local o Continuation Local Storage sa Kotlin coroutine.
Maaari, ngunit hindi inirerekomenda — ang paghahalo ay nawawalan ng kakayahang mag-automatic indexing. Kung ang bahagi ng mga log ay text, kailangan silang i-parse gamit ang regular na expression, na nagbabawas sa pagganap at pagiging maaasahan ng paghahanap. Mas mainam na i-migrate ang lahat ng log sa structured format.
Buod
Gagawa kami ng mobile application na turnkey
Gumagawa ang IT Sectr ng mga iOS at Android application para sa mga startup at negosyo mula noong 2017. Magpapayo kami sa iyo at magmumungkahi ng pinakamahusay na solusyon.
Basahin din