Created
September 18, 2025 10:23
-
-
Save juampi92/898df98e1724acb802358d6ecc059141 to your computer and use it in GitHub Desktop.
A bash script that generates W3C traceparent headers for testing, waits while you use the traceparent in your tests, then sends the completed trace span to Jaeger using OTLP Http..
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/bin/bash | |
| # Traceparent Generator and Jaeger Trace Sender | |
| # | |
| # This script generates a W3C traceparent header, allows time to copy it, | |
| # and then sends a corresponding trace span to Jaeger via OpenTelemetry HTTP protocol. | |
| # | |
| # Requirements: curl (usually pre-installed on macOS/Linux) | |
| # | |
| # Usage: | |
| # - Run: ./otel_trace_generator.sh | |
| # - Copy the generated traceparent header when displayed | |
| # - Press Enter when ready to close the span and send to Jaeger | |
| # | |
| # Help: | |
| # - Run: ./otel_trace_generator.sh --help | |
| set -e # Exit on error | |
| # Colors for output | |
| RED='\033[0;31m' | |
| GREEN='\033[0;32m' | |
| YELLOW='\033[1;33m' | |
| BLUE='\033[0;34m' | |
| CYAN='\033[0;36m' | |
| NC='\033[0m' # No Color | |
| # Default configuration | |
| DEFAULT_JAEGER_PORT=4318 | |
| # Function to generate random hex string | |
| generate_hex() { | |
| local length=$1 | |
| openssl rand -hex $((length/2)) | |
| } | |
| # Function to get current time in nanoseconds | |
| get_time_ns() { | |
| if [[ "$OSTYPE" == "darwin"* ]]; then | |
| # macOS | |
| python3 -c "import time; print(int(time.time() * 1000000000))" | |
| else | |
| # Linux | |
| date +%s%N | |
| fi | |
| } | |
| # Function to format timestamp for display (removed due to compatibility issues) | |
| format_timestamp() { | |
| echo "timestamp" | |
| } | |
| # Function to create OTLP trace JSON | |
| create_trace_json() { | |
| local trace_id=$1 | |
| local span_id=$2 | |
| local start_time_ns=$3 | |
| local end_time_ns=$4 | |
| local service_name=$5 | |
| cat <<EOF | |
| { | |
| "resourceSpans": [ | |
| { | |
| "resource": { | |
| "attributes": [ | |
| { | |
| "key": "service.name", | |
| "value": {"stringValue": "$service_name"} | |
| }, | |
| { | |
| "key": "service.version", | |
| "value": {"stringValue": "1.0.0"} | |
| } | |
| ] | |
| }, | |
| "scopeSpans": [ | |
| { | |
| "scope": { | |
| "name": "trace-generator", | |
| "version": "1.0.0" | |
| }, | |
| "spans": [ | |
| { | |
| "traceId": "$trace_id", | |
| "spanId": "$span_id", | |
| "name": "manual-trace-span", | |
| "kind": 1, | |
| "startTimeUnixNano": "$start_time_ns", | |
| "endTimeUnixNano": "$end_time_ns", | |
| "attributes": [ | |
| { | |
| "key": "span.type", | |
| "value": {"stringValue": "manual"} | |
| }, | |
| { | |
| "key": "generator.script", | |
| "value": {"stringValue": "trace_generator.sh"} | |
| } | |
| ], | |
| "status": { | |
| "code": 1 | |
| } | |
| } | |
| ] | |
| } | |
| ] | |
| } | |
| ] | |
| } | |
| EOF | |
| } | |
| # Function to send trace to Jaeger | |
| send_trace_to_jaeger() { | |
| local json_data=$1 | |
| local jaeger_endpoint=$2 | |
| local response | |
| local http_code | |
| response=$(curl -s -w "\n%{http_code}" \ | |
| -X POST \ | |
| -H "Content-Type: application/json" \ | |
| -H "User-Agent: trace-generator-script/1.0.0" \ | |
| -d "$json_data" \ | |
| "$jaeger_endpoint" 2>/dev/null) | |
| http_code=$(echo "$response" | tail -n1) | |
| if [[ "$http_code" == "200" ]]; then | |
| return 0 | |
| else | |
| echo "HTTP $http_code: $(echo "$response" | head -n -1)" | |
| return 1 | |
| fi | |
| } | |
| # Function to show usage | |
| show_usage() { | |
| echo "Usage: $0 [service-name] [--port=PORT]" | |
| echo "" | |
| echo "Arguments:" | |
| echo " service-name Name of the service (default: trace-generator-script)" | |
| echo "" | |
| echo "Options:" | |
| echo " --port=PORT Jaeger OTLP HTTP port (default: $DEFAULT_JAEGER_PORT)" | |
| echo " --help Show this help message" | |
| echo "" | |
| echo "Examples:" | |
| echo " $0 # Use defaults" | |
| echo " $0 my-service # Use custom service name" | |
| echo " $0 my-service --port=4318 # Custom name and port" | |
| echo " $0 --port=14268 # Custom port, default name" | |
| } | |
| # Function to parse command line arguments | |
| parse_arguments() { | |
| local service_name="trace-generator-script" | |
| local jaeger_port=$DEFAULT_JAEGER_PORT | |
| while [[ $# -gt 0 ]]; do | |
| case $1 in | |
| --port=*) | |
| jaeger_port="${1#*=}" | |
| if ! [[ "$jaeger_port" =~ ^[0-9]+$ ]] || [[ "$jaeger_port" -lt 1 ]] || [[ "$jaeger_port" -gt 65535 ]]; then | |
| echo -e "${RED}β Error: Invalid port number '$jaeger_port'. Must be between 1-65535.${NC}" >&2 | |
| exit 1 | |
| fi | |
| shift | |
| ;; | |
| --help|-h) | |
| show_usage | |
| exit 0 | |
| ;; | |
| --*) | |
| echo -e "${RED}β Error: Unknown option '$1'${NC}" >&2 | |
| echo "" | |
| show_usage | |
| exit 1 | |
| ;; | |
| *) | |
| # This is the service name (positional argument) | |
| service_name="$1" | |
| shift | |
| ;; | |
| esac | |
| done | |
| echo "$service_name|$jaeger_port" | |
| } | |
| # Main script | |
| main() { | |
| local parsed_args=$(parse_arguments "$@") | |
| local service_name="${parsed_args%|*}" | |
| local jaeger_port="${parsed_args#*|}" | |
| local jaeger_endpoint="http://localhost:${jaeger_port}/v1/traces" | |
| echo -e "${BLUE}π Traceparent Generator & Jaeger Trace Sender${NC}" | |
| echo "==================================================" | |
| # Step 1: Generate traceparent header | |
| local version="00" | |
| local trace_id=$(generate_hex 32) | |
| local span_id=$(generate_hex 16) | |
| local trace_flags="01" | |
| local traceparent="${version}-${trace_id}-${span_id}-${trace_flags}" | |
| local start_time_ns=$(get_time_ns) | |
| echo | |
| echo -e "${YELLOW}π Generated traceparent header:${NC}" | |
| echo " $traceparent" | |
| echo | |
| echo -e "${CYAN}π Trace Details:${NC}" | |
| echo " Service: $service_name" | |
| echo " Trace ID: $trace_id" | |
| echo " Span ID: $span_id" | |
| echo | |
| echo -e "${YELLOW}βοΈ Copy the traceparent header above if needed.${NC}" | |
| echo -e "${YELLOW}β³ Press Enter when ready to close the span and send to Jaeger...${NC}" | |
| # Step 2: Wait for user input | |
| read -r | |
| # Step 3: Calculate duration and create trace data | |
| local end_time_ns=$(get_time_ns) | |
| local duration_ms=$(( (end_time_ns - start_time_ns) / 1000000 )) | |
| echo | |
| echo -e "${CYAN}β±οΈ Span Duration: ${duration_ms} ms${NC}" | |
| # Step 4: Create and send trace data | |
| local trace_json=$(create_trace_json "$trace_id" "$span_id" "$start_time_ns" "$end_time_ns" "$service_name") | |
| echo | |
| echo -e "${BLUE}π Sending trace to Jaeger (port ${jaeger_port})...${NC}" | |
| if send_trace_to_jaeger "$trace_json" "$jaeger_endpoint"; then | |
| echo -e "${GREEN}β Trace successfully sent to Jaeger!${NC}" | |
| echo | |
| echo -e "${CYAN}π View in Jaeger UI:${NC}" | |
| echo " http://localhost:16686/trace/$trace_id" | |
| else | |
| echo -e "${RED}β Failed to send trace to Jaeger${NC}" | |
| echo | |
| echo -e "${YELLOW}π‘ Make sure Jaeger is running with OTLP HTTP receiver on port ${jaeger_port}${NC}" | |
| echo " Docker: docker run -p 16686:16686 -p ${jaeger_port}:4318 jaegertracing/all-in-one:latest" | |
| exit 1 | |
| fi | |
| } | |
| # Handle Ctrl+C gracefully | |
| trap 'echo -e "\n\n${RED}β Operation cancelled by user.${NC}"; exit 0' INT | |
| # Run main function | |
| main "$@" |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment