When I started building small utilities to track habits and expenses I quickly ran into a problem: every tool used a different format. My workout tracker stored records as CSV rows, my finance app wrote JSON objects, and a homemade notebook export used a custom text syntax. Analyzing data across projects meant writing conversion scripts for each source. I wanted a single schema that could describe any event in a human friendly way. This article outlines the approach I took to design a universal logging format that now powers several of my apps.
The design goals were simple. The schema needed to be easy to read in plain text, flexible enough to capture most personal data, and efficient to parse. After experimenting with YAML and JSON I settled on a line oriented structure inspired by logfmt. Each record is a single line with key value pairs, separated by spaces. Timestamps appear first in ISO format, followed by a category field. Additional keys can be added as needed. The result looks like this:
2024-07-12T08:15:00Z workout type=run distance=5km mood=great
Because the schema is just text, creating logs is as easy as appending a line to a file. My phone shortcut for logging expenses uses the same structure as the desktop script that records stock trades. I can grep for “category=food” across all files and immediately get a combined picture. The consistency has eliminated the brittle mapping layers that used to sit between each tool.
Versioning is another key aspect. Fields evolve over time, so the schema supports optional key sets. If a new app adds a location field it does not break older consumers. Parsers simply ignore keys they do not understand. To keep track of changes, I maintain a separate metadata file that lists known categories and suggested fields. This documentation doubles as a design guide when I build new utilities.
One challenge was representing complex objects like checklists or nested data. I resisted the temptation to embed JSON blobs, which would defeat the purpose of a universal format. Instead I lean on prefixes. For example, a task log might include entries like task.id=42 and task.status=done. Tools that care about tasks can group those keys, while others treat them as simple strings. It is not perfect, but it keeps the core format approachable.
The schema also encourages intentionality. Because writing a log line requires choosing a category and relevant fields, I think more carefully about what data is worth collecting. This has trimmed several vanity metrics from my routines. When an event feels awkward to describe, it is usually a sign that I do not actually need to track it. The format nudges me toward data that supports real decisions.
Today the logging schema underpins my budgeting app, workout tracker, and even a journal tool that tags entries with moods and topics. Once a week a script aggregates the logs and generates reports with visualizations. Since everything is text based, the system remains fast and portable. I can sync the files via Git and use any editor to explore them. The universal schema has become a quiet foundation that keeps my projects interoperable without adding unnecessary complexity.
If you are drowning in disparate logs, consider drafting your own schema. Start with the kinds of events you capture most often and define a handful of fields. Keep the format human readable so you can tweak it on the fly. Over time the schema will evolve, but the consistency will save you hours of transformation work. A universal logging approach has made my tools simpler to maintain and far more powerful when used together.