Compare commits

...

17 commits
v0.90 ... main

Author SHA1 Message Date
Simon Cruanes
5065cdd985 prepare for 0.91
Some checks failed
format / format (push) Has been cancelled
github pages / deploy (push) Has been cancelled
build / build (ghcr.io/ocaml-tracing/ocaml-opentelemetry/ci-4.08:latest, false, 4.08) (push) Has been cancelled
build / build (ghcr.io/ocaml-tracing/ocaml-opentelemetry/ci-4.14:latest, false, 4.14) (push) Has been cancelled
build / build (ghcr.io/ocaml-tracing/ocaml-opentelemetry/ci-5.4:latest, true, 5.4) (push) Has been cancelled
2026-04-23 10:08:53 -04:00
Simon Cruanes
0cf72525b2 fix warning 2026-04-23 10:08:53 -04:00
Simon Cruanes
3bf18fed69 fix test being in the wrong package 2026-04-23 10:08:18 -04:00
Simon Cruanes
a4d95409ee better error message for otlp http failures 2026-04-17 11:27:46 -04:00
Simon Cruanes
59e2e854e5 docs 2026-04-15 10:19:11 -04:00
Simon Cruanes
5f3b162290 bounded queue: provide a per-item measure function for better errors/metrics
we can now know how big the batches we drop are
2026-04-10 15:09:59 -04:00
Simon Cruanes
2401745f1a fix: retries are self_debug logged at warning level 2026-04-10 15:09:59 -04:00
Simon Cruanes
fd47118c51 fix 2026-04-10 15:09:59 -04:00
Simon Cruanes
9cb9c1081c config: better defaults in Sdk, have batching enabled by default 2026-04-10 15:09:59 -04:00
Simon Cruanes
7a93a2582b better warning in bounded_queue_sync 2026-04-10 14:28:50 -04:00
Simon Cruanes
e9bb76edd1
expose Self_debug.level_above 2026-04-09 09:24:13 -04:00
Simon Cruanes
b766f86019
CI 2026-04-06 15:56:41 -04:00
Simon Cruanes
78e44e916c
move from ocurl to curl 2026-04-06 15:48:16 -04:00
Simon Cruanes
755509893e
fix docker build 2026-04-06 15:47:39 -04:00
Simon Cruanes
5031be8d91
use docker images for CI (#130)
* use docker images for CI

* run gha as root in docker

using the opam user wouldn't work for actions like checkout

* make our own docker images from ubuntu LTS

* details

* fix eio step

* fix build issues in docker
2026-04-06 15:47:16 -04:00
Simon Cruanes
8ebc582a00
add gh-pages back (!) 2026-04-06 09:25:38 -04:00
Simon Cruanes
7691512ace fix dumb circular dep 2026-04-04 01:06:42 -04:00
34 changed files with 250 additions and 116 deletions

View file

@ -1,5 +1,3 @@
name: format
on:
@ -11,20 +9,10 @@ on:
jobs:
format:
name: format
strategy:
matrix:
ocaml-compiler:
- '5.3'
runs-on: 'ubuntu-latest'
runs-on: ubuntu-latest
container: ghcr.io/ocaml-tracing/ocaml-opentelemetry/ci-4.14:latest
steps:
- uses: actions/checkout@main
- name: Use OCaml ${{ matrix.ocaml-compiler }}
uses: ocaml/setup-ocaml@v3
with:
ocaml-compiler: ${{ matrix.ocaml-compiler }}
dune-cache: true
allow-prerelease-opam: true
- uses: actions/checkout@v6
- run: opam install ocamlformat.0.27.0 lwt.6.1.1
- run: opam exec -- make format-check

38
.github/workflows/gh-pages.yml vendored Normal file
View file

@ -0,0 +1,38 @@
name: github pages
on:
push:
branches:
- main
permissions:
contents: write
packages: read
jobs:
deploy:
runs-on: ubuntu-latest
container: ghcr.io/ocaml-tracing/ocaml-opentelemetry/ci-5.4:latest
steps:
- uses: actions/checkout@v6
with:
submodules: recursive
- name: Install local packages
run: opam exec -- dune build @install && opam exec -- dune install
- name: Build documentation
run: |
opam exec -- odig odoc --cache-dir=_doc/ \
opentelemetry opentelemetry-client opentelemetry-lwt \
opentelemetry-cohttp-lwt opentelemetry-client-ocurl \
opentelemetry-client-ocurl-lwt opentelemetry-client-cohttp-lwt \
opentelemetry-client-cohttp-eio opentelemetry-logs
- name: Deploy
uses: peaceiris/actions-gh-pages@v3
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
publish_dir: ./_doc/html
enable_jekyll: false

View file

@ -11,65 +11,37 @@ jobs:
strategy:
fail-fast: false
matrix:
os:
- ubuntu-latest
#- windows-latest
#- macos-latest
ocaml-compiler:
- 4.08.x
- 4.13.x
- 5.0.x
- 5.3.x
include:
- ocaml-version: "4.08"
container: ghcr.io/ocaml-tracing/ocaml-opentelemetry/ci-4.08:latest
eio: false
- ocaml-version: "4.14"
container: ghcr.io/ocaml-tracing/ocaml-opentelemetry/ci-4.14:latest
eio: false
- ocaml-version: "5.4"
container: ghcr.io/ocaml-tracing/ocaml-opentelemetry/ci-5.4:latest
eio: true
runs-on: ${{ matrix.os }}
runs-on: ubuntu-latest
container: ${{ matrix.container }}
steps:
- name: Checkout code
uses: actions/checkout@v4
- uses: actions/checkout@v6
with:
submodules: recursive
# needed for depext to work
- run: sudo apt-get update && sudo apt-get install mccs
if: ${{ matrix.os == 'ubuntu-latest' }}
- name: Build
run: opam exec -- dune build @install -p opentelemetry,opentelemetry-client,opentelemetry-lwt,opentelemetry-cohttp-lwt,opentelemetry-client-ocurl,opentelemetry-client-ocurl-lwt,opentelemetry-client-cohttp-lwt,opentelemetry-logs
- name: Use OCaml ${{ matrix.ocaml-compiler }}
uses: ocaml/setup-ocaml@v3
with:
ocaml-compiler: ${{ matrix.ocaml-compiler }}
opam-depext-flags: --with-test
dune-cache: true
allow-prerelease-opam: true
- name: Build eio packages
if: ${{ matrix.eio }}
run: opam exec -- dune build @install -p opentelemetry-client-cohttp-eio,opentelemetry,opentelemetry-client,opentelemetry-lwt,opentelemetry-cohttp-lwt,opentelemetry-client-ocurl,opentelemetry-client-ocurl-lwt,opentelemetry-client-cohttp-lwt,opentelemetry-logs
- run: |
opam install pbrt.4.0 -y
opam install ambient-context lwt.5.9.2
- name: Lint (protoc check)
run: opam exec -- dune build @lint
# We cannot install packages that need eio on ocaml versions before 5
- run: |
packages=$(ls ./*.opam | grep -v eio)
opam install $packages --deps-only --with-test --solver=mccs
if: ${{ ! (startsWith(matrix.ocaml-compiler, '5')) }}
- name: Check no generated files changed
run: git diff --exit-code
# We should be able to install all packages on ocaml 5
- run: opam install . --deps-only --with-test --solver=mccs
if: ${{ startsWith(matrix.ocaml-compiler, '5') }}
- run: opam exec -- dune build @install -p opentelemetry,opentelemetry-client,opentelemetry-lwt,opentelemetry-client-ocurl,opentelemetry-cohttp-lwt,opentelemetry-client-cohttp-lwt,opentelemetry-logs
- run: opam install trace
- run: opam exec -- dune build @install -p opentelemetry
- run: opam install lwt.6.1.1 -y
if: ${{ matrix.ocaml-compiler == '5.3.x' }}
- run: opam exec -- dune build @install -p opentelemetry,opentelemetry-client,opentelemetry-lwt,opentelemetry-client-cohttp-lwt
if: ${{ matrix.ocaml-compiler == '5.3.x' }}
- run: opam install ocaml-protoc
- run: opam exec -- dune build @lint
# check that nothing changed
- run: git diff --exit-code
- run: opam exec -- dune build @runtest
if: ${{ matrix.os == 'ubuntu-latest' }}
- name: Run tests
run: opam exec -- dune build @runtest

1
.gitignore vendored
View file

@ -7,3 +7,4 @@ _opam
*.install
*.exe
*.tmp
/.env

View file

@ -1,4 +1,14 @@
## 0.91
- expose Self_debug.level_above
- config: better defaults in Sdk, have batching enabled by default
- better error message for otlp http failures
- bounded queue: provide a per-item measure function for better errors/metrics
- fix: retries are self_debug logged at warning level
- move from ocurl to curl as a dep
## 0.90
- major refactor: split library into `opentelemetry.core`, `opentelemetry`,

View file

@ -36,6 +36,8 @@ WATCH ?= @all
watch:
@dune build $(WATCH) -w $(OPTS)
include deps/Makefile.ci
VERSION=$(shell awk '/^version:/ {print $$2}' opentelemetry.opam)
update_next_tag:
@echo "update version to $(VERSION)..."

44
deps/Makefile.ci vendored Normal file
View file

@ -0,0 +1,44 @@
# CI Docker images — included by top-level Makefile
CI_REGISTRY = ghcr.io/ocaml-tracing/ocaml-opentelemetry
CI_VERSIONS = 4.08 4.14 5.4
# To update: curl -s https://api.github.com/repos/ocaml/opam-repository/commits/master | jq -r .sha
OPAM_REPO_COMMIT ?= 67472cd54293d750a62d6d4423024d55f77268b0
CI_BASE_OS_PACKAGES = pkg-config libcurl4-openssl-dev libgmp-dev mccs
CI_COMMON_PACKAGES = ptime hmap pbrt pbrt_yojson ambient-context mtime \
thread-local-storage lwt_ppx ambient-context-lwt \
cohttp cohttp-lwt cohttp-lwt-unix \
ezcurl ezcurl-lwt ocurl logs alcotest containers \
trace ocaml-protoc
CI_PACKAGES_408 = $(CI_COMMON_PACKAGES) lwt.5.9.2
CI_PACKAGES_414 = $(CI_COMMON_PACKAGES) lwt.5.9.2 ocamlformat.0.27.0
CI_PACKAGES_54 = $(CI_COMMON_PACKAGES) lwt.6.1.1 \
ambient-context-eio cohttp-eio tls-eio ca-certs mirage-crypto-rng eio_main odig
CI_BUILD = docker build -f deps/dockerfile.ocaml \
--build-arg OPAM_REPO_COMMIT=$(OPAM_REPO_COMMIT) \
--build-arg "BASE_OS_PACKAGES=$(CI_BASE_OS_PACKAGES)"
build-ci-docker:
$(CI_BUILD) --build-arg OCAML_VERSION=4.08.1 --build-arg "BASE_PACKAGES=$(CI_PACKAGES_408)" -t $(CI_REGISTRY)/ci-4.08:latest .
$(CI_BUILD) --build-arg OCAML_VERSION=4.14.2 --build-arg "BASE_PACKAGES=$(CI_PACKAGES_414)" -t $(CI_REGISTRY)/ci-4.14:latest .
$(CI_BUILD) --build-arg OCAML_VERSION=5.4.1 --build-arg "BASE_PACKAGES=$(CI_PACKAGES_54)" -t $(CI_REGISTRY)/ci-5.4:latest .
CI_NON_EIO_PACKAGES = opentelemetry,opentelemetry-client,opentelemetry-lwt,opentelemetry-cohttp-lwt,opentelemetry-client-ocurl,opentelemetry-client-ocurl-lwt,opentelemetry-client-cohttp-lwt,opentelemetry-logs
CI_RUN = docker run --pull=never --rm -t -v $(PWD):/src:z -w /src
run-ci:
@for v in $(CI_VERSIONS); do \
echo "=== OCaml $$v ===" ; \
$(CI_RUN) $(CI_REGISTRY)/ci-$$v:latest \
sh -c "opam exec -- dune build @install -p $(CI_NON_EIO_PACKAGES) && opam exec -- dune build @runtest" \
|| exit 1 ; \
done
$(CI_RUN) $(CI_REGISTRY)/ci-5.4:latest \
opam exec -- dune build @install -p opentelemetry-client-cohttp-eio
upload-ci-docker:
@for v in $(CI_VERSIONS); do \
docker push $(CI_REGISTRY)/ci-$$v:latest ; \
done || ( echo "to login: docker login ghcr.io -u <your-github-username>" ; exit 1 )

40
deps/dockerfile.ocaml vendored Normal file
View file

@ -0,0 +1,40 @@
ARG BASE_OS=ubuntu:24.04
# --- Stage 1: base (shared, no OCaml) ---
FROM $BASE_OS AS base
ARG BASE_OS_PACKAGES=""
ENV OPAMROOTISOK=1 OPAMYES=1 OPAMCONFIRMLEVEL=unsafe-yes
RUN --mount=type=cache,target=/var/cache/apt,sharing=locked \
--mount=type=cache,target=/var/lib/apt,sharing=locked \
rm -f /etc/apt/apt.conf.d/docker-clean && \
apt-get update && \
apt-get install -y --no-install-recommends ca-certificates curl git unzip build-essential netbase $BASE_OS_PACKAGES
RUN curl -fsSL https://github.com/ocaml/opam/releases/download/2.5.0/opam-2.5.0-x86_64-linux -o /usr/local/bin/opam && \
chmod +x /usr/local/bin/opam && \
git config --system --add safe.directory '*'
WORKDIR /root/w
# --- Stage 2: opam-setup (builds the switch, discarded) ---
FROM base AS opam-setup
ARG OCAML_VERSION
ARG OPAM_REPO_COMMIT=master
ARG BASE_PACKAGES=""
RUN git init /tmp/opam-repo && cd /tmp/opam-repo && \
git remote add origin https://github.com/ocaml/opam-repository.git && \
git fetch --depth 1 origin $OPAM_REPO_COMMIT && \
git checkout FETCH_HEAD
RUN opam init --disable-sandboxing --bare --no-setup -k local /tmp/opam-repo && \
opam switch create /root/w --packages=ocaml-base-compiler.$OCAML_VERSION
RUN opam install --no-depexts $BASE_PACKAGES && \
opam clean -a -y && \
rm -rf /tmp/opam-repo
# --- Stage 3: final image (base + switch only) ---
FROM base
COPY --from=opam-setup /root/.opam /root/.opam
COPY --from=opam-setup /root/w/_opam /root/w/_opam
ENV OPAMROOT=/root/.opam OPAMSWITCH=/root/w PATH=/root/w/_opam/bin:$PATH
WORKDIR /root/w

View file

@ -7,7 +7,7 @@
(source
(github ocaml-tracing/ocaml-opentelemetry))
(version 0.90)
(version 0.91)
(implicit_transitive_deps false)
@ -31,10 +31,6 @@
hmap
(odoc :with-doc)
(alcotest :with-test)
(opentelemetry-client
(and
:with-test
(= :version)))
(pbrt
(and
(>= 4.0)
@ -98,7 +94,7 @@
(name opentelemetry-client-ocurl)
(depends
(ocaml
(>= "4.08"))
(>= "4.11"))
(mtime
(>= "1.4"))
; for spans
@ -110,7 +106,7 @@
(odoc :with-doc)
(ezcurl
(>= 0.2.3))
ocurl
curl
(alcotest :with-test)
(cohttp-lwt-unix :with-test)
(containers :with-test)
@ -121,7 +117,7 @@
(name opentelemetry-client-ocurl-lwt)
(depends
(ocaml
(>= "4.08"))
(>= "4.11"))
(mtime
(>= "1.4"))
(opentelemetry
@ -209,11 +205,7 @@
cohttp-lwt
cohttp-lwt-unix
(alcotest :with-test)
(containers :with-test)
(opentelemetry-lwt
(and
:with-test
(= :version))))
(containers :with-test))
(synopsis "Collector client for opentelemetry, using cohttp + lwt"))
(package

View file

@ -1,6 +1,6 @@
# This file is generated by dune, edit dune-project instead
opam-version: "2.0"
version: "0.90"
version: "0.91"
synopsis: "Collector client for opentelemetry, using cohttp + eio"
maintainer: ["ocaml-tracing"]
authors: ["ocaml-tracing" "ELLIOTTCABLE <opam@ell.io>" "the imandra team"]

View file

@ -1,6 +1,6 @@
# This file is generated by dune, edit dune-project instead
opam-version: "2.0"
version: "0.90"
version: "0.91"
synopsis: "Collector client for opentelemetry, using cohttp + lwt"
maintainer: ["ocaml-tracing"]
authors: ["ocaml-tracing" "ELLIOTTCABLE <opam@ell.io>" "the imandra team"]
@ -22,7 +22,6 @@ depends: [
"cohttp-lwt-unix"
"alcotest" {with-test}
"containers" {with-test}
"opentelemetry-lwt" {with-test & = version}
]
build: [
["dune" "subst"] {dev}

View file

@ -1,6 +1,6 @@
# This file is generated by dune, edit dune-project instead
opam-version: "2.0"
version: "0.90"
version: "0.91"
synopsis: "Collector client for opentelemetry, using ezcurl-lwt"
maintainer: ["ocaml-tracing"]
authors: ["ocaml-tracing" "ELLIOTTCABLE <opam@ell.io>" "the imandra team"]
@ -9,7 +9,7 @@ homepage: "https://github.com/ocaml-tracing/ocaml-opentelemetry"
bug-reports: "https://github.com/ocaml-tracing/ocaml-opentelemetry/issues"
depends: [
"dune" {>= "3.11"}
"ocaml" {>= "4.08"}
"ocaml" {>= "4.11"}
"mtime" {>= "1.4"}
"opentelemetry" {= version}
"opentelemetry-client" {= version}

View file

@ -1,6 +1,6 @@
# This file is generated by dune, edit dune-project instead
opam-version: "2.0"
version: "0.90"
version: "0.91"
synopsis: "Collector client for opentelemetry, using http + ezcurl"
maintainer: ["ocaml-tracing"]
authors: ["ocaml-tracing" "ELLIOTTCABLE <opam@ell.io>" "the imandra team"]
@ -9,13 +9,13 @@ homepage: "https://github.com/ocaml-tracing/ocaml-opentelemetry"
bug-reports: "https://github.com/ocaml-tracing/ocaml-opentelemetry/issues"
depends: [
"dune" {>= "3.11"}
"ocaml" {>= "4.08"}
"ocaml" {>= "4.11"}
"mtime" {>= "1.4"}
"opentelemetry" {= version}
"opentelemetry-client" {= version}
"odoc" {with-doc}
"ezcurl" {>= "0.2.3"}
"ocurl"
"curl"
"alcotest" {with-test}
"cohttp-lwt-unix" {with-test}
"containers" {with-test}

View file

@ -1,6 +1,6 @@
# This file is generated by dune, edit dune-project instead
opam-version: "2.0"
version: "0.90"
version: "0.91"
synopsis: "Client SDK for https://opentelemetry.io"
maintainer: ["ocaml-tracing"]
authors: ["ocaml-tracing" "ELLIOTTCABLE <opam@ell.io>" "the imandra team"]

View file

@ -1,6 +1,6 @@
# This file is generated by dune, edit dune-project instead
opam-version: "2.0"
version: "0.90"
version: "0.91"
synopsis: "Opentelemetry tracing for Cohttp HTTP servers"
maintainer: ["ocaml-tracing"]
authors: ["ocaml-tracing" "ELLIOTTCABLE <opam@ell.io>" "the imandra team"]

View file

@ -1,6 +1,6 @@
# This file is generated by dune, edit dune-project instead
opam-version: "2.0"
version: "0.90"
version: "0.91"
synopsis: "Opentelemetry-based reporter for Logs"
maintainer: ["ocaml-tracing"]
authors: ["ocaml-tracing" "ELLIOTTCABLE <opam@ell.io>" "the imandra team"]

View file

@ -1,6 +1,6 @@
# This file is generated by dune, edit dune-project instead
opam-version: "2.0"
version: "0.90"
version: "0.91"
synopsis: "Lwt-compatible instrumentation for https://opentelemetry.io"
maintainer: ["ocaml-tracing"]
authors: ["ocaml-tracing" "ELLIOTTCABLE <opam@ell.io>" "the imandra team"]

View file

@ -1,6 +1,6 @@
# This file is generated by dune, edit dune-project instead
opam-version: "2.0"
version: "0.90"
version: "0.91"
synopsis:
"Core library for instrumentation and serialization for https://opentelemetry.io"
maintainer: ["ocaml-tracing"]
@ -16,7 +16,6 @@ depends: [
"hmap"
"odoc" {with-doc}
"alcotest" {with-test}
"opentelemetry-client" {with-test & = version}
"pbrt" {>= "4.0" & < "5.0"}
"pbrt_yojson" {>= "4.0" & < "5.0"}
"ambient-context" {>= "0.2"}

View file

@ -169,6 +169,7 @@ let create_exporter ?(config = Config.make ()) ~sw ~env () =
let consumer = create_consumer ~config ~sw ~env () in
let bq =
Opentelemetry_client_sync.Bounded_queue_sync.create
~measure:Any_signal_l.length
~high_watermark:Bounded_queue.Defaults.high_watermark ()
in
Exporter_queued.create ~clock:Clock.ptime_clock ~q:bq ~consumer ()

View file

@ -102,6 +102,7 @@ let create_exporter ?(config = Config.make ()) () =
let consumer = create_consumer ~config () in
let bq =
Opentelemetry_client_sync.Bounded_queue_sync.create
~measure:OTEL.Any_signal_l.length
~high_watermark:Bounded_queue.Defaults.high_watermark ()
in
Exporter_queued.create ~clock:Clock.ptime_clock ~q:bq ~consumer ()

View file

@ -79,6 +79,7 @@ let create_exporter ?(config = Config.make ()) () =
let consumer = create_consumer ~config () in
let bq =
Opentelemetry_client_sync.Bounded_queue_sync.create
~measure:OTEL.Any_signal_l.length
~high_watermark:Bounded_queue.Defaults.high_watermark ()
in
Exporter_queued.create ~clock:Clock.ptime_clock ~q:bq ~consumer ()

View file

@ -81,6 +81,7 @@ let create_exporter ?(config = Config.make ()) () : OTEL.Exporter.t =
let consumer = consumer ~config () in
let bq =
Opentelemetry_client_sync.Bounded_queue_sync.create
~measure:OTEL.Any_signal_l.length
~high_watermark:OTELC.Bounded_queue.Defaults.high_watermark ()
in

View file

@ -12,10 +12,12 @@ let str_to_hex (s : string) : string =
Opentelemetry_util.Util_bytes_.bytes_to_hex (Bytes.unsafe_of_string s)
(** Report the error on stderr. *)
let report_err ~level:(provided_level : [ `Debug | `Auto ]) (err : t) : unit =
let report_err ~level:(provided_level : [ `Debug | `Warning | `Auto ]) (err : t)
: unit =
let compute_level lvl =
match provided_level with
| `Debug -> Opentelemetry.Self_debug.Debug
| `Warning -> Opentelemetry.Self_debug.Warning
| `Auto -> lvl
in
match err with
@ -24,7 +26,7 @@ let report_err ~level:(provided_level : [ `Debug | `Auto ]) (err : t) : unit =
"opentelemetry: ctrl-c captured, stopping")
| `Failure msg ->
Opentelemetry.Self_debug.log (compute_level Error) (fun () ->
Printf.sprintf "opentelemetry: export failed: %s" msg)
Printf.sprintf "opentelemetry: export failed:\n%s" msg)
| `Status
( code,
{
@ -57,8 +59,9 @@ let decode_invalid_http_response ~attempt_descr ~code ~url (body : string) : t =
let bt = Printexc.get_backtrace () in
`Failure
(Printf.sprintf
"httpc: decoding of status (url=%S, code=%d) failed with:\n\
"http server at %s returned code %d;\n\
trying to decode the body as protobuf failed:\n\
%s\n\
HTTP body: %s\n\
raw HTTP body (hex): %s\n\
%s"
url code (Printexc.to_string e) (str_to_hex body) bt)

View file

@ -82,7 +82,7 @@ end = struct
| Error err
when should_retry err && attempt < self.config.retry_max_attempts ->
let delay_s = delay_ms /. 1000. in
Export_error.report_err ~level:`Debug err;
Export_error.report_err ~level:`Warning err;
let* () = sleep_s delay_s in
let next_delay =

View file

@ -88,21 +88,27 @@ type 'a state = {
high_watermark: int;
q: 'a Q.t;
on_non_empty: Cb_set.t;
measure: 'a -> int;
}
let measure_all_ measure xs = List.fold_left (fun acc x -> acc + measure x) 0 xs
let push (self : _ state) x =
if x <> [] then (
match
Q.push_while_not_full self.q ~high_watermark:self.high_watermark x
with
| Closed ->
ignore (Atomic.fetch_and_add self.n_discarded (List.length x) : int)
let n = measure_all_ self.measure x in
ignore (Atomic.fetch_and_add self.n_discarded n : int)
| Pushed { num_discarded } ->
if num_discarded > 0 then (
ignore (Atomic.fetch_and_add self.n_discarded num_discarded : int);
let n_signals = measure_all_ self.measure x in
let total = Atomic.fetch_and_add self.n_discarded n_signals in
Opentelemetry.Self_debug.log Warning (fun () ->
Printf.sprintf "otel: dropped %d signals (exporter queue full)"
num_discarded)
Printf.sprintf
"otel: dropped %d signals (queue full: %d/%d, total dropped: %d)"
n_signals (Q.size self.q) self.high_watermark (total + n_signals))
);
(* wake up potentially asleep consumers *)
Cb_set.trigger self.on_non_empty
@ -129,13 +135,14 @@ let to_bounded_queue (self : 'a state) : 'a BQ.t =
recv = { try_pop; on_non_empty; common };
}
let create ~high_watermark () : _ BQ.t =
let create ?(measure = fun _ -> 1) ~high_watermark () : _ BQ.t =
let st =
{
high_watermark;
q = Q.create ();
n_discarded = Atomic.make 0;
on_non_empty = Cb_set.create ();
measure;
}
in
to_bounded_queue st

View file

@ -2,6 +2,11 @@
This is not the fastest queue but it should be versatile. *)
val create : high_watermark:int -> unit -> 'a Bounded_queue.t
val create :
?measure:('a -> int) -> high_watermark:int -> unit -> 'a Bounded_queue.t
(** [create ~high_watermark ()] creates a new bounded queue based on
{!Sync_queue} *)
{!Sync_queue}.
@param measure
maps each item to its signal count (e.g. number of spans in a batch). Used
to report accurate signal counts when items are dropped. Default:
[fun _ -> 1]. *)

View file

@ -19,6 +19,11 @@ let pp out = function
| Metrics m -> pp_list Proto.Metrics.pp_metric out m
| Logs l -> pp_list Proto.Logs.pp_log_record out l
let length = function
| Spans l -> List.length l
| Metrics l -> List.length l
| Logs l -> List.length l
let of_logs_or_empty = function
| [] -> []
| l -> [ Logs l ]

View file

@ -54,8 +54,9 @@ let run_tick_callbacks : unit -> unit = Globals.run_tick_callbacks
from their ticker. *)
let tick : unit -> unit = Globals.run_tick_callbacks
let set ?(traces = Provider_config.default) ?(metrics = Provider_config.default)
?(logs = Provider_config.default) (exp : Exporter.t) : unit =
let set ?(traces = Provider_config.make ~batch:400 ())
?(metrics = Provider_config.make ~batch:200 ())
?(logs = Provider_config.make ~batch:400 ()) (exp : Exporter.t) : unit =
Self_debug.log Info (fun () -> "opentelemetry: SDK set up");
Atomic.set exporter (Some exp);
let tracer : Tracer.t =

View file

@ -16,17 +16,21 @@ let string_of_level = function
| Warning -> "warning"
| Error -> "error"
let to_stderr ?(min_level = Warning) () : unit =
open struct
let[@inline] int_of_level_ = function
| Debug -> 0
| Info -> 1
| Warning -> 2
| Error -> 3
in
let threshold = int_of_level_ min_level in
end
let level_above ~min_level level : bool =
int_of_level_ level >= int_of_level_ min_level
let to_stderr ?(min_level = Warning) () : unit =
logger :=
fun level mk_msg ->
if int_of_level_ level >= threshold then (
if level_above ~min_level level then (
let msg = mk_msg () in
Printf.eprintf "[otel:%s] %s\n%!" (string_of_level level) msg
)

View file

@ -25,6 +25,11 @@ val logger : logger ref
val string_of_level : level -> string
(** String representation of a level. *)
val level_above : min_level:level -> level -> bool
(** [level_above ~min_level lvl] is true if messages at level [lvl] should be
logged.
@since NEXT_RELEASE *)
val log : level -> (unit -> string) -> unit
(** [log level mk_msg] emits a diagnostic message if the current logger is
active. [mk_msg] is called lazily only if the message will be emitted. *)

View file

@ -1,6 +1,9 @@
open Common_
module Extensions = struct
(* extend [Trace]'s types with OTEL specific variants, eg to have a
[Trace.span] be a wrapper around [OTEL.Span.t], or to declare custom actions
to link spans together, or to be able to use [OTEL]-specific metrics types *)
type Trace.span += Span_otel of OTEL.Span.t
type Trace.extension_event +=
@ -21,6 +24,14 @@ end
open Extensions
(* Inject ambient span into [Trace], relying on the [Ambient_context]
library. We use the generic ambient context to carry a [Hmap.t] around with
possible the current [Trace.span], and it is also used by [OTEL] itself
(ambient [OTEL.Span_ctx.t]).
This mechanism is used by [Trace] so that nested [Trace.with_span] can infer
the correct parent-child relation from implicit context, and produce OTEL
spans accordingly; without it every span would be parentless. *)
module Ambient_span_provider_ = struct
let get_current_span () =
match OTEL.Ambient_span.get () with

View file

@ -1,4 +1,4 @@
(tests
(names test_client_lib)
(package opentelemetry)
(package opentelemetry-client)
(libraries alcotest opentelemetry-client))

View file

@ -1,4 +1,4 @@
(tests
(names test_trace_context t_size t_histogram test_span_dummy)
(package opentelemetry)
(libraries pbrt opentelemetry opentelemetry-client))
(libraries pbrt opentelemetry))

View file

@ -19,7 +19,11 @@ let test_exporter : Otel.Exporter.t =
let with_test_exporter f =
(* uncomment for eprintf debugging: *)
(* let test_exporter = Opentelemetry_client.Exporter_debug.debug test_exporter in*)
Otel.Sdk.set test_exporter;
Otel.Sdk.set
~traces:(Otel.Provider_config.make ())
~metrics:(Otel.Provider_config.make ())
~logs:(Otel.Provider_config.make ())
test_exporter;
Fun.protect f ~finally:(fun () ->
let sq = Opentelemetry_client_sync.Sync_queue.create () in
Otel.Sdk.remove