# Spans

A span represents a unit of work with defined *start* and *end* logs. Spans are useful when instrumenting blocks of time, e.g., "How long was a loading spinner displayed?"

=== "Android (kotlin)"

    ```kotlin
    val span = Logger.startSpan(
      "loading_spinner",
      LogLevel.INFO
      mapOf(),
    )

    // ...

    span?.end(SpanResult.SUCCESS, mapOf())

    // or:

    Logger.trackSpan("operation", LogLevel.INFO) {
      operation()
    }
    ```

=== "Android (Java)"

    ```java
    Optional<Span> span = Logger.startSpan(
      "loading_spinner",
      LogLevel.INFO,
      new HashMap(),
    )

    // ...

    span.ifPresent(s -> s.end(SpanResult.SUCCESS, new HashMap()))
    ```

=== "iOS (Swift)"

    ```swift
    let span = Logger.startSpan(
      name: "loading_spinner",
      level: .info,
      fields: [:]
    )

    // ...

    span?.end(.success, fields: [:])
    ```

The SDK calculates and attaches information about the span duration each time a span ends.

!!! info
    See the [Timeline Waterfalls](../../product/timeline/spans-visualization.md) section for seeing how this information is displayed in the product.

## Spans Hierarchy

Spans can be nested hierarchically by providing a parentID to the start call. The parent span ID is the ID of the span that started the child span.

```mermaid
graph TD
  A[Span A] --> B[Span B]
  A --> C[Span C]
  B --> D[Span D]
  C --> E[Span E]
```

In the example above, Span A is the parent of Spans B and C. Span B is the parent of Span D, and Span C is the parent of Span E.

This is specially useful when spans are rendered in the waterfall chart of the [Timeline](../../product/timeline/spans-visualization.md) view.

## Custom start & end time (advanced)

The SDK allows you to provide custom start and end times for spans. This is useful when you have a specific time source or timing heuristic that you want to use for your spans. These custom times are also used to display the logs in the correct position in the [Timeline view](../../product/timeline/session-view.md). When providing custom times, **you need to provide both the start and end times**, failing to provide one of them will result in the span being tracked using system time.

=== "Android (kotlin)"

    ```kotlin
    val span = Logger.startSpan(
      "loading_spinner",
      LogLevel.INFO,
      mapOf(),
      startTimeMs = 1234567890000L,
    )

    // ...

    span?.end(
      SpanResult.SUCCESS,
      mapOf(),
      endTimeMs = 1234567900000L,
    )
    ```
=== "iOS (Swift)"

    ```swift
    let span = Logger.startSpan(
      name: "loading_spinner",
      level: .info,
      fields: [:],
      startTimeInterval: 1234567890.0
    )
    // ...
    span?.end(.success, fields: [:], endTimeInterval: 1234567900.0)
    ```


!!! warning
    Please note that this is an advanced feature and should be used with caution, as workflows match in the order logs are received, regardless of the provided time.

{% raw %}
## Fields {#span-logs-fields}
{% endraw %}

Span logs contain multiple out-of-the-box fields outlined below.

### Span Start Fields

  | Field Name | Field Key | Example Values | Notes |
  |---|---|---|---|
  | Span Parent | `_span_parent_id` | foobar-7b3a-44c7-8c8e-47c5c15f2412 | Spans can be nested hirarchically. The parent span ID is the ID of the span that started the child span. |
  | Span ID | `_span_id` | 8bcbbef6-7b3a-44c7-8c8e-47c5c15f2412 | Each span start-end logs pair shares the same span ID value. |
  | Span Name | `_span_name` | `spinner_loading` ||
  | Span Type | `_span_type` | `start` ||

### Span Start End

  | Field Name | Field Key | Example Values | Notes |
  |---|---|---|---|
  | Duration | `_duration_ms` | 123 ||
  | Result | `_result` | `success`, `failure`, `canceled`, `unknown` | The span result |
  | Span Parent | `_span_parent_id` | foobar-7b3a-44c7-8c8e-47c5c15f2412 | Spans can be nested hirarchically. The parent span ID is the ID of the span that started the child span. |
  | Span ID | `_span_id` | 8bcbbef6-7b3a-44c7-8c8e-47c5c15f2412 | Each span start-end logs pair shares the same span ID value. |
  | Span Name | `_span_name` | `spinner_loading` ||
  | Span Type | `_span_type` | `end` ||
