Changelog
View SourceAll notable changes to this project will be documented in this file.
[1.1.1] - 2026-05-16
Fixed
observable_counterinstruments now render as Prometheuscounterwith the_totalsuffix instead ofgauge, in both unlabeled and labeled exposition. Previouslycreate_observable_instrument/3hardcoded gauge-shaped underlying storage and the labeled write path tagged the vec asgauge, so tooling that relies on# TYPE … counterto decide rate-ability (Grafana,rate(), alerting rules) saw the wrong type.instrument_meter:add/3on a labeledup_down_counterno longer crashes on negative deltas. The labeled write path previously hardcoded counter-shaped vec storage and hitinstrument_counter:inc_counter/2'sVal >= 0guard. It now routes through gauge-shaped vec storage with a sign split, soadd(Instrument, -1, #{label => ...})decrements the per-label-set value.
[1.1.0] - 2026-05-11
Changed
- Histogram bucket counts and the running sum are now backed by a single
OTP
atomics' array per histogram (slot 1 = IEEE-754 bits of the sum via CAS retry, slots 2..N+2 = signed int64 bucket counts viaatomics:add/3'). Drops the per-bucket NIF resources and makesget_histogram' /collect' ~1.5x faster;observe_histogram' is unchanged. Counters, gauges, and up-down counters remain on the NIF path. - Histogramcount' and per-bucketcount' fields in the collected map are now integers, matching theinstrumentmetrics_exporter' spec which already declared them asinteger()'. Callers that compared these fields with=:=' againstfloat()' values must update their expectations. ### Added -instrument_atomics' module: thin wrapper overatomics' providing signed-integer slots and IEEE-754 double slots via bit-cast with a CAS retry loop. ## [1.0.0] - 2026-05-03 First stable release. Hardens the runtime under contention and at high cardinality, brings the OTLP path up to spec, fixes deadlock and leak risks in the export pipeline, and lands a full audit of the documentation against the actual public API. ### Added -OTEL_METRIC_CARDINALITY_LIMIT(default 2000) caps distinct label sets per vector metric. Excess label sets aggregate into one shared series taggedotel.metric.overflow=true. Dropped count exposed viainstrument_registry:cardinality_dropped/1. -instrument_otlp_retrymodule: bounded exponential backoff withRetry-Afterhonoured, classifying transport and HTTP errors per the OTel spec. Configurable viaOTEL_EXPORTER_OTLP_MAX_RETRIES,OTEL_EXPORTER_OTLP_RETRY_INITIAL_DELAY_MS,OTEL_EXPORTER_OTLP_RETRY_MAX_DELAY_MS. - Span attribute value length limit (OTEL_ATTRIBUTE_VALUE_LENGTH_LIMIT), per-event and per-link attribute count limits (OTEL_EVENT_ATTRIBUTE_COUNT_LIMIT,OTEL_LINK_ATTRIBUTE_COUNT_LIMIT); excess attributes counted indropped_attributes_countand emitted asdroppedAttributesCountin OTLP. - Tracestate caps at 32 entries / 256 bytes; baggage caps at 180 entries / 8192 bytes per W3C trace-context. -instrument_attributes:apply_limits/2,3andtruncate_value/2helpers. - Span Export Path section in the design and internals guide explaining the full chain fromend_spanto OTLP, with explicit notes thatinstrument_tracer_nifserves the flight recorder only. - Test coverage for 28 documented public APIs that previously had no call sites in CT (instrument_propagation:inject_headers/extract_headers/call_with_context/cast_with_context,instrument_context:remove_value/spawn_link_with_context,instrument_config:set_verbose_tracing/is_verbose_tracing/enable_exporter/disable_exporter,instrument_tracer:record_exception/update_name,instrument_test:assert_log_trace_context,instrument_logger:add_trace_context/emit,instrument_metric:remove_label/clear_labels/set_gauge_to_current_time, exporter callback contracts). ### Changed - Batch processorforce_flush/0and the max-batch-size trigger no longer block the gen_server loop. An export worker is spawned and completion arrives as{export_done, ...}; concurrent flush callers are batched and replied to viagen_server:reply/2. A kill timer enforcesexport_timeout_milliswithout blocking the loop. -instrument_exportershutdown now casts the hook unregister so the reply path stays unblocked. -instrument_span_processor:on_start/2now has a 5 s safety timeout; the tracer hot path uses the inlinepersistent_termform. - OTLP exporters return{error, retryable, }vs{error, permanent, }. The batch processor keeps retryable batches for up tomax_batch_retriescycles and drops permanent errors. - Probability sampler hashes the upper 8 bytes of the trace id, matching the Java/Go/Python reference SDKs. - Status transitions now follow the OTel spec:unset -> ok|error,error -> ok(success overrides),error -> errorupdates the description,okis final. - Batch processor clampsmax_export_batch_sizetomax_queue_sizeon init with a warning. - Documentation snippets fixed acrossguides/,book/, andREADME.md: 6 syntax bugs, 8+ calls to non-existent or wrong-arity functions, wrong arg shapes forset_sampler,parent_basedconfig,metric_viewrecord literal,exporter_otlp:export, and stale config keys (schedule_delay_millis,export_timeout_millis). - Book chapter prose smoothed for readability. ### Fixed - Histogram exemplar reservoirs are now freed on unregister. - Registry unregister no longer scans the globalpersistent_termindex; iterates the metric's ownlabels_mapinstead. - Baggageset/remove/clearuseset_current/1so process-dictionary context tokens no longer accumulate. -instrument_exporter_console:export/2andinstrument_metrics_exporter_console:exporter_export/2no longer crash when configured withoutput => {file, Path}. The{file, Fd}wrapper used byshutdown/1is now unwrapped beforeio:put_chars/2. ### Removed -instrument_exporter_kafkadocumentation section: the module never existed insrc/exporters/`. ### Deprecated - _None. ## [0.6.1] - 2026-04-16 ### Fixed - Moved hex packagefileslist fromrebar.configtoinstrument.app.srcsodo_build.sh,do_cmake.sh, andc_src/build assets are actually shipped in the published tarball (the rebar.config{hex, [{files, ...}]}entry was silently ignored for non-standard files) - ex_doc XML parse errors caused by<<...>>literals and comparison operators in doc comments ## [0.6.0] - 2026-04-16 ### Changed - Renamedinstrumentmodule toinstrument_metricto avoid conflict with Erlang'sruntime_toolsinstrument module - Bumped application version ininstrument.app.srcto 0.6.0 ## [0.5.0] - 2026-04-08 ### Added - OTel spec compliance features: span limits, dropped counts tracking, exemplar support - B3 ParentSpanId injection for nested spans - Aggregation temporality support (cumulative/delta) - Observable instrument 1-arity callbacks with attributes - Tests for OTel spec compliance (30 new test cases) - Throughput optimizations for exporter and processor lookup - Updated benchmarks documentation ### Fixed - Spawned-child trace leak with session-based cleanup - OpenTelemetry spec compliance issues in OTLP export - Preserved tracer scope in OTLP span export ## [0.4.0] - 2026-04-07 ### Added - Tail-based sampling span processor - Generic client tracing utilities and attribute-based sampling - Flight recorder using erl_tracer NIF for low-overhead message tracing - Global tracing enable flag for performance optimization - Custom span_id support to tracer API -instrument_testmodule for validating instrumentation -startTimeUnixNanoto OTLP metrics export - Debug logging to broad exception handlers - Error logging to span processor callbacks - Benchmarks for OpenTelemetry APIs and client tracing strategies - Design and internals documentation - Book chapters and reference guides - Elixir users guide - Runnable cross-process tracing and logging examples - Tests for metric names and attributes in exporter - Tests for tracing disabled and custom span_id - Regression tests for 4 bug fixes (record_only sampling, metric description/unit, histogram view boundaries, OTLP scope config) ### Fixed - Critical tracing and OTLP spec compliance issues - Histogram and OTLP spec compliance issues - Empty bucket validation crash in histogram - Tuple metric name handling for OTEL metrics - Race condition in tracer exporter list - Race condition in metric index updates - Vec metric cleanup and concurrent attribute race condition -mark/1,2not working in spawned child processes - erl_tracer issues: teardown, idempotency, async parent spans - Multiple bugs in client and tail sampler - 5 bugs in span processors, metrics, and context propagation - 5 client tracing issues - Test failures in metrics exporter and span processor - E2E test skip behavior and timing issues ### Changed - Replaced seq_trace with erl_tracer NIF for flight recorder performance - Improved flight recorder eviction performance - Improved config auto-registration and processor shutdown handling - Improved edge case handling in tail sampler - Renamed exporter callbacks to avoid gen_server conflicts - Added xref checks - Documented processor callback restrictions - Filter internal tracer bootstrap messages in trace_receive ## [0.3.0] - 2026-04-01 ### Added - OpenTelemetry-compatible API with native implementation - Context propagation viainstrument_contextmodule - W3C TraceContext format support ininstrument_propagation- W3C Baggage propagation viainstrument_baggagemodule - B3 single-header propagator (instrument_propagator_b3) for Zipkin compatibility - B3 multi-header propagator (instrument_propagator_b3_multi) for X-B3-* headers - Support forb3andb3multiinOTEL_PROPAGATORSenvironment variable - Native span implementation viainstrument_tracerwith full lifecycle management - OTel-compatible MeterProvider/Meter API viainstrument_meter- Attribute handling viainstrument_attributes- Erlang logger integration viainstrument_loggerwith automatic trace correlation - Trace/Span ID generation per W3C spec viainstrument_id- Span exporter system viainstrument_exporterwith batch processing - Console exporter (instrument_exporter_console) with text and JSON formats - OTLP HTTP exporter (instrument_exporter_otlp) for OpenTelemetry collectors - Cross-process context propagation helpers - New test suites for context, tracer, meter, and exporter modules - Newinstrument_otel.hrlheader with OTel record definitions - Documentation guides: getting started, instrumentation, context propagation, exporters - E2E tests with Docker (Prometheus + Jaeger) - Stress tests and race condition tests - OpenTelemetry compatibility info to README - Sampling and processing guide, external collectors documentation ### Fixed - Context/memory leaks with instrument cleanup ### Changed - Extendedmetricrecord with OTel fields (description, unit, meter, attributes) - Updated application description to mention OpenTelemetry support - Added hackney 3.2.1 as dependency for OTLP HTTP export - Documentation updates for B3 propagation and OTel clarity ## [0.2.0] - 2026-03-31 ### Added - Vec API for labeled metrics (prometheus-cpp style):new_counter_vec/3,new_gauge_vec/3,new_histogram_vec/3- Direct vec operations:inc_counter_vec/2,3,get_counter_vec/2,inc_gauge_vec/2,3,dec_gauge_vec/2,3,set_gauge_vec/3,get_gauge_vec/2,observe_histogram_vec/3,get_histogram_vec/2-labels/2function to get labeled metric instances - Prometheus text format export viainstrument_prometheus:format/0- GitHub Actions CI for OTP 26/27 on Linux and macOS - ex_doc documentation support - Type specs for prometheus, vector, and registry modules ### Changed - Modernized NIF code from C++ to C11 with CMake build system - Updated README with examples and API documentation - Updated copyright to 2017-2026 ## [0.1.0] - 2017-04-28 ### Added - Initial release - Counter metrics withnew_counter/2,inc_counter/1,2,get_counter/1- Gauge metrics withnew_gauge/2,inc_gauge/1,2,dec_gauge/1,2,set_gauge/2,get_gauge/1- Histogram metrics withnew_histogram/2,3,observe_histogram/2,get_histogram/1- Vector support for labeled metrics - NIF-based implementation for high performance