Menu

Sign in to track your progress and unlock all features.

Theme style

Log in

Full lesson preview

Combine Timing and Logging in One Decorator

Create a decorator that measures execution time and records a structured log for each call while preserving original function metadata.

Python practice30 minDecorators FundamentalsAdvancedLast updated April 15, 2026

Problem statement

Implement combine_timing_logging — a decorator (that can be used with or without arguments) which wraps any function and records two pieces of information on the wrapper function after each call: - last_duration_ms: the measured execution time in milliseconds rounded to 3 decimals when timing is enabled, or None when timing is disabled. - last_log: a single-line string describing the call (function name, arguments, result) and whether timing was measured. Behavior details: - The decorator should support both usages: @combine_timing_logging and @combine_timing_logging(enabled=False). - Use functools.wraps to preserve the wrapped function's metadata (__name__, __doc__, etc). - When enabled is True (default), measure execution time using time.perf_counter(), compute milliseconds, and round to 3 decimals. - The last_log for successful calls should begin with "CALL <name>(<args>) -> <result>" and include either "in <ms>ms" when timing is enabled or the phrase "(timing disabled)" when disabled. - For kwargs in the log, list them sorted by key to keep deterministic ordering (e.g., "a=1, b=2"). - The wrapper should re-raise any exceptions raised by the wrapped function but still set last_duration_ms and last_log appropriately before re-raising. You will be given several decorated functions in the starter code. Implement the decorator so those functions behave as described and expose last_duration_ms and last_log.

Task

Implement a reusable decorator that (optionally) measures execution time, produces a consistent log string including arguments and result, and exposes the last measured duration and log on the wrapped function.

Examples

Basic usage

Input

add(1, 2)

Output

3

add is decorated with combine_timing_logging (timing enabled by default). The call returns the original function result (3). After the call, add.last_duration_ms is a non-negative float and add.last_log documents the call.

Input format

A call expression invoking one of the decorated functions (e.g., add(2,3)).

Output format

Return the original function's return value. The decorator will also attach last_duration_ms and last_log attributes to the wrapper function object.

Constraints

Do not change the wrapped function's return value. Use functools.wraps to preserve metadata. For kwargs in logs, sort keys for deterministic output.

Samples

Sample 1

Input

add(1, 2)

Output

3

add returns 3. The decorator records timing and a log string on add.last_duration_ms and add.last_log.