def log_usage_with_additional_info()

in client/commands/remote_logging.py [0:0]


def log_usage_with_additional_info(command_name: str) -> _DecoratorWithDynamicLogging:
    """
    This decorator is a variant of `log_usage`.

    With `log_usage`, what to log needs to be determined prior to running the
    decorated command. In contrast, `log_usage_with_additional_info` collects what
    to log after the decorated command is done executing. Logging content can
    therefore depend on the execution result after-the-fact.

    In exchange for the flexibility, `log_usage_with_additional_info` requires slightly
    more sophisticated setup: the decorated function should not only return a
    `commands.ExitCode`, but also attach the dynamically-computed logging dictionary
    alongside with the return code. The decorator itself will make sure that the
    additional info will be faithfully forwarded when invoking the underlying logging
    API.
    """
    auxiliary_info: Dict[str, Optional[str]] = {
        "cwd": os.getcwd(),
        "client_version": version.__version__,
        "command_line": " ".join(sys.argv),
        "command": command_name,
    }

    def decorator(
        __command: "Callable[Concatenate[configuration_module.Configuration, TParams], ExitCodeWithAdditionalLogging]",  # noqa: B950
    ) -> "Callable[Concatenate[configuration_module.Configuration, TParams], commands.ExitCode]":  # noqa: B950
        def decorated(
            configuration: configuration_module.Configuration,
            *args: TParams.args,
            **kwargs: TParams.kwargs
        ) -> commands.ExitCode:
            command_timer: timer.Timer = timer.Timer()

            def log_success(
                exit_code: int, additional_logging: Dict[str, Optional[str]]
            ) -> None:
                statistics_logger.log_with_configuration(
                    category=statistics_logger.LoggerCategory.USAGE,
                    configuration=configuration,
                    integers={
                        "exit_code": exit_code,
                        "runtime": int(command_timer.stop_in_millisecond()),
                    },
                    normals={**auxiliary_info, **additional_logging},
                )

            def log_failure(
                error: Exception, exit_code: int = commands.ExitCode.FAILURE
            ) -> None:
                statistics_logger.log_with_configuration(
                    category=statistics_logger.LoggerCategory.USAGE,
                    configuration=configuration,
                    integers={
                        "exit_code": exit_code,
                        "runtime": int(command_timer.stop_in_millisecond()),
                    },
                    normals={
                        **auxiliary_info,
                        "client_exception": str(error),
                    },
                )

            try:
                result = __command(configuration, *args, **kwargs)
                exit_code = result.exit_code
                log_success(exit_code, result.additional_logging)
                return exit_code
            except configuration_module.InvalidConfiguration as error:
                log_failure(error, exit_code=commands.ExitCode.CONFIGURATION_ERROR)
                raise
            except Exception as error:
                log_failure(error)
                raise

        return decorated

    # pyre-ignore[7]: (T84575843) This should be fine.
    return decorator