Optimizely will be sunsetting Full Stack Experimentation on July 29, 2024. See the recommended Feature Experimentation migration timeline and documentation.

Dev GuideAPI Reference
Dev GuideAPI ReferenceUser GuideLegal TermsGitHubDev CommunityOptimizely AcademySubmit a ticketLog In
Dev Guide

Customize logger

This topic describes how to customize the log information about experiments to help with debugging.

The logger logs information about your experiments to help you with debugging. You can customize where log information is sent and what kind of information is tracked.

You can use our SimpleLogger implementation out of the box.

To improve your experience setting up the SDK and configuring your production environment, we recommend that you pass in a logger for your Optimizely client. See the code example below.

import logging
from optimizely import logger
from optimizely import optimizely

# To set a log level choose one of the following:
# INFO: logging.INFO
# NOTSET: logging.NOTSET
# DEBUG: logging.DEBUG
# WARNING: logging.WARNING
# ERROR: logging.ERROR
# CRITICAL: logging.CRITICAL

# To define a minimum logging level pass it in during initialization.
# The example below shows a minimum logging level of INFO.
optimizely_client = optimizely.Optimizely(datafile, logger=logger.SimpleLogger(min_level=logging.INFO))

For finer control over your SDK configuration in a production environment, pass in a custom logger for your Optimizely client. A custom logger is a function that takes an argument, the level, and the message. See the code example below to create and set a custom logger.

import logging

def get_custom_logger(name, level=logging.INFO):
  """ Example of a custom logger.
  
    This function takes in two parameters: name and level and logs to console.
    The place to log in this case is defined by the handler which we set
    to logging.StreamHandler().
    
    Args:
      name: Name for the logger.
      level: Minimum level for messages to be logged
  """
  logger = logging.getLogger(name)
  logger.setLevel(level)

  if not logger.handlers:
    handler = logging.StreamHandler()
    formatter = logging.Formatter("Optimizely({}): %(levelname)s %(message)s".format(name))
    handler.setFormatter(formatter)
    logger.addHandler(handler)

  return logger


# Here we initialize the SDK with the custom logger.
optimizely_client = optimizely.Optimizely(datafile, logger=get_custom_logger('my_optimizely_logger'))

Log levels

The table below lists the log levels for the Python SDK.

Log LevelExplanation
logging.CRITICALEvents that cause the app to crash are logged.
logging.ERROREvents that prevent feature flags from functioning correctly (for example, invalid datafile in initialization and invalid feature keys) are logged. The user can take action to correct.
logging.WARNINGEvents that don't prevent feature flags from functioning correctly, but can have unexpected outcomes (for example, future API deprecation, logger or error handler are not set properly, and nil values from getters) are logged.
logging.INFOEvents of significance (for example, activate started, activate succeeded, tracking started, and tracking succeeded) are logged. This is helpful in showing the lifecycle of an API call.
logging.DEBUGAny information related to errors that can help us debug the issue (for example, the feature flag is not running, user is not included in the rollout) are logged.
logging.NOTSETLevel set when a logger is created. Causes all messages to be processed when the logger is the root logger (or delegation to the parent when the logger is a non-root logger).