require 'elastic-apm' module Ecoportal module API module Common class Client module ElasticApmIntegration include Ecoportal::API::Common::Client::Error::Checks APM_SERVICE_NAME = 'ecoportal-api-gem'.freeze # Log only errors that are only server's responsibility def log_unexpected_server_error(response) msg = "Expecting Ecoportal::API::Common::Response. Given: #{response.class}" raise msg unless response.is_a?(Common::Response) return unless elastic_apm_service return unless unexpected_server_error_code?(response.status) return unless ElasticAPM.running? ElasticAPM.report( Ecoportal::API::Common::Client::Error::UnexpectedServerError.new( response.body, code: response.status ) ) end private # finalizer to stop the agent close_elastic_apm = proc do |_id| next unless ElasticAPM.running? puts "Stopping ElasticAPM service" ElasticAPM.stop rescue StandardError # Silent end ObjectSpace.define_finalizer("ElasticAPM", close_elastic_apm) def elastic_apm_service return false if @disable_apm ElasticAPM.start(**elastic_apm_options) unless ElasticAPM.running? rescue StandardError => err @disable_apm = true puts "ElasticAPM services not available: #{err}" end def elastic_apm_options { service_name: APM_SERVICE_NAME, server_url: elastic_apm_url, secret_token: elastic_apm_key, environment: environment, # http_compression: false, transaction_sample_rate: 0.1, transaction_max_spans: 100, span_frames_min_duration: "5ms" }.tap do |options| # next unless false # options.merge!({ # log_level: ::Logger::DEBUG, # log_path: File.join('log', "elastic_apm.log") # }) end end def elastic_apm_url @elastic_apm_url ||= "https://".tap do |url| url << elastic_apm_account_id.to_s url << ".#{elastic_apm_base_url}" url << ":#{elastic_apm_port}" end end def elastic_apm_key @elastic_apm_key ||= ENV['ELASTIC_APM_KEY'] end def elastic_apm_account_id @elastic_apm_account_id ||= ENV['ELASTIC_APM_ACCOUNT_ID'] end def elastic_apm_base_url @elastic_apm_base_url ||= "apm.#{elastic_apm_region}.aws.cloud.es.io" end def elastic_apm_region @elastic_apm_region ||= ENV['ELASTIC_APM_REGION'] || "ap-southeast-2" end def elastic_apm_port @elastic_apm_port ||= ENV['ELASTIC_APM_PORT'] || "443" end def environment @environment ||= "unknown".tap do |value| next unless instance_variable_defined?(:@host) next unless (env = @host.gsub(".ecoportal.com", '')) value.clear << env end end end end end end end