Skip to content

feat(err): add context manager and tag functions#239

Merged
oliverb123 merged 35 commits intomasterfrom
err/scopes-and-tags
Jun 6, 2025
Merged

feat(err): add context manager and tag functions#239
oliverb123 merged 35 commits intomasterfrom
err/scopes-and-tags

Conversation

@oliverb123
Copy link
Contributor

We've been hacking around this internally with tag_queries for a while, but we should just actually support it properly in the SDK.

@oliverb123 oliverb123 requested review from a team, daibhin and hpouillot June 5, 2025 09:45
Copy link
Contributor

@greptile-apps greptile-apps bot left a comment

Choose a reason for hiding this comment

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

PR Summary

Added error tracking enhancements with new context management and tagging capabilities to the PostHog Python SDK.

  • Introduced thread-local context management via posthog.new_context() and a @posthog.tracked decorator for adding metadata to exceptions
  • Implemented duplicate capture prevention using __posthog_exception_captured flag in client.py
  • Warning: Thread-local storage in scopes.py may not be suitable for async contexts and could cause memory leaks in long-running apps
  • Issue: Nested contexts completely override parent tags instead of inheriting them, which may lead to lost context
  • Risk: Potential circular import in scopes.py when importing posthog inside the tracked decorator

6 file(s) reviewed, 2 comment(s)
Edit PR Review Bot Settings | Greptile

@oliverb123 oliverb123 requested review from daibhin and pauldambra June 6, 2025 11:05
Comment on lines +470 to +473
# Grab current context tags, if any exist
context_tags = get_tags()
if context_tags:
properties.update(context_tags)
Copy link
Member

Choose a reason for hiding this comment

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

this placement is cool
since it looks to me like i can set a super property
and then use context to override it sometimes

that is pleasing

Copy link
Member

@pauldambra pauldambra left a comment

Choose a reason for hiding this comment

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

i'm invested in getting my other PR in so 🚢 🚢 🚢 🚢 🚢

(thanks for moving context to capture, i think that will super powerful)

Copy link
Contributor

@daibhin daibhin left a comment

Choose a reason for hiding this comment

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

Epic stuff!! Think a lot of my questions & points you worked through with Paul yesterday.

Left one comment about whether tags should live on the client. I'm sure whatever we choose someone will want the alternative. Also happy to go with the approach as it is now for simplicity sake and can revisit if necessary

@@ -0,0 +1,120 @@
import contextvars
Copy link
Contributor

Choose a reason for hiding this comment

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

In our query_tagging.py we just rely on thread_local_storage = threading.local() to manage the contexts. I don't know much about the Python runtime / API but this sounds more correct to me. Do you know of any reason to use local threading or should we just not be using that in the Django app?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

We should be using contextvars I think, but since we don't use async python in our django app (as far as I know?) I think it doesn't make a huge difference.

Co-authored-by: David Newell <d.newell1@outlook.com>
@oliverb123 oliverb123 merged commit 243b98d into master Jun 6, 2025
6 checks passed
@oliverb123 oliverb123 deleted the err/scopes-and-tags branch June 6, 2025 11:49
tag = tag
get_tags = get_tags
clear_tags = clear_tags
tracked = scoped
Copy link
Contributor

Choose a reason for hiding this comment

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

Did you mean for tracked to be different to scoped? It means things like @posthoganalytics.scoped in the example should actually be @posthoganalytics.tracked

Copy link
Contributor Author

@oliverb123 oliverb123 Jun 11, 2025

Choose a reason for hiding this comment

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

GAH

I went back and forth a few times on the name and ended up with scoped, but I guess I never fixed the export 🤦

Copy link
Contributor Author

Choose a reason for hiding this comment

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

We can probably stamp a quick release with the change - it's breaking, but I think that's ok if we catch it fast enough

Copy link
Contributor

Choose a reason for hiding this comment

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

Yeah totally fine to call it a fix. Pretty sure we're the only ones using it given it's not even a week old or documented yet

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants

Comments