Skip to content

Commit bbf6280

Browse files
panagosg7meta-codesync[bot]
authored andcommitted
[flow] Add per-error flow_typing_errors Scuba logging for recheck events
Summary: Changelog: [internal] Reviewed By: SamChou19815 Differential Revision: D98086794 fbshipit-source-id: 5186f4ccf4752ce0add8d4b86f60587c9bcef7a6
1 parent 6fbbeff commit bbf6280

8 files changed

Lines changed: 127 additions & 0 deletions

File tree

src/commands/commandUtils.ml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1555,6 +1555,7 @@ let make_options
15551555
opt_lazy_mode;
15561556
opt_lint_severities = lint_severities;
15571557
opt_llm_context_include_imports = FlowConfig.llm_context_include_imports flowconfig;
1558+
opt_log_per_error_typing_telemetry = FlowConfig.log_per_error_typing_telemetry flowconfig;
15581559
opt_log_file;
15591560
opt_log_saving = FlowConfig.log_saving flowconfig;
15601561
opt_long_lived_workers =

src/commands/config/flowConfig.ml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,7 @@ module Opts = struct
101101
jest_integration: bool;
102102
lazy_mode: lazy_mode option;
103103
llm_context_include_imports: bool;
104+
log_per_error_typing_telemetry: bool;
104105
log_saving: Options.log_saving SMap.t;
105106
long_lived_workers: bool;
106107
max_files_checked_per_worker: int;
@@ -262,6 +263,7 @@ module Opts = struct
262263
jest_integration = false;
263264
lazy_mode = None;
264265
llm_context_include_imports = false;
266+
log_per_error_typing_telemetry = false;
265267
log_saving = SMap.empty;
266268
long_lived_workers = false;
267269
max_files_checked_per_worker = 100;
@@ -1142,6 +1144,9 @@ module Opts = struct
11421144
( "experimental.llm_context.include_imports",
11431145
boolean (fun opts v -> Ok { opts with llm_context_include_imports = v })
11441146
);
1147+
( "experimental.log_per_error_typing_telemetry",
1148+
boolean (fun opts v -> Ok { opts with log_per_error_typing_telemetry = v })
1149+
);
11451150
("experimental.module.automatic_require_default", automatic_require_default_parser);
11461151
( "experimental.multi_platform",
11471152
boolean (fun opts v -> Ok { opts with multi_platform = Some v })
@@ -2041,6 +2046,8 @@ let lazy_mode c = c.options.Opts.lazy_mode
20412046

20422047
let llm_context_include_imports c = c.options.Opts.llm_context_include_imports
20432048

2049+
let log_per_error_typing_telemetry c = c.options.Opts.log_per_error_typing_telemetry
2050+
20442051
(* global defaults for lint severities and strict mode *)
20452052
let lint_severities c = c.lint_severities
20462053

src/commands/config/flowConfig.mli

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -179,6 +179,8 @@ val lazy_mode : config -> lazy_mode option
179179

180180
val llm_context_include_imports : config -> bool
181181

182+
val log_per_error_typing_telemetry : config -> bool
183+
182184
(* global defaults for lint suppressions and strict mode *)
183185
val lint_severities : config -> Severity.severity LintSettings.t
184186

src/common/options.ml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -151,6 +151,7 @@ type t = {
151151
opt_lazy_mode: bool;
152152
opt_lint_severities: Severity.severity LintSettings.t;
153153
opt_llm_context_include_imports: bool;
154+
opt_log_per_error_typing_telemetry: bool;
154155
opt_log_file: File_path.t;
155156
opt_log_saving: log_saving SMap.t;
156157
opt_long_lived_workers: bool;
@@ -333,6 +334,8 @@ let lint_severities opts = opts.opt_lint_severities
333334

334335
let llm_context_include_imports opts = opts.opt_llm_context_include_imports
335336

337+
let log_per_error_typing_telemetry opts = opts.opt_log_per_error_typing_telemetry
338+
336339
let log_file opts = opts.opt_log_file
337340

338341
let log_saving opts = opts.opt_log_saving

src/server/error_collator/errorCollator.ml

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -264,6 +264,62 @@ type error_resolution_stat = {
264264
time_to_resolve_all_subtyping_errors_in_one_file: float option;
265265
}
266266

267+
type per_error_info = {
268+
error_code: string;
269+
line_agnostic_hash: string;
270+
error_message: string option;
271+
}
272+
273+
type per_file_errors = {
274+
file_path: string;
275+
errors: per_error_info list;
276+
}
277+
278+
let compute_per_file_errors ~with_context_limit collated_errors =
279+
let open Flow_errors_utils in
280+
let context_count = ref 0 in
281+
let process_errors filename errors acc =
282+
if ConcreteLocPrintableErrorSet.is_empty errors then
283+
acc
284+
else
285+
let file_path =
286+
match filename with
287+
| File_key.SourceFile s
288+
| File_key.JsonFile s
289+
| File_key.ResourceFile s
290+
| File_key.LibFile s ->
291+
s
292+
in
293+
let error_infos =
294+
ConcreteLocPrintableErrorSet.fold
295+
(fun error acc ->
296+
let lsp = Lsp_output.lsp_of_error ~has_detailed_diagnostics:false error in
297+
let code_str = lsp.Lsp_output.code in
298+
let hash_input = code_str ^ ":" ^ lsp.Lsp_output.message in
299+
let hash = Printf.sprintf "%x" (Hashtbl.hash hash_input) in
300+
let error_message =
301+
if !context_count < with_context_limit then begin
302+
context_count := !context_count + 1;
303+
let msg = lsp.Lsp_output.message in
304+
let msg =
305+
if String.length msg > 400 then
306+
String.sub msg 0 400 ^ "..."
307+
else
308+
msg
309+
in
310+
Some msg
311+
end else
312+
None
313+
in
314+
{ error_code = code_str; line_agnostic_hash = hash; error_message } :: acc)
315+
errors
316+
[]
317+
in
318+
{ file_path; errors = error_infos } :: acc
319+
in
320+
let acc = FilenameMap.fold process_errors collated_errors.collated_merge_errors [] in
321+
FilenameMap.fold process_errors collated_errors.collated_local_errors acc
322+
267323
let update_error_state_timestamps collated_errors =
268324
let current_time = Unix.gettimeofday () in
269325
let init_timestamps = collated_errors.error_state_timestamps in

src/server/error_collator/errorCollator.mli

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,11 +43,24 @@ type error_resolution_stat = {
4343
time_to_resolve_all_subtyping_errors_in_one_file: float option;
4444
}
4545

46+
type per_error_info = {
47+
error_code: string;
48+
line_agnostic_hash: string;
49+
error_message: string option;
50+
}
51+
52+
type per_file_errors = {
53+
file_path: string;
54+
errors: per_error_info list;
55+
}
56+
4657
(* Update error_state_timestamps,
4758
* and return a collection of times to resolve different kinds of errors
4859
* under different initial conditions *)
4960
val update_error_state_timestamps : Collated_errors.t -> Collated_errors.t * error_resolution_stat
5061

62+
val compute_per_file_errors : with_context_limit:int -> Collated_errors.t -> per_file_errors list
63+
5164
val get_without_suppressed :
5265
ServerEnv.env ->
5366
Flow_errors_utils.ConcreteLocPrintableErrorSet.t

src/services/inference/types_js.ml

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1694,6 +1694,49 @@ let recheck_impl
16941694
~first_internal_error
16951695
~scm_changed_mergebase:changed_mergebase
16961696
~profiling;
1697+
if Options.log_per_error_typing_telemetry options then begin
1698+
let per_file_errors =
1699+
ErrorCollator.compute_per_file_errors ~with_context_limit:10 collated_errors
1700+
in
1701+
let typing_errors_data =
1702+
let open Hh_json in
1703+
let error_info_to_json (info : ErrorCollator.per_error_info) =
1704+
let props =
1705+
[
1706+
("error_code", JSON_String info.ErrorCollator.error_code);
1707+
("line_agnostic_hash", JSON_String info.ErrorCollator.line_agnostic_hash);
1708+
]
1709+
in
1710+
let props =
1711+
match info.ErrorCollator.error_message with
1712+
| Some msg -> ("error_context", JSON_String msg) :: props
1713+
| None -> props
1714+
in
1715+
JSON_Object props
1716+
in
1717+
let by_file =
1718+
List.map
1719+
(fun ({ ErrorCollator.file_path; errors } : ErrorCollator.per_file_errors) ->
1720+
(file_path, JSON_Array (List.map error_info_to_json errors)))
1721+
per_file_errors
1722+
in
1723+
let total_count =
1724+
List.fold_left
1725+
(fun acc ({ ErrorCollator.errors; _ } : ErrorCollator.per_file_errors) ->
1726+
acc + List.length errors)
1727+
0
1728+
per_file_errors
1729+
in
1730+
json_to_string
1731+
(JSON_Object
1732+
[
1733+
("total_count", JSON_Number (string_of_int total_count));
1734+
("by_file", JSON_Object by_file);
1735+
]
1736+
)
1737+
in
1738+
FlowEventLogger.log_typing_errors ~data:typing_errors_data
1739+
end;
16971740
record_recheck_time ()
16981741
in
16991742

src/stubs/flowEventLogger.ml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,8 @@ let recheck
111111
~scm_changed_mergebase:_ =
112112
()
113113

114+
let log_typing_errors ~data:_ = ()
115+
114116
let recheck_canceled
115117
~priority:_ ~num_files_to_prioritize:_ ~num_files_to_recheck:_ ~num_files_to_force:_ =
116118
()

0 commit comments

Comments
 (0)