diff --git a/infer/man/man1/infer-full.txt b/infer/man/man1/infer-full.txt index a17f492e0..de83a1f25 100644 --- a/infer/man/man1/infer-full.txt +++ b/infer/man/man1/infer-full.txt @@ -1707,6 +1707,10 @@ INTERNAL OPTIONS add an extra string (normal) field to be set for each sample of scuba, format = + --scuba-tags +key=value + add an extra set of strings (tagset) field to be set for each + sample of scuba, format =(,,|NONE) + --seconds-per-iteration float Set the number of seconds per iteration (see --iterations) diff --git a/infer/src/base/Config.ml b/infer/src/base/Config.ml index e0c695ca6..d9c6a34b4 100644 --- a/infer/src/base/Config.ml +++ b/infer/src/base/Config.ml @@ -2169,6 +2169,12 @@ and scuba_normals = "add an extra string (normal) field to be set for each sample of scuba, format =" +and scuba_tags = + CLOpt.mk_string_map ~long:"scuba-tags" + "add an extra set of strings (tagset) field to be set for each sample of scuba, format \ + =(,,|NONE)" + + and siof_safe_methods = CLOpt.mk_string_list ~long:"siof-safe-methods" ~in_help:InferCommand.[(Analyze, manual_siof)] @@ -3163,6 +3169,8 @@ and scuba_logging = !scuba_logging and scuba_normals = !scuba_normals +and scuba_tags = String.Map.map !scuba_tags ~f:(fun v -> String.split v ~on:',') + and seconds_per_iteration = !seconds_per_iteration and select = !select diff --git a/infer/src/base/Config.mli b/infer/src/base/Config.mli index f4d071809..32a98be7c 100644 --- a/infer/src/base/Config.mli +++ b/infer/src/base/Config.mli @@ -619,6 +619,8 @@ val scuba_logging : bool val scuba_normals : string String.Map.t +val scuba_tags : string list String.Map.t + val seconds_per_iteration : float option val select : int option diff --git a/infer/src/scuba/Scuba.ml b/infer/src/scuba/Scuba.ml index 9f006cc83..e02a510ad 100644 --- a/infer/src/scuba/Scuba.ml +++ b/infer/src/scuba/Scuba.ml @@ -13,14 +13,17 @@ type table = InferEvents type sample = { int_section: int SMap.t (** All integer type fields and their values *) ; normal_section: string SMap.t - (** All string (normal in Scuba terminology) type fields and their values *) } + (** All string (normal in Scuba terminology) type fields and their values *) + ; tagset_section: string list SMap.t + (** All sets of strings (tagsets in Scuba terminology) type fields and their values *) } let new_sample ~time = let time = match time with Some time -> time | None -> int_of_float (Unix.time ()) in { (* time is a single mandatory field in scuba. without it, scuba disregards all samples *) int_section= SMap.singleton "time" time - ; normal_section= SMap.empty } + ; normal_section= SMap.empty + ; tagset_section= SMap.empty } let add_int ~name ~value sample = @@ -33,6 +36,11 @@ let add_normal ~name ~value sample = {sample with normal_section} +let add_tagset ~name ~value sample = + let tagset_section = SMap.set sample.tagset_section ~key:name ~data:value in + {sample with tagset_section} + + let sample_to_json sample = let map_to_assoc value_to_json key_value_map = let pairs = SMap.to_alist key_value_map in @@ -41,8 +49,11 @@ let sample_to_json sample = in let ints_to_assoc = map_to_assoc (fun data -> `Int data) in let normals_to_assoc = map_to_assoc (fun data -> `String data) in + let tags_to_assoc = map_to_assoc (fun data -> `List (List.map data ~f:(fun d -> `String d))) in `Assoc - [("int", ints_to_assoc sample.int_section); ("normal", normals_to_assoc sample.normal_section)] + [ ("int", ints_to_assoc sample.int_section) + ; ("normal", normals_to_assoc sample.normal_section) + ; ("tags", tags_to_assoc sample.tagset_section) ] let sample_to_json_string sample = sample |> sample_to_json |> Yojson.Basic.to_string diff --git a/infer/src/scuba/Scuba.mli b/infer/src/scuba/Scuba.mli index a5e30905c..7ce7ff766 100644 --- a/infer/src/scuba/Scuba.mli +++ b/infer/src/scuba/Scuba.mli @@ -30,5 +30,9 @@ val add_normal : name:string -> value:string -> sample -> sample (** Set a new string (normal in Scuba terminology) field and its value to the sample. Overwrites if a field with this name was already set. *) +val add_tagset : name:string -> value:string list -> sample -> sample +(** Set a new set of strings (tagset in Scuba terminology) field and its value to the sample. + Overwrites if a field with this name was already set. *) + val log : table -> sample list -> unit (** The main function. Log a collection of samples to the given table. *) diff --git a/infer/src/scuba/ScubaLogging.ml b/infer/src/scuba/ScubaLogging.ml index 6521534da..7a18d1d8c 100644 --- a/infer/src/scuba/ScubaLogging.ml +++ b/infer/src/scuba/ScubaLogging.ml @@ -21,6 +21,11 @@ let set_command_line_normales sample = Map.fold Config.scuba_normals ~init:sample ~f:add_normal +let set_command_line_tagsets sample = + let add_tagset ~key ~data = Scuba.add_tagset ~name:key ~value:data in + Map.fold Config.scuba_tags ~init:sample ~f:add_tagset + + let set_common_fields sample = let open Scuba in sample @@ -42,7 +47,7 @@ let sample_from_event ({label; created_at_ts; data} : LogEntry.t) = (Printf.sprintf "time.%s" label, duration_ms) in Scuba.new_sample ~time:(Some created_at_ts) - |> set_common_fields |> set_command_line_normales + |> set_common_fields |> set_command_line_normales |> set_command_line_tagsets |> Scuba.add_normal ~name:"event" ~value:event_name |> Scuba.add_int ~name:"value" ~value