From 0ad6cb121e2e76aebd9aec982cf91ee7f3a4dbb4 Mon Sep 17 00:00:00 2001 From: Nathaniel May Date: Fri, 5 Nov 2021 19:35:33 -0400 Subject: [PATCH] use event types in main even before the logger is set up. (#4219) --- core/dbt/events/types.py | 52 ++++++++++++++++++++++++++++++++++++++++ core/dbt/main.py | 32 +++++++++++-------------- 2 files changed, 66 insertions(+), 18 deletions(-) diff --git a/core/dbt/events/types.py b/core/dbt/events/types.py index 1a347914f53..ebb250e6ea9 100644 --- a/core/dbt/events/types.py +++ b/core/dbt/events/types.py @@ -1,4 +1,5 @@ from abc import ABCMeta, abstractmethod +import argparse from dataclasses import dataclass from typing import Any, List, Optional, Dict from dbt import ui @@ -68,6 +69,51 @@ def cli_msg(self) -> str: raise Exception("cli_msg not implemented for cli event") +class MainKeyboardInterrupt(InfoLevel, CliEventABC): + def cli_msg(self) -> str: + return "ctrl-c" + + +@dataclass +class MainEncounteredError(ErrorLevel, CliEventABC): + e: BaseException + + def cli_msg(self) -> str: + return f"Encountered an error:\n{str(self.e)}" + + +@dataclass +class MainStackTrace(DebugLevel, CliEventABC): + stack_trace: str + + def cli_msg(self) -> str: + return self.stack_trace + + +@dataclass +class MainReportVersion(InfoLevel, CliEventABC): + v: str # could be VersionSpecifier instead if we resolved some circular imports + + def cli_msg(self): + return f"Running with dbt{self.v}" + + +@dataclass +class MainReportArgs(DebugLevel, CliEventABC): + args: argparse.Namespace + + def cli_msg(self): + return f"running dbt with arguments {str(self.args)}" + + +@dataclass +class MainTrackingUserState(DebugLevel, CliEventABC): + user_state: str + + def cli_msg(self): + return f"Tracking: {self.user_state}" + + class ParsingStart(InfoLevel, CliEventABC): def cli_msg(self) -> str: return "Start parsing." @@ -1728,6 +1774,12 @@ def cli_msg(self) -> str: # # TODO remove these lines once we run mypy everywhere. if 1 == 0: + MainReportVersion('') + MainKeyboardInterrupt() + MainEncounteredError(BaseException('')) + MainStackTrace('') + MainReportVersion('') + MainTrackingUserState('') ParsingStart() ParsingCompiling() ParsingWritingManifest() diff --git a/core/dbt/main.py b/core/dbt/main.py index 7e6ae6ac03d..1af838f9f9d 100644 --- a/core/dbt/main.py +++ b/core/dbt/main.py @@ -1,5 +1,5 @@ from typing import List -from dbt.logger import GLOBAL_LOGGER as logger, log_cache_events, log_manager +from dbt.logger import log_cache_events, log_manager import argparse import os.path @@ -9,6 +9,11 @@ from pathlib import Path import dbt.version +from dbt.events.functions import fire_event +from dbt.events.types import ( + MainEncounteredError, MainKeyboardInterrupt, MainReportVersion, MainReportArgs, + MainTrackingUserState, MainStackTrace +) import dbt.flags as flags import dbt.task.build as build_task import dbt.task.clean as clean_task @@ -34,7 +39,6 @@ from dbt.utils import ExitCodes from dbt.config.profile import DEFAULT_PROFILES_DIR, read_user_config from dbt.exceptions import ( - RuntimeException, InternalException, NotImplementedException, FailedToConnectException @@ -127,7 +131,8 @@ def main(args=None): exit_code = ExitCodes.ModelError.value except KeyboardInterrupt: - logger.info("ctrl-c") + # if the logger isn't configured yet, it will use the default logger + fire_event(MainKeyboardInterrupt()) exit_code = ExitCodes.UnhandledError.value # This can be thrown by eg. argparse @@ -135,16 +140,8 @@ def main(args=None): exit_code = e.code except BaseException as e: - logger.warning("Encountered an error:") - logger.warning(str(e)) - - if log_manager.initialized: - logger.debug(traceback.format_exc()) - elif not isinstance(e, RuntimeException): - # if it did not come from dbt proper and the logger is not - # initialized (so there's no safe path to log to), log the - # stack trace at error level. - logger.error(traceback.format_exc()) + fire_event(MainEncounteredError(e=e)) + fire_event(MainStackTrace(stack_trace=traceback.format_exc())) exit_code = ExitCodes.UnhandledError.value sys.exit(exit_code) @@ -208,7 +205,7 @@ def track_run(task): ) except (NotImplementedException, FailedToConnectException) as e: - logger.error('ERROR: {}'.format(e)) + fire_event(MainEncounteredError(e=e)) dbt.tracking.track_invocation_end( config=task.config, args=task.args, result_type="error" ) @@ -228,13 +225,12 @@ def run_from_args(parsed): # set log_format in the logger parsed.cls.pre_init_hook(parsed) - logger.info("Running with dbt{}".format(dbt.version.installed)) + fire_event(MainReportVersion(v=dbt.version.installed)) # this will convert DbtConfigErrors into RuntimeExceptions # task could be any one of the task objects task = parsed.cls.from_args(args=parsed) - - logger.debug("running dbt with arguments {parsed}", parsed=str(parsed)) + fire_event(MainReportArgs(args=parsed)) log_path = None if task.config is not None: @@ -242,7 +238,7 @@ def run_from_args(parsed): # we can finally set the file logger up log_manager.set_path(log_path) if dbt.tracking.active_user is not None: # mypy appeasement, always true - logger.debug("Tracking: {}".format(dbt.tracking.active_user.state())) + fire_event(MainTrackingUserState(dbt.tracking.active_user.state())) results = None