Class: Contrast::Agent::Inventory::DependencyUsageAnalysis
- Includes:
- Dependencies, Components::Logger::InstanceMethods, Singleton
- Defined in:
- lib/contrast/agent/inventory/dependency_usage_analysis.rb
Overview
Used to analyze class usage for reporting
Constant Summary
Constants included from Dependencies
Contrast::Agent::Inventory::Dependencies::CONTRAST_AGENT
Instance Method Summary collapse
-
#associate_file(path) ⇒ Object
This method is invoked once per TracePoint :end - to map a specific file being required to the gem to which it belongs.
-
#catchup ⇒ Object
This method is invoked once, along with the rest of our catchup code to report libraries and their associated files that have already been loaded pre-contrast.
-
#generate_library_usage ⇒ Contrast::Agent::Reporting::ObservedLibraryUsage?
Populate the library_usages field of the Activity message using the data stored in the @gemdigest_cache.
-
#initialize ⇒ DependencyUsageAnalysis
constructor
A new instance of DependencyUsageAnalysis.
Methods included from Dependencies
Methods included from Components::Logger::InstanceMethods
Constructor Details
#initialize ⇒ DependencyUsageAnalysis
Returns a new instance of DependencyUsageAnalysis.
19 20 21 22 23 24 |
# File 'lib/contrast/agent/inventory/dependency_usage_analysis.rb', line 19 def initialize return unless enabled? @lock = Mutex.new @lock.synchronize { @gemdigest_cache = Hash.new { |hash, key| hash[key] = Set.new } } end |
Instance Method Details
#associate_file(path) ⇒ Object
This method is invoked once per TracePoint :end - to map a specific file being required to the gem to which it belongs.
51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 |
# File 'lib/contrast/agent/inventory/dependency_usage_analysis.rb', line 51 def associate_file path return unless enabled? spec_lookup_path = adjust_path_for_spec_lookup(path) spec = Gem::Specification.find_by_path(spec_lookup_path) unless spec logger.debug('Unable to resolve gem spec for path', path: path) return end digest = Contrast::Utils::Sha256Builder.instance.build_from_spec(spec) unless digest logger.debug('Unable to resolve digest for gem spec', spec: spec.to_s) if logger.debug? return end report_path = adjust_path_for_reporting(path, spec) @lock.synchronize { @gemdigest_cache[digest] << report_path } rescue StandardError => e logger.error('Unable to inventory file path', e, path: path) end |
#catchup ⇒ Object
This method is invoked once, along with the rest of our catchup code to report libraries and their associated files that have already been loaded pre-contrast.
28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 |
# File 'lib/contrast/agent/inventory/dependency_usage_analysis.rb', line 28 def catchup return unless enabled? loaded_specs.each do |_name, spec| # Get a digest of the Gem file itself. next unless (digest = Contrast::Utils::Sha256Builder.instance.build_from_spec(spec)) loaded_files_from_gem = $LOADED_FEATURES.select { |f| f.start_with?(spec.full_gem_path) } new_files = loaded_files_from_gem.each_with_object(Set.new) do |file_path, set| set << adjust_path_for_reporting(file_path, spec) logger.trace('Recording loaded file for inventory analysis', line: file_path) end # Even if new_files is empty, still need to add digest key for library discovery. @lock.synchronize { @gemdigest_cache[digest].merge(new_files) } end end |
#generate_library_usage ⇒ Contrast::Agent::Reporting::ObservedLibraryUsage?
Populate the library_usages field of the Activity message using the data stored in the @gemdigest_cache. If no libraries had files loaded, or inventory analysis is disabled, return nil instead.
76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 |
# File 'lib/contrast/agent/inventory/dependency_usage_analysis.rb', line 76 def generate_library_usage return unless enabled? return unless @gemdigest_cache.any? # Disconnect gemdigest_cache and replace it with an empty one; synch so new libs cannot be added between the # assignment and the replace gem_spec_digest_to_files = @lock.synchronize do hold = @gemdigest_cache @gemdigest_cache = Hash.new { |hash, key| hash[key] = Set.new } hold end observed_library_usage = Contrast::Agent::Reporting::ObservedLibraryUsage.new gem_spec_digest_to_files.each_pair do |digest, files| next unless files.any? usage = Contrast::Agent::Reporting::LibraryUsageObservation.new(digest, files) observed_library_usage.observations << usage end observed_library_usage.observations.any? ? observed_library_usage : nil rescue StandardError => e logger.error('Unable to generate library usage.', e) end |