-
Notifications
You must be signed in to change notification settings - Fork 8
support opentelemetry python #42
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 2 commits
66666eb
8f08af7
5539f6b
64e4329
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 |
|---|---|---|
| @@ -0,0 +1,11 @@ | ||
| venv/ | ||
| __pycache__/ | ||
| kieker-lang-pack-python/ | ||
| results/ | ||
| config.ini | ||
| *.log | ||
| *.bak | ||
| *.zip | ||
| results-OpenTelemetry-python/ | ||
| .DS_Store | ||
| zipkin.jar |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,36 @@ | ||
| DIR=$(cd "$(dirname "$0")" && pwd) | ||
| source "$DIR/config.rc" | ||
| source "$DIR/labels.sh" | ||
| source "$DIR/functions.sh" | ||
| source "$DIR/../../common-functions.sh" | ||
|
|
||
| echo " # Preparing Environment..." | ||
| if [ -d "$VENV_DIR" ]; then rm -rf "$VENV_DIR"; fi | ||
|
|
||
| # For windows compatibility | ||
| if command -v python3 &>/dev/null; then | ||
| PYTHON_EXE=python3 | ||
| else | ||
| PYTHON_EXE=python | ||
| fi | ||
|
|
||
| $PYTHON_EXE -m venv "$VENV_DIR" | ||
| source "$VENV_DIR/bin/activate" | ||
|
|
||
| pip install -q --upgrade pip | ||
| pip install -q -r "$REQUIREMENTS_FILE" | ||
| opentelemetry-bootstrap -a install | ||
|
|
||
| cp "$CONFIG_TEMPLATE" "$CONFIG_FILE" | ||
|
|
||
| export NUM_OF_LOOPS=${NUM_OF_LOOPS:-10} | ||
| export TOTAL_NUM_OF_CALLS=${TOTAL_NUM_OF_CALLS:-2000000} | ||
| export RECURSION_DEPTH=${RECURSION_DEPTH:-10} | ||
| export METHOD_TIME=${METHOD_TIME:-0} | ||
| export SLEEP_TIME=${SLEEP_TIME:-15} | ||
|
|
||
| echo " # Starting Benchmark with $NUM_OF_LOOPS loops" | ||
| executeAllLoops | ||
|
|
||
| deactivate | ||
| echo " # Completed." |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,10 @@ | ||
| [Benchmark] | ||
| total_calls = 2000000 | ||
| recursion_depth = 10 | ||
| method_time = 0 | ||
| config_path = /tmp/monitoring.ini | ||
| inactive = False | ||
| # so it doesn't use kieker instrumentation | ||
| instrumentation_on = False | ||
| approach = 1 | ||
| output_filename = results.csv |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,34 @@ | ||
| # OpenTelemetry-python configuration | ||
|
|
||
| # 1. Resolve Paths | ||
| RAW_BASE_DIR=$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd) | ||
|
|
||
| if command -v cygpath &>/dev/null; then | ||
| BASE_DIR=$(cygpath -w "$RAW_BASE_DIR") | ||
| RAW_MAIN_DIR="$RAW_BASE_DIR/../../" | ||
| MAIN_DIR=$(cygpath -w "$RAW_MAIN_DIR") | ||
| PYTHON_BIN="python" | ||
| else | ||
| BASE_DIR="$RAW_BASE_DIR" | ||
| MAIN_DIR="$RAW_BASE_DIR/../../" | ||
| PYTHON_BIN="python3" | ||
| fi | ||
|
|
||
| if [ -f "${MAIN_DIR}/config.rc" ]; then | ||
| source "${MAIN_DIR}/config.rc" | ||
| fi | ||
|
|
||
| # 3. Directories & Files | ||
| export VENV_DIR="$BASE_DIR/venv" | ||
| export REQUIREMENTS_FILE="$BASE_DIR/requirements.txt" | ||
| export CONFIG_TEMPLATE="$BASE_DIR/config.ini.template" | ||
|
||
| export CONFIG_FILE="$BASE_DIR/config.ini" | ||
|
|
||
| # Standardized Naming | ||
| export RESULTS_DIR="$BASE_DIR/results-OpenTelemetry-python" | ||
| export RAWFN="$RESULTS_DIR/raw" | ||
|
|
||
| # Tool Path (Renamed per reviewer request) | ||
| export MOOBENCH_BIN_PY="$MAIN_DIR/tools/pybenchmark/benchmark.py" | ||
|
|
||
| mkdir -p "$RAW_BASE_DIR/results-OpenTelemetry-python" | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,85 @@ | ||
| export RECURSION_DEPTH="${RECURSION_DEPTH:-10}" | ||
|
||
|
|
||
| # helper to inject filename | ||
| function updateConfigFilename { | ||
| local filename=$1 | ||
| grep -v "output_filename" "$CONFIG_TEMPLATE" > "$CONFIG_FILE" | ||
| echo "output_filename = $filename" >> "$CONFIG_FILE" | ||
| } | ||
|
|
||
| function get_os_path { | ||
| local raw_path=$1 | ||
| if command -v cygpath &>/dev/null; then cygpath -w "$raw_path"; else echo "$raw_path"; fi | ||
| } | ||
|
|
||
| function runNoInstrumentation { | ||
| local k=$1 | ||
| local i=$2 | ||
|
|
||
| # use the global RESULTS_DIR directly (Fixes the /output read-only error) | ||
| local RAW_CSV="${RAWFN}-${i}-${RECURSION_DEPTH}-${k}.csv" | ||
| local CSV_FILE=$(get_os_path "$RAW_CSV") | ||
| local LOG_FILE="${RESULTS_DIR}/output-raw-${i}-${RECURSION_DEPTH}-${k}.txt" | ||
|
|
||
| echo " # Running Config $k: ${TITLE[$k]} (Iter $i)" | ||
|
|
||
| updateConfigFilename "$CSV_FILE" | ||
| export ENABLE_OTEL="false" | ||
|
|
||
| python3 "$MOOBENCH_BIN_PY" "$CONFIG_FILE" > "$LOG_FILE" 2>&1 | ||
| } | ||
|
|
||
| function runOpenTelemetryNoExport { | ||
| local k=$1 | ||
| local i=$2 | ||
|
|
||
| local RAW_CSV="${RAWFN}-${i}-${RECURSION_DEPTH}-${k}.csv" | ||
| local CSV_FILE=$(get_os_path "$RAW_CSV") | ||
| local LOG_FILE="${RESULTS_DIR}/output-raw-${i}-${RECURSION_DEPTH}-${k}.txt" | ||
|
|
||
| echo " # Running Config $k: ${TITLE[$k]} (Iter $i)" | ||
| updateConfigFilename "$CSV_FILE" | ||
|
|
||
| export ENABLE_OTEL="true" | ||
| export OTEL_TRACES_EXPORTER="none" | ||
| export OTEL_METRICS_EXPORTER="none" | ||
| export OTEL_LOGS_EXPORTER="none" | ||
|
|
||
| python3 "$MOOBENCH_BIN_PY" "$CONFIG_FILE" > "$LOG_FILE" 2>&1 | ||
| } | ||
|
|
||
| function runOpenTelemetryZipkin { | ||
| local k=$1 | ||
| local i=$2 | ||
|
|
||
| local RAW_CSV="${RAWFN}-${i}-${RECURSION_DEPTH}-${k}.csv" | ||
| local CSV_FILE=$(get_os_path "$RAW_CSV") | ||
| local LOG_FILE="${RESULTS_DIR}/output-raw-${i}-${RECURSION_DEPTH}-${k}.txt" | ||
|
|
||
| startZipkin | ||
| echo " # Running Config $k: ${TITLE[$k]} (Iter $i)" | ||
| updateConfigFilename "$CSV_FILE" | ||
|
|
||
| export ENABLE_OTEL="true" | ||
| export OTEL_SERVICE_NAME="moobench-python" | ||
| export OTEL_TRACES_EXPORTER="zipkin" | ||
| export OTEL_EXPORTER_ZIPKIN_ENDPOINT="http://localhost:9411/api/v2/spans" | ||
| export OTEL_METRICS_EXPORTER="none" | ||
| export OTEL_LOGS_EXPORTER="none" | ||
|
|
||
| python3 "$MOOBENCH_BIN_PY" "$CONFIG_FILE" > "$LOG_FILE" 2>&1 | ||
|
|
||
| stopBackgroundProcess | ||
| } | ||
|
|
||
| function executeBenchmark { | ||
| for index in $MOOBENCH_CONFIGURATIONS | ||
| do | ||
| case $index in | ||
| 0) runNoInstrumentation 0 $i ;; | ||
| 1) runOpenTelemetryNoExport 1 $i ;; | ||
| 2) runOpenTelemetryZipkin 2 $i ;; | ||
| esac | ||
| sleep 1 | ||
| done | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,4 @@ | ||
| MOOBENCH_CONFIGURATIONS="0 1 2" | ||
| TITLE[0]="No Instrumentation" | ||
| TITLE[1]="OpenTelemetry No Export" | ||
| TITLE[2]="OpenTelemetry Zipkin" |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,4 @@ | ||
| opentelemetry-distro | ||
| opentelemetry-exporter-zipkin | ||
| opentelemetry-sdk | ||
| opentelemetry-api |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,83 +1,113 @@ | ||
| # -*- coding: utf-8 -*- | ||
| # standard import | ||
| import sys | ||
| import time | ||
| import configparser | ||
| import re | ||
| # instrumentation | ||
| import os | ||
|
|
||
| try: | ||
| from opentelemetry import trace | ||
| from opentelemetry.sdk.trace import TracerProvider | ||
| from opentelemetry.sdk.trace.export import BatchSpanProcessor | ||
| from opentelemetry.exporter.zipkin.json import ZipkinExporter | ||
| from opentelemetry.sdk.resources import Resource | ||
| from opentelemetry.semconv.resource import ResourceAttributes | ||
| OTEL_AVAILABLE = True | ||
| except ImportError: | ||
| OTEL_AVAILABLE = False | ||
|
|
||
| try: | ||
| from monitoring.controller import SingleMonitoringController | ||
| from tools.importhookast import InstrumentOnImportFinder | ||
| from tools.importhook import PostImportFinder | ||
| KIEKER_AVAILABLE = True | ||
| except ImportError: | ||
| KIEKER_AVAILABLE = False | ||
|
|
||
| # read argumetns | ||
| if len(sys.argv) < 2: | ||
| print('Path to the benchmark configuration file was not provided.') | ||
| sys.exit(1) | ||
|
|
||
| parser = configparser.ConfigParser() | ||
| parser.read(sys.argv[1]) | ||
|
|
||
| total_calls =int(parser.get('Benchmark','total_calls')) | ||
| recursion_depth = int(parser.get('Benchmark','recursion_depth')) | ||
| method_time = int(parser.get('Benchmark','method_time')) | ||
| ini_path = parser.get('Benchmark','config_path') | ||
| inactive = parser.getboolean('Benchmark', 'inactive') | ||
| instrumentation_on = parser.getboolean('Benchmark', 'instrumentation_on') | ||
| approach = parser.getint('Benchmark', 'approach') | ||
| output_filename = parser.get('Benchmark', 'output_filename') | ||
|
|
||
| # debug | ||
| #print(f"total_calls = {total_calls}") | ||
| #print(f"recurison_depth = {recursion_depth}") | ||
| #print(f"method_time = {method_time}") | ||
|
|
||
| # instrument | ||
| from monitoring.controller import SingleMonitoringController | ||
| from tools.importhookast import InstrumentOnImportFinder | ||
| from tools.importhook import PostImportFinder | ||
| ex =[] | ||
| some_var = SingleMonitoringController(ini_path) | ||
| if instrumentation_on: | ||
| # print ('Instrumentation is on.') | ||
| try: | ||
| total_calls = int(parser.get('Benchmark','total_calls')) | ||
| recursion_depth = int(parser.get('Benchmark','recursion_depth')) | ||
| method_time = int(parser.get('Benchmark','method_time')) | ||
| output_filename = parser.get('Benchmark', 'output_filename') | ||
| ini_path = parser.get('Benchmark','config_path') | ||
| inactive = parser.getboolean('Benchmark', 'inactive') | ||
| instrumentation_on = parser.getboolean('Benchmark', 'instrumentation_on') | ||
| approach = parser.getint('Benchmark', 'approach') | ||
| except Exception as e: | ||
| print(f"Error parsing config: {e}") | ||
| sys.exit(1) | ||
|
|
||
| # Setup Kieker only if requested | ||
| if KIEKER_AVAILABLE and instrumentation_on: | ||
| # This segment runs only for the original Kieker framework logic | ||
| some_var = SingleMonitoringController(ini_path) | ||
| if approach == 2: | ||
| # print("2nd instrumentation approach is chosen") | ||
| #if not inactive: | ||
| #print("Instrumentation is activated") | ||
| #else: | ||
| # print("Instrumentation is not activated") | ||
|
|
||
| sys.meta_path.insert(0, InstrumentOnImportFinder(ignore_list=ex, empty=inactive, debug_on=False)) | ||
| sys.meta_path.insert(0, InstrumentOnImportFinder(ignore_list=[], empty=inactive, debug_on=False)) | ||
| else: | ||
| #print("1st instrumentation approach is chosen") | ||
| #if not inactive: | ||
| # print("Instrumentation is activated") | ||
| #else: | ||
| # print("Instrumentation is not activated") | ||
|
|
||
| pattern_object = re.compile('monitored_application') | ||
| exclude_modules = list() | ||
| sys.meta_path.insert(0, PostImportFinder(pattern_object, exclude_modules, empty = inactive)) | ||
| #else: | ||
| # print('Instrumentation is off') | ||
| sys.meta_path.insert(0, PostImportFinder(pattern_object, exclude_modules, empty=inactive)) | ||
|
|
||
| # opentelemetry manual instrumentation | ||
| tracer = None | ||
| # Only enable if installed and requested via environment variable | ||
| enable_otel = os.environ.get("ENABLE_OTEL", "false").lower() == "true" | ||
|
|
||
| if OTEL_AVAILABLE and enable_otel: | ||
| resource = Resource(attributes={ | ||
| ResourceAttributes.SERVICE_NAME: "moobench-python" | ||
| }) | ||
|
|
||
| provider = TracerProvider(resource=resource) | ||
|
|
||
| exporter_type = os.environ.get('OTEL_TRACES_EXPORTER', 'none') | ||
|
|
||
| if exporter_type == 'zipkin': | ||
| print("Initializing Zipkin Exporter...") | ||
| zipkin_endpoint = os.environ.get('OTEL_EXPORTER_ZIPKIN_ENDPOINT', "http://localhost:9411/api/v2/spans") | ||
| zipkin_exporter = ZipkinExporter(endpoint=zipkin_endpoint) | ||
| provider.add_span_processor(BatchSpanProcessor(zipkin_exporter)) | ||
|
|
||
| trace.set_tracer_provider(provider) | ||
| tracer = trace.get_tracer("moobench.benchmark") | ||
|
|
||
| import monitored_application | ||
|
|
||
| # setup | ||
| output_file = open(output_filename, "w") | ||
| print(f"Writing results to: {output_filename}") | ||
| print(f"Starting execution: {total_calls} calls.") | ||
|
|
||
| output_file = open(output_filename, "w") | ||
| thread_id = 0 | ||
|
|
||
| start_ns = 0 | ||
| stop_ns = 0 | ||
| timings = [] | ||
|
|
||
| # run experiment | ||
| for i in range(total_calls): | ||
|
|
||
| start_ns = time.time_ns() | ||
| monitored_application.monitored_method(method_time, recursion_depth) | ||
|
|
||
| if OTEL_AVAILABLE and tracer: | ||
| with tracer.start_as_current_span("monitored_method"): | ||
| monitored_application.monitored_method(method_time, recursion_depth) | ||
| else: | ||
| monitored_application.monitored_method(method_time, recursion_depth) | ||
|
|
||
| stop_ns = time.time_ns() | ||
| timings.append(stop_ns-start_ns) | ||
| if i%100000 == 0: | ||
| print(timings[-1]) | ||
|
|
||
| duration = stop_ns - start_ns | ||
|
|
||
| if i % 100000 == 0 and i > 0: | ||
| print(f"Call {i}: {duration} ns") | ||
|
|
||
| output_file.write(f"{thread_id};{timings[-1]}\n") | ||
| output_file.write(f"{thread_id};{duration}\n") | ||
|
|
||
| output_file.close() | ||
|
|
||
| # end | ||
| if OTEL_AVAILABLE and os.environ.get('OTEL_TRACES_EXPORTER') == 'zipkin': | ||
| print("Flushing traces to Zipkin (waiting 5s)...") | ||
| time.sleep(5) | ||
|
|
||
| print("Benchmark finished.") |
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.
Don't duplicate
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.
This is still present
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.
I have removed the duplicate.