Skip to content

feat: Multi user context#196

Closed
monoxgas wants to merge 1 commit into
mainfrom
feat/multi-user-context
Closed

feat: Multi user context#196
monoxgas wants to merge 1 commit into
mainfrom
feat/multi-user-context

Conversation

@monoxgas
Copy link
Copy Markdown
Contributor

@monoxgas monoxgas commented Oct 3, 2025

Support tracking and exporting spans with api key overrides to support multi-user services

Key Changes

  • Reworks our span exporter to check for an override attribute and create a dedicated export instance for those spans - routing them per api key/user.
  • Added an dn.run(..., api_key=) argument and with dn.using_api_key() to override this context on demand.
  • Ensured that get_run_context carries this override information so if we have a backend stack passing around user-local context, it's reflected in the exports.

Example

import dreadnode as dn
import threading

OTHER_API_KEY = "..."


with dn.run("testing", project="context"):
    dn.log_input("x", 5)
    dn.log_output("z", 15)


def continue_run_in_thread(context):
    with dn.continue_run(context):
        dn.log_input("a", 10)
        dn.log_output("b", 20)

with dn.using_api_key(OTHER_API_KEY):
    with dn.run("other", project="context") as run:
        dn.log_input("y", 10)
        dn.log_output("y", 10)

        context = dn.get_run_context()
        
        thread = threading.Thread(target=continue_run_in_thread, args=(context,))
        thread.start()
        thread.join()

Generated Summary:

PR Description

This pull request introduces significant modifications to the SDK's tracing mechanism, enhancing support for multi-user scenarios by allowing the use of API keys for span exports.

  • Refactored the get_run_context method to simplify the extraction of run context data.
  • Introduced a new context manager, using_api_key, to facilitate temporary overriding of the API key used for exporting spans during nested operations.
  • Added api_key as an optional parameter to run and initialize methods, enabling context-specific tracing.
  • Replaced the BatchSpanProcessor with a new RoutingSpanProcessor that allows spans to be routed based on user-specific tokens.
  • Updated the RunContext structure to include export_auth_token to maintain API key information across different contexts.
  • Cleaned up unused imports and comments related to OpenTelemetry integrations.

These changes enable more flexible tracing capabilities and improve the SDK's usability in multi-user applications, allowing for controlled export configurations based on individual API keys.

This summary was generated with ❤️ by rigging

@dreadnode-renovate-bot dreadnode-renovate-bot Bot added area/docs Changes to documentation and guides type/docs Documentation updates and improvements labels Oct 3, 2025
@monoxgas monoxgas requested a review from Copilot October 3, 2025 04:53
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

Introduces multi-user context support to enable tracking and exporting spans with API key overrides, allowing services to handle multiple users with dedicated export instances per API key.

  • Added RoutingSpanProcessor to route spans based on user-specific API keys instead of using a single BatchSpanProcessor
  • Introduced using_api_key() context manager and api_key parameter to run() for per-user span export control
  • Enhanced RunContext to include export authentication token for cross-thread/process context continuity

Reviewed Changes

Copilot reviewed 6 out of 6 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
dreadnode/tracing/span.py Added export auth token context management and updated RunSpan to support API key overrides
dreadnode/tracing/processors.py New RoutingSpanProcessor for multi-user span routing based on API keys
dreadnode/tracing/constants.py Added constant for span resource attribute token
dreadnode/main.py Replaced BatchSpanProcessor with RoutingSpanProcessor and added using_api_key context manager
dreadnode/init.py Exported using_api_key function
docs/sdk/main.mdx Updated documentation to reflect new API key functionality

Tip: Customize your code reviews with copilot-instructions.md. Create the file or learn how to get started.

Comment thread dreadnode/tracing/span.py
Comment on lines +326 to 335
class RunContext(te.TypedDict, total=False):
"""Context for transferring and continuing runs in other places."""

run_id: str
run_name: str
project: str
trace_context: dict[str, str]
export_auth_token: str | None


Copy link

Copilot AI Oct 3, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Changing RunContext from a required TypedDict to total=False makes all fields optional, which could break existing code that assumes required fields like 'run_id' are always present. Consider using separate required and optional field groups or create a new TypedDict for the optional fields.

Suggested change
class RunContext(te.TypedDict, total=False):
"""Context for transferring and continuing runs in other places."""
run_id: str
run_name: str
project: str
trace_context: dict[str, str]
export_auth_token: str | None
class RunContextBase(te.TypedDict):
"""Required fields for RunContext."""
run_id: str
run_name: str
project: str
trace_context: dict[str, str]
class RunContext(RunContextBase, total=False):
"""Context for transferring and continuing runs in other places, with optional fields."""
export_auth_token: str | None

Copilot uses AI. Check for mistakes.
server_url: str,
default_token: str,
*,
token_header_name: str = "X-Api-Key", # noqa: S107
Copy link

Copilot AI Oct 3, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The noqa comment suggests this is flagged as a security issue. Consider using a constant or configuration value instead of a hardcoded string literal for the API key header name.

Copilot uses AI. Check for mistakes.
Comment thread docs/sdk/main.mdx
Example

```python
with dreadnode.with_api_key("other_user_api_key"):
Copy link

Copilot AI Oct 3, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The example code uses dreadnode.with_api_key() but the actual function name is using_api_key(). This inconsistency will cause the example to fail.

Copilot uses AI. Check for mistakes.
Comment thread docs/sdk/main.mdx

Example:
~~~
with dreadnode.with_api_key("other_user_api_key"):
Copy link

Copilot AI Oct 3, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The documentation example uses with_api_key() but the actual function name is using_api_key(). This inconsistency will cause the example to fail.

Copilot uses AI. Check for mistakes.
@monoxgas monoxgas closed this Dec 2, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area/docs Changes to documentation and guides type/docs Documentation updates and improvements

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants