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

# User Tracking

The Users view provides an overview of all users. It also offers an in-depth look into individual users.

It's easy to map data in ABV to individual users. Just pass a unique identifier as the `userId` when you create a `trace`. This can be a username, email, or any other unique identifier. The `userId` is optional, but using it helps you get more from ABV. See the integration docs to learn more.

## Implementation with Python SDK

Install package

```bash theme={null}
pip install abvdev
```

When using the @observe() decorator and initialization via constructor arguments:

```python theme={null}
from abvdev import observe
from abvdev import ABV

# ABV client initialization          
abv = ABV(
    api_key="sk-abv-...", # your api key here
    host="https://app.abv.dev", # host="https://eu.app.abv.dev", for EU region
)
 
@observe()
def process_request(): 
    # Add to the current trace
    abv.update_current_trace(user_id="user_12345")
 
    # ...your processing logic...
    return "Processing complete"


# call the function
process_request()
```

When creating spans directly:

```python theme={null}
from abvdev import ABV

# ABV client initialization          
abv = ABV(
    api_key="sk-abv-...", # your api key here
    host="https://app.abv.dev", # host="https://eu.app.abv.dev", for EU region
)
 
# You can set the user_id when creating the root span via update_trace
with abv.start_as_current_span(
    name="process-user-request"
) as root_span:
    # Add user_id to the trace
    root_span.update_trace(user_id="user_12345")
 
    # All spans in this trace will be associated with this user
    with root_span.start_as_current_observation(
        as_type='generation',
        name="generate-response",
        model="gpt-4o"
    ) as gen:
        # ...generate response...
        pass
```

You can also update the user\_id of the current trace without a direct reference to a span:

```python theme={null}
from abvdev import ABV

# ABV client initialization          
abv = ABV(
    api_key="sk-abv-...", # your api key here
    host="https://app.abv.dev", # host="https://eu.app.abv.dev", for EU region
)
 
with abv.start_as_current_span(name="handle-user-interaction"):
    # Add user_id to the current trace
    abv.update_current_trace(user_id="user_12345")
```

## Implementation with JS/TS SDK

**Install packages**

```bash theme={null}
npm install @abvdev/tracing @abvdev/otel @opentelemetry/sdk-node dotenv
```

**Add credentials**

Add your ABV credentials to your environment variables. Make sure that you have a `.env` file in your project root and a package like dotenv to load the variables.

<CodeblockTabs>
  .env

  ```typescript theme={null}
  ABV_API_KEY = "sk-abv-..."
  ABV_BASE_URL = "https://app.abv.dev" # US region
  //ABV_BASE_URL = "https://eu.app.abv.dev" # EU region
  ```
</CodeblockTabs>

Create`instrumentation.ts` file and use `dotenv` package to load the variables.

Additional parameters are provided to get trace visible in the UI immediately.

<CodeblockTabs>
  instrumentation.ts

  ```typescript theme={null}
  import dotenv from "dotenv";
  dotenv.config();

  import { NodeSDK } from "@opentelemetry/sdk-node";
  import { ABVSpanProcessor } from "@abvdev/otel";

  const sdk = new NodeSDK({
    spanProcessors: [
      new ABVSpanProcessor({
        apiKey: process.env.ABV_API_KEY,
        baseUrl: process.env.ABV_BASE_URL,
        exportMode: "immediate",
        flushAt: 1,
        flushInterval: 1,
        additionalHeaders: {
          "Content-Type": "application/json",
          "Accept": "application/json"
        }
      })
    ],
  });

  sdk.start();
  ```
</CodeblockTabs>

Import the `instrumentation.ts` file at the top of your application.

**When using the context manager:**

```typescript theme={null}
import "./instrumentation"; // Must be the first import

import {
  startActiveObservation,
  startObservation,
  updateActiveTrace,
} from "@abvdev/tracing";
 
async function main() {
    await startActiveObservation("context-manager", async (span) => {
        span.update({
            input: { query: "What is the capital of France?" },
        });
        
        updateActiveTrace({
            userId: "user-123",
        });
    });
}

main();
```

**When using the **`observe`** wrapper:**

```typescript theme={null}
import "./instrumentation"; // Must be the first import
import { observe, updateActiveTrace } from "@abvdev/tracing";
 
// An existing function
async function fetchData(source: string) {
  updateActiveTrace({
    userId: "user-123",
  });
 
  // ... logic to fetch data
  return { data: `some data from ${source}` };
}
 
// Wrap the function to trace it
const tracedFetchData = observe(fetchData, {
  name: "observe-wrapper",
});
 
async function main() {
    const result = await tracedFetchData("API");
}

main();
```

**When creating spans manually:**

```typescript theme={null}
import "./instrumentation"; // Must be the first import
import { startObservation } from "@abvdev/tracing";
 
const span = startObservation("manual-observation", {
  input: { query: "What is the capital of France?" },
});
 
span.updateTrace({
  userId: "user-123",
});
 
span.update({ output: "Paris" }).end();
```

See [JS/TS SDK docs](/developer/sdks/js-ts/overview) for more details.

## View all users

The user list provides an overview of all users that have been tracked by ABV. It makes it simple to segment by overall token usage, number of traces, and user feedback.

<img src="https://mintlify.s3.us-west-1.amazonaws.com/abv-2be93c70/images/7O1_3sr6mWoUwjsHaTQCg_image.png" alt="" />

## Individual user view

The individual user view provides an in-depth look into a single user. Explore aggregated metrics or view all traces and feedback for a user.

You can deep link to this view via the following URL format: `https://<hostname>/project/{projectId}/users/{userId}`
