Skip to content

radical.asyncflow.logging

StructuredLogger

StructuredLogger(logger: Logger)

Drop-in replacement that adds structured logging capabilities.

Source code in doc_env/lib/python3.13/site-packages/radical/asyncflow/logging.py
180
181
def __init__(self, logger: logging.Logger):
    self._logger = logger

info

info(message: str, **kwargs)

Enhanced info() that accepts both old and new usage patterns.

Source code in doc_env/lib/python3.13/site-packages/radical/asyncflow/logging.py
183
184
185
186
187
188
def info(self, message: str, **kwargs):
    """Enhanced info() that accepts both old and new usage patterns."""
    if kwargs:
        self._logger.info(message, extra=kwargs)
    else:
        self._logger.info(message)

init_default_logger

init_default_logger(log_level: Union[int, str] = INFO, *, output_file: Optional[Union[str, Path]] = None, file_log_level: Optional[Union[int, str]] = None, use_colors: bool = True, show_details: bool = False, style: str = 'modern', clear_handlers: bool = False, logger_name: Optional[str] = None, structured_logging: bool = False, structured_file: Optional[Union[str, Path]] = None) -> Logger

Setup and configure logging with enhanced features.

Parameters:

Name Type Description Default
log_level Union[int, str]

Base logging level for console output.

INFO
output_file Optional[Union[str, Path]]

Path to log file. If provided, file logging is enabled.

None
file_log_level Optional[Union[int, str]]

Logging level for file output. Defaults to log_level.

None
use_colors bool

Enable colored console output.

True
show_details bool

Include thread/process info in log messages.

False
style str

Format style - 'modern', 'core', 'execution_backend', or 'minimal'.

'modern'
clear_handlers bool

Remove existing handlers from root logger.

False
logger_name Optional[str]

Name for the logger. If None, returns root logger.

None
structured_logging bool

Enable JSON structured logging to file.

False
structured_file Optional[Union[str, Path]]

Custom path for structured JSON log file.

None

Returns:

Type Description
Logger

Configured logger instance.

Source code in doc_env/lib/python3.13/site-packages/radical/asyncflow/logging.py
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
def init_default_logger(
    log_level: Union[int, str] = logging.INFO,
    *,
    output_file: Optional[Union[str, pathlib.Path]] = None,
    file_log_level: Optional[Union[int, str]] = None,
    use_colors: bool = True,
    show_details: bool = False,
    style: str = "modern",
    clear_handlers: bool = False,
    logger_name: Optional[str] = None,
    structured_logging: bool = False,
    structured_file: Optional[Union[str, pathlib.Path]] = None,
) -> logging.Logger:
    """Setup and configure logging with enhanced features.

    Args:
        log_level: Base logging level for console output.
        output_file: Path to log file. If provided, file logging is enabled.
        file_log_level: Logging level for file output. Defaults to log_level.
        use_colors: Enable colored console output.
        show_details: Include thread/process info in log messages.
        style: Format style - 'modern', 'core', 'execution_backend', or 'minimal'.
        clear_handlers: Remove existing handlers from root logger.
        logger_name: Name for the logger. If None, returns root logger.
        structured_logging: Enable JSON structured logging to file.
        structured_file: Custom path for structured JSON log file.

    Returns:
        Configured logger instance.
    """
    # Get or create logger
    logger = logging.getLogger(logger_name) if logger_name else logging.getLogger()

    # Clear existing handlers if requested
    if clear_handlers:
        logger.handlers.clear()

    # Console always uses colored formatter (never JSON)
    console_formatter = _ColoredFormatter(
        use_colors=use_colors, show_details=show_details, style=style
    )

    # Console handler
    console_handler = logging.StreamHandler(sys.stdout)
    console_handler.setFormatter(console_formatter)
    console_handler.setLevel(log_level)

    if show_details:
        console_handler.addFilter(_thread_info_filter)

    logger.addHandler(console_handler)

    # Regular file handler (if requested) - uses colored formatter without colors
    if output_file is not None:
        file_level = log_level if file_log_level is None else file_log_level
        file_path = pathlib.Path(output_file)
        file_path.parent.mkdir(parents=True, exist_ok=True)

        file_handler = logging.FileHandler(file_path)
        file_formatter = _ColoredFormatter(
            use_colors=False,  # No colors in file
            show_details=show_details,
            style=style,
        )
        file_handler.setFormatter(file_formatter)
        file_handler.setLevel(file_level)

        if show_details:
            file_handler.addFilter(_thread_info_filter)

        logger.addHandler(file_handler)

    # Structured JSON file handler (if requested)
    if structured_logging:
        # Auto-generate structured log file name if not provided
        if structured_file is None:
            if output_file is not None:
                # Use same directory as regular log file
                structured_file = pathlib.Path(output_file).with_suffix(".json")
            else:
                # Default to structured.log in current directory
                structured_file = "radical.asyncflow.logs.json"

        struct_level = log_level if file_log_level is None else file_log_level
        struct_path = pathlib.Path(structured_file)
        struct_path.parent.mkdir(parents=True, exist_ok=True)

        struct_handler = logging.FileHandler(struct_path)
        struct_formatter = _StructuredFormatter()
        struct_handler.setFormatter(struct_formatter)
        struct_handler.setLevel(struct_level)

        if show_details:
            struct_handler.addFilter(_thread_info_filter)

        logger.addHandler(struct_handler)

    # Set logger level
    logger.setLevel(logging.NOTSET)

    # Capture warnings
    logging.captureWarnings(True)

    # Log configuration info
    level_name = (
        logging.getLevelName(log_level) if isinstance(log_level, int) else log_level
    )
    file_level_name = (
        logging.getLevelName(file_log_level)
        if isinstance(file_log_level, int)
        else file_log_level
    )

    structured_info = str(structured_file) if structured_logging else "disabled"

    logger.info(
        "Logger configured successfully - "
        "Console: %s, File: %s (%s), Structured: %s, Style: %s",
        level_name,
        output_file or "disabled",
        file_level_name or "N/A",
        structured_info,
        style,
    )

    return logger

get_structured_logger

get_structured_logger(name: str = None, level: Union[int, str] = INFO) -> StructuredLogger

Get a structured logger that supports both old and new usage patterns.

Source code in doc_env/lib/python3.13/site-packages/radical/asyncflow/logging.py
353
354
355
356
357
358
359
360
361
362
363
def get_structured_logger(
    name: str = None, level: Union[int, str] = logging.INFO
) -> StructuredLogger:
    """Get a structured logger that supports both old and new usage patterns."""
    # Check if logger already configured, if not configure it with structured logging
    base_logger = logging.getLogger(name)
    if not base_logger.handlers:
        init_default_logger(level, logger_name=name, structured_logging=True)
        base_logger = logging.getLogger(name)

    return StructuredLogger(base_logger)

get_logger

get_logger(name: str = None, level: Union[int, str] = INFO) -> Logger

Quick logger setup for simple use cases.

Source code in doc_env/lib/python3.13/site-packages/radical/asyncflow/logging.py
367
368
369
370
371
372
373
def get_logger(
    name: str = None, level: Union[int, str] = logging.INFO
) -> logging.Logger:
    """Quick logger setup for simple use cases."""
    if not logging.getLogger().handlers:
        init_default_logger(level, logger_name=name, style="modern")
    return logging.getLogger(name)