require "time" unless defined?(Time.zone_offset) require "chef-licensing" require_relative "telemetry/null" require_relative "telemetry/http" require_relative "telemetry/run_context_probe" module Inspec class Telemetry @@instance = nil @@config = nil def self.instance @@instance ||= determine_backend_class.new end def self.determine_backend_class # Don't perform telemetry action for other InSpec distros # Don't perform telemetry action if running under Automate - Automate does LDC tracking for us # Don't perform telemetry action if license is a commercial license # Don't perform telemetry action if running under Test Kitchen if Inspec::Dist::EXEC_NAME != "inspec" || Inspec::Telemetry::RunContextProbe.under_automate? || license&.license_type&.downcase == "commercial" || Inspec::Telemetry::RunContextProbe.guess_run_context == "test-kitchen" Inspec::Log.debug "Determined telemetry operation is not applicable and hence aborting it." return Inspec::Telemetry::Null end if Inspec::Dist::EXEC_NAME == "inspec" && telemetry_disabled? # Issue a warning if an InSpec user is explicitly trying to opt out of telemetry using cli option Inspec::Log.warn "Telemetry opt-out is not permissible." end Inspec::Log.debug "Determined HTTP instance for telemetry" Inspec::Telemetry::HTTP end def self.license Inspec::Log.debug "Fetching license context for telemetry check" @license = ChefLicensing.license_context end ###### # These class methods make it convenient to call from anywhere within the InSpec codebase. ###### def self.run_starting(opts) @@config ||= opts[:conf] instance.run_starting(opts) rescue StandardError => e Inspec::Log.debug "Encountered error in Telemetry start run call -> #{e.message}" end def self.run_ending(opts) @@config ||= opts[:conf] instance.run_ending(opts) rescue StandardError => e Inspec::Log.debug "Encountered error in Telemetry end run call -> #{e.message}" end def self.note_feature_usage(feature_name) instance.note_feature_usage(feature_name) end def self.config @@config end def self.telemetry_disabled? config.telemetry_options["enable_telemetry"].nil? ? false : !config.telemetry_options["enable_telemetry"] end end end