Skip to content
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

Fix ReceiverProtocols confusion #13

Merged
merged 22 commits into from
Jul 30, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,5 @@ __pycache__/
.idea
.vscode/
*.egg-info/
cos-tool-*
cos-tool-*
src/prometheus_alert_rules/consolidated_rules/**
13 changes: 13 additions & 0 deletions charmcraft.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,11 @@ provides:


requires:
self-tracing:
interface: tracing
description: |
Integration to enable Tempo to send its own traces to another Tempo instance.
limit: 1
s3:
interface: s3
limit: 1
Expand Down Expand Up @@ -136,3 +141,11 @@ config:
description: Force-enable the receiver for the 'otlp_http' protocol in Tempo, even if there is no integration currently requesting it.
type: boolean
default: false
always_enable_jaeger_thrift_http:
description: Force-enable the receiver for the 'jaeger_thrift_http' protocol in Tempo, even if there is no integration currently requesting it.
type: boolean
default: false
always_enable_jaeger_grpc:
description: Force-enable the receiver for the 'jaeger_grpc' protocol in Tempo, even if there is no integration currently requesting it.
type: boolean
default: false
17 changes: 7 additions & 10 deletions lib/charms/tempo_k8s/v2/tracing.py
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ def __init__(self, *args):

# Increment this PATCH version before using `charmcraft publish-lib` or reset
# to 0 if you are raising the major API version
LIBPATCH = 7
LIBPATCH = 8

PYDEPS = ["pydantic"]

Expand All @@ -116,14 +116,13 @@ def __init__(self, *args):
DEFAULT_RELATION_NAME = "tracing"
RELATION_INTERFACE_NAME = "tracing"

# Supported list rationale https://github.com/canonical/tempo-coordinator-k8s-operator/issues/8
ReceiverProtocol = Literal[
"zipkin",
"kafka",
"opencensus",
"tempo_http",
"tempo_grpc",
"otlp_grpc",
"otlp_http",
"jaeger_grpc",
"jaeger_thrift_http",
]

RawReceiver = Tuple[ReceiverProtocol, str]
Expand All @@ -141,14 +140,12 @@ class TransportProtocolType(str, enum.Enum):
grpc = "grpc"


receiver_protocol_to_transport_protocol = {
receiver_protocol_to_transport_protocol: Dict[ReceiverProtocol, TransportProtocolType] = {
"zipkin": TransportProtocolType.http,
"kafka": TransportProtocolType.http,
"opencensus": TransportProtocolType.http,
"tempo_http": TransportProtocolType.http,
"tempo_grpc": TransportProtocolType.grpc,
"otlp_grpc": TransportProtocolType.grpc,
"otlp_http": TransportProtocolType.http,
"jaeger_thrift_http": TransportProtocolType.http,
"jaeger_grpc": TransportProtocolType.grpc,
}
"""A mapping between telemetry protocols and their corresponding transport protocol.
"""
Expand Down
87 changes: 69 additions & 18 deletions scripts/tracegen.py
Original file line number Diff line number Diff line change
@@ -1,47 +1,98 @@
import os
import time
from pathlib import Path
from typing import Any, Literal
from typing import Any, Literal, get_args
import requests

from opentelemetry import trace
from opentelemetry.exporter.otlp.proto.grpc.trace_exporter import OTLPSpanExporter as GRPCExporter
from opentelemetry.exporter.otlp.proto.http.trace_exporter import OTLPSpanExporter as HTTPExporter
from opentelemetry.exporter.zipkin.json import ZipkinExporter
from opentelemetry.exporter.jaeger.thrift import JaegerExporter as JaegerThriftHttpExporter
from opentelemetry.exporter.jaeger.proto.grpc import JaegerExporter as JaegerGRPCExporter
from opentelemetry.sdk.resources import Resource
from opentelemetry.sdk.trace import TracerProvider
from opentelemetry.sdk.trace.export import (
BatchSpanProcessor,
ConsoleSpanExporter,
)

ReceiverProtocol = Literal[
"zipkin",
"otlp_grpc",
"otlp_http",
"jaeger_grpc",
"jaeger_thrift_http",
]

def set_envvars(cert: Path = None):
ca_cert_path = str(Path(cert).absolute()) if cert else ""
os.environ['OTEL_EXPORTER_OTLP_TRACES_CERTIFICATE'] = ca_cert_path
os.environ['OTEL_EXPORTER_JAEGER_CERTIFICATE'] = ca_cert_path
# jaeger thrift http exporter does not expose a parameter to set path for CA verification
os.environ['SSL_CERT_FILE'] = ca_cert_path
os.environ["REQUESTS_CA_BUNDLE"] = ca_cert_path

def initialize_exporter(protocol: str, endpoint: str, cert: Path = None):
# ip:4317
if protocol == "otlp_grpc":
return GRPCExporter(
endpoint=endpoint,
insecure=not cert,
)
# scheme://ip:4318/v1/traces
elif protocol == "otlp_http":
return HTTPExporter(
endpoint=endpoint,
)
# scheme://ip:9411/v1/traces
elif protocol == "zipkin":
# zipkin does not expose an arg to pass certificate
session = requests.Session()
if cert:
session.verify = cert
return ZipkinExporter(
endpoint=endpoint,
session=session,
)
# scheme://ip:14268/api/traces?format=jaeger.thrift
elif protocol == "jaeger_thrift_http":
return JaegerThriftHttpExporter(
collector_endpoint=endpoint,
)
# ip:14250
elif protocol == "jaeger_grpc":
return JaegerGRPCExporter(
collector_endpoint = endpoint,
insecure=not cert,
)
else:
raise ValueError(f"Unsupported protocol: {protocol}")

def emit_trace(
endpoint: str,
log_trace_to_console: bool = False,
cert: Path = None,
protocol: Literal["grpc", "http", "ALL"] = "grpc",
protocol: ReceiverProtocol = "otlp_http",
nonce: Any = None
):
os.environ['OTEL_EXPORTER_OTLP_TRACES_CERTIFICATE'] = str(Path(cert).absolute()) if cert else ""
if protocol == "ALL":
for proto in get_args(protocol):
emit_trace(endpoint, log_trace_to_console, cert, proto, nonce=nonce)
michaeldmitry marked this conversation as resolved.
Show resolved Hide resolved
else:
set_envvars(cert)
span_exporter = initialize_exporter(protocol, endpoint, cert)
return _export_trace(span_exporter, log_trace_to_console=log_trace_to_console, nonce=nonce, protocol = protocol)

if protocol == "grpc":
span_exporter = GRPCExporter(
endpoint=endpoint,
insecure=not cert,
)
elif protocol == "http":
span_exporter = HTTPExporter(
endpoint=endpoint,
)
else: # ALL
return (emit_trace(endpoint, log_trace_to_console, cert, "grpc", nonce=nonce) and
emit_trace(endpoint, log_trace_to_console, cert, "http", nonce=nonce))


return _export_trace(span_exporter, log_trace_to_console=log_trace_to_console, nonce=nonce)




def _export_trace(span_exporter, log_trace_to_console: bool = False, nonce: Any = None):
def _export_trace(span_exporter, log_trace_to_console: bool = False, nonce: Any = None, protocol: ReceiverProtocol = "otlp_http"):
resource = Resource.create(attributes={
"service.name": "tracegen",
"service.name": f"tracegen-{protocol}",
"nonce": str(nonce)
}
)
Expand Down
Loading
Loading