-
Notifications
You must be signed in to change notification settings - Fork 560
chore(remoteconfig): refresh client identity on runtime refresh #19818
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We鈥檒l occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -5,18 +5,21 @@ | |
| from typing import Optional | ||
| from typing import Sequence | ||
| import uuid | ||
| import weakref | ||
|
|
||
| import ddtrace | ||
| from ddtrace.internal import forksafe | ||
| from ddtrace.internal import gitmetadata | ||
| from ddtrace.internal import process_tags | ||
| from ddtrace.internal import runtime | ||
| from ddtrace.internal.hostname import get_hostname | ||
| from ddtrace.internal.logger import get_logger | ||
| from ddtrace.internal.packages import is_distribution_available | ||
| from ddtrace.internal.remoteconfig import ConfigMetadata | ||
| from ddtrace.internal.remoteconfig import Payload | ||
| from ddtrace.internal.remoteconfig import PayloadType | ||
| from ddtrace.internal.remoteconfig import RCCallback | ||
| from ddtrace.internal.runtime import get_runtime_id | ||
| from ddtrace.internal.runtime import on_runtime_id_change | ||
| from ddtrace.internal.settings._agent import config as agent_config | ||
| from ddtrace.internal.settings._core import DDConfig | ||
| from ddtrace.internal.telemetry import telemetry_writer | ||
|
|
@@ -98,6 +101,17 @@ def __init__(self) -> None: | |
| self._native: Optional[Any] = None | ||
| self._reader: Optional[Any] = None | ||
|
|
||
| client_ref = weakref.ref(self) | ||
|
|
||
| # Runtime keeps callbacks in a module-level set, so registering a bound | ||
| # method would keep this client alive after callers drop their reference. | ||
| def _on_identity_refresh(new_runtime_id: str) -> None: | ||
| client = client_ref() | ||
| if client is not None: | ||
| client._on_identity_refresh(new_runtime_id) | ||
|
|
||
| on_runtime_id_change(_on_identity_refresh) | ||
|
|
||
| def ensure_native(self) -> Any: | ||
| if self._native is None: | ||
| from ddtrace.internal.native import RemoteConfigClient as _NativeClient | ||
|
|
@@ -109,7 +123,7 @@ def ensure_native(self) -> Any: | |
| agent_url=str(self.agent_url), | ||
| tracer_version=tracer_version, | ||
| client_id=self.id, | ||
| runtime_id=runtime.get_runtime_id(), | ||
| runtime_id=get_runtime_id(), | ||
| service=ddtrace.config.service or "", | ||
| env=ddtrace.config.env or "", | ||
| app_version=ddtrace.config.version or "", | ||
|
|
@@ -125,6 +139,25 @@ def ensure_native(self) -> Any: | |
| def renew_id(self) -> None: | ||
| self.id = str(uuid.uuid4()) | ||
|
|
||
| def _on_identity_refresh(self, new_runtime_id: str) -> None: | ||
| # Regenerate the client id and drop the native client, which bakes both ids in | ||
| # as immutable constructor arguments (get_client_id() is documented "stable for | ||
| # the process lifetime"). The next ensure_native() call rebuilds it bound to the | ||
|
Comment on lines
+144
to
+145
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Given this definition of "stable for the process lifetime", the new changes to refresh the runtime id at runtime seem to go against this expectation. Should MicroVM be using a different identifier for this instead of runtime-id? Do we need to change all expectations in shared components in libdatadog and all repos to no longer assume runtime-id is process stable? which is mostly the changes we are making here |
||
| # fresh ids. Safe across threads: request() captures self._native into a local | ||
| # before calling .poll(), so an in-flight poll on the old client is unaffected. | ||
| # After fork, keep a reader over inherited SHM before dropping the inherited | ||
| # native client; otherwise forked consumers lose the only handles they can read. | ||
| if forksafe.is_fork_child(): | ||
| if self._native is not None and self._reader is None: | ||
| try: | ||
| self._reader = self._native.make_reader() | ||
| except Exception: | ||
| log.debug("failed to create remote config reader after fork", exc_info=True) | ||
| else: | ||
| self._reader = None | ||
| self.renew_id() | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
When Useful? React with 馃憤聽/ 馃憥.
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Remote Config data cannot match AppSec spans from a restored runtime. Assertion details
Was this helpful? React 馃憤 or 馃憥 |
||
| self._native = None | ||
|
litianningdatadog marked this conversation as resolved.
Comment on lines
+158
to
+159
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
When AGENTS.md reference: AGENTS.md:L135-L136 Useful? React with 馃憤聽/ 馃憥.
Comment on lines
+158
to
+159
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
When identity refresh overlaps the first Useful? React with 馃憤聽/ 馃憥. |
||
|
|
||
| def register_callback(self, product_name: "RemoteConfigProduct", callback: RCCallback) -> None: | ||
| self._product_callbacks[product_name] = callback | ||
| log.debug("[%s][P: %s] Registered callback for product %s", os.getpid(), os.getppid(), product_name) | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
we should probably just add a
remove_on_runtime_id_change(func)method, then this can all go away and we get: