From bf4ac37f21f7ce2910f020ffed4ce2177a96542c Mon Sep 17 00:00:00 2001 From: Matt Bray Date: Mon, 28 Mar 2022 18:12:12 +0100 Subject: [PATCH 1/3] feat: use runtime metric conventions; add runtime attributes See https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/metrics/semantic_conventions/runtime-environment-metrics.md#runtime-environment-specific-metrics---processruntimeenvironment --- src/opentelemetry.ml | 90 ++++++++++++++++++++++++++++++++------------ 1 file changed, 66 insertions(+), 24 deletions(-) diff --git a/src/opentelemetry.ml b/src/opentelemetry.ml index c1eada3e..394fb553 100644 --- a/src/opentelemetry.ml +++ b/src/opentelemetry.ml @@ -208,6 +208,38 @@ end = struct let of_hex s = of_bytes (Util_.bytes_of_hex s) end +module Conventions = struct + module Attributes = struct + module Process = struct + module Runtime = struct + let name = "process.runtime.name" + let version = "process.runtime.version" + let description = "process.runtime.description" + end + end + module Service = struct + let name = "service.name" + let namespace = "service.namespace" + end + end + + module Metrics = struct + module Process = struct + module Runtime = struct + module Ocaml = struct + module GC = struct + let compactions = "process.runtime.ocaml.gc.compactions" + let major_collections = "process.runtime.ocaml.gc.major_collections" + let major_heap = "process.runtime.ocaml.gc.major_heap" + let minor_allocated = "process.runtime.ocaml.gc.minor_allocated" + let minor_collections = "process.runtime.ocaml.gc.minor_collections" + end + end + end + end + end +end + (** Process-wide metadata, environment variables, etc. *) module Globals = struct open Proto.Common @@ -418,15 +450,16 @@ module Trace = struct ~spans () in let attributes = let open Proto.Common in + let open Conventions.Attributes in let l = List.map _conv_key_value attrs in let l = - default_key_value ~key:"service.name" + default_key_value ~key:Service.name ~value:(Some (String_value service_name)) () :: l in let l = match !Globals.service_namespace with | None -> l | Some v -> - default_key_value ~key:"service.namespace" + default_key_value ~key:Service.namespace ~value:(Some (String_value v)) () :: l in l |> Globals.merge_global_attributes_ @@ -681,6 +714,14 @@ module GC_metrics : sig val get_metrics : unit -> Metrics.t list (** Get a few metrics from the current state of the GC *) end = struct + (** See https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/resource/semantic_conventions/process.md#process-runtimes *) + let runtime_attributes : Proto.Common.key_value list = + Conventions.Attributes.[ + (Process.Runtime.name, "ocaml"); + (Process.Runtime.version, Sys.ocaml_version); + ] + |> List.map (fun (key, value) -> + Proto.Common.default_key_value ~key ~value:(Some (String_value value)) ()) let basic_setup () = let trigger() = @@ -701,26 +742,27 @@ end = struct let gc = Gc.quick_stat () in let start_time_unix_nano = !last in last := Timestamp_ns.now_unix_ns(); - Metrics.( - [ - gauge ~name:"ocaml.gc.major_heap" ~unit_:"B" - [ int (word_to_bytes gc.Gc.heap_words) ]; - sum ~name:"ocaml.gc_minor_allocated" - ~aggregation_temporality:Metrics.Aggregation_temporality_cumulative - ~is_monotonic:true - ~unit_:"B" - [ float ~start_time_unix_nano (word_to_bytes_f gc.Gc.minor_words) ]; - sum ~name:"ocaml.gc.minor_collections" - ~aggregation_temporality:Metrics.Aggregation_temporality_cumulative - ~is_monotonic:true - [ int ~start_time_unix_nano gc.Gc.minor_collections ]; - sum ~name:"ocaml.gc.major_collections" - ~aggregation_temporality:Metrics.Aggregation_temporality_cumulative - ~is_monotonic:true - [ int ~start_time_unix_nano gc.Gc.major_collections ]; - sum ~name:"ocaml.gc.compactions" - ~aggregation_temporality:Metrics.Aggregation_temporality_cumulative - ~is_monotonic:true - [ int ~start_time_unix_nano gc.Gc.compactions ]; - ]) + let open Metrics in + let open Conventions.Metrics in + [ + gauge ~name:Process.Runtime.Ocaml.GC.major_heap ~unit_:"B" + [ int (word_to_bytes gc.Gc.heap_words) ]; + sum ~name:Process.Runtime.Ocaml.GC.minor_allocated + ~aggregation_temporality:Metrics.Aggregation_temporality_cumulative + ~is_monotonic:true + ~unit_:"B" + [ float ~start_time_unix_nano (word_to_bytes_f gc.Gc.minor_words) ]; + sum ~name:Process.Runtime.Ocaml.GC.minor_collections + ~aggregation_temporality:Metrics.Aggregation_temporality_cumulative + ~is_monotonic:true + [ int ~start_time_unix_nano gc.Gc.minor_collections ]; + sum ~name:Process.Runtime.Ocaml.GC.major_collections + ~aggregation_temporality:Metrics.Aggregation_temporality_cumulative + ~is_monotonic:true + [ int ~start_time_unix_nano gc.Gc.major_collections ]; + sum ~name:Process.Runtime.Ocaml.GC.compactions + ~aggregation_temporality:Metrics.Aggregation_temporality_cumulative + ~is_monotonic:true + [ int ~start_time_unix_nano gc.Gc.compactions ]; + ] end From 66693280ecc2049d61a7df8aba2bccf2a4637e48 Mon Sep 17 00:00:00 2001 From: Matt Bray Date: Tue, 12 Apr 2022 16:25:52 +0100 Subject: [PATCH 2/3] expose GC_metrics.get_runtime_attributes --- src/opentelemetry.ml | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/src/opentelemetry.ml b/src/opentelemetry.ml index 394fb553..9bb60a75 100644 --- a/src/opentelemetry.ml +++ b/src/opentelemetry.ml @@ -711,17 +711,21 @@ module GC_metrics : sig val basic_setup : unit -> unit (** Setup a hook that will emit GC statistics regularly *) + val get_runtime_attributes : unit -> Span.key_value list + (** Get OCaml name and version runtime attributes *) + val get_metrics : unit -> Metrics.t list (** Get a few metrics from the current state of the GC *) end = struct (** See https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/resource/semantic_conventions/process.md#process-runtimes *) - let runtime_attributes : Proto.Common.key_value list = - Conventions.Attributes.[ - (Process.Runtime.name, "ocaml"); - (Process.Runtime.version, Sys.ocaml_version); - ] - |> List.map (fun (key, value) -> - Proto.Common.default_key_value ~key ~value:(Some (String_value value)) ()) + let runtime_attributes = + lazy + Conventions.Attributes.[ + (Process.Runtime.name, `String "ocaml"); + (Process.Runtime.version, `String Sys.ocaml_version); + ] + + let get_runtime_attributes () = Lazy.force runtime_attributes let basic_setup () = let trigger() = From 1919154085044a8b3c59da02789a127e5353b580 Mon Sep 17 00:00:00 2001 From: Matt Bray Date: Tue, 12 Apr 2022 16:26:08 +0100 Subject: [PATCH 3/3] add runtime attrs to GC stats --- src/client/opentelemetry_client_ocurl.ml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/client/opentelemetry_client_ocurl.ml b/src/client/opentelemetry_client_ocurl.ml index 2f99a524..e7d9c8c8 100644 --- a/src/client/opentelemetry_client_ocurl.ml +++ b/src/client/opentelemetry_client_ocurl.ml @@ -47,7 +47,9 @@ let gc_metrics = AList.make() (* side channel for GC, appended to {!E_metrics}'s collection *) let sample_gc_metrics () = Atomic.set needs_gc_metrics false; - let l = OT.Metrics.make_resource_metrics @@ Opentelemetry.GC_metrics.get_metrics() in + let l = OT.Metrics.make_resource_metrics + ~attrs:(Opentelemetry.GC_metrics.get_runtime_attributes ()) + @@ Opentelemetry.GC_metrics.get_metrics() in AList.add gc_metrics l let lock_ : (unit -> unit) ref = ref ignore