~/posts/3ln25vz44372u
cd ..

Introducing locol

5 min read

The best projects to work on are the ones that scratch a few different itches at once. I've wanted to write a native macOS application for years now, but I've always found building GUIs to be tedious and -- frankly -- hard to wrap my head around. I've also wanted a better way to manage a local OpenTelemetry Collector on my Mac for quite a while as well. Thanks to the magic of artificial intelligence and a little bit of gumption, I've accomplished both of these goals. Introducing locol.

What It Does

The goal of locol is fairly straightforward -- it manages local Collector instances for you. You can view the logs and metrics of the Collector in real-time, edit the configuration YAML, and start/stop the Collector. This isn't really that earthshattering, but it is nice to have it in a single GUI. One fun feature is that you can create different profiles -- so, different versions of the Collector, and switch between them. Nice if you're working with multiple different configurations as well.

The locol settings view

I've exposed a few fun things that I think a lot of people don't know about -- first, you can easily view all of the various feature gates that the Collector exposes and toggle them on and off. More entertainingly, you can also see all of the components bundled into the Collector, and click on their names to jump to their documentation. This actually theoretically would work on any Collector distribution that's built using ocb and the Collector manifest, so I might allow for a manual override of the download URL to let you use it with a custom build in the future.

The locol component view

You can monitor the Collector by looking at the metrics and logs from the instance as well, and even easily run a data generator to test your config.

The datagen view

How It Was Made

Perhaps the more interesting part of this story is how I built the entire application in, more or less, two weeks after never touching Swift before. I have a passing familiarity with the language, but I'm by no means an expert. I will also not say that the application is perfectly polished (especially in its current state), nor is it without bugs and edge cases. That said, I'd like to think it's pretty impressive for ~2 weeks of work.

This wouldn't have been possible without AI code assistance, full stop. Cursor wrote ~90% of this program, easily. What did I do? Well, it took two weeks for a reason...

What It's Like To Build With AI

One of the biggest problems I think a lot of developers have with AI is that they fall into two camps:

  1. They are smart enough to catch the AI's mistakes and feel like they spend just as much time cleaning up after the AI as they do working with code.
  2. They are not smart enough to catch the AI's mistakes and will gladly let it lead them around like an overeager but confused puppy.

When it comes to Swift and GUI development, I am far closer to the second camp than the first. I spent quite a bit of time independently researching the Swift documentation and blog posts in order to find good references to feed to Cursor. I also relied quite a bit on my formal experience in CS and my professional/domain expertise in order to coach the AI into building solutions that were, if not perfect, were at least correct enough to get me to the next step.

A great example of this is the metrics parsing and rendering in locol, seen below:

The locol metrics view

This was a huge pain and I'm still not entirely sure it's right or that it won't blow up in weird ways. Turns out that writing an interpreter and parser for Prometheus metrics in Swift isn't exactly trivial. I was aided by the fact that I knew, more or less, what I wanted to do and, crucially, what a correct result looked like. If you look at the code, this is one of the best-tested parts of it (ok, the only tested part of it) because the tendency of AI to eat its own creation was very strong when working on the metrics code. Having a test suite that I could run was very, very helpful here.

A particular downside to working with Swift and Cursor is that the VS Code integration for Swift is poor. This isn't the case for server-side Swift and swiftpm projects, but it certainly is for xcodebuild projects. Cursor's agent mode relies heavily on the LSP and linting for ensuring that it's not going off the rails. I think if I was doing this whole thing as a webapp (or an Electron app) it would have taken a third of the time. Hell, I'm still not entirely sure I don't want to throw it out and re-do it as an Electron app if I wasn't so tired of frigging webapps. I built this to solve my problems, not yours.

Next Steps

Right now I'm testing out locol with some colleagues to make sure it's in a more or less releasable state. I worry that once I actually put it out into the world that I'm gonna lose interest in it. My real goal is to enhance it to add an actual in-memory database and lightweight query functionality for OTLP data, but that seems like a very 'draw the rest of the Owl' sort of problem. Anyway, try it out and let me know what you think -- you can download it from GitHub.

Three months later...

Turns out, I did kinda lose interest in it after I got it more or less working. I'm still not sure it's super releasable, but it's something I want to put more time into later this year when I have more free time.

$date -r January 21, 2025