Repository: dbt-labs/dbt-core

Issue:
[CT-1652] [Regression] [main/1.4] Failure to raise initialization exception
### Is this a regression in a recent version of dbt-core?

- [X] I believe this is a regression in dbt-core functionality
- [X] I have searched the existing issues, and I could not find an existing issue for this regression

### Current Behavior

If I run `dbt` with a profile that expects an adapter to be installed, and the adapter is not in fact installed, I do not see any error from `dbt run`:

```bash
$ dbt run
```
(no output)
```bash
$ dbt --debug run
$ echo $?
2
```
(no other output)

I do see the expected error from `dbt debug`:
```bash
$ dbt debug
15:46:40  Running with dbt=1.4.0-a1
dbt version: 1.4.0-a1
python version: 3.10.9
python path: /Users/jerco/dev/product/dbt-core/env/bin/python3
os info: macOS-12.4-arm64-arm-64bit
Using profiles.yml file at /Users/jerco/.dbt/profiles.yml
Using dbt_project.yml file at /Users/jerco/dev/scratch/testy/dbt_project.yml

15:46:40  Error importing adapter: No module named 'dbt.adapters.bigquery'
Configuration:
  profiles.yml file [ERROR invalid]
  dbt_project.yml file [OK found and valid]

Required dependencies:
 - git [OK found]

1 check failed:
Profile loading failed for the following reason:
Runtime Error
  Credentials in profile "sandbox-bigquery", target "dev" invalid: Runtime Error
    Could not find adapter type bigquery!
```

### Expected/Previous Behavior

`dbt run` should raise the same error as `dbt debug`, if there is an error during initialization (e.g. trying to use an uninstalled adapter)

### Steps To Reproduce

1. Install dbt from the `main` branch
2. Specify a profile that requires an adapter that isn't installed
3. `dbt run`

### Relevant log output

_No response_

### Environment

```markdown
- OS: macOS 12.4
- Python: Python 3.10.9
- dbt (working version): 1.3
- dbt (regression version): 1.4.0-a1
```


### Which database adapter are you using with dbt?

_No response_

### Additional Context

_No response_


Discussion:
If I drop a breakpoint here (line 197):
https://github.com/dbt-labs/dbt-core/blob/83b1fee06228055f6fe573d778775160c7127454/core/dbt/main.py#L196-L198

On `main` branch:
```python
ipdb> task, res = run_from_args(parsed)
*** dbt.exceptions.RuntimeException: Runtime Error
  Could not run dbt
```
On `1.3.latest` branch:
```python
ipdb> task, res = run_from_args(parsed)
15:59:14  Error importing adapter: No module named 'dbt.adapters.bigquery'
15:59:14  Encountered an error while reading profiles:
15:59:14    ERROR: Runtime Error
  Credentials in profile "sandbox-bigquery", target "dev" invalid: Runtime Error
    Could not find adapter type bigquery!
15:59:14  Defined profiles:
15:59:14   - sandbox-bigquery
15:59:14   - sandbox-databricks
15:59:14   - demo_data
15:59:14   - garage-spark
15:59:14   - garage-firebolt
15:59:14   - garage-postgres
15:59:14   - garage-snowflake
15:59:14   - integration_tests
15:59:14   - jaffle_shop
15:59:14   - sandbox-galaxy
15:59:14   - sandbox-redshift
15:59:14   - sandbox-snowflake
15:59:14
For more information on configuring profiles, please consult the dbt docs:

https://docs.getdbt.com/docs/configure-your-profile

*** dbt.exceptions.RuntimeException: Runtime Error
  Could not run dbt
```
The exception is occurring on this line:
https://github.com/dbt-labs/dbt-core/blob/83b1fee06228055f6fe573d778775160c7127454/core/dbt/main.py#L223-L225

The profile config error is being appropriately caught & handled here:
https://github.com/dbt-labs/dbt-core/blob/83b1fee06228055f6fe573d778775160c7127454/core/dbt/task/base.py#L110-L126

But we're not doing any logging, or bubbling up the `RuntimeException`, as we were in previous versions.
I think this change is due to a change from https://github.com/dbt-labs/dbt-core/pull/6291:

https://github.com/dbt-labs/dbt-core/blob/84782625805f4457e0169c474159832ef01e4648/core/dbt/events/functions.py#L21-L23

The codepath with the exception is being executed before we've called `setup_event_logger`. Previously, if we fired events before `setup_event_logger` had been called, they would go to a simple stdout logger. That one used defaults that didn't respect user-supplied configuration... but still, better than not seeing these logs/exceptions at all!
Potential fix: initialize a "basic" `EventManager`, which then gets replaced as soon as we make it to the real `setup_event_logger`. This ensures that, if we run into an initialization error before then, any associated events (including exceptions / tracebacks) aren't swallowed.

Illustrative code in this commit: https://github.com/dbt-labs/dbt-core/commit/93935138e941cbd0be2d308fde976ab917e5c308

Using the changes in that commit:
```
$ dbt run
16:30:50  Error importing adapter: No module named 'dbt.adapters.bigquery'
16:30:50  Encountered an error while reading profiles:
16:30:50    ERROR: Runtime Error
  Credentials in profile "sandbox-bigquery", target "dev" invalid: Runtime Error
    Could not find adapter type bigquery!
16:30:50  Defined profiles:
16:30:50   - sandbox-bigquery
16:30:50   - sandbox-databricks
16:30:50   - demo_data
16:30:50   - garage-spark
16:30:50   - garage-firebolt
16:30:50   - garage-postgres
16:30:50   - garage-snowflake
16:30:50   - integration_tests
16:30:50   - jaffle_shop
16:30:50   - sandbox-galaxy
16:30:50   - sandbox-redshift
16:30:50   - sandbox-snowflake
16:30:50
For more information on configuring profiles, please consult the dbt docs:

https://docs.getdbt.com/docs/configure-your-profile

16:30:50  Encountered an error:
Runtime Error
  Could not run dbt
```

Resolving patch:
diff --git a/core/dbt/events/functions.py b/core/dbt/events/functions.py
--- a/core/dbt/events/functions.py
+++ b/core/dbt/events/functions.py
@@ -38,7 +38,7 @@ def setup_event_logger(log_path: str, level_override: Optional[EventLevel] = Non
         EVENT_MANAGER.add_logger(_get_logfile_config(os.path.join(log_path, "dbt.log")))
 
 
-def _get_stdout_config(level: Optional[EventLevel]) -> LoggerConfig:
+def _get_stdout_config(level: Optional[EventLevel] = None) -> LoggerConfig:
     fmt = LineFormat.PlainText
     if flags.LOG_FORMAT == "json":
         fmt = LineFormat.Json
@@ -90,7 +90,7 @@ def _logfile_filter(log_cache_events: bool, evt: BaseEvent) -> bool:
     )
 
 
-def _get_logbook_log_config(level: Optional[EventLevel]) -> LoggerConfig:
+def _get_logbook_log_config(level: Optional[EventLevel] = None) -> LoggerConfig:
     config = _get_stdout_config(level)
     config.name = "logbook_log"
     config.filter = NoFilter if flags.LOG_CACHE_EVENTS else lambda e: not isinstance(e, Cache)
@@ -110,15 +110,14 @@ def cleanup_event_logger():
     EVENT_MANAGER.callbacks.clear()
 
 
-# The default event manager will not log anything, but some tests run code that
-# generates events, without configuring the event manager, so we create an empty
-# manager here until there is a better testing strategy in place.
+# Since dbt-rpc does not do its own log setup, and since some events can
+# currently fire before logs can be configured by setup_event_logger(), we
+# create a default configuration with default settings and no file output.
 EVENT_MANAGER: EventManager = EventManager()
+EVENT_MANAGER.add_logger(
+    _get_logbook_log_config() if flags.ENABLE_LEGACY_LOGGER else _get_stdout_config()
+)
 
-# Since dbt-rpc does not do its own log setup, we set up logbook if legacy
-# logging is enabled.
-if flags.ENABLE_LEGACY_LOGGER:
-    EVENT_MANAGER.add_logger(_get_logbook_log_config(None))
 
 # This global, and the following two functions for capturing stdout logs are
 # an unpleasant hack we intend to remove as part of API-ification. The GitHub


Test patch: