Hacker News new | past | comments | ask | show | jobs | submit | more zulu-inuoe's comments login

I really wish I'd thought of this method when I was building a search based application. It was my first time and I struggled with structuring everything


404 on that Torvalds link


The HN renderer is rendering the closing round bracket and semicolon as part of the HTML link, which is unfortunate for this case, but good to know :)



What I find so interesting is that we all effectively do TDD, except without commitment to it - Imagine writing some code and not at least testing it out with several test cases.

The absolute bare minimum should be for you to write those informal tests down and commit them to the repo. That's some golden knowledge I've gotten over time

It just requires the overhead of setting up the test runner


But the orthodoxy seems to be write the tests first, see them fail, then write code, not write a little bit of code, write some test cases, repeat. How "test first, then code" works in a compiled language like C++ or Rust be beyond me (unless I'm taking this to a literal conclusion).


> How "test first, then code" works in a compiled language like C++ or Rust be beyond me

It's not really any different than in dynamic/interpreted/weakly-typed languages. "Writing the test" for a function sometimes just includes writing a method/function with the appropriate type signature that does nothing (maybe returns a dummy value).

Forcing you to view the code you're implementing from the viewpoint of someone calling that code from the very beginning is one of the advantages/goals of TDD. If you find that it's difficult to set up the objects/data you need to write a test, eg, your code has a bunch of implicit dependencies on other components being in a particular state or it takes a ton of arguments that all have to be constructed, that's usually a strong indicator that you should rethink the design. You're getting early feedback on your API design before you waste time implementing it.


Of course somebody thought of this already


Say I'm building a logging library, is there any sort of generally agreed-upon standard per what a log file should look like? I know there's several formats that lnav supports, but I'm not familiar with them.

I've always had trouble before figuring out what a good compromise between log format and flexibility looks like. Especially wrt newlines in the log message itself (eg if I want to log a stack trace)

Any thoughts for a format that would generally work ootb in lnav or other log viewers?


Not sure about lnav but most log aggregation systems support json and logfmt-formatted logs, and there are many standard logging libraries that supports emitting those formats

Of those json is better if you want to be able to do more advanced stuff (nest dictionaries, use lists, ...) and logfmt is better if you want to have human-readable logs without external tools as well, an example line can look like

    msg="Request finished" tag=request_finish status=200 user=brandur@mutelight.org user_id=1234 app=mutelight app_id=1234
Some more info here https://www.brandur.org/logfmt


Agree with logfmt. I wrote the logfmter python library: https://github.com/jteppinette/python-logfmter. You can quickly have all of your logs (including 3rd party) converted to this style.


Has anybody written an actual spec for logfmt? I noticed that different implementations handle escaping of quoted strings subtly differently


Thank you! Now when you say json logging, are there any common patterns you can guide me to look at? Just looking around for JSON logging gives me results like [1] which talk about JSONL (object per line, presumably JSON serializer makes sure to not emit literal newlines).

But some other places describe this a bit more liberally. And [2] notes that I should include a time stamp in each log entry which makes sense.

[1]: https://stackoverflow.com/questions/10699953/format-for-writ... [2]: https://www.papertrail.com/solution/tips/8-essential-tips-fo...


In general if you use things like filebeat or promtail to do log ingestion into centralized log search systems (elasticsearch or loki in these examples) they prefer one object per line.

It makes parsing and keeping track of the "state" of the file a lot easier. Say that your application crashes/gets killed halfway through writing a log message / json dict and then gets restarted and appends to the log file. How should the log reader handle that case if it suddenly becomes a valid nested object? And even if it doesn't, should it throw away the first new log message as well because that was embedded in the invalid json object? Much easier to just say "one line is one json object, if there are literal newlines that's the delimeter to start a new parse".

And yes in any case it's good to have a timestamp on your log message no matter the format, unless you're logging somewhere you know that it gets added immediately (like the systemd journal). Your log parser/forwarder can add a timestamp for when it reads your log message but that is not necessarily the same as when your application emits it.


Another benefit with json/logfmt that bears mentioning explicitly: it has structure.

This means that you shouldn't just write (to reuse the previous example):

    msg="Request for brandur@mutelight.org finished with status 200"
you should do it like

    msg="Request finished" status=200 user=brandur@mutelight.org
and not put any variables into the msg key (and not really do advanced formatting for any of the keys for that matter). This way once you get it put into a log system that understands your format you can do searches like "all log messages where user=foo" or "all statuses that are >=500 and <600" or search on specific messages, all without having to craft elaborate regular expressions and with better performance since the log search system can do indexing and various optimizations so that it doesn't have to be a full-text search every time.


lnav does support JSON-lines and logfmt logs. For JSON-lines, it will pretty-print the log messages to make them human readable.

For logfmt, I seem to remember the spec not being very clear on quoting semantics (maybe I'm wrong). Anyhow, I would suggest using JSON since it has pretty broad support at this point.


Hmmm, it doesn't say in https://lnav.org/features#automatic-log-format-detection but i see that at least json (and xml) is mentioned under the pretty-printing header.

You would know what is supported what with you being the author, just saying that the docs aren't super clear from a quick glance :).

And yes, I second the suggestion to focus on JSON. The main benefit of logfmt is that it's simpler for a human to parse directly but in general you probably shouldn't aim for that so..


> Hmmm, it doesn't say in https://lnav.org/features#automatic-log-format-detection but i see that at least json (and xml) is mentioned under the pretty-printing header.

Yes, I should mention it on the features page. It's currently only mentioned in the main docs:

https://docs.lnav.org/en/latest/formats.html


You can use logfmt with Serilog on dotnet too:

https://github.com/serilog-contrib/Serilog.Logfmt


There is a bunch of them (log formats). I don't think any is like ISO/ANSI standarized, but many tools work with many of the different formats.

Probably the most common one (or at least was most common, maybe not anymore) would be "NCSA Common log format" (or just CLF) which looks something like this:

    127.0.0.1 user-identifier frank [10/Oct/2000:13:55:36 -0700] "GET /apache_pb.gif HTTP/1.0" 200 2326
https://en.wikipedia.org/wiki/Common_Log_Format

Many tools for getting analytics out of server-side logs can work with CLF and the various variations. But probably today there are more "modern" formats as well.


Take a look at the docs linked on the main page of Serilog[1] and the various videos[2] and blog posts[3] by the devs who make Seq.

[1]: https://serilog.net/

[2]: https://datalust.co/

[3]: https://blog.datalust.co/


Structured logs. Probably json.


I hate you


They did mention it. They use it for some of their older games but it seems like Ruffle isn't yet feature-complete with Action Script 3 and thus cannot be used to run their newer games


While Ruffle's AS3 support is still lacking a lot of features, since a couple months ago it's been able to play some simple games that require it. The build used on author's site is from 2021, and I just checked that the latest build is able to play several more AS3 games hosted there.

(note: I'm a Ruffle dev)


That's great news! I've been meaning to write a cron script or something to fetch the latest Ruffle every week or so, so thanks for reminding me to do that. Thanks also for your work on Ruffle, it's really great.


I'm waiting for it to develop further, I'm very excited, especially because I still play Crystal Saga everyday, I don't know why, but it's got something that I haven't been able to find in any other games.

But sadly, I haven't been able to make Crystal Saga work using Ruffle


MMOs are pretty much the last game Ruffle or any in-browser emulator will get to support - not just because it's likely some of the most complex piece of code you can find, but also because MMOs are likely to use sockets, which AFAIK can't really be accessed in modern browsers at all.


It sounds like adding those features to ruffle would have been three order of magnitudes easier than writing a flash player from scratch

I understand contributing to OSS is a pain (I often end up with half implemented features in my own branch and never manage to merge them upstream) but he could have saved himself some trouble.


Ruffle plays compiled Flash swf files

The tool that the author made reads Flash fla files and exports data from that.

Swf files contain binary data. The ActionScript code has been compiled into bytecode. The vector data is probably also represented in binary format.

Fla files, as pointed out in the OP blog post, contain XML data.

It sounds like OP is doing something quite different from what Ruffle does.

Ruffle tries to be a player for swf files.

OP wanted to export data from Fla XML to other formats, so that he could build executable games.


It seems to me like a very different skillset required to reimplement a runtime like the SWF player vs hacking together an alternative FLA compiler that's just good enough to work on your own games.

Ruffle still doesn't support Actionscript 3.0, I suspect the task is not that straightforward.


Ditto.


If I hadn't used it at work at a large C++ shop, I'd never have stumbled upon how great Incredibuild is


Closest equivalent that I can think of is the change-class function in CL. That one also happens to be generic so you can control the finer details of what it means to change A to B


Consider applying for YC's Spring batch! Applications are open till Feb 11.

Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: