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 karton debug #220

Merged
merged 10 commits into from
Jul 20, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,5 @@ karton.ini
config.ini
docs/_build
.mypy_cache
build
karton_core.egg-info/
16 changes: 16 additions & 0 deletions docs/advanced_concepts.rst
Original file line number Diff line number Diff line change
Expand Up @@ -230,3 +230,19 @@ The simplest way to do that is to perform all of these actions synchronously, in
# If analysis has been finished: get the results and process them
analysis = sandbox.get_results(analysis_id)
self.process_results(analysis)


Karton debug mode
-----------------

During your karton services development endeavours you'll often have the urge to test them out on the production environment.

While this is totally fine, you have to be careful not to disrupt the production services by consuming the tasks meant for them. In most cases you also don't want to propagate logs from your experiments to the production log pipeline.

Karton debug mode was crafted especially for this purpose. It adds a random suffix to the service identity to create a new, non-conflicting task queue.
It also permanently sets the consumer persistence to False and disables log forwarding.

You can enable it by setting:
- :code:`KARTON_KARTON_DEBUG` environment value to "1"
- :code:`debug` parameter to `1` in the :code:`[karton]` config section
- :code:`--debug` command-line parameter
2 changes: 2 additions & 0 deletions docs/service_configuration.rst
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ Common Karton configuration fields are listed below:
[redis] socket_timeout Socket timeout for Redis operations in seconds (default: 30, use 0 to turn off if timeout doesn't work properly)
[karton] identity Karton service identity override (overrides the name provided in class / constructor arguments)
[karton] persistent Karton service queue persistency override
[karton] debug Karton debug mode for service development
[karton] task_timeout Karton service task execution timeout in seconds. Useful if your service sometimes hangs. Karton will schedule SIGALRM if this value is set.
[logging] level Logging level for Karton service logger (default: INFO)
[signaling] status Turns on producing of 'karton.signaling.status' tasks, signalling the task start and finish events by Karton service (default: 0, off)
Expand Down Expand Up @@ -90,6 +91,7 @@ All settings can be set using command-line.
--identity IDENTITY Alternative identity for Karton service
--log-level LOG_LEVEL
Logging level of Karton logger
--debug Enable debugging mode
--setup-bucket Create missing bucket in S3 storage
--disable-gc Do not run GC in this instance
--disable-router Do not run task routing in this instance
Expand Down
18 changes: 16 additions & 2 deletions karton/core/base.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import abc
import argparse
import logging
import os
import textwrap
from contextlib import contextmanager
from typing import Optional, Union, cast
Expand Down Expand Up @@ -44,6 +45,11 @@ def __init__(
if self.config.has_option("karton", "identity"):
self.identity = self.config.get("karton", "identity")

self.debug = self.config.getboolean("karton", "debug", False)

if self.debug:
self.identity += "-" + os.urandom(4).hex() + "-dev"

self.service_info = None
if self.identity is not None and self.with_service_info:
self.service_info = KartonServiceInfo(
Expand Down Expand Up @@ -101,7 +107,9 @@ def setup_logger(self, level: Optional[Union[str, int]] = None) -> None:
logging.Formatter("[%(asctime)s][%(levelname)s] %(message)s")
)
logger.addHandler(stream_handler)
logger.addHandler(self._log_handler)

if not self.debug:
logger.addHandler(self._log_handler)

@property
def log_handler(self) -> KartonLogHandler:
Expand Down Expand Up @@ -154,6 +162,9 @@ def args_parser(cls) -> argparse.ArgumentParser:
"--identity", help="Alternative identity for Karton service"
)
parser.add_argument("--log-level", help="Logging level of Karton logger")
parser.add_argument(
"--debug", help="Enable debugging mode", action="store_true", default=None
)
return parser

@classmethod
Expand All @@ -166,7 +177,10 @@ def config_from_args(cls, config: Config, args: argparse.Namespace) -> None:
"""
config.load_from_dict(
{
"karton": {"identity": args.identity},
"karton": {
"identity": args.identity,
"debug": args.debug,
},
"logging": {"level": args.log_level},
}
)
Expand Down
5 changes: 3 additions & 2 deletions karton/core/karton.py
Original file line number Diff line number Diff line change
Expand Up @@ -121,8 +121,9 @@ def __init__(
if self.filters is None:
raise ValueError("Cannot bind consumer on Empty binds")

self.persistent = self.config.getboolean(
"karton", "persistent", self.persistent
self.persistent = (
self.config.getboolean("karton", "persistent", self.persistent)
and not self.debug
)
self.task_timeout = self.config.getint("karton", "task_timeout")
self.current_task: Optional[Task] = None
Expand Down
Loading