GitHub

C / POSIX

Build, configure, and run the Honch C/POSIX SDK on macOS, Linux, and embedded Linux.

The C/POSIX port runs on macOS and Linux. It targets embedded Linux devices and gateways, and doubles as the fastest way to exercise core behavior on your development machine — its queue is file-backed, so you can watch events move through pending/ and dead/ directories on disk.

Status

Stable · 0.3.0. Reports $sdk_platform as c-posix.

Before You Start

  • Requirements: CMake 3.20+, a C11 compiler, libcurl, and a POSIX threads (pthreads) implementation.
  • Each active client needs its own writable queue_directory. Do not point two clients at the same directory.
  • Unlike the device ports, this port's API is multi-client: every call takes an explicit honch_client_t *.

1. Build The SDK

cmake -S . -B build -DHONCH_BUILD_TESTS=ON -DHONCH_BUILD_EXAMPLES=ON
cmake --build build
ctest --test-dir build --output-on-failure

The build is warnings-as-errors. To compile out crash/error reporting ($crash + $error), configure with -DHONCH_ENABLE_ERROR_TRACKING=OFF.

To install and link from another CMake project:

cmake -S . -B build-install -DHONCH_BUILD_TESTS=OFF -DHONCH_BUILD_EXAMPLES=OFF -DCMAKE_INSTALL_PREFIX=/opt/honch-posix
cmake --build build-install --target honch_posix
cmake --install build-install
find_package(honch_posix REQUIRED)
target_link_libraries(app PRIVATE honch::honch_posix)

2. Configure And Send A First Event

#include "honch/honch.h"

honch_config_t config = {
    .api_key = "your-api-key",
    .endpoint_url = "https://i.honch.io",
    .device_model = "linux-gateway",
    .firmware_version = "1.0.0",
    .queue_directory = "/var/lib/honch",
};

honch_client_t *client = NULL;
if (honch_init(&client, &config) != HONCH_STATUS_OK) {
    return 1;
}

const honch_property_t props[] = { honch_prop("role", honch_str("developer")) };
honch_identify(client, "local-user-001", props, 1);

honch_session_start(client, "demo");
honch_track(client, "button_pressed", NULL, 0);
honch_session_end(client);

honch_flush(client);
honch_shutdown(client);

Required fields are api_key, endpoint_url, device_model, firmware_version, and queue_directory. Everything else falls back to the shared defaults. honch_init() is synchronous — it validates config, reconciles the queue directory, persists identity, and queues $device_boot — but does no network I/O.

FieldDefaultNotes
device_idgenerated + persistedA random ID is created on first run if you do not set one.
environment"production"
durability_modeOS_BUFFEREDSYNC_ALWAYS fsyncs every write for power-loss safety at a throughput cost.
flush_interval_seconds120
flush_event_threshold20
transport_timeout_ms8000
connectivity_callbackReturn offline so ticks skip DNS/TLS and keep events pending.

3. Pump Delivery

Call honch_tick(client) from a dedicated thread. It performs a synchronous HTTP POST on the calling thread and blocks up to transport_timeout_ms, so keep it off latency-sensitive paths.

while (running) {
    honch_tick(client);
    sleep(1);
}

honch_flush(client) forces queued batches out immediately — handy in short-lived processes before exit.

4. Inspect Local Storage

The queue is a directory tree you can read directly:

<queue_directory>/
  pending/   events waiting to upload (one file each)
  dead/      permanently rejected events
  state/     device_id, distinct_id, firmware_version

Events are written atomically (temp file then rename) and evicted oldest-first when the queue is full. Retryable failures leave events in pending/; permanent rejections move them to dead/. This visibility is the main reason to validate an integration here before moving to a constrained device.

5. Crash Breadcrumbs (Optional)

honch_install_error_handlers(queue_directory) installs async-signal-safe handlers for SIGABRT, SIGSEGV, SIGBUS, SIGILL, and SIGFPE. They write a bounded breadcrumb file to the directory; the next honch_init() imports it as a $crash event. The path is process-global, so use it with a single client. Because the breadcrumb is persisted to disk, a fatal crash is delivered on the next run even though the in-memory queue does not survive it. POSIX captures the signal/reset context, not a coredump — there is no symbolicated backtrace on this port. For handled, non-fatal errors call honch_core_report_log_error(client, component, message).

Transport Contract

POST <endpoint_url>/capture
Content-Type: application/vnd.honch.chunk
X-Honch-Project-Key: <api_key>
X-Honch-Stream-Id: <stream_id>

Transport is libcurl with TLS verification enabled (peer and host); only http/https are allowed and redirects are not followed. Use https:// in production.

Examples

The repository ships runnable examples under ports/posix/example/: posix_device (the snippet above), connected_camera, posix_gpio (edge-tracking from a host GPIO source), and identify_merge.

Debugging Failures

When a call returns a non-HONCH_OK status, honch_core_get_last_error() gives the reason behind it:

honch_error_detail_t detail;
if (honch_tick(client) != HONCH_OK &&
    honch_core_get_last_error(client, &detail) == HONCH_OK) {
    char line[192];
    honch_error_detail_format(&detail, line, sizeof(line));
    fprintf(stderr, "honch: %s\n", line);
    // "transport error: HTTP 503 - server returned an error status (reason=http_status)"
    // or, for a connect-phase failure (raw CURLcode in os_error):
    // "transport error: DNS resolution failed - check the configured endpoint (reason=dns_failed) os_error=6"
}

The libcurl transport fills http_status from the response and maps the CURLcode of a connect/DNS/TLS failure into reason (with the raw code in os_error). The core also emits the same one-line summary once per distinct failure through the platform log hook. See Error Context & Diagnostics.

Public API

FunctionPurpose
honch_init(&client, &config)Create and initialize a client.
honch_core_get_last_error(client, &detail)Structured detail (reason, http_status, os_error) for the last failure.
honch_track(client, event, props, count)Queue an event.
honch_identify(client, distinct_id, traits, count)Set identity; emits $identify.
honch_set_property(client, key, value)Emit $set_property.
honch_session_start(client, name) / honch_session_end(client)Bracket a session.
honch_core_report_log_error(client, component, message)Report a handled, non-fatal error as an $error.
honch_install_error_handlers(queue_directory)Install crash-breadcrumb signal handlers ($crash on next run).
honch_tick(client)Cooperative delivery step.
honch_flush(client)Send queued batches now.
honch_reset(client)Clear identity, session, and queue.
honch_shutdown(client)Emit $device_shutdown, final flush, free the client.
honch_get_device_id(client)Borrowed device-ID pointer.
honch_copy_device_id(client, buf, size)Copy the device ID into your buffer (thread-safe).
honch_status_string(status)Human-readable status text.

Calls return honch_status_t (HONCH_STATUS_OK on success), except honch_get_device_id and honch_status_string, which return const char *.

honch.

Product analytics for consumer hardware.