Skip to content

Commit

Permalink
opentelemetry: instrument OSBS base task
Browse files Browse the repository at this point in the history
We are initilizing opentelemetry libraries at
the start of every task.

This will allow us to get traces of all HTTP requests
made in different tasks.

* MMENG-3834

Signed-off-by: Harsh Modi <hmodi@redhat.com>
  • Loading branch information
hjmodi committed Sep 13, 2023
1 parent 0ed6e07 commit a31e9e3
Show file tree
Hide file tree
Showing 11 changed files with 288 additions and 12 deletions.
2 changes: 2 additions & 0 deletions atomic_reactor/constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,8 @@
IMAGE_TYPE_OCI = 'oci'
IMAGE_TYPE_OCI_TAR = 'oci-tar'

OTEL_SERVICE_NAME = 'osbs'

PLUGIN_KOJI_PROMOTE_PLUGIN_KEY = 'koji_promote'
PLUGIN_KOJI_IMPORT_PLUGIN_KEY = 'koji_import'
PLUGIN_KOJI_IMPORT_SOURCE_CONTAINER_PLUGIN_KEY = 'koji_import_source_container'
Expand Down
8 changes: 8 additions & 0 deletions atomic_reactor/schemas/source_containers_user_params.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,14 @@
"kind": {"type": "string"},
"koji_target": {"type": "string"},
"koji_task_id": {"type": "integer"},
"opentelemetry_info": {
"type": "object",
"properties": {
"traceparent": {"type": ["string", "null"]},
"otel_url": {"type": ["string", "null"]}
},
"additionalProperties": false
},
"reactor_config_map": {"type": "string"},
"scratch": {"type": "boolean"},
"signing_intent": {"type": "string"},
Expand Down
8 changes: 8 additions & 0 deletions atomic_reactor/schemas/user_params.json
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,14 @@
"koji_task_id": {"type": "integer"},
"name": {"type": "string"},
"operator_csv_modifications_url": {"type": "string"},
"opentelemetry_info": {
"type": "object",
"properties": {
"traceparent": {"type": ["string", "null"]},
"otel_url": {"type": ["string", "null"]}
},
"additionalProperties": false
},
"platform": {"type": "string"},
"platforms": {
"type": "array",
Expand Down
43 changes: 40 additions & 3 deletions atomic_reactor/tasks/common.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,20 +7,28 @@
"""

import abc
import signal
import json
import logging
import os
import signal
from dataclasses import dataclass
from functools import cached_property
from pathlib import Path
from typing import Dict, Any, ClassVar, Generic, TypeVar, Optional
from functools import cached_property

from opentelemetry.instrumentation.requests import RequestsInstrumentor
from otel_extensions import TelemetryOptions, init_telemetry_provider, get_tracer

from atomic_reactor import config
from atomic_reactor import dirs
from atomic_reactor import inner
from atomic_reactor import source
from atomic_reactor import util
from atomic_reactor.constants import OTEL_SERVICE_NAME
from atomic_reactor.plugin import TaskCanceledException

logger = logging.getLogger(__name__)


def write_task_result(output_file, msg):
with open(output_file, 'w') as f:
Expand Down Expand Up @@ -88,6 +96,7 @@ class Task(abc.ABC, Generic[ParamsT]):
ignore_sigterm: ClassVar[bool] = False
# Automatically save context data before exiting? (Note: do not use for parallel tasks)
autosave_context_data: ClassVar[bool] = True
task_name = 'default'

def __init__(self, params: ParamsT):
"""Initialize a Task."""
Expand Down Expand Up @@ -122,7 +131,35 @@ def run(self, *args, **kwargs):
else:
signal.signal(signal.SIGTERM, self.throw_task_canceled_exception)

result = self.execute(*args, **kwargs)
opentelemetry_info = self._params.user_params.get('opentelemetry_info', {})
traceparent = opentelemetry_info.get('traceparent', None)
otel_url = opentelemetry_info.get('otel_url', None)

span_exporter = ''
otel_protocol = 'http/protobuf'
if not otel_url:
otel_protocol = 'custom'
span_exporter = '"opentelemetry.sdk.trace.export.ConsoleSpanExporter"'

if traceparent:
os.environ['TRACEPARENT'] = traceparent
logger.info('traceparent is set to %s', traceparent)
otel_options = TelemetryOptions(
OTEL_SERVICE_NAME=OTEL_SERVICE_NAME,
OTEL_EXPORTER_CUSTOM_SPAN_EXPORTER_TYPE=span_exporter,
OTEL_EXPORTER_OTLP_ENDPOINT=otel_url,
OTEL_EXPORTER_OTLP_PROTOCOL=otel_protocol,
)
init_telemetry_provider(otel_options)

RequestsInstrumentor().instrument()

span_name = self.task_name
if hasattr(self._params, 'platform'):
span_name += '_' + self._params.platform
tracer = get_tracer(module_name=span_name, service_name=OTEL_SERVICE_NAME)
with tracer.start_as_current_span(span_name):
result = self.execute(*args, **kwargs)
if self._params.task_result:
write_task_result(self._params.task_result, json.dumps(result))

Expand Down
1 change: 0 additions & 1 deletion atomic_reactor/tasks/plugin_based.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,6 @@ class PluginBasedTask(Task[ParamsT]):
# {"name": "add_filesystem", "args": {...}}
# Refer to plugins.json schema for the details.
plugins_conf: ClassVar[List[Dict[str, Any]]] = []
task_name = 'default'

def prepare_workflow(self) -> inner.DockerBuildWorkflow:
"""Fully initialize the workflow instance to be used for running the list of plugins."""
Expand Down
8 changes: 8 additions & 0 deletions otel-requirements.in
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
calver
hatchling
opentelemetry-api
opentelemetry-exporter-otlp
opentelemetry-instrumentation-requests
opentelemetry-sdk
otel-extensions
urllib3 < 2.0
112 changes: 112 additions & 0 deletions otel-requirements.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
#
# This file is autogenerated by pip-compile with Python 3.8
# by the following command:
#
# pip-compile --output-file=otel-requirements.txt otel-requirements.in
#
backoff==2.2.1
# via
# opentelemetry-exporter-otlp-proto-grpc
# opentelemetry-exporter-otlp-proto-http
calver==2022.6.26
# via -r otel-requirements.in
certifi==2023.7.22
# via requests
charset-normalizer==3.2.0
# via requests
deprecated==1.2.14
# via
# opentelemetry-api
# opentelemetry-exporter-otlp-proto-grpc
# opentelemetry-exporter-otlp-proto-http
editables==0.5
# via hatchling
googleapis-common-protos==1.60.0
# via
# opentelemetry-exporter-otlp-proto-grpc
# opentelemetry-exporter-otlp-proto-http
grpcio==1.57.0
# via opentelemetry-exporter-otlp-proto-grpc
hatchling==1.18.0
# via -r otel-requirements.in
idna==3.4
# via requests
importlib-metadata==6.8.0
# via opentelemetry-api
opentelemetry-api==1.19.0
# via
# -r otel-requirements.in
# opentelemetry-exporter-otlp-proto-grpc
# opentelemetry-exporter-otlp-proto-http
# opentelemetry-instrumentation
# opentelemetry-instrumentation-requests
# opentelemetry-sdk
# otel-extensions
opentelemetry-exporter-otlp==1.19.0
# via -r otel-requirements.in
opentelemetry-exporter-otlp-proto-common==1.19.0
# via
# opentelemetry-exporter-otlp-proto-grpc
# opentelemetry-exporter-otlp-proto-http
opentelemetry-exporter-otlp-proto-grpc==1.19.0
# via opentelemetry-exporter-otlp
opentelemetry-exporter-otlp-proto-http==1.19.0
# via opentelemetry-exporter-otlp
opentelemetry-instrumentation==0.40b0
# via opentelemetry-instrumentation-requests
opentelemetry-instrumentation-requests==0.40b0
# via -r otel-requirements.in
opentelemetry-proto==1.19.0
# via
# opentelemetry-exporter-otlp-proto-common
# opentelemetry-exporter-otlp-proto-grpc
# opentelemetry-exporter-otlp-proto-http
opentelemetry-sdk==1.19.0
# via
# -r otel-requirements.in
# opentelemetry-exporter-otlp-proto-grpc
# opentelemetry-exporter-otlp-proto-http
# otel-extensions
opentelemetry-semantic-conventions==0.40b0
# via
# opentelemetry-instrumentation-requests
# opentelemetry-sdk
opentelemetry-util-http==0.40b0
# via opentelemetry-instrumentation-requests
otel-extensions==0.2.5
# via -r otel-requirements.in
packaging==23.1
# via hatchling
pathspec==0.11.2
# via hatchling
pluggy==1.3.0
# via hatchling
protobuf==4.24.2
# via
# googleapis-common-protos
# opentelemetry-proto
pydantic==1.10.12
# via otel-extensions
requests==2.31.0
# via opentelemetry-exporter-otlp-proto-http
tomli==2.0.1
# via hatchling
trove-classifiers==2023.8.7
# via hatchling
typing-extensions==4.7.1
# via
# opentelemetry-sdk
# pydantic
urllib3==1.26.16
# via
# -r otel-requirements.in
# requests
wrapt==1.15.0
# via
# deprecated
# opentelemetry-instrumentation
zipp==3.16.2
# via importlib-metadata

# The following packages are considered to be unsafe in a requirements file:
# setuptools
1 change: 1 addition & 0 deletions requirements-devel.in
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
-r requirements.in
-r otel-requirements.in
-r tests/requirements.in
pyflakes
pep8
Loading

0 comments on commit a31e9e3

Please sign in to comment.