Data & analysis

LogViewer

A desktop viewer, written in Go, that decodes binary diagnostic files into a table you can query with SQL.

Tools
Go · Wails · SQLite
Outcome
Superseded

Context

An app for decoding binary diagnostic files. A CSV file, called a baseline, defines the packet structure used to decode the binary.

Built in Go, developed on a Linux host, targeting Windows.

TL;DR

A Go decoder shared between a desktop window and a headless CLI, producing the same byte-for-byte output either way, so a technician can reproduce from the command line exactly what the window showed. Decoded records land in a SQLite database, one column per signal. Searches can be run using SQL — velocita > 100 AND allarme = 1 — instead of a stack of dropdown menus (a necessary choice, given the large number of columns expected).

What I built

After stepping back from Windows development, I turned down several jobs because the target was Windows. That didn’t cost me much: for years, once the web took over, desktop applications fell out of fashion, surviving only in a few niches. The rise of smartphone apps then partly reversed that shift — installed, native software became relevant again, if now on phones rather than desktops.

A few years ago I started looking at Go as a good way to target Windows while developing on a Linux host, thanks to its excellent cross-compilation support.

GUI, though, was still tricky: back then, no framework felt mature enough for what I needed. Fyne looked like a wonderful toolkit, and one that’s been gaining traction lately — it was my first attempt at building the application’s GUI (the CLI version already existed by then). It didn’t prove up to the task, though.

I didn’t want to toss away the work already done on the CLI, so I kept looking: I found Wails, and LogViewer was born.

The Go backend performed well at decoding the bit-packed binary files and writing them into a dynamically created SQLite table, and the interface came together easily with Vue.js. Everything was fine — until the day it wasn’t. I’d expected to deal with diagnostic packets with many fields, but one day I got a call: “Can’t read this file.” I ran LogViewer from a terminal and saw the error: too many columns on binary_0?! I opened the baseline defining the packet structure and found that the number of fields exceeded the maximum number of columns SQLite supports (i.e. 2000). The video shows a baseline with 3,600+ fields, obtained from the real one by mangling the field names. (This is a good example of how a bad data decision made early on compounds quickly if left unaddressed, and causes bigger problems down the road.)

I tried switching to DuckDB in place of SQLite; it solved the column-count problem, but the initial bulk insert went from 7 seconds to more than 2.5 minutes — some slowdown was expected, given DuckDB’s columnar design isn’t friendly to single-row inserts, but that was far too much.

So I decided to recompile the SQLite library to support more than 32,000 columns (that’s open source at its best: compile defining symbol SQLITE_MAX_COLUMN what you want). That’s where AI can really save you hours: within a few minutes, rebuilding the library was folded into the normal Wails build. Credit to Go, and to how well it interoperates with plain C.

I’d call this project a failure: the software was eventually replaced with what looks like a Visual Basic rewrite of it (likely the customer preferred to move away from Go, back to something more familiar to their own staff). But I should restrict that failure to the commercial side — on the technical side, I have nothing to regret. (I still think I’ll give Fyne another try, someday, given the chance.)