mirror of
				https://github.com/cmur2/dyndnsd.git
				synced 2025-10-31 20:25:07 +01:00 
			
		
		
		
	tracing: migrate from OpenTracing to OpenTelemetry
- still uses Jaeger client (`AgentExporter`) and supports similar configuration except host + port which can be done via https://github.com/open-telemetry/opentelemetry-ruby/tree/main/exporter/jaeger#how-can-i-configure-the-jaeger-exporter
This commit is contained in:
		
							
								
								
									
										12
									
								
								README.md
									
									
									
									
									
								
							
							
						
						
									
										12
									
								
								README.md
									
									
									
									
									
								
							| @@ -271,9 +271,9 @@ users: | ||||
|  | ||||
| ### Tracing (experimental) | ||||
|  | ||||
| For tracing, dyndnsd.rb is instrumented using the [OpenTracing](http://opentracing.io/) framework and will emit span tracing data for the most important operations happening during the request/response cycle. Using a middleware for Rack allows handling incoming OpenTracing span information properly. | ||||
| For tracing, dyndnsd.rb is instrumented using the [OpenTelemetry](https://opentelemetry.io/docs/ruby/) framework and will emit span tracing data for the most important operations happening during the request/response cycle. Using an [instrumentation for Rack](https://github.com/open-telemetry/opentelemetry-ruby/tree/main/instrumentation/rack) allows handling incoming OpenTelemetry parent span information properly (when desired, turned off by default to reduce attack surface). | ||||
|  | ||||
| Currently, only one OpenTracing-compatible tracer implementation named [CNCF Jaeger](https://github.com/jaegertracing/jaeger) can be configured to use with dyndnsd.rb. | ||||
| Currently, the [OpenTelemetry trace exporter](https://github.com/open-telemetry/opentelemetry-ruby/tree/main/exporter/jaeger) for [CNCF Jaeger](https://github.com/jaegertracing/jaeger) can be enabled via dyndnsd.rb configuration. Alternatively, you can also enable other exporters via the environment variable `OTEL_TRACES_EXPORTER`, e.g. `OTEL_TRACES_EXPORTER=console`. | ||||
|  | ||||
| ```yaml | ||||
| host: "0.0.0.0" | ||||
| @@ -282,11 +282,9 @@ db: "/opt/dyndnsd/db.json" | ||||
| domain: "dyn.example.org" | ||||
| # enable and configure tracing using the (currently only) tracer jaeger | ||||
| tracing: | ||||
|   trust_incoming_span: false # default value, change to accept incoming OpenTracing spans as parents | ||||
|   jaeger: | ||||
|     host: 127.0.0.1 # defaults for host and port of local jaeger-agent | ||||
|     port: 6831 | ||||
|     service_name: "my.dyndnsd.identifier" | ||||
|   trust_incoming_span: false # default value, change to accept incoming OpenTelemetry spans as parents | ||||
|   service_name: "my.dyndnsd.identifier" # default unset, will be populated by OpenTelemetry | ||||
|   jaeger: true # enables the Jaeger AgentExporter | ||||
| # configure the updater, here we use command_with_bind_zone, params are updater-specific | ||||
| updater: | ||||
|   name: "command_with_bind_zone" | ||||
|   | ||||
| @@ -28,11 +28,11 @@ Gem::Specification.new do |s| | ||||
|   s.required_ruby_version = '>= 2.5' | ||||
|  | ||||
|   s.add_runtime_dependency 'async-dns', '~> 1.2.0' | ||||
|   s.add_runtime_dependency 'jaeger-client', '~> 1.1.0' | ||||
|   s.add_runtime_dependency 'metriks' | ||||
|   s.add_runtime_dependency 'opentracing', '~> 0.5.0' | ||||
|   s.add_runtime_dependency 'opentelemetry-exporter-jaeger', '~> 0.18.0' | ||||
|   s.add_runtime_dependency 'opentelemetry-instrumentation-rack', '~> 0.18.0' | ||||
|   s.add_runtime_dependency 'opentelemetry-sdk', '~> 1.0.0.rc1' | ||||
|   s.add_runtime_dependency 'rack', '~> 2.0' | ||||
|   s.add_runtime_dependency 'rack-tracer', '~> 0.9.0' | ||||
|   s.add_runtime_dependency 'webrick', '>= 1.6.1' | ||||
|  | ||||
|   s.add_development_dependency 'bundler' | ||||
|   | ||||
| @@ -8,9 +8,9 @@ require 'json' | ||||
| require 'yaml' | ||||
| require 'rack' | ||||
| require 'metriks' | ||||
| require 'opentelemetry/instrumentation/rack' | ||||
| require 'opentelemetry/sdk' | ||||
| require 'metriks/reporter/graphite' | ||||
| require 'opentracing' | ||||
| require 'rack/tracer' | ||||
|  | ||||
| require 'dyndnsd/generator/bind' | ||||
| require 'dyndnsd/updater/command_with_bind_zone' | ||||
| @@ -69,7 +69,7 @@ module Dyndnsd | ||||
|     # @return [Boolean] | ||||
|     def authorized?(username, password) | ||||
|       Helper.span('check_authorized') do |span| | ||||
|         span.set_tag('dyndnsd.user', username) | ||||
|         span.set_attribute('enduser.id', username) | ||||
|  | ||||
|         allow = Helper.user_allowed?(username, password, @users) | ||||
|         if !allow | ||||
| @@ -170,7 +170,7 @@ module Dyndnsd | ||||
|     def process_changes(hostnames, myips) | ||||
|       changes = [] | ||||
|       Helper.span('process_changes') do |span| | ||||
|         span.set_tag('dyndnsd.hostnames', hostnames.join(',')) | ||||
|         span.set_attribute('dyndnsd.hostnames', hostnames.join(',')) | ||||
|  | ||||
|         hostnames.each do |hostname| | ||||
|           # myips order is always deterministic | ||||
| @@ -252,6 +252,8 @@ module Dyndnsd | ||||
|       Dyndnsd.logger.progname = 'dyndnsd' | ||||
|       Dyndnsd.logger.formatter = LogFormatter.new | ||||
|       Dyndnsd.logger.level = config['debug'] ? Logger::DEBUG : Logger::INFO | ||||
|  | ||||
|       OpenTelemetry.logger = Dyndnsd.logger | ||||
|     end | ||||
|  | ||||
|     # @return [void] | ||||
| @@ -296,16 +298,31 @@ module Dyndnsd | ||||
|     # @param config [Hash{String => Object}] | ||||
|     # @return [void] | ||||
|     private_class_method def self.setup_tracing(config) | ||||
|       # configure OpenTracing | ||||
|       if config.dig('tracing', 'jaeger') | ||||
|         require 'jaeger/client' | ||||
|       # by default do not try to emit any traces until the user opts in | ||||
|       ENV['OTEL_TRACES_EXPORTER'] ||= 'none' | ||||
|  | ||||
|         host = config['tracing']['jaeger']['host'] || '127.0.0.1' | ||||
|         port = config['tracing']['jaeger']['port'] || 6831 | ||||
|         service_name = config['tracing']['jaeger']['service_name'] || 'dyndnsd' | ||||
|         OpenTracing.global_tracer = Jaeger::Client.build( | ||||
|           host: host, port: port, service_name: service_name, flush_interval: 1 | ||||
|         ) | ||||
|       # configure OpenTelemetry | ||||
|       OpenTelemetry::SDK.configure do |c| | ||||
|         if config.dig('tracing', 'jaeger') | ||||
|           require 'opentelemetry/exporter/jaeger' | ||||
|  | ||||
|           c.add_span_processor( | ||||
|             OpenTelemetry::SDK::Trace::Export::BatchSpanProcessor.new( | ||||
|               OpenTelemetry::Exporter::Jaeger::AgentExporter.new | ||||
|             ) | ||||
|           ) | ||||
|         end | ||||
|  | ||||
|         if config.dig('tracing', 'service_name') | ||||
|           c.service_name = config['tracing']['service_name'] | ||||
|         end | ||||
|  | ||||
|         c.service_version = Dyndnsd::VERSION | ||||
|         c.use('OpenTelemetry::Instrumentation::Rack') | ||||
|       end | ||||
|  | ||||
|       if !config.dig('tracing', 'trust_incoming_span') | ||||
|         OpenTelemetry.propagation = OpenTelemetry::Context::Propagation::NoopTextMapPropagator.new | ||||
|       end | ||||
|     end | ||||
|  | ||||
| @@ -331,8 +348,7 @@ module Dyndnsd | ||||
|         app = Responder::DynDNSStyle.new(app) | ||||
|       end | ||||
|  | ||||
|       trust_incoming_span = config.dig('tracing', 'trust_incoming_span') || false | ||||
|       app = Rack::Tracer.new(app, trust_incoming_span: trust_incoming_span) | ||||
|       app = OpenTelemetry::Instrumentation::Rack::Middlewares::TracerMiddleware.new(app) | ||||
|  | ||||
|       Rack::Handler::WEBrick.run app, Host: config['host'], Port: config['port'] | ||||
|     end | ||||
|   | ||||
| @@ -45,24 +45,17 @@ module Dyndnsd | ||||
|     # @param block [Proc] | ||||
|     # @return [void] | ||||
|     def self.span(operation, &block) | ||||
|       scope = OpenTracing.start_active_span(operation) | ||||
|       span = scope.span | ||||
|       span.set_tag('component', 'dyndnsd') | ||||
|       span.set_tag('span.kind', 'server') | ||||
|       begin | ||||
|       tracer = OpenTelemetry.tracer_provider.tracer(Dyndnsd.name, Dyndnsd::VERSION) | ||||
|       tracer.in_span( | ||||
|         operation, | ||||
|         attributes: {'component' => 'dyndnsd'}, | ||||
|         kind: :server | ||||
|       ) do |span| | ||||
|         Dyndnsd.logger.debug "Creating span ID #{span.context.hex_span_id} for trace ID #{span.context.hex_trace_id}" | ||||
|         block.call(span) | ||||
|       rescue StandardError => e | ||||
|         span.set_tag('error', true) | ||||
|         span.log_kv( | ||||
|           event: 'error', | ||||
|           'error.kind': e.class.to_s, | ||||
|           'error.object': e, | ||||
|           message: e.message, | ||||
|           stack: e.backtrace&.join("\n") || '' | ||||
|         ) | ||||
|         span.record_exception(e) | ||||
|         raise e | ||||
|       ensure | ||||
|         scope.close | ||||
|       end | ||||
|     end | ||||
|   end | ||||
|   | ||||
| @@ -18,7 +18,7 @@ module Dyndnsd | ||||
|         return if !db.changed? | ||||
|  | ||||
|         Helper.span('updater_update') do |span| | ||||
|           span.set_tag('dyndnsd.updater.name', self.class.name&.split('::')&.last || 'None') | ||||
|           span.set_attribute('dyndnsd.updater.name', self.class.name&.split('::')&.last || 'None') | ||||
|  | ||||
|           # write zone file in bind syntax | ||||
|           File.open(@zone_file, 'w') { |f| f.write(@generator.generate(db)) } | ||||
|   | ||||
| @@ -35,7 +35,7 @@ module Dyndnsd | ||||
|       # @return [void] | ||||
|       def update(db) | ||||
|         Helper.span('updater_update') do |span| | ||||
|           span.set_tag('dyndnsd.updater.name', self.class.name&.split('::')&.last || 'None') | ||||
|           span.set_attribute('dyndnsd.updater.name', self.class.name&.split('::')&.last || 'None') | ||||
|  | ||||
|           soa_rr = Resolv::DNS::Resource::IN::SOA.new( | ||||
|             @zone_nameservers[0], @zone_email_address, | ||||
|   | ||||
| @@ -24,9 +24,7 @@ describe Dyndnsd::Daemon do | ||||
|  | ||||
|     app = Rack::Auth::Basic.new(daemon, 'DynDNS', &daemon.method(:authorized?)) | ||||
|  | ||||
|     app = Dyndnsd::Responder::DynDNSStyle.new(app) | ||||
|  | ||||
|     Rack::Tracer.new(app, trust_incoming_span: false) | ||||
|     Dyndnsd::Responder::DynDNSStyle.new(app) | ||||
|   end | ||||
|  | ||||
|   it 'requires authentication' do | ||||
|   | ||||
		Reference in New Issue
	
	Block a user