104 lines
		
	
	
		
			2.6 KiB
		
	
	
	
		
			Ruby
		
	
	
	
			
		
		
	
	
			104 lines
		
	
	
		
			2.6 KiB
		
	
	
	
		
			Ruby
		
	
	
	
| # frozen_string_literal: true
 | |
| 
 | |
| module Gitlab
 | |
|   module Ci
 | |
|     module Pipeline
 | |
|       class Logger
 | |
|         include ::Gitlab::Utils::StrongMemoize
 | |
| 
 | |
|         def self.current_monotonic_time
 | |
|           ::Gitlab::Metrics::System.monotonic_time
 | |
|         end
 | |
| 
 | |
|         def initialize(project:, destination: Gitlab::AppJsonLogger)
 | |
|           @started_at = current_monotonic_time
 | |
|           @project = project
 | |
|           @destination = destination
 | |
|           @log_conditions = []
 | |
| 
 | |
|           yield(self) if block_given?
 | |
|         end
 | |
| 
 | |
|         def log_when(&block)
 | |
|           log_conditions.push(block)
 | |
|         end
 | |
| 
 | |
|         def instrument(operation)
 | |
|           return yield unless enabled?
 | |
| 
 | |
|           raise ArgumentError, 'block not given' unless block_given?
 | |
| 
 | |
|           op_started_at = current_monotonic_time
 | |
| 
 | |
|           result = yield
 | |
| 
 | |
|           observe("#{operation}_duration_s", current_monotonic_time - op_started_at)
 | |
| 
 | |
|           result
 | |
|         end
 | |
| 
 | |
|         def observe(operation, value)
 | |
|           return unless enabled?
 | |
| 
 | |
|           observations[operation.to_s].push(value)
 | |
|         end
 | |
| 
 | |
|         def commit(pipeline:, caller:)
 | |
|           return unless log?
 | |
| 
 | |
|           attributes = {
 | |
|             class: self.class.name.to_s,
 | |
|             pipeline_creation_caller: caller,
 | |
|             project_id: project.id,
 | |
|             pipeline_id: pipeline.id,
 | |
|             pipeline_persisted: pipeline.persisted?,
 | |
|             pipeline_source: pipeline.source,
 | |
|             pipeline_creation_service_duration_s: age
 | |
|           }.stringify_keys.merge(observations_hash)
 | |
| 
 | |
|           destination.info(attributes)
 | |
|         end
 | |
| 
 | |
|         def observations_hash
 | |
|           observations.transform_values do |values|
 | |
|             next if values.empty?
 | |
| 
 | |
|             {
 | |
|               'count' => values.size,
 | |
|               'min' => values.min,
 | |
|               'max' => values.max,
 | |
|               'avg' => values.sum / values.size
 | |
|             }
 | |
|           end.compact
 | |
|         end
 | |
| 
 | |
|         private
 | |
| 
 | |
|         attr_reader :project, :destination, :started_at, :log_conditions
 | |
|         delegate :current_monotonic_time, to: :class
 | |
| 
 | |
|         def age
 | |
|           current_monotonic_time - started_at
 | |
|         end
 | |
| 
 | |
|         def log?
 | |
|           return false unless enabled?
 | |
|           return true if log_conditions.empty?
 | |
| 
 | |
|           log_conditions.any? { |cond| cond.call(observations) }
 | |
|         end
 | |
| 
 | |
|         def enabled?
 | |
|           strong_memoize(:enabled) do
 | |
|             ::Feature.enabled?(:ci_pipeline_creation_logger, project, type: :ops, default_enabled: :yaml)
 | |
|           end
 | |
|         end
 | |
| 
 | |
|         def observations
 | |
|           @observations ||= Hash.new { |hash, key| hash[key] = [] }
 | |
|         end
 | |
|       end
 | |
|     end
 | |
|   end
 | |
| end
 |