### Log Task Start and Completion with tasklogger Source: https://github.com/scottgigante/tasklogger/blob/master/README.rst Use tasklogger.start_task and tasklogger.complete_task to log the beginning and end of tasks, receiving timed updates mid-computation. Ensure tasklogger is imported. ```python >>> import tasklogger >>> import time >>> tasklogger.start_task("Supertask") Calculating Supertask... >>> time.sleep(1) >>> tasklogger.start_task("Subtask") Calculating Subtask... >>> time.sleep(1) >>> tasklogger.complete_task("Subtask") Calculated Subtask in 1.01 seconds. >>> time.sleep(1) >>> tasklogger.complete_task("Supertask") Calculated Supertask in 3.02 seconds. ``` -------------------------------- ### Start and Complete Tasks Manually Source: https://context7.com/scottgigante/tasklogger/llms.txt Manually start and complete tasks using `start_task` and `complete_task`. This pattern allows for explicit control and returns the runtime. Nested tasks can be managed by calling these methods sequentially. ```python import tasklogger import time logger = tasklogger.TaskLogger("etl_pipeline") # Manual start/complete pattern logger.start_task("Load data") time.sleep(0.5) runtime = logger.complete_task("Load data") print(f"Returned runtime: {runtime:.2f}s") # Output: # Calculating Load data... # Calculated Load data in 0.50 seconds. # Returned runtime: 0.50s # Nested tasks logger.start_task("Full pipeline") logger.start_task("Preprocessing") time.sleep(0.2) logger.complete_task("Preprocessing") logger.start_task("Model training") time.sleep(0.3) logger.complete_task("Model training") logger.complete_task("Full pipeline") # Output: # Calculating Full pipeline... # Calculating Preprocessing... # Calculated Preprocessing in 0.20 seconds. # Calculating Model training... # Calculated Model training in 0.30 seconds. # Calculated Full pipeline in 0.50 seconds. # Functional API using the default global logger tasklogger.log_start("batch job") time.sleep(0.1) elapsed = tasklogger.log_complete("batch job") # Output: # Calculating batch job... # Calculated batch job in 0.10 seconds. ``` -------------------------------- ### TaskLogger.start_task / tasklogger.log_start Source: https://context7.com/scottgigante/tasklogger/llms.txt Initiate timing for a task. Logs a start message and stores the task name for later completion. Supports nested tasks and can be used via the class method or the functional API. ```APIDOC ## `TaskLogger.start_task` / `tasklogger.log_start` — Begin timing a task Starts timing a named task and logs `"Calculating ..."` at INFO level. The task name is stored internally; call `complete_task` with the same name to close it. Multiple tasks can be open simultaneously (enabling nested task trees). The functional `log_start` delegates to the default global logger named `"TaskLogger"` (or a named one via the `logger` parameter). ```python import tasklogger import time logger = tasklogger.TaskLogger("etl_pipeline") # Manual start/complete pattern logger.start_task("Load data") time.sleep(0.5) runtime = logger.complete_task("Load data") print(f"Returned runtime: {runtime:.2f}s") # Output: # Calculating Load data... # Calculated Load data in 0.50 seconds. # Returned runtime: 0.50s # Nested tasks logger.start_task("Full pipeline") logger.start_task("Preprocessing") time.sleep(0.2) logger.complete_task("Preprocessing") logger.start_task("Model training") time.sleep(0.3) logger.complete_task("Model training") logger.complete_task("Full pipeline") # Output: # Calculating Full pipeline... # Calculating Preprocessing... # Calculated Preprocessing in 0.20 seconds. # Calculating Model training... # Calculated Model training in 0.30 seconds. # Calculated Full pipeline in 0.50 seconds. # Functional API using the default global logger tasklogger.log_start("batch job") time.sleep(0.1) elapsed = tasklogger.log_complete("batch job") # Output: # Calculating batch job... # Calculated batch job in 0.10 seconds. ``` ``` -------------------------------- ### Simplify Logging with tasklogger.log_task Context Manager Source: https://github.com/scottgigante/tasklogger/blob/master/README.rst The tasklogger.log_task context manager simplifies logging task start and completion. It automatically handles the timing and output for nested tasks. Ensure tasklogger and time are imported. ```python >>> import tasklogger >>> import time >>> with tasklogger.log_task("Supertask"): ... time.sleep(1) ... with tasklogger.log_task("Subtask"): ... time.sleep(1) ... time.sleep(1) Calculating Supertask... Calculating Subtask... Calculated Subtask in 1.01 seconds. Calculated Supertask in 3.02 seconds. ``` -------------------------------- ### TaskLogger.log_task / tasklogger.log_task Source: https://context7.com/scottgigante/tasklogger/llms.txt Use the `log_task` context manager for automatic task timing. It ensures tasks are started and completed, even if exceptions occur, simplifying task management and guaranteeing proper closure. ```APIDOC ## `TaskLogger.log_task` / `tasklogger.log_task` — Context manager for automatic task timing A `contextlib.contextmanager` that calls `start_task` on entry and `complete_task` on exit (even if an exception occurs). This is the recommended API for most use cases as it guarantees the task is always closed. Works with nested `with` blocks for hierarchical task trees. ```python import tasklogger import time logger = tasklogger.TaskLogger("processor", if_exists="ignore") # Simple context manager with logger.log_task("Data ingestion"): time.sleep(0.5) # Output: # Calculating Data ingestion... # Calculated Data ingestion in 0.50 seconds. # Deeply nested tasks with logger.log_task("Full ETL"): time.sleep(0.1) with logger.log_task("Extract"): time.sleep(0.2) with logger.log_task("Transform"): time.sleep(0.15) with logger.log_task("Normalize"): time.sleep(0.05) with logger.log_task("Load"): time.sleep(0.1) # Output: ``` -------------------------------- ### Context Manager for Automatic Task Timing Source: https://context7.com/scottgigante/tasklogger/llms.txt Use `log_task` as a context manager for automatic task start and completion, ensuring tasks are always closed. This is the recommended API for most use cases and supports nested task hierarchies. ```python import tasklogger import time logger = tasklogger.TaskLogger("processor", if_exists="ignore") # Simple context manager with logger.log_task("Data ingestion"): time.sleep(0.5) # Output: # Calculating Data ingestion... # Calculated Data ingestion in 0.50 seconds. # Deeply nested tasks with logger.log_task("Full ETL"): time.sleep(0.1) with logger.log_task("Extract"): time.sleep(0.2) with logger.log_task("Transform"): time.sleep(0.15) with logger.log_task("Normalize"): time.sleep(0.05) with logger.log_task("Load"): time.sleep(0.1) # Output: ``` -------------------------------- ### Create TaskLogger Instances Source: https://context7.com/scottgigante/tasklogger/llms.txt Instantiate TaskLogger with various configurations for name, level, timer, stream, and duplicate name handling. Custom callable timers and specific duplicate name strategies can be applied. ```python import tasklogger import time # Basic logger with defaults logger = tasklogger.TaskLogger() # Custom logger: CPU timer, debug level, stderr output, 4-space indent cpu_logger = tasklogger.TaskLogger( name="cpu_logger", level=2, # DEBUG: print all messages timer="cpu", # measure CPU time, not wall time stream="stderr", min_runtime=0, # always print completion messages indent=4, if_exists="increment" # auto-rename if "cpu_logger" already exists ) # Custom callable timer (e.g., nanoseconds) ns_logger = tasklogger.TaskLogger( name="ns_logger", timer=time.monotonic_ns, if_exists="ignore" ) # Duplicate name handling logger_a = tasklogger.TaskLogger("pipeline") logger_b = tasklogger.TaskLogger("pipeline", if_exists="increment") print(logger_b.name) # "pipeline_1" logger_c = tasklogger.TaskLogger("pipeline", if_exists="ignore") assert logger_c.logger is logger_a.logger # same underlying Logger ``` -------------------------------- ### Basic TaskLogger Usage Source: https://context7.com/scottgigante/tasklogger/llms.txt Demonstrates basic logging using the functional API with a global logger and a named logger. ```python # Functional API (global logger) with tasklogger.log_task("global task"): time.sleep(0.1) # Output: # Calculating global task... # Calculated global task in 0.10 seconds. ``` ```python # Named logger via functional API tasklogger.TaskLogger("my_module", if_exists="ignore") with tasklogger.log_task("operation", logger="my_module"): time.sleep(0.05) ``` ``` -------------------------------- ### General Logging with tasklogger.log_info and tasklogger.log_debug Source: https://github.com/scottgigante/tasklogger/blob/master/README.rst Use tasklogger.log_info for general messages and tasklogger.log_debug for detailed debugging information. The logging level can be adjusted using tasklogger.set_level(). Ensure tasklogger is imported. ```python >>> import tasklogger >>> tasklogger.log_info("Log some stuff that doesn't need timing") Log some stuff that doesn't need timing >>> tasklogger.log_debug("Log some stuff that normally isn't needed") >>> tasklogger.set_level(2) Set TaskLogger logging to DEBUG >>> tasklogger.log_debug("Log some stuff that normally isn't needed") Log some stuff that normally isn't needed ``` -------------------------------- ### TaskLogger Class Initialization Source: https://context7.com/scottgigante/tasklogger/llms.txt Instantiate a TaskLogger object to manage named, independent logger instances. Configure name, timer type, log level, stream output, and duplicate name handling. ```APIDOC ## `tasklogger.TaskLogger` — Create a named task logger instance `TaskLogger` is the core class providing all timing and logging functionality. It wraps Python's `logging.Logger` with task lifecycle management. The `name` must be unique unless `if_exists` is set to `"ignore"` or `"increment"`. The `timer` parameter accepts `"wall"` (default), `"cpu"`, or any zero-argument callable. `level` ranges from `-3` (silence all) to `2` (debug), with `1` (INFO) as default. Output goes to `stdout` by default but can be redirected to `stderr` or any file-like object. ```python import tasklogger import time # Basic logger with defaults logger = tasklogger.TaskLogger() # Custom logger: CPU timer, debug level, stderr output, 4-space indent cpu_logger = tasklogger.TaskLogger( name="cpu_logger", level=2, # DEBUG: print all messages timer="cpu", # measure CPU time, not wall time stream="stderr", min_runtime=0, # always print completion messages indent=4, if_exists="increment" # auto-rename if "cpu_logger" already exists ) # Custom callable timer (e.g., nanoseconds) ns_logger = tasklogger.TaskLogger( name="ns_logger", timer=time.monotonic_ns, if_exists="ignore" ) # Duplicate name handling logger_a = tasklogger.TaskLogger("pipeline") logger_b = tasklogger.TaskLogger("pipeline", if_exists="increment") print(logger_b.name) # "pipeline_1" logger_c = tasklogger.TaskLogger("pipeline", if_exists="ignore") assert logger_c.logger is logger_a.logger # same underlying Logger ``` ``` -------------------------------- ### Custom Timer Logging with TaskLogger Class API Source: https://github.com/scottgigante/tasklogger/blob/master/README.rst Instantiate TaskLogger with a custom timer (e.g., 'cpu', time.monotonic_ns) to log specific types of time. The min_runtime parameter can control when logs are displayed. Ensure tasklogger and time are imported. ```python >>> import tasklogger >>> import time >>> logger = tasklogger.TaskLogger(name='cpu_logger', timer='cpu', min_runtime=0) >>> with logger.log_task("Supertask"): ... time.sleep(1) ... with logger.log_task("Subtask"): ... _ = [[(i,j) for j in range(i)] for i in range(1000)] ... time.sleep(1) Calculating Supertask... Calculating Subtask... Calculated Subtask in 0.09 seconds. Calculated Supertask in 0.09 seconds. ``` ```python >>> logger = tasklogger.TaskLogger(name='nano_logger', timer=time.monotonic_ns) >>> with logger.log_task("Supertask"): ... time.sleep(1) ... with logger.log_task("Subtask"): ... time.sleep(1) ... time.sleep(1) Calculating Supertask... Calculating Subtask... Calculated Subtask in 1001083511.00 seconds. Calculated Supertask in 3003702161.00 seconds. ``` -------------------------------- ### Retrieve or create a named TaskLogger instance Source: https://context7.com/scottgigante/tasklogger/llms.txt Use tasklogger.get_tasklogger to safely retrieve an existing TaskLogger by name or create a new one with default settings if it doesn't exist. This prevents RuntimeErrors from duplicate instantiation and is useful for cross-module logger access. ```python import tasklogger # First call: creates the default TaskLogger logger = tasklogger.get_tasklogger() # Subsequent calls: returns same instance logger2 = tasklogger.get_tasklogger() assert logger is logger2 # True # Named loggers: isolated instances db_logger = tasklogger.get_tasklogger("database") api_logger = tasklogger.get_tasklogger("api") assert db_logger is not api_logger # True # Safe cross-module usage: module A creates, module B retrieves # module_a.py tasklogger.TaskLogger("app", if_exists="ignore") # module_b.py (imported after module_a) logger = tasklogger.get_tasklogger("app") # retrieves existing, no error with logger.log_task("DB query"): pass ``` -------------------------------- ### `TaskLogger.set_timer` / `tasklogger.set_timer` Source: https://context7.com/scottgigante/tasklogger/llms.txt Configures the timing function used to measure task durations. It can be set to "wall" for real elapsed time (default), "cpu" for CPU time only, or any callable that returns a numeric value. This allows for flexible measurement of task performance and supports method chaining. ```APIDOC ## `TaskLogger.set_timer` / `tasklogger.set_timer` — Set the timing function Configures how task durations are measured. `"wall"` uses `time.time` (real elapsed time, default). `"cpu"` uses `time.process_time` (CPU time only, excludes sleep). Any zero-argument callable returning a numeric value is accepted. Returns `self` for chaining. ```python import tasklogger import time logger = tasklogger.TaskLogger("timer_test", if_exists="ignore") # Wall clock time (default) - includes sleep/IO wait logger.set_timer("wall") with logger.log_task("wall timed"): time.sleep(0.5) # Calculated wall timed in 0.50 seconds. # CPU time - excludes sleep logger.set_timer("cpu") with logger.log_task("cpu timed"): time.sleep(0.5) # sleeping: CPU time stays near 0 # Calculated cpu timed in 0.00 seconds. (or not printed if < min_runtime) # Custom callable: milliseconds logger.set_timer(lambda: time.time() * 1000) with logger.log_task("ms timed"): time.sleep(0.1) # Calculated ms timed in 100.xx seconds. (units are ms, label is misleading) # Monotonic nanoseconds for high-precision profiling logger = tasklogger.TaskLogger("ns_timer", timer=time.monotonic_ns, min_runtime=0, if_exists="ignore") with logger.log_task("nanosecond task"): _ = sum(range(10_000_000)) # Calculated nanosecond task in 123456789.00 seconds. (value is nanoseconds) # Functional API tasklogger.set_timer("cpu") tasklogger.set_timer("wall") # reset to default ``` ``` -------------------------------- ### Set Timing Function with TaskLogger Source: https://context7.com/scottgigante/tasklogger/llms.txt Configures how task durations are measured using 'wall' (real time) or 'cpu' (CPU time). Accepts any zero-argument callable returning a numeric value. Returns `self` for chaining. ```python import tasklogger import time logger = tasklogger.TaskLogger("timer_test", if_exists="ignore") # Wall clock time (default) - includes sleep/IO wait logger.set_timer("wall") with logger.log_task("wall timed"): time.sleep(0.5) # Calculated wall timed in 0.50 seconds. ``` ```python # CPU time - excludes sleep logger.set_timer("cpu") with logger.log_task("cpu timed"): time.sleep(0.5) # sleeping: CPU time stays near 0 # Calculated cpu timed in 0.00 seconds. (or not printed if < min_runtime) ``` ```python # Custom callable: milliseconds logger.set_timer(lambda: time.time() * 1000) with logger.log_task("ms timed"): time.sleep(0.1) # Calculated ms timed in 100.xx seconds. (units are ms, label is misleading) ``` ```python # Monotonic nanoseconds for high-precision profiling logger = tasklogger.TaskLogger("ns_timer", timer=time.monotonic_ns, min_runtime=0, if_exists="ignore") with logger.log_task("nanosecond task"): _ = sum(range(10_000_000)) # Calculated nanosecond task in 123456789.00 seconds. (value is nanoseconds) ``` ```python # Functional API tasklogger.set_timer("cpu") tasklogger.set_timer("wall") # reset to default ``` -------------------------------- ### Log messages at specific levels with TaskLogger Source: https://context7.com/scottgigante/tasklogger/llms.txt Use convenience methods like log_debug, log_info, log_warning, log_error, and log_critical to log messages at specific levels. These methods respect the current log level and apply indentation based on open tasks. The functional equivalents operate on the global or named logger. ```python import tasklogger import time logger = tasklogger.TaskLogger("msg_test", level=2, if_exists="ignore") # All log levels logger.log_debug("Entering preprocessing loop") # only shown at level >= 2 logger.log_info("Processing 1000 records") # shown at level >= 1 logger.log_warning("Missing values detected: 42") # shown at level >= 0 logger.log_error("Failed to connect to DB, retrying") # shown at level >= -1 logger.log_critical("Disk full - aborting pipeline") # shown at level >= -2 # Messages are indented when tasks are active with logger.log_task("Pipeline"): logger.log_info("Starting stage 1") # indented 2 spaces with logger.log_task("Stage 1"): logger.log_debug("Processing chunk 1") # indented 4 spaces logger.log_warning("Stage 1 slow") # indented 2 spaces # Output: # Calculating Pipeline... # Starting stage 1 # Calculating Stage 1... # Processing chunk 1 # Calculated Stage 1 in 0.00 seconds. # Stage 1 slow # Calculated Pipeline in 0.00 seconds. # Functional API on global logger tasklogger.log_info("Batch complete: 500 items processed") tasklogger.log_warning("Rate limit approaching") tasklogger.log_error("Upstream timeout on request #42") # Named logger via functional API tasklogger.TaskLogger("ingest", if_exists="ignore") tasklogger.log_info("Record count: 9999", logger="ingest") ``` -------------------------------- ### Configure Log Verbosity with TaskLogger Source: https://context7.com/scottgigante/tasklogger/llms.txt Set the logging level using integers or booleans. Changing the level is reflected immediately. Returns `self` for method chaining. ```python import tasklogger logger = tasklogger.TaskLogger("verbose_test", if_exists="ignore") logger.set_level(2) # DEBUG: all messages printed logger.set_level(1) # INFO: tasks + info messages (default) logger.set_level(True) # same as 1 (INFO) logger.set_level(0) # WARNING and above only logger.set_level(False)# same as 0 (WARNING) logger.set_level(-1) # ERROR and above only logger.set_level(-2) # CRITICAL only logger.set_level(-3) # IGNORE: suppress all output ``` ```python # Method chaining tasklogger.TaskLogger("chain_test").set_level(2).set_timer("cpu").set_indent(4) ``` ```python # Functional API tasklogger.set_level(2) # sets DEBUG on global "TaskLogger" ``` ```python # Conditionally enable debug during development import os level = 2 if os.getenv("DEBUG") else 1 tasklogger.set_level(level) ``` ```python # Demonstrate effect logger.set_level(2) logger.log_debug("This appears at DEBUG level") # prints logger.set_level(1) logger.log_debug("This does not appear at INFO") # suppressed logger.log_info("This appears at INFO level") # prints ``` -------------------------------- ### TaskLogger.log_info / log_debug / log_warning / log_error / log_critical Source: https://context7.com/scottgigante/tasklogger/llms.txt Convenience methods to log plain messages at specific levels without any task timing. Each method respects the current log level and applies indentation based on how many tasks are currently open. ```APIDOC ## `TaskLogger.log_info` / `log_debug` / `log_warning` / `log_error` / `log_critical` — Level-specific message logging Convenience methods to log plain messages at specific levels without any task timing. Each method respects the current log level and applies indentation based on how many tasks are currently open. The functional equivalents (`tasklogger.log_info`, etc.) operate on the global or named logger. ### Usage ```python import tasklogger logger = tasklogger.TaskLogger("msg_test", level=2, if_exists="ignore") # All log levels logger.log_debug("Entering preprocessing loop") # only shown at level >= 2 logger.log_info("Processing 1000 records") # shown at level >= 1 logger.log_warning("Missing values detected: 42") # shown at level >= 0 logger.log_error("Failed to connect to DB, retrying") # shown at level >= -1 logger.log_critical("Disk full - aborting pipeline") # shown at level >= -2 # Messages are indented when tasks are active with logger.log_task("Pipeline"): logger.log_info("Starting stage 1") # indented 2 spaces with logger.log_task("Stage 1"): logger.log_debug("Processing chunk 1") # indented 4 spaces logger.log_warning("Stage 1 slow") # indented 2 spaces # Functional API on global logger tasklogger.log_info("Batch complete: 500 items processed") tasklogger.log_warning("Rate limit approaching") tasklogger.log_error("Upstream timeout on request #42") # Named logger via functional API tasklogger.TaskLogger("ingest", if_exists="ignore") tasklogger.log_info("Record count: 9999", logger="ingest") ``` ``` -------------------------------- ### Configure Indentation with TaskLogger Source: https://context7.com/scottgigante/tasklogger/llms.txt Controls the number of spaces added per nesting level for task messages. Set to `0` to disable indentation. Returns `self` for chaining. ```python import tasklogger import time # Default 2-space indent logger = tasklogger.TaskLogger("indent_test", if_exists="ignore") with logger.log_task("outer"): with logger.log_task("inner"): pass # Calculating outer... # Calculating inner... # Calculated inner in 0.00 seconds. # Calculated outer in 0.00 seconds. ``` ```python # 4-space indent logger.set_indent(4) with logger.log_task("outer"): with logger.log_task("inner"): pass # Calculating outer... # Calculating inner... # Calculated inner in 0.00 seconds. # Calculated outer in 0.00 seconds. ``` ```python # Disable indentation logger.set_indent(0) with logger.log_task("outer"): with logger.log_task("inner"): pass # Calculating outer... # Calculating inner... # Calculated inner in 0.00 seconds. # Calculated outer in 0.00 seconds. ``` ```python # Functional API tasklogger.set_indent(4) ``` -------------------------------- ### `TaskLogger.set_level` / `tasklogger.set_level` Source: https://context7.com/scottgigante/tasklogger/llms.txt Configures the logging verbosity level for TaskLogger. It accepts integers or booleans to map to Python's standard logging levels, allowing fine-grained control over which messages are displayed. The setting is applied immediately and can be chained with other TaskLogger methods. ```APIDOC ## `TaskLogger.set_level` / `tasklogger.set_level` — Configure log verbosity Sets the logging level using an integer scale that maps to Python's standard `logging` levels. Accepts integers or booleans. Changing the level is reflected immediately and logged as a DEBUG message. Returns `self` (or the `TaskLogger` instance) for method chaining. ```python import tasklogger logger = tasklogger.TaskLogger("verbose_test", if_exists="ignore") logger.set_level(2) # DEBUG: all messages printed logger.set_level(1) # INFO: tasks + info messages (default) logger.set_level(True) # same as 1 (INFO) logger.set_level(0) # WARNING and above only logger.set_level(False)# same as 0 (WARNING) logger.set_level(-1) # ERROR and above only logger.set_level(-2) # CRITICAL only logger.set_level(-3) # IGNORE: suppress all output # Method chaining tasklogger.TaskLogger("chain_test").set_level(2).set_timer("cpu").set_indent(4) # Functional API tasklogger.set_level(2) # sets DEBUG on global "TaskLogger" # Conditionally enable debug during development import os level = 2 if os.getenv("DEBUG") else 1 tasklogger.set_level(level) # Demonstrate effect logger.set_level(2) logger.log_debug("This appears at DEBUG level") # prints logger.set_level(1) logger.log_debug("This does not appear at INFO") # suppressed logger.log_info("This appears at INFO level") # prints ``` ``` -------------------------------- ### `TaskLogger.set_indent` / `tasklogger.set_indent` Source: https://context7.com/scottgigante/tasklogger/llms.txt Configures the number of spaces used for indentation per nesting level in task messages. The default is 2 spaces, but this can be adjusted or disabled entirely by setting it to 0. This setting supports method chaining for convenient configuration. ```APIDOC ## `TaskLogger.set_indent` / `tasklogger.set_indent` — Configure indentation of nested tasks Controls how many spaces are added per nesting level when printing task messages. The default is `2` spaces per level. Set to `0` to disable indentation entirely. Returns `self` for chaining. ```python import tasklogger import time # Default 2-space indent logger = tasklogger.TaskLogger("indent_test", if_exists="ignore") with logger.log_task("outer"): with logger.log_task("inner"): pass # Calculating outer... # Calculating inner... # Calculated inner in 0.00 seconds. # Calculated outer in 0.00 seconds. # 4-space indent logger.set_indent(4) with logger.log_task("outer"): with logger.log_task("inner"): pass # Calculating outer... # Calculating inner... # Calculated inner in 0.00 seconds. # Calculated outer in 0.00 seconds. # Disable indentation logger.set_indent(0) with logger.log_task("outer"): with logger.log_task("inner"): pass # Calculating outer... # Calculating inner... # Calculated inner in 0.00 seconds. # Calculated outer in 0.00 seconds. # Functional API tasklogger.set_indent(4) ``` ``` -------------------------------- ### tasklogger.get_tasklogger Source: https://context7.com/scottgigante/tasklogger/llms.txt Retrieve or create a named logger. Returns an existing TaskLogger by name, or creates a new one with defaults if none exists. This is the safe way to access loggers across modules without risking RuntimeError from duplicate instantiation. ```APIDOC ## `tasklogger.get_tasklogger` — Retrieve or create a named logger Returns an existing `TaskLogger` by name, or creates a new one with defaults if none exists. This is the safe way to access loggers across modules without risking `RuntimeError` from duplicate instantiation. ### Usage ```python import tasklogger # First call: creates the default TaskLogger logger = tasklogger.get_tasklogger() # Subsequent calls: returns same instance logger2 = tasklogger.get_tasklogger() assert logger is logger2 # True # Named loggers: isolated instances db_logger = tasklogger.get_tasklogger("database") api_logger = tasklogger.get_tasklogger("api") assert db_logger is not api_logger # True # Safe cross-module usage: module A creates, module B retrieves # module_a.py tasklogger.TaskLogger("app", if_exists="ignore") # module_b.py (imported after module_a) logger = tasklogger.get_tasklogger("app") # retrieves existing, no error with logger.log_task("DB query"): pass ``` ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.