> ## Documentation Index
> Fetch the complete documentation index at: https://docs.galileo.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Galileo Logger

> Get granular control over logging with the GalileoLogger class

{/* <!-- markdownlint-enable MD044 --> */}

The `GalileoLogger` class provides the most granular control over logging in Galileo. You can create a logger yourself, or use one from the current context from inside a decorated or wrapped function or when using a third-party SDK integration.

## Overview

The `GalileoLogger` class allows you to:

* Start sessions
* Manually create and manage traces
* Add spans of different types to your traces
* Control exactly what data gets logged
* Explicitly manage when traces are flushed to Galileo

This approach requires more code than using wrappers or decorators but gives you the most control over the logging process.

<CardGroup cols={2}>
  <Card title="Python SDK reference" icon="code" horizontal href="/sdk-api/python/reference/logger/logger">
    The full SDK reference for the `GalileoLogger` Python class.
  </Card>

  <Card title="TypeScript SDK reference" icon="code" horizontal href="/sdk-api/typescript/reference/README/classes/GalileoLogger">
    The full SDK reference for the `GalileoLogger` TypeScript class.
  </Card>
</CardGroup>

## Environment variables

`GalileoLogger` loads configurations from environment variables:

* Galileo API key in `GALILEO_API_KEY`
* Project to log to:
  * Project name in `GALILEO_PROJECT` (most common usage)
  * Project ID in `GALILEO_PROJECT_ID` (alternative usage)
* Log stream to log to in `GALILEO_LOG_STREAM`

The project name, project ID, or Log stream name can also be set in code (the [`GalileoLogger`](http://localhost:3000/sdk-api/python/reference/logger/logger) SDK reference has more info).

A example `.env` file is available in [this Python SDK repository location](https://github.com/rungalileo/sdk-examples/tree/main/python/logging-samples/galileologger).

## Basic usage

Here's a simple example of using the `GalileoLogger` to log an LLM call. The full Python code is available as `basic-example.py` in [this folder](https://github.com/rungalileo/sdk-examples/tree/main/python/logging-samples/galileologger).

<CodeGroup>
  ```python Python theme={null}
  from galileo import GalileoLogger

  # Create a logger instance
  logger = GalileoLogger()

  # Start a session
  session_id = logger.start_session(name="Test session")

  # Start a new trace
  trace = logger.start_trace("Say this is a test")

  # Add an LLM span to the trace
  logger.add_llm_span(
      input="Say this is a test",
      output="Hello, this is a test",
      model="gpt-4o",
      num_input_tokens=10,
      num_output_tokens=3,
      total_tokens=13,
      duration_ns=1000,
  )

  # Conclude the trace with the final output
  logger.conclude(output="Hello, this is a test", duration_ns=1000)

  # Flush the trace to Galileo
  logger.flush()
  ```

  ```typescript TypeScript theme={null}
  import { GalileoLogger } from "galileo";

  // Create a logger instance with project and Log stream
  const galileoLogger = new GalileoLogger({
      projectName: "my-project",
      logStreamName: "my-log-stream",
  });

  const sessionId = galileoLogger.startSession({
      name: "Test session"
  });

  // Start a new trace
  const trace = galileoLogger.startTrace({
      input: "Say this is a test"
  });

  // Add an LLM span to the trace
  galileoLogger.addLlmSpan({
      input: "Say this is a test",
      output: "Hello, this is a test",
      model: "gpt-4o",
      numInputTokens: 10,
      numOutputTokens: 3,
      totalTokens: 13,
      durationNs: 1000,
  });

  // Conclude the trace with the final output
  galileoLogger.conclude({
      output: "Hello, this is a test"
  });

  // Flush the trace to Galileo
  galileoLogger.flush();
  ```
</CodeGroup>

This example:

1. Starts a new session
2. Starts a trace inside the session
3. Adds an LLM span to the trace
4. Concludes the trace
5. Flushes the logger to send the session to Galileo

## Detailed API

### Initialization

<CodeGroup>
  ```python Python theme={null}
  from galileo import GalileoLogger

  # Initialize with default settings (uses environment variables)
  logger = GalileoLogger()

  # Or specify project and Log stream
  logger = GalileoLogger(
      project="my-project",
      log_stream="my-log-stream"
  )
  ```

  ```typescript TypeScript theme={null}
  import { GalileoLogger } from "galileo";

  // Initialize with default settings (uses environment variables)
  const galileoLogger = new GalileoLogger();

  // Or specify project and Log stream
  const galileoLogger = new GalileoLogger({
      projectName: "my-project",
      logStreamName: "my-log-stream",
  });
  ```
</CodeGroup>

See the `GalileoLogger` [Python SDK docs](/sdk-api/python/reference/logger/logger) or [TypeScript SDK docs](/sdk-api/typescript/reference/README/classes/GalileoLogger) for more details.

### Get the current logger from the current context

The Galileo context management keeps track of loggers. You can get the current logger, which will create a new one if there isn't an existing logger.

<CodeGroup>
  ```python Python theme={null}
  from galileo import galileo_context

  # Get the current logger
  logger = galileo_context.get_logger_instance()
  ```

  ```typescript TypeScript theme={null}
  import { getLogger } from "galileo";

  // Get the current logger
  const galileoLogger = getLogger();
  ```
</CodeGroup>

If you are using any of the decorators, wrappers, or third-party integrations then this allows you to get the logger created by those components. For example, if you are adding a call inside a method decorated by the Python `@log` decorator, wrapped in the TypeScript `log` wrapper, or created automatically by an experiment, then this will return that logger instance so you can manually add additional spans.

<CodeGroup>
  ```python Python theme={null}
  from galileo import log, galileo_context

  @log(span_type="llm")
  def logged_function(input_text):
      # Get the current logger
      logger = galileo_context.get_logger_instance()

      # Add a span
      workflow_span = logger.add_workflow_span(
          input="My workflow"
      )
  ```

  ```typescript TypeScript theme={null}
  import { getLogger, log } from "galileo";

  const wrappedFunc = log({}, async (input: any) => {
      // Get the current logger
      const galileoLogger = getLogger();

      // Add a span
      const workflowSpan = galileoLogger.addWorkflowSpan({
          input: "Process user request",
      });
  });
  ```
</CodeGroup>

See the [`galileo_context` Python SDK docs](/sdk-api/python/reference/decorator) or [`getLogger` TypeScript SDK docs](/sdk-api/typescript/reference/README/functions/getLogger) for more details.

### Manage sessions

All traces live inside a session. If you don't create a session, then one is created automatically with a generated name.

#### Start a session

You can start a new session, providing a name and an external ID.

<CodeGroup>
  ```python Python theme={null}
  session_id = logger.start_session(name="My session"
                                    external_id="chat-1")
  ```

  ```typescript TypeScript theme={null}
  const sessionId = galileoLogger.startSession({
      name: "My session",
      externalId: "chat-1"
  });
  ```
</CodeGroup>

The name and external ID fields are optional. If you want to connect a session to another ID that you are using internally, for example a unique ID for a chatbot conversation, then you can set this in the external ID field.

#### Add metadata to a session

You can attach metadata to a session when starting it. Metadata is a dictionary of string key-value pairs that can be used to add structured information to your session, such as customer IDs, environment names, or application versions.

<CodeGroup>
  ```python Python theme={null}
  # Start a session with metadata
  session_id = logger.start_session(
      name="My session",
      external_id="chat-1",
      metadata={"brand_id": "acme", "environment": "production"}
  )
  ```

  ```typescript TypeScript theme={null}
  // Start a session with metadata
  const sessionId = await logger.startSession({
    name: "My session",
    externalId: "chat-1",
    metadata: { brand_id: "acme", environment: "production" }
  });
  ```
</CodeGroup>

For more information on using tags and metadata, see [Tags and Metadata](/sdk-api/logging/tags-and-metadata).

See the [`start_session` Python SDK docs](/sdk-api/python/reference/logger/logger#start-session) or [`startSession` TypeScript SDK docs](/sdk-api/typescript/reference/README/classes/GalileoLogger#startsession) for more details on all available parameters.

#### Continue an existing session

If you want to add a trace to an existing session, you can set the current session for the logger, passing the session ID. This is useful if you want to persist a session, for example saving a chatbot conversation with a user mid conversation, then resuming the next time a user connects.

<CodeGroup>
  ```python Python theme={null}
  logger.set_session(session_id=my_session_id)
  ```

  ```typescript TypeScript theme={null}
  galileoLogger.setSessionId(mySessionId);
  ```
</CodeGroup>

See the [`set_session` Python SDK docs](/sdk-api/python/reference/logger/logger#set-session) or [`setSession` TypeScript SDK docs](/sdk-api/typescript/reference/README/classes/GalileoLogger#setsession) for more details.

You can also continue a conversation using an external ID using the start session function.

<CodeGroup>
  ```python Python theme={null}
  session_id = logger.start_session(external_id=conversation_id)
  ```

  ```typescript TypeScript theme={null}
  const sessionId = galileoLogger.startSession({
      externalId: conversationId
  });
  ```
</CodeGroup>

#### End a session

To stop logging to a session, you can clear the current session.

<CodeGroup>
  ```python Python theme={null}
  logger.clear_session()
  ```

  ```typescript TypeScript theme={null}
  logger.clearSession()
  ```
</CodeGroup>

See the [`clear_session` Python SDK docs](/sdk-api/python/reference/logger/logger#clear-session) or [`clearSession` TypeScript SDK docs](/sdk-api/typescript/reference/README/classes/GalileoLogger#clearsession) for more details.

### Start a trace

Once a trace is started, all spans added to that logger will be added to that trace.

<CodeGroup>
  ```python Python theme={null}
  # Start a basic trace
  trace = logger.start_trace(input="User query")

  # Start a trace with additional metadata
  trace = logger.start_trace(
      input="User query",
      name="User Interaction",
      tags=["production", "user-123"],
      metadata={"session_id": "abc123", "user_id": "user-456"},
      duration_ns=1000000,  # Optional duration in nanoseconds
      created_at=datetime.now()  # Optional creation timestamp
  )
  ```

  ```typescript TypeScript theme={null}
  // Start a basic trace
  const trace = galileoLogger.startTrace({
      input: "User query"
  });

  // Start a trace with additional metadata
  const trace = galileoLogger.startTrace({
      input: "User query",
      name: "User Interaction",
      tags: ["production", "user-123"],
      metadata: {"session_id": "abc123", "user_id": "user-456"},
      durationNs: 1000000,  // Optional duration in nanoseconds
      createdAt: new Date()  // Optional creation timestamp
  });
  ```
</CodeGroup>

See the [`start_trace` Python SDK docs](/sdk-api/python/reference/logger/logger#start-trace) or [`startTrace` TypeScript SDK docs](/sdk-api/typescript/reference/README/classes/GalileoLogger#starttrace) for more details.

### Add spans

The `GalileoLogger` supports adding different types of spans to your traces. All spans take the input and output, as well as a name, duration, tags, and other metadata.

| Span Type | Description                                                                                                                                                 |
| :-------- | :---------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Agent     | A span for logging agent actions. You can specify the agent type, for example a supervisor, planner, router, or judge.                                      |
| LLM       | A span for logging calls to an LLM. You can specify the number of tokens, time to first token, temperature, model, and any tools.                           |
| Retriever | A span for logging RAG actions. In the output for this span you can provide all the data returned from the RAG platform for evaluating your RAG processing, |
| Tool      | A span for logging calls to tools including MCP servers. You can specify the tool call ID to tie to an LLM tool call.                                       |
| Workflow  | Workflow spans are for creating logical groupings of spans based on different flows in your app.                                                            |

#### Agent spans

Agent spans are for logging the input and output to agents of different types. The type of agent can be set when creating the span, such as supervisor or planner.

<CodeGroup>
  ```python Python theme={null}
  from galileo_core.schemas.logging.agent import AgentType

  logger.add_agent_span(
      input="What is the capital of France?",
      output="The capital of France is Paris.",
      name="Capital Query",  # Optional name
      duration_ns=1000000,  # Optional duration in nanoseconds
      metadata={"temperature": "0.7"},  # Optional metadata
      tags=["geography"],  # Optional tags
      agent_type=AgentType.planner
  )
  ```

  ```typescript TypeScript theme={null}
  import { AgentType } from "galileo/types";

  galileoLogger.startTrace({ input: "Test Trace" });

  galileoLogger.addAgentSpan({
      input: "What is the capital of France?",
      output: "The capital of France is Paris.",
      name: "Capital Query",  // Optional name
      durationNs: 1000000,  // Optional duration in nanoseconds
      metadata: {"temperature": "0.7"},  // Optional metadata
      tags: ["geography"],  // Optional tags
      agentType: AgentType.PLANNER
  });
  ```
</CodeGroup>

See the [`add_agent_span` Python SDK docs](/sdk-api/python/reference/logger/logger#add-agent-span) or [`addAgentSpan` TypeScript SDK docs](/sdk-api/typescript/reference/README/classes/GalileoLogger#addagentspan) for more details.

#### LLM spans

LLM spans are for logging calls to LLMs. You can log the input and output, tools, and details like input and output tokens.

<CodeGroup>
  ```python Python theme={null}
  logger.add_llm_span(
      input="What is the capital of France?",
      output="The capital of France is Paris.",
      model="gpt-4o",
      tools=None,  # Optional list of tools used
      name="Capital Query",  # Optional name
      duration_ns=1000000,  # Optional duration in nanoseconds
      metadata={"temperature": "0.7"},  # Optional metadata
      tags=["geography"],  # Optional tags
      num_input_tokens=10,  # Optional token counts
      num_output_tokens=5,
      total_tokens=15,
      temperature=0.7,  # Optional model parameters
      status_code=200,  # Optional status code
      time_to_first_token_ns=500000  # Optional time to first token
  )
  ```

  ```typescript TypeScript theme={null}
  galileoLogger.addLlmSpan({
      input: "What is the capital of France?",
      output: "The capital of France is Paris.",
      model: "gpt-4.1-mini",
      tools: [],  // Optional list of tools used
      name: "Capital Query",  // Optional name
      durationNs: 1000000,  // Optional duration in nanoseconds
      metadata: {"temperature": "0.7"},  // Optional metadata
      tags: ["geography"],  // Optional tags
      numInputTokens: 10,  // Optional token counts
      numOutputTokens: 5,
      totalTokens: 15,
      temperature: 0.7,  // Optional model parameters
      statusCode: 200,  // Optional status code
      timeToFirstTokenNs: 500000  // Optional time to first token
  });
  ```
</CodeGroup>

See the [`add_llm_span` Python SDK docs](/sdk-api/python/reference/logger/logger#add-llm-span) or [`addLlmSpan` TypeScript SDK docs](/sdk-api/typescript/reference/README/classes/GalileoLogger#addllmspan) for more details.

#### Retriever spans

Retriever spans are for logging calls to RAG systems. You can log the output from the RAG system to evaluate metrics like [Context Adherence](/concepts/metrics/rag/generation-quality/context-adherence).

<CodeGroup>
  ```python Python theme={null}
  logger.add_retriever_span(
      input="Query about Roman history",
      output=["Rome was founded in 753 BC...", "The Roman Empire reached its peak..."],
      name="History Retrieval",  # Optional
      duration_ns=500000,  # Optional
      metadata={"source": "history_db"},  # Optional
      tags=["history"],  # Optional
      status_code=200  # Optional
  )
  ```

  ```typescript TypeScript theme={null}
  galileoLogger.startTrace({ input: "Test Trace" });

  galileoLogger.addRetrieverSpan({
      input: "Query about Roman history",
      output: ["Rome was founded in 753 BC...", "The Roman Empire reached its peak..."],
      name: "History Retrieval",  // Optional
      durationNs: 500000,  // Optional
      metadata: {"source": "history_db"},  // Optional
      tags: ["history"],  // Optional
      statusCode: 200  // Optional
  });
  ```
</CodeGroup>

See the [`add_retriever_span` Python SDK docs](/sdk-api/python/reference/logger/logger#add-retriever-span) or [`addRetrieverSpan` TypeScript SDK docs](/sdk-api/typescript/reference/README/classes/GalileoLogger#addretrieverspan) for more details.

#### Tool spans

Tool spans log calls to tools, including tools exposed by MCP servers.

<CodeGroup>
  ```python Python theme={null}
  logger.add_tool_span(
      input=json.dumps({"operation": "add", "numbers": [1, 2, 3]}),
      output=json.dumps({"result": 6}),
      name="Calculator",  # Optional
      duration_ns=100000,  # Optional
      metadata={"tool_version": "1.0"},  # Optional
      tags=["math"],  # Optional
      status_code=200,  # Optional
      tool_call_id="tool-123"  # Optional
  )
  ```

  ```typescript TypeScript theme={null}
  galileoLogger.startTrace({ input: "Test Trace" });

  galileoLogger.addToolSpan({
      input: JSON.stringify({"operation": "add", "numbers": [1, 2, 3]}),
      output: JSON.stringify({"result": 6}),
      name: "Calculator",  // Optional
      durationNs: 100000,  // Optional
      metadata: {"tool_version": "1.0"},  // Optional
      tags: ["math"],  // Optional
      statusCode: 200,  // Optional
      toolCallId: "tool-123"  // Optional
  });
  ```
</CodeGroup>

See the [`add_tool_span` Python SDK docs](/sdk-api/python/reference/logger/logger#add-tool-span) or [`addToolSpan` TypeScript SDK docs](/sdk-api/typescript/reference/README/classes/GalileoLogger#addtoolspan) for more details.

#### Workflow spans

Workflow spans allow you to group spans into separate workflows for easier monitoring.

<CodeGroup>
  ```python Python theme={null}
  # Start a workflow span
  workflow_span = logger.add_workflow_span(
      input="Process user request",
      output=None,  # Can be set later
      name="Main Process",  # Optional
      duration_ns=None,  # Optional, can be set later
      metadata={"workflow_type": "user_request"},  # Optional
      tags=["workflow"]  # Optional
  )

  # Later, you can conclude the workflow span when concluding the trace
  ```

  ```typescript TypeScript theme={null}
  // Start a workflow span
  const workflowSpan = galileoLogger.addWorkflowSpan({
      input: "Process user request",
      name: "Main Process",  // Optional
      durationNs: 1000,  // Optional, can be set later
      metadata: {"workflow_type": "user_request"},  // Optional
      tags: ["workflow"]  // Optional
  });

  // Later, you can conclude the workflow span when concluding the trace
  ```
</CodeGroup>

Workflow spans are created as child spans of the current trace, or the current workflow span if one was created already and not concluded. Once you create a workflow span, all subsequent spans are created as children of that workflow span.

To end a workflow span, call `conclude` on the logger. The `output` passed to `conclude` will be set as the output of the workflow span. Once the workflow span is concluded, any newly added spans will be created on that workflow spans parent span or trace.

See the [`add_workflow_span` Python SDK docs](/sdk-api/python/reference/logger/logger#add-workflow-span) or [`addWorkflowSpan` TypeScript SDK docs](/sdk-api/typescript/reference/README/classes/GalileoLogger#addworkflowspan) for more details.

### Conclude

When you have finished logging a trace, you can conclude it with the final output. This ends the trace, and a new trace needs to be created to continue logging. The wrappers and third-party integrations will conclude traces for you.

<CodeGroup>
  ```python Python theme={null}
  # Conclude the trace with the final output
  logger.conclude(
      output="Final response to the user",
      duration_ns=2000000,  # Optional duration in nanoseconds
      status_code=200,  # Optional status code
      conclude_all=False  # Whether to conclude all open spans
  )
  ```

  ```typescript TypeScript theme={null}
  // Conclude the trace with the final output
  logger.conclude({
      output: "Final response to the user",
      durationNs: 2000000,  // Optional duration in nanoseconds
      statusCode: 200,      // Optional status code
      concludeAll: false    // Whether to conclude all open spans
  });
  ```
</CodeGroup>

See the [`conclude` Python SDK docs](/sdk-api/python/reference/logger/logger#conclude) or [`conclude` TypeScript SDK docs](/sdk-api/typescript/reference/README/classes/GalileoLogger#conclude) for more details.

## Flush

Logs are not continuously sent to Galileo to help your application stay performant. You can flush logs when you are ready. The wrappers and third-party integrations will flush logs for you at the end of each trace.

<CodeGroup>
  ```python Python theme={null}
  # Flush the trace to Galileo
  logger.flush()
  ```

  ```typescript TypeScript theme={null}
  // This will upload the trace to Galileo
  await flush();
  ```
</CodeGroup>

See the [`flush` Python SDK docs](/sdk-api/python/reference/logger/logger#flush) or [`flush` TypeScript SDK docs](/sdk-api/typescript/reference/README/classes/GalileoLogger#flush) for more details.

The flush call on the logger will just flush that specific logger. To flush all loggers, you can flush at the context level.

<CodeGroup>
  ```python Python theme={null}
  from galileo import galileo_context

  # Flush the logger for the current project and Log stream
  galileo_context.flush()

  # Flush all loggers across all projects and Log streams
  galileo_context.flush_all()
  ```

  ```typescript TypeScript theme={null}
  import { flush } from "galileo";

  // Flush the logger for the current project and Log stream
  await flush();
  ```
</CodeGroup>

## Advanced usage

### Create a single LLM span trace

For simple LLM calls, you can create a trace with a single LLM span in one step:

<CodeGroup>
  ```python Python theme={null}
  logger.add_single_llm_span_trace(
      input="What is the capital of France?",
      output="The capital of France is Paris.",
      model="gpt-4o",
      tools=None,
      name="Capital Query",
      duration_ns=1000000,
      metadata={"temperature": "0.7"},
      tags=["geography"],
      num_input_tokens=10,
      num_output_tokens=5,
      total_tokens=15
  )
  ```

  ```typescript TypeScript theme={null}
  galileoLogger.addSingleLlmSpanTrace({
      input: "What is the capital of France?",
      output: "The capital of France is Paris.",
      model: "gpt-4.1-mini",
      tools: [],
      name: "Capital Query",
      durationNs: 1000000,
      metadata: {"temperature": "0.7"},
      tags: ["geography"],
      numInputTokens: 10,
      numOutputTokens: 5,
      totalTokens: 15
  });
  ```
</CodeGroup>

See the [`add_single_llm_span_trace` Python SDK docs](/sdk-api/python/reference/logger/logger#add-single-llm-span-trace) or [`addSingleLlmSpanTrace` TypeScript SDK docs](/sdk-api/typescript/reference/README/classes/GalileoLogger#addsinglellmspantrace) for more details.

### Complex trace example

Here's an example of creating a more complex trace with multiple spans. The full Python code is available as `retriever-example.py` in [this folder](https://github.com/rungalileo/sdk-examples/tree/main/python/logging-samples/galileologger).

<CodeGroup>
  ```python Python theme={null}
  from galileo import GalileoLogger

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

  # Start a trace for a user query
  trace = logger.start_trace(
      input="Who's a good bot?",
      name="User Query",
      tags=["bot-interaction"]
  )

  # Add a retriever span for document retrieval
  logger.add_retriever_span(
      input="Who's a good bot?",
      output=["Research shows that I am a good bot."],
      name="Document Retrieval",
      duration_ns=1000000
  )

  # Add an LLM span for generating a response
  logger.add_llm_span(
      input="Who's a good bot?",
      output="I am!",
      model="gpt-4o",
      name="Response Generation",
      num_input_tokens=25,
      num_output_tokens=3,
      total_tokens=28,
      duration_ns=1000000
  )

  # Conclude the trace
  logger.conclude(output="I am!", duration_ns=2000000)

  # Flush the trace to Galileo
  logger.flush()
  ```

  ```typescript TypeScript theme={null}
  import { GalileoLogger } from "galileo";

  const galileoLogger = new GalileoLogger({
      projectName: "my-project",
      logStreamName: "my-log-stream",
  });

  // Start a trace for a user query
  const trace = galileoLogger.startTrace({
      input: "Who's a good bot?",
      name: "User Query",
      tags: ["bot-interaction"]
  });

  // Add a retriever span for document retrieval
  galileoLogger.addRetrieverSpan({
      input: "Who's a good bot?",
      output: ["Research shows that I am a good bot."],
      name: "Document Retrieval",
      durationNs: 1000000
  });

  // Add an LLM span for generating a response
  galileoLogger.addLlmSpan({
      input: "Who's a good bot?",
      output: "I am!",
      model: "gpt-4.1-mini",
      name: "Response Generation",
      numInputTokens: 25,
      numOutputTokens: 3,
      totalTokens: 28,
      durationNs: 1000000
  });

  // Conclude the trace
  galileoLogger.conclude({
      output: "I am!",
      durationNs: 2000000
  })

  // Flush the trace to Galileo
  galileoLogger.flush();
  ```
</CodeGroup>

## Best practices

1. **Use higher-level abstractions when possible**: The `@log` decorator and wrappers are easier to use and less error-prone.
2. **Flush traces when appropriate**: Call `flush()` at the end of a request or user interaction to ensure data is sent to Galileo.
3. **Include relevant metadata**: Add tags and metadata to make it easier to filter and analyze your traces.
4. **Structure spans logically**: Create a span hierarchy that reflects the logical structure of your application.
5. **Handle errors gracefully**: Include status codes and error information in your spans to help with debugging.

## Next steps

### Basic logging components

<CardGroup cols={2}>
  <Card title="Log decorator" icon="code" horizontal href="/sdk-api/logging/log-decorator/log-decorator">
    Quickly add logging to your code with the log decorator and wrapper.
  </Card>

  <Card title="Galileo context" icon="code" horizontal href="/sdk-api/logging/galileo-context">
    Manage logging using the Galileo context manager.
  </Card>
</CardGroup>

### Integrations with third-party SDKs

<CardGroup cols={2}>
  <Card title="OpenAI wrapper" icon="code" horizontal href="/sdk-api/third-party-integrations/openai/openai">
    Automatically log calls to the OpenAI SDK with a wrapper.
  </Card>

  <Card title="OpenAI Agents trace processor" icon="code" horizontal href="/sdk-api/third-party-integrations/openai-agents/openai-agents">
    Automatically log all the steps in your OpenAI Agent SDK apps using the Galileo trace processor.
  </Card>

  <Card title="LangChain callback" icon="code" horizontal href="/sdk-api/third-party-integrations/langchain/langchain">
    Automatically log all the steps in your LangChain or LangGraph application with the Galileo callback.
  </Card>
</CardGroup>
