Introduction

When building a Generative AI application, it is crucial to understand its behavior: what data is processed, where errors occur, and how long responses take. Galileo solves this by providing OpenAI (Python, TypeScript) and LangChain (Python) wrappers, which help you generate application traces with minimal set up.

However, when you need more control over the logging process, the Galileo SDK offers a few other solutions:

  • galileo_context for simple, session-based logging
  • GalileoLogger class for flexible control
  • @log decorator (or log function wrapper) for granular, function-level logging

This guide compares these approaches and offers guidance on when to use each one. If you’re in a hurry, you can jump right to the summary here.

galileo_context

The Galileo Context manager provides a way to control logging for a block of code. It allows you to start logging quickly while handling details like creating traces or saving events to the Galileo Console for you. You can use it to access your project’s logger instance.

Example

Galileo Context manager can be used to access a managed GalileoLogger instance, so that you can add custom traces and spans based on your application’s flow.

import os
from galileo import log, galileo_context
from galileo.openai import openai

client = openai.OpenAI(api_key=os.environ.get("OPENAI_API_KEY"))

def call_openai(prompt):
    # This will be automatically logged as a child span
    chat_completion = client.chat.completions.create(
        model="gpt-4o",
        messages=[{"role": "user", "content": prompt}]
    )
    return chat_completion.choices[0].message.content

@log
def make_nested_call():
    # Gets the currently active logger
    galileo_logger = galileo_context.get_logger_instance()
    galileo_logger.add_workflow_span(
        input="The Roman Empire",
    )
    # This creates a parent workflow span
    first_result = call_openai("Tell me about the Roman Empire")
    second_result = call_openai(f"Summarize this: {first_result}")
    return second_result

# When called, this will create a trace with a workflow span and two nested LLM spans
response = make_nested_call()
print(response)

When to use galileo_context

The Galileo Context manager is great when your logic is contained in a single block of code, or you want to quickly get started logging. It is also ideal for experimenting in Python Notebooks (e.g. Jupyter).

GalileoLogger

The GalileoLogger class gives you more flexible control over logging. You can decide when your logging session starts or ends, and create spans and traces manually. You get a lot more control over the data you can send to Galileo Console, including the ability to tag and add custom metadata to your spans.

GalileoLogger is available in both the Python and TypeScript SDKs. It supports multiple span types (LLM, retriever, tool, workflow, agent), in addition to logging session management.

Example

The example below shows how to

  1. Create a GalileoLogger instance
  2. Manually create a Trace for your application events
  3. Add Spans to the Trace, and
  4. Both conclude and flush the logs.

Although the steps are shown in sequence here, you can perform each wherever it makes sense to do so in your app: just create the logger instance and pass its reference to anywhere you want to create traces and spans.

from galileo import GalileoLogger

# Initialize the logger
logger = GalileoLogger(project="my-project", log_stream="my-log-stream")

# Start a new trace
trace = logger.start_trace(input="What's the weather in San Francisco?")

# Add spans to the trace
llm_span = logger.add_llm_span(
    input="What's the weather in San Francisco?",
    output="The weather in San Francisco is currently sunny with a temperature of 72°F.",
    model="gpt-4o",
    temperature=0.7
)

# Conclude the trace
logger.conclude(output="The weather in San Francisco is currently sunny with a temperature of 72°F.")

# Flush the trace to Galileo
logger.flush()

When to use GalileoLogger

This approach is ideal for complex applications that require fine-grained logging control, or where your app logic is spread around different functions.

@log decorator or log function wrapper

The @log decorator (Python) or log function wrapper (TypeScript) is the most granular approach to capturing events in your application. Use it to capture the inputs and outputs of individual function calls—even generator functions!—as spans.

You can decorate or wrap any function you want to log, and specify the type of Span you want to create. The @log decorator supports different Span types: if there is no current trace when your function runs, log will generate a single-span trace.

Example

The example below shows how to create different types of spans with the log decorator or function wrapper (depending on your SDK). Calling the decorated or wrapped function will generate the corresponding Span in your log stream.

from galileo import log

# Create a workflow span (default)
@log
def my_workflow_function(input):
    # This can contain multiple steps and child spans
    return result

# Create an LLM span
@log(span_type="llm")
def my_llm_function(input):
    # This should be for direct LLM calls
    return result

# Create a retriever span
@log(span_type="retriever")
def my_retriever_function(query):
    # For functions that retrieve documents
    # If the output is an array, it will be captured as documents
    return ["doc1", "doc2"]

# Create a tool span
@log(span_type="tool")
def my_tool_function(input="tool call input"):
    # For functions that act as tools in an agent system
    return "tool call output"

When to use log

This approach is ideal for creating spans to log an LLM response, tool usage, or some other helper function. If your log context does not have a Trace, calling a log-decorated function will create a single-span Trace. Otherwise, the span will be added to the current context. log is best used on functions that represent meaningful work units in your app.

Note that, if your application has a lot of units to be manually logged, this approach may require a little more work than the others. In such cases, consider combining it with other methods that automatically generate traces, such as galileo_context or a GalileoLogger instance.

Visit the Python or TypeScript docs for more information.

When to Use Each Method

MethodUse When…
galileo_contextYou are using the Python SDK, want to log events with minimal code, and your logic is in a single block
GalileoLoggerYou need more flexible control over your logging session, and/or your application logic depends on more than one file
@log decoratorYou want to capture individual function calls within your logging session, and/or combine them into custom workflows

Conclusion

Each Galileo logging method helps you capture your application’s activity, but the right choice depends on your needs:

  • Use galileo_context to log a block of code with minimal setup
  • Use GalileoLogger when you need to control when logging begins/ends, and what is sent to the Galileo Console
  • Use @log to track individual function calls, so that you can see their inputs and outputs

You can also combine these methods for even more flexibility.

Next Steps

Learn more about:

  • Spans - the smallest units that make up your application logs
  • Traces - how to create and use traces
  • Sessions - logging sessions and how to use them
  • OpenAI Agent Integration - get started with OpenAI agents in Galileo