Send Events

This tutorial walks through sending your first events to Honeycomb. You’ll learn how events are sent to the Honeycomb API, how datasets and schema are created automatically, and about the relationship between events you send to Honeycomb and how you query them.

Requirements to complete this tutorial

Summary

In this tutorial, you will:

  1. Send events tracking properties of HTTP GET requests you are making (using curl) to the Honeycomb API (using curl / HTTP POST).
  2. Review the dataset overview and schema pages.
  3. Query sent events to learn how to work with display settings and time selection in Honeycomb.

About events

Honeycomb data is a series of Events, each of which represents something in your environment worth tracking. When you send events to Honeycomb, you collect related or recurring events under a single Dataset.

Example events:

Honeycomb provides various SDKs to help you construct and send events in the language of your choice, but for the purposes of this tutorial we will take a look at sending bare bones events using the Hypertext Transfer Protocol.

Send some events

To send an event to the Honeycomb API, you craft an HTTP request with a JSON payload describing the event parameters as the body, and the X-Honeycomb-Team header set to the value of your team’s write key to authenticate.

Start sending some events in your shell right now:

Copy your write key from the Account page and use it to set WRITEKEY in your shell.

WRITEKEY=<copied value>

Start a loop in the shell to send some events to Honeycomb.

Copy the following command and paste it in your shell. Make sure you have copied the full block.

for i in $(seq 1 5000)
do
  curl --location --silent --write-out '{
    "time_total_seconds": %{time_total},
    "time_namelookup_seconds": %{time_namelookup},
    "time_connect_seconds": %{time_connect},
    "content_type": "%{content_type}",
    "http_version": "%{http_version}",
    "http_code": %{http_code},
    "speed_download": %{speed_download},
    "url": "%{url_effective}"
  }' -o /dev/null https://api.honeycomb.io/ |
  curl --silent --include --data @- \
  --header "X-Honeycomb-Team: $WRITEKEY" \
  "https://api.honeycomb.io/1/events/$(whoami)-first-dataset" |
  grep HTTP
done

You should see some output like this:

HTTP/1.1 200 OK
HTTP/1.1 200 OK
HTTP/1.1 200 OK
HTTP/1.1 200 OK
HTTP/1.1 200 OK
...

If that looks good, you are officially sending your first events to Honeycomb! (If you see 401 Unauthorized, make sure your write key is set correctly as indicated above). Allow that loop to continue running while you take a look at the results in the web app.

What just happened?

1. When Honeycomb got a request to add an event to a dataset it hadn’t created yet, it created the dataset.

If you take a look at your landing page on ui.honeycomb.io you will see that there is a new Dataset, called <your name>-first-dataset. This is where the events you just created are stored.

Click on the dataset name to access the query builder for the dataset.

In the Query Builder, you can construct queries to visualize and inspect the information in our dataset. But first, let’s take a look at the dataset’s high-level properties. To access these, look at the dataset overview.

Click the Overview link in the top right hand corner to go to the Dataset overview page.

In the Settings page you can see information about the dataset including an editable description, how much space the dataset is using on disk, and so on. This page is also available from the Settings & Overview sub-header you might have noticed by the dataset name in the main landing page.

2. The dataset schema was inferred automatically.

When it received events, Honeycomb inspected them to infer that a field like url in the received events is a string, and a field like time_total_seconds is a floating point number. Therefore, you don’t need to specify a schema in advance. If you want to add a field to a dataset later on, or only send it with some events, you can just add it.

Click the Schema link on the left hand column to go to the Schema page.

Here you can see the schema that Honeycomb inferred automatically and make changes if you wish. Honeycomb schemas are updated automatically, so if you suddenly start sending a new field, it will appear here. You do not need to specify that you are adding a new field to your events anywhere, Honeycomb will infer this automatically when you add it to your events.

Honeycomb handles “sparse” data just fine, so if you want to send a field with only a small subset of requests, e.g., error, you can.

3. The sent events are added to the dataset for querying.

Once events have been received and stored by Honeycomb, they are available for querying. Let’s take a look.

Click Overview >> New Query or use the back button to navigate back to the Query Builder for the dataset.

Query the data you sent

Click the Samples button at the top of the page (inside the gray header) to see a table that contains the structured event you just sent in, along with a Timestamp column.

The Samples button will always display the 10 most recently received events for a dataset.

Each of these events represents a JSON blob that we sent to the Honeycomb API (i.e., an event). The “Golden Rule of Honeycomb” is:

If you can represent it as JSON, you can observe it.

In this example, for each iteration of the loop, you make an HTTP request to https://api.honeycomb.io/ using curl, and emit some information about this first HTTP GET request as JSON (using curl’s --write-out flag to indicate the format). For instance, time_total_seconds shows the total time in seconds each HTTP request took to complete. Timers such as this are a valuable part of instrumentation with Honeycomb because they can help you identify bottlenecks. Using https://api.honeycomb.io is arbitrary for the observed requests here – you can observe requests to any URL.

Since the first curl prints the properties of these GET requests to the terminal as JSON, use another curl to POST that information to the Honeycomb API with our write key. (Note: This is handled by the -d @-, meaning to read the request body from standard input, in the second curl of the shell loop).

Now, let’s start visualizing that information:

Add COUNT (the total # of events received per time bucket) and MIN(speed_download) (the minimum value received for speed_download per time bucket) in the CALCULATE box in the Query Builder. Click Run Query.

You should see a graph that looks somewhat like this:

The empty space in the graph is the time before you started sending events, and the colored line on the right hand side represents the calculations you requested. Click and drag across the range where events were sent to zoom in on that subset of events.

Click and drag across the region where events were sent. Click the magnifying glass to zoom in.

You should now see the visualization for only the time range you selected. Click Run Query again for increased granularity.

Note the spikes down to zero in the graph. This is not because these properties were actually set to zero in received events, but rather because Honeycomb did not receive any events in those time buckets and is setting the values to zero by default in the representation. Because missed events are valuable signal, this is the default, but you can toggle this setting using Graph Settings >> Omit Missing Values on the right hand side of the chart.

This will smooth out the visualization at the cost of losing some signal regarding missing events. Now it is easy to see where the valleys in MIN(speed_download) are.

A Few Words On Time

All events in Honeycomb have an associated timestamp. If an event sets a timestamp field in its JSON, Honeycomb stores that event as occurring at that point in time. This means you can ingest data from the past and still query it with an accurate time range. For instance, Honeycomb’s log parsing agent Honeytail will backfill events based on log lines this way. If timestamp is not set, Honeycomb stores the event as occurring at the time the request was received.

To navigate through time in your datasets you have a variety of options. You’ve already seen that you can select a time range directly on the graph to refine an existing time range. You can also use the left-hand menu to set time directly.

The default is REL or relative time selection: Here you will find shortcuts to snap the time range to the past 30 minutes, past 48 hours, etc. If you then select a range manually, the left hand drop down updates automatically to reflect the newly specified ABS or absolute time range.

Click on Custom in the time selection dropdown for more options. For example, you can specify an absolute time range directly. This is especially useful if an issue occurred in your application during a particular time range and you want to see the events in time occurring in that period.

There is also a setting for Granularity: the intervals at which the Honeycomb display places time buckets. Honeycomb will adapt automatically to a reasonable time bucket interval, but for visualizing long term trends and in a few other instances it is useful to toggle granularity.

What next?

You are now equipped with a good functional basic knowledge of Honeycomb usage! Congrats!

You now have several options:

Exercises

Want to improve your Honeycomb skills? Here are some suggestions for directions to explore in the dataset you just created to become a better Honeycomber.

Suggested Reading