Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Introduce LOGGING_OVERRIDE config var #10808

Open
wants to merge 5 commits into
base: master
Choose a base branch
from

Conversation

simonrw
Copy link
Contributor

@simonrw simonrw commented May 13, 2024

Motivation

While debugging DNS issues, we found the need to add additional logging to help debugging, but only for a specific module. The DNS resolution process is too noisy to use current debug logs.

See #10809 for an application of this new config feature.

Changes

@dfangl suggested we support a per-logger override for the log level. This would mean that if we are interested in a specific logger (or can disable some logs), we can specify this in a structured environment variable.

Note: we are planning on re-working the logging overall, so this functionality should only be used in specific cases, to enable more detailed logs for specific aspects of LocalStack's internals, and not documented.

@simonrw simonrw added the semver: patch Non-breaking changes which can be included in patch releases label May 13, 2024
@simonrw simonrw self-assigned this May 13, 2024
Copy link

github-actions bot commented May 13, 2024

S3 Image Test Results (AMD64 / ARM64)

  2 files    2 suites   3m 25s ⏱️
398 tests 346 ✅  52 💤 0 ❌
796 runs  692 ✅ 104 💤 0 ❌

Results for commit aa4269c.

♻️ This comment has been updated with latest results.

Copy link

github-actions bot commented May 13, 2024

LocalStack Community integration with Pro

    2 files  ±0      2 suites  ±0   1h 36m 52s ⏱️ +2s
2 950 tests ±0  2 648 ✅ ±0  302 💤 ±0  0 ❌ ±0 
2 952 runs  ±0  2 648 ✅ ±0  304 💤 ±0  0 ❌ ±0 

Results for commit aa4269c. ± Comparison against base commit 9d80628.

♻️ This comment has been updated with latest results.

Copy link
Member

@dfangl dfangl left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for implementing this, configuring specific components to log on a higher level will hopefully be useful in support cases.

@@ -418,6 +418,9 @@ def in_docker():
LS_LOG = eval_log_type("LS_LOG")
DEBUG = is_env_true("DEBUG") or LS_LOG in TRACE_LOG_LEVELS

# allow setting custom log levels for individual loggers
LOGGING_OVERRIDE = os.environ.get("LOGGING_OVERRIDE", "{}")
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure about the name, maybe LOG_LEVEL_CONFIG or LOGGING_CONFIG? Since this is for now an undocumented change, it might not be that important, but those changes sometimes stay :)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this name is misleading, since it sounds like it updates the entire config, rather than just allowing overrides. WDYT?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You are right, let's keep it to override for now :)

@@ -78,6 +79,23 @@ def setup_logging_from_config():
for name, level in trace_internal_log_levels.items():
logging.getLogger(name).setLevel(level)

if raw_value := config.LOGGING_OVERRIDE:
try:
logging_overrides = json.loads(raw_value)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

WDYT json vs key-value pairs? I think the latter might be easier to write, and we do not need nested structures. I do not have a strong opinion though.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think that's a good usability improvement 👍

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Implemented in db163ef

@@ -78,6 +79,23 @@ def setup_logging_from_config():
for name, level in trace_internal_log_levels.items():
logging.getLogger(name).setLevel(level)

if raw_value := config.LOGGING_OVERRIDE:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure if we can use this syntax here - this file is imported by the cli if the debug flag is set. Our tests pass, but that flag might break.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good point, thanks!

@simonrw simonrw force-pushed the config/logging-level-overrides branch 2 times, most recently from 3dd89f1 to 2474a6d Compare May 13, 2024 15:05
@simonrw simonrw marked this pull request as ready for review May 13, 2024 16:02
Copy link
Member

@alexrashed alexrashed left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for challenging the logging config and testing new approaches.
I only added 2 questions to the code, but I am not 100% sure about the reasoning behind it.
We already have the distinction between default_log_levels, trace_log_levels, and trace_internal_log_levels. Are the logs really so noisy that they are even too verbose for trace_internal_log_levels?

except RuntimeError:
raise
except Exception as e:
raise RuntimeError(
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

q: Can this exception really only be raised in case the value is malformed?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am not sure, so since we "raise ... from e" I am happy to remove the "malformed input" part of the error message as it only printed e anyway.

Comment on lines +542 to +549
if len(items) != 2:
raise ValueError(f"invalid key/value pair: '{pair}'")
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

q: Since maxsplit=2 is set, this means that this check really only checks if the pair does not contain = right?
Maybe it would be better to remove the maxsplit to also catch cases like a=b=c?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You are right, thanks!

@@ -533,3 +533,18 @@ def is_comma_delimited_list(string: str, item_regex: Optional[str] = None) -> bo
if pattern.match(string) is None:
return False
return True


def parse_key_value_pairs(raw_text: str) -> dict:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: could add a docstring here with for example the values from one of the test cases below to clearly demonstrate its purpose.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the suggestion!

@simonrw simonrw force-pushed the config/logging-level-overrides branch from e098af2 to aa4269c Compare May 15, 2024 15:47
Copy link
Member

@thrau thrau left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

really nice addition! thanks for going through the review iterations, i think the reviews improved the already great PR a lot!

My only nit would be that I'm also not 100% sold on the name. If we're overriding log levels, then i believe those three words should appear in the config variable, LOG_LEVEL_OVERRIDES for instance?

  • LOG_LEVEL to indicate what it is you're configuring
  • OVERRIDES (plural) to indicate that you're overriding multiple log level configs

Comment on lines +89 to +91
raise RuntimeError(
f"Failed to configure logging overrides ({raw_logging_override}): '{level_name}' is not a valid log level"
)
Copy link
Member

@thrau thrau May 15, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: is there a specific reason to raise RuntimeError and not ValueError?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
semver: patch Non-breaking changes which can be included in patch releases
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

5 participants