-
Notifications
You must be signed in to change notification settings - Fork 13
chore!: Refactor OTel exporters to be signal-specific #125
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’ll 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 |
|---|---|---|
|
|
@@ -15,53 +15,70 @@ class ExporterProtocol(str, enum.Enum): | |
|
|
||
|
|
||
| @dataclasses.dataclass(frozen=True, kw_only=True) | ||
| class OtelConfig: | ||
| class ExporterConfig: | ||
| endpoint: str | ||
| protocol: str | ||
|
|
||
|
|
||
| @dataclasses.dataclass(frozen=True, kw_only=True) | ||
| class OtelConfig: | ||
| service_name: str | ||
| service_version: str | ||
| trace_exporter: ExporterConfig | None = None | ||
|
|
||
|
|
||
| def _resolve_exporter( | ||
| endpoint_var: str, | ||
| protocol_var: str, | ||
| ) -> ExporterConfig | None: | ||
| endpoint = os.environ.get(endpoint_var) | ||
| if not endpoint: | ||
| return None | ||
|
|
||
| protocol = os.environ.get(protocol_var, ExporterProtocol.GRPC) | ||
|
|
||
| if not endpoint.startswith(("http://", "https://")): | ||
| raise ValueError( | ||
| f"Invalid OTel endpoint format: {endpoint}. " | ||
| f"Expected format: http://<host>:<port> or https://<host>:<port>" | ||
| ) | ||
| try: | ||
| ExporterProtocol(protocol) | ||
| except ValueError: | ||
| raise ValueError( | ||
| f"Invalid OTel protocol: {protocol}. " | ||
| f"Expected values: {', '.join(e.value for e in ExporterProtocol)}" | ||
| ) | ||
|
|
||
| return ExporterConfig(endpoint=endpoint, protocol=protocol) | ||
|
|
||
|
|
||
| def resolve( | ||
| service_name: str | None = None, | ||
| service_version: str | None = None, | ||
| ) -> OtelConfig | None: | ||
| """Read and validate shared OTel configuration from environment variables. | ||
| """Read and validate OTel configuration from environment variables. | ||
|
|
||
| Returns None if OTel is not configured (no exporter endpoint set). | ||
| Raises ValueError if the configuration is invalid. | ||
| Returns None if no signals are configured (no exporter endpoints set). | ||
| Raises ValueError if any configured exporter has invalid settings. | ||
| """ | ||
| otel_endpoint = os.environ.get("TANGLE_OTEL_EXPORTER_ENDPOINT") | ||
| if not otel_endpoint: | ||
| return None | ||
|
|
||
| otel_protocol = os.environ.get( | ||
| "TANGLE_OTEL_EXPORTER_PROTOCOL", ExporterProtocol.GRPC | ||
| trace_exporter = _resolve_exporter( | ||
| endpoint_var="TANGLE_OTEL_TRACE_EXPORTER_ENDPOINT", | ||
| protocol_var="TANGLE_OTEL_TRACE_EXPORTER_PROTOCOL", | ||
| ) | ||
|
|
||
| if trace_exporter is None: | ||
| return None | ||
|
|
||
| if service_name is None: | ||
| app_env = os.environ.get("TANGLE_ENV", "unknown") | ||
| service_name = f"tangle-{app_env}" | ||
|
|
||
| if service_version is None: | ||
| service_version = os.environ.get("TANGLE_SERVICE_VERSION", "unknown") | ||
|
Collaborator
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. Do we have this env set today? what the versioning strategy do we use?
Collaborator
Author
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. Technically, it's up to the OSS user of Tangle (someone who clones and deploys Tangle themselves). They can use their commit shas, semantic versioning, whatever they feel is right. For our case, we use a revision (commit sha) provided by our CD platform. As for recommendations, we could add some to our documentation of this variable which is upstack. Suitable values would be build ids, URLs, or commit shas.
Collaborator
Author
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. PS: I'm not fully happy with the docs yet even after this full stack as it is now. I'd love to collaborate and hear ideas on how in-depth we want to go on docs and where our source of truth should be for metric information. |
||
|
|
||
| if not otel_endpoint.startswith(("http://", "https://")): | ||
| raise ValueError( | ||
| f"Invalid OTel endpoint format: {otel_endpoint}. " | ||
| f"Expected format: http://<host>:<port> or https://<host>:<port>" | ||
| ) | ||
| try: | ||
| ExporterProtocol(otel_protocol) | ||
| except ValueError: | ||
| raise ValueError( | ||
| f"Invalid OTel protocol: {otel_protocol}. " | ||
| f"Expected values: {', '.join(e.value for e in ExporterProtocol)}" | ||
| ) | ||
|
|
||
| return OtelConfig( | ||
| endpoint=otel_endpoint, | ||
| protocol=otel_protocol, | ||
| service_name=service_name, | ||
| service_version=service_version, | ||
| trace_exporter=trace_exporter, | ||
| ) | ||
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.
What are possible values for TANGLE_ENV? Where it is being set?
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 improve the documentation for this upstack but happy to answer here:
This is used as part of the service name for your OTel exports. This is literally your env, so
development,staging, etc.Alexey and I landed on this name for it in an earlier merged PR.