Ask HN: How do you log application events?

221 points by GaiusCoffee ↗ HN
We are currently inserting our logs in an sql database, with timestamp, logType, userId, userAgent and description columns. It makes it trivial for us to debug any event by just querying the db. However, after three and a half years of continued use, the table is now way too large.

How do you guys log application events in such a way that extracting information from it is easy, but still keep the size of the logs manageable?

110 comments

[ 3.9 ms ] story [ 113 ms ] thread
Why do you feel the log is way too large?

If log entries take up too much disk space, switching to a different system will not help; you will have to do something with the data. You can either archive old years (export in some way, compress, put in cold storage) or throw them away, either partially or fully (do you need to keep debug logging around forever?). Using partitions can help here, as it makes it faster to drop older data (http://www.postgresql.org/docs/current/interactive/ddl-parti...)

You also may consider compressing some fields inside the database (did you normalize logType and userAgent or are they strings? Can your database compress descriptions?), but that may affect logging performance (that's a _may_. There's extra work to do, but less data to write)

If, on the other hand, indexes take up too much space or querying gets too slow, consider using a partial index (http://en.m.wikipedia.org/wiki/Partial_index). You won't be able to efficiently query older data, but if you do that only rarely, that may be sufficient.

Could you expand on how do you use the log data ? How often do you query it, what time periods do you query, have you considered building a data warehouse for your analytics?
We generally run them through central syslog servers or directly to a logstash tcp or udp input. One way or another all logs from around the world end up in an elasticsearch cluster where we either query for things manually or use kibana to interact with them. Works pretty well actually.
I use a logging library called Winston (https://github.com/winstonjs/winston). I have it hooked up to Pushbullet with Winston-Pushbullet (https://github.com/michaelmcmillan/winston-pushbullet) so that when an unhandled exception or error is thrown I get an instant notification on my Nexus 5 and MacBook.

Winston is a node/iojs library though, but I guess you could find something equivalent in any other stack. The Pushbullet part is really useful.

Edit: I run a pretty small site however (http://littlist.no). I don't think I would enable the Pushbullet part if I had several hundred thousand visitors per day.

Edit: I should have known better than to post this to HN, some guy found a procedure which threw an uncaught exception. I was bombarded with push notifications (hahaha). At least I fixed a bug (-:
We stage stuff out.

After a week, it goes out of cache. After a month, we no longer keep multiple copies around. After 3 months, we gather stats from it, and push it to some tar.xz files, which we store. So its out of the database.

We can still do processing runs over it, and do... but it is no longer indexed, so they take longer.

After 3 years, the files are deleted.

It depends on what type of data you are logging.

For performance metrics we use graphite/stats-d This allows us to log hits/access times for many things, all without state handling code inside the app.

This allows us to get rid of a lot of logs after only a few days. As we're not doing silly things like shipping verbose logs for processing.

However in your usercase this might not be appropriate. As other people have mentioned, truncing the tables and shipping out to cold storage is a good idea if you really need three years of full resolution data.

We push data into shared memory. Then we have clients that can read the memory and present it. This makes it possible to log millions of lines per second with a very limited cost.

This has the benefit of making logging more or less asynchronous. You still need to handle the logs coming out of this, of course.

I run services that log to plaintext files and I use logrotate to periodically gzip and rotate them out for archival.

Just use grep to query recent logs, zgrep if you have to dig a little.

zgrep works for both plain text and gzipped streams so you can do something like this (assuming you have both deflated and non-deflated files that matches the glob pattern):

    zgrep somepattern /var/log/messages*
It depends on the priority and importance of events.

For instance, we use a log file for HTTP access logs but I store all of errors and warnings from MongoDB. However, I clean the log storages every month.

We use NodeJS and MongoDB in www.floatalk.com

You could also take a look at Graylog (https://www.graylog.org/), it supports structured data in a variety of formats and can send alerts as well.

It's similar in spirit to elasticsearch + logstash + kibana, but more integrated.

Disclaimer: I work on it, so I'm not going say what's better, just giving another pointer.

I am biased, but you should look into a logging system like splunk. You shouldn't be using an RDBMS for your logs. Your logs don't have a schema.

With splunk, you just output your logs in this format:

<timestamp> key1=value key2=value key3=value

install splunk agent on your machines, and splunk takes care of everything from there. You can search, filter, graph, create alerts etc...

Splunk indexer allows you to age your logs, and keeps the newer ones in hot buckets for fast access.

Splunk is indexing system, not a logging system.
Splunk is a log management first and foremost. It has an indexer system to index your logs of course.

Disclaimer: I work at splunk.

I just log to a file, rotating/deleting when/if needed
ElasticSearch + Logstash + Kibana.

Custom NLog renderer which implements SysLog protocol and NLog target which pushes logs to RabbitMQ.

We use this at my startup. There's a lot of tools that support pushing to logstash in addition, logstash can parse any on disk log file. It's very useful especially for clustered applications that span multiple servers (since a single user session should be even spread out due to load balancing).
Just wondering b/c where I work, sessions are persisted to a single host (there's load balancing but cookie based persistence through Citrix netscalars). Admittedly it's not great b/c if that host goes down, user session is lost, but it does simplify matter a bit.

Do you persist sessions in some global cache (We'd use Oracle coherence at my work, but I guess you could use redis/memcache/infinispan?). Side note...does anyone have experience with Infinispan?

Making web apps stateful by "sticky" load balancing always felt like a hack. It seems much more elegant to separate the webservers from state. No need to drain machines or anything like that. And as an added benefit, separating things makes it easier to persist sessions, so you can provide a better user experience instead of balancing RAM vs "session timed out" pages.

I might be biased, though, against all the idiotic uses of session that just tend to wreck the user experience. It's not specific to any type of technology, I suppose. Maybe it's just being stateful, overall. (Looking at my bank which can't handle multiple tabs doing transactions at once, or Lenovo which will silently corrupt the displayed pricing info if you price two machines at once, or the new Azure Portal, which manages to display the wrong data even with a single tab.)

I've always been strongly in the stateful web app camp, and I don't find anything hacky about sticky sessions:) But I think the divide between the stateless and stateful camps may come down to a combination of initial technologies used, and web application complexity.

At some point, with a complex enough application, reconstituting all of the required session data and state for each request becomes a massive performance bottleneck, and stateful sessions solve that very nicely. Most app tiers support session failover pretty nicely, and many clients I've worked with have logic where if the session doesn't exist (i.e. if their session's sticky server has crashed or been removed) then reconstitute the state based on a cookie value. Either approach gives you the best of both worlds - the performance of stateful sticky sessions, and the cluster flexibility of stateless.

But with simpler applications, with less session data/state to manage then stateless is probably fine.

Sorry if I'm misunderstanding yours or GPs point but I think GP was recommending storing app session in some 3rd party cache outside your app server tier, not having nothing stored in session at all.

But reconstructing session from cookie value would work just as well I suppose, at the tradeoff of having everything you want stored in cookie (vs storing just session ID in cookie and having that ID mapped to data in one of the aforementioned caches or other alternative)?

We use Redis as a shared session store.
How do you find logging over RabbitMQ? I have a guy at my place who's pushing to get log messages flowing over the message bus, but using Rabbit as a logging mechanism makes me feel a bit uneasy. Do you find that it pollutes your regular messages? Or do you have them on a separate control bus?
We have several teams pushing logs into a shared Logstash, over RMQ. Depending on the amount of logs you have, I would suggest you have a separate RMQ cluster for the logs. That said RMQ is a great buffer for logs, incase there is an issue with logstash / es at the far end.
Do you really need to debug events from 3 and half years ago? Full logs only really need to stick around as long as you're likely to want to debug them. Log rotation is a must (I've seen debug logs nobody reads sitting in the gigabytes ...) Past that, you can cherry pick and store metadata about the events (e.g. X hits from userAgent Y on this day) with enough information you'll need to do trend analysis, although it's generally a good idea to keep backups of old full logs in case you need to reload the logs to find out that one thing you forgot to add to your metadata ... If you do genuinely need all of the data back that far, you should look at partitioning the data so you're not indexing over millions of rows - how you do that depends how you're intending on using the data.
If the table is too large, make it smaller by moving some of the data to a colder, slower, store. Whether that's json documents or text file gzips on 6x USB drives, data retention is mostly cheap.

The question is, what information do you want available within the second about logs from a year ago? Aggregate that, and move the rest.

Rollbar has been pretty fantastic for us.

Also NewRelic if you want to spend the money (or get it throuhg Amazon/Rackspace for free)

We use elmah (https://code.google.com/p/elmah/) for logging our ASP.NET/MVC apps.

It works well for us, nice accessible UI if you need it and a solid database behind it. Also RSS/Email alerts if you need it. We've got thousands of entries in there and even on the old SQL2005 box we use, it seems to work just fine.

Elasticsearch is amazing. It lives up to the hype. It's perfect for rolling over logs, and they have lots of documentation on how to make it work just right.

Just as an example of how awesome Elasticsearch is, you can trivially segment your storage tiers (say, SSD versus HDD) and then easily move older data to other storage, with a single command.

They have a log-specific handler called Logstash, and a dashboard system called Kibana (which is sorta neat but the UI seems a big laggy in my brief experience). Apparently some folks use Logstash/Elasticsearch to record millions and millions of events per day and ES does a great job.

If you want hosted, check out Stackify. I'm totally blown away with the product (no affiliation other than being a new user). You can send log info to them and they'll sort it all out, similar to Splunk, but not ridiculously priced and no dealing with terrible sales teams. But it gets better - they offer all sorts of ways to define app-specific data and metrics, so you can get KPIs and dashboards just adding a line or two of code here and there. It's a lot easier than running your own system, and it looks like it can make ops a ton easier.

Another hosted service is SumoLogic. I only used them for logging, but it seemed to work well enough.

Is there a pricing page for Stackify? I've rooted round their site and cannot track one down. Just like Splunk...
I always have to Google it. http://stackify.com/errors-log-management/ Dunno why it's not more discoverable. Maybe they're doing tests, because it's underpriced IMO. I've not found any service like them - maybe New Relic but that's 10x the price, last I checked. Azure has something they're pushing in their UI, too, but a brief look made it seem nontrivial to implement.

Apart from that, Stackify is $15/server/mo for the server monitoring and app metrics, IIRC.

Wow. Stackify looks really good.

At my current employer, we are currently implementing Splunk. And it's taking forever and they do charge arm and a leg for their offering. I don't mind if a good product costs money but you shouldn't need a consultant on premise just to configure your logging solution.

Site wouldn't load for me :-(
I manage a 2.5 TB/day Splunk cluster at my current employer and can offer a few tips for making Splunk less painful to manage:

- Make frequent visits to answers.splunk.com. It has a very active community, and I've frequently been able to type "how do I do X in Splunk" into Google and found multiple answers on Splunk Answers.

- Deployment Server. Make friends with it. In a perfect world, it should hold your configurations for all Indexers, Heavy Forwarders, and Forwarders. If you're having to populate $SPLUNK_HOME/etc/system/local/ yourself, you're doing it wrong.

- Make friends with the "splunk btool config_file_name list --debug" command. That makes it dead simple to know which configuration options a Splunk install is running. Append "| grep -v system/default" on the end of that command to filter out the defaults and you'll more easily see which of your options are being used.

- If you have the cash, attend Splunk Conf and load your schedule up with presentations. It's worth every penny.

Hope that helps.

Second that.

We use Splunk for logging and I wrote custom app for fraud detection in financial security field, custom events correlation and alerting.

It's very good tool for enterprise data analytics as well as for any custom dashboarding and event processing.

Yeah I don't get it either. Splunk is still losing money after many years. Their model seems to be "spend $2 to make $1". Compared with how arrogant the sales people are - one told me they really just don't care as there's so much demand for the product - something doesn't make sense.

It was cool software, a bit slow (this was several years back). But with things like Elasticsearch catching up release over release (even if you don't use it directly, other platforms will build on it), Splunk is no longer the totally unique thing they used to be. I can't figure out their $8bn+ market cap with revenue under 500M and costs increasing as they grow.

Installing and configuring Splunk to ingest and index data is close to being dead-simple.

Splunk consultant maybe needed if you have complex enterprise deployment scenario or wish to develop really advanced apps - but configuring logging solution?

It's a point and click exercise.

What kind of log data do you mean exactly? E.g. what's the granularity?

We have web server logs going 30 days back, on disk, managed by logrotate. Then we have error logging in Sentry. For user level events, we track in Analytics, but we also have our own database-backed event logging for certain events. Currently this is in the same db as everything else, but we have deliberately factored the tables such that there are no key constraints/joins across these tables and the rest of the schema, which means it should be trivial to shard it out in its own db in time.

Exactly that, but rotating after three years. If it's three years ago it probably doesn't matter any more.
Rotate it, but save the old ones. You never know how far into the past you have to dig one day. Be it for statistics or tracking a security issue.
Log analytics is a big topic so I'll hit the main points. The approach you take to logging depends on the analysis you want to do after the log event has been recorded. The value of the logs diminishes rapidly as the age of the events get older. Most places want to keep the logs hot for a period ranging from a day to week. After that,the logs are compressed using gzip or Google snappy compression. Even though they are in a compressed form they should still be searchable.

The most commont logging formats I've come across in production environments are:

1.log4j(java) or nlog(.NET)

2.json

3.syslog

Tools that I've used to search ,visualize and analyse log data have been:

1.Elasticsearch, Logstash and Kibana (ELK) stack

2.splunk (commercial)

3.Logscape (commercial)

Changes to the fields representing your data with the database approach is expensive because you are locked in by the schema. The database schema will never fully represent your full understanding of the data. With the tools I've mentioned above you have the option to extract ad-hoc fields at runtime.

Hope this helps.

We're currently evaluating options, but for .NET Serilog is shaping up extremely nicely, and Seq/Logg.ly as log sinks are nice...

Seq is great because you can set up your own instance very near to your servers for low-latency/high-bandwidth logging, which really changes the game in terms of what you can feasibly (perf/financially) log. It also has some decent visualization options, and it's got some great integrations, with a decent plugin architecture to create your own real-time log processing code.

Logg.ly has some amazing GUI/search options.

We've been using Serilog/Seq and we're extremely happy with it. I'm a little surprised that you didn't mention the buzzword "Structured Logging", which is the special sauce that makes Serilog stand out. Instead of concatenating strings with values, you assign keywords to values which you can later search on. For example,

Log.Info("Customer# {customerNumber} completed transaction {transactionId}", customerNumber, transactionId);

Then using the Seq log viewer you can simply click on "transactionId" in the log line and filter by "transactionId = 456" or whatever. It's one of the most exciting advancements I've seen in the .Net logging world.

EDIT: I realized I didn't really answer OPs question regarding space. If you used Serilog, you can set up different sinks to export to, with different options. For example, you could send all your logs to mongodb, and just recent 1 week rolling logs to the Seq server.

When I've heard "structured logging" used, it has been in the context of much more key-value pairs than just having keywords next to values, e.g.

    Log.Info("customerNum={customerNumber} transactionId={transactionId} state=completed", cN, tID)
or the ever popular logstash-y format:

    Log.Info(LogState.Add("state", "completed").Add("customerId", customerId).Add("transactionId", transactionId));
where `LogState` would build up a key-value dict and its `ToString` would emit the logstash JSON format.

I guess the version that works best depends on the tool that is consuming the log text.

In the end, serilog, depending on the sink, makes your log look like the template, and attaches the meta data of your template variable names and replacement values to the message itself.
Are you able to use Serilog for metrics in addition to application events? I'm thinking something like average time for a method to execute, things like that. And if so, what tools do you use to comb through that data (to determine average execution times, for example).

Right now at work everyone just logs to a single CSV with an inconsistent format and it makes me cringe every time I look at it. It's also really difficult to parse.

I recently used the SerilogMetrics [1] NuGet package to determine the elapsed time between method calls. Worked great, although I couldn't figure out how to use my standard logging config that is carried in the static logging object and had to redefine the seq server I wanted those lines logged to in the class itself. This may have just been unfamiliarity on my part.

Your current way does sound like a headache. If your logging lines are in the standard NLog format, you should be able to drop in serilog without many changes.

[1] https://github.com/serilog-metrics/serilog-metrics

We've evaluated loggly, logentries, splunk, and Seq. The first 3 are fine depending on your logging needs. Seq can handle a TON of events thrown at it, and the latest stuff (~1 day old or so) is extremely accessible. The older stuff takes a little longer to search through though.
We're currently using Splunk (and may move to the ELK stack) for logging, but some types of "application events" are really more useful as metrics. We're using Ganglia for those metrics and limiting application logs to actions that are needed for audit purposes and for warning and error-level application problems.

Using a system like Ganglia (or the Etsy inspired statsd) is an important idea since the OP's original question included how to limit the size of logged data. These systems provide a natural way to aggregate data.

I'd recommend looking at Graylog. It uses Elasticsearch under the hood, surrounds it with an application that focuses on log management specifically. https://www.graylog.org/
Graylog is absolutely brilliant. Storing several TB of data in it, using it for alerting/monitoring (you can configure streams, which you can think of as constrained views of logging data), etc. Highly recommend it.
You didn't specify your location, but in some counties like the Netherlands, it's not legal to store PI (personally identifiable) data that long. There is no reason to keep access logs for 3+ years. What are you ever going to do with that data?

Like others here said, extract what you want to keep (unique visitors per day or so) and throw the rest out after a few weeks.

> It makes it trivial for us to debug any event by just querying the db. However, after three and a half years of continued use, the table is now way too large.

Why are you keeping all of the logs? Are you doing anything with it?

Are the old logs relevant at all? If your program structure has changed, then anything logged before that point isn't even applicable.

My advice: If what you is working, but only failed because of volume of data, apply a retention policy and delete data older than some point in time.

An example: Nuke all data older than 1 month for starters, and if you find that you really don't use even that much (perhaps you only need 7 days to provide customer support and debug new releases) then be more aggressive and store less.