Structured Events
An event is a collection of information about what it took to complete a unit of work. For example, an event might be the process of accepting an HTTP request, doing the required work, and then passing back a response. An event is structured because each field of its data is labelled. Fundamentally, any data that comes into Honeycomb enters as a structured event. A structured event is a blob of JSON, sent over HTTP. This is an example from an internal Honeycomb dataset:trace fields help identify that this event is a part of a trace.
The event refers to a single unit of work and it attempts to describe what had to be done to service specifically this bucketRequest operation.
The user can now query on this data.
Group and query on any field, and Honeycomb will rapidly aggregate on it.
For example, you might be interested in knowing whether latency (duration_ms) is higher depending on app.group_buckets.
You might even want to identify outliers across all of the fields simultaneously with BubbleUp.
You create these events by instrumenting your code.
In this code snippet, we create a new event by calling libhoney.new_event, we add some data to it with add and add_field, and then we send it to Honeycomb with ev.send().
Structured Logs
A structured log is a message, or a collection of messages, with a group of fields in a fixed structure. Because of this framework, a structured log can easily turn into a structured event. The easiest way to think of a structured log is as what you might expect to see in an Excel table or a comma-separated-value list. Here, for example, is a header and a line from a structured log:Other Approaches to Data
Structured events and structured logs can help us build rich perspectives on how a system is operating. We contrast these with a few other perspectives.Preaggregated Events and Metrics
Each event in Honeycomb is meant to be a standalone description of a single unit of work. For example, an event could be one user looked at one URL, it returned a particular status, and it took this long. But there are other ways to bring data in. For example, you can bring in pre-aggregated data, sometimes called application metrics:avg_duration_cache_hit_true, and another row for _cache_hit_false.
But we would need to repeat that, too, for p95_duration...cache_hit_true, and all the other variants.
The list of pre-aggregated data is getting longer and longer.
This situation leads to “the curse of dimensionality” — the fact that if you decide you also want to track by cache hit, and also by page, and perhaps by user ID or build ID, each of those changes costs hundreds or thousands more aggregated rows.
By bringing in disaggregated data, Honeycomb is able to flexibly ask questions about any event.
Unstructured Logs
A log is a message, or a collection of messages. They usually have a timestamp attached. Individual log messages may or may not be related to each other. The log file we saw before was structured: every event roughly looks the same, and we can compare the events by their columns. Let us contrast that example with an unstructured log. When Honeycomb starts itsretriever service, the console prints something like this:
Controlling Event Volume
It might be natural to ask whether, compared to metrics, event code requires too much data. A pre-aggregated metric should compress to be far smaller than a rich event, right? In our experience, that is not always the case. The curse of dimensionality means that in order to ask reasonable questions, users often need to create many metrics, losing many of those cost savings. If event data is overwhelming event volumes, it is also possible to sample your data. For example, you could send one in a hundredstatus:200s, but send every single status:500.
Honeycomb will automatically multiply out sampled events, so that query results remain accurate.
Read more about sampling in Honeycomb.
Code Examples
In this section, we show how the same piece of code can be instrumented for events and metrics, and for metrics and logs. We show that while the instrumentation code is very similar, the effects are very different: the events are more powerful and allow more flexible use.Events vs. Metrics

Events Output
In this example, Honeycomb was used for events. Although a graph was rendered, we are showing the raw data for a more equal comparison.
Metrics Output
In this example, StatsD was used for metrics.
Comparison of Events vs. Metrics Outputs
Both of these examples capture the duration in milliseconds as well as how many times the example app was run. At first glance, the metrics output appears to have more data, but all of those can be calculated from the data output from events. Metrics tools need to do this calculation before write time. We can calculate all of the same metrics in Honeycomb, but we also gain further context. Events let us add the richer information of input and output and the timestamp when they occurred.Events vs. Unstructured Logs

Events Raw Output
In this example, Honeycomb was used for events. Although a graph was rendered, we are showing the raw data for a more equal comparison.
Logs Output
In this example, we logged the output to the terminal: