Commit 282958dc authored by Stan Hu's avatar Stan Hu

Migrate Geo logs to structured JSON in geo.log

parent c96dadf9
...@@ -4,6 +4,8 @@ module Geo ...@@ -4,6 +4,8 @@ module Geo
EmptyCloneUrlPrefixError = Class.new(StandardError) EmptyCloneUrlPrefixError = Class.new(StandardError)
class BaseSyncService class BaseSyncService
include ::Gitlab::Geo::ProjectLogHelpers
class << self class << self
attr_accessor :type attr_accessor :type
end end
...@@ -19,9 +21,9 @@ module Geo ...@@ -19,9 +21,9 @@ module Geo
def execute def execute
try_obtain_lease do try_obtain_lease do
log("Started #{type} sync") log_info("Started #{type} sync")
sync_repository sync_repository
log("Finished #{type} sync") log_info("Finished #{type} sync")
end end
end end
...@@ -46,11 +48,11 @@ module Geo ...@@ -46,11 +48,11 @@ module Geo
end end
def try_obtain_lease def try_obtain_lease
log("Trying to obtain lease to sync #{type}") log_info("Trying to obtain lease to sync #{type}")
repository_lease = Gitlab::ExclusiveLease.new(lease_key, timeout: LEASE_TIMEOUT).try_obtain repository_lease = Gitlab::ExclusiveLease.new(lease_key, timeout: LEASE_TIMEOUT).try_obtain
unless repository_lease unless repository_lease
log("Could not obtain lease to sync #{type}") log_info("Could not obtain lease to sync #{type}")
return return
end end
...@@ -59,14 +61,14 @@ module Geo ...@@ -59,14 +61,14 @@ module Geo
# We should release the lease for a repository, only if we have obtained # We should release the lease for a repository, only if we have obtained
# it. If something went wrong when syncing the repository, we should wait # it. If something went wrong when syncing the repository, we should wait
# for the lease timeout to try again. # for the lease timeout to try again.
log("Releasing leases to sync #{type}") log_info("Releasing leases to sync #{type}")
Gitlab::ExclusiveLease.cancel(lease_key, repository_lease) Gitlab::ExclusiveLease.cancel(lease_key, repository_lease)
end end
def update_registry(type, started_at: nil, finished_at: nil) def update_registry(type, started_at: nil, finished_at: nil)
return unless started_at || finished_at return unless started_at || finished_at
log("Updating #{type} sync information") log_info("Updating #{type} sync information")
attrs = {} attrs = {}
...@@ -83,9 +85,5 @@ module Geo ...@@ -83,9 +85,5 @@ module Geo
def type def type
self.class.type self.class.type
end end
def log(message)
Rails.logger.info("#{self.class.name}: #{message} for project #{project.path_with_namespace} (#{project.id})")
end
end end
end end
...@@ -33,7 +33,7 @@ module Geo ...@@ -33,7 +33,7 @@ module Geo
Geo::EventLog.create!("#{self.class.event_type}" => build_event) Geo::EventLog.create!("#{self.class.event_type}" => build_event)
rescue ActiveRecord::RecordInvalid, NoMethodError => e rescue ActiveRecord::RecordInvalid, NoMethodError => e
log("#{self.event_type.to_s.humanize} could not be created", e) log_error("#{self.event_type.to_s.humanize} could not be created", e)
end end
private private
...@@ -43,8 +43,13 @@ module Geo ...@@ -43,8 +43,13 @@ module Geo
"#{self.class} does not implement #{__method__}" "#{self.class} does not implement #{__method__}"
end end
def log(message, error) def log_error(message, error)
Rails.logger.error("#{self.class.name}: #{message} for project #{project.path_with_namespace} (#{project.id}): #{error}") Gitlab::Geo::Logger.error(
class: self.class.name,
message: message,
error: error,
project_id: project.id,
project_path: project.path_with_namespace)
end end
end end
end end
...@@ -15,8 +15,8 @@ module Geo ...@@ -15,8 +15,8 @@ module Geo
def downloader def downloader
klass = "Gitlab::Geo::#{service_klass_name}Downloader".constantize klass = "Gitlab::Geo::#{service_klass_name}Downloader".constantize
klass.new(object_type, object_db_id) klass.new(object_type, object_db_id)
rescue NameError rescue NameError => e
log("Unknown file type: #{object_type}") log_error('Unknown file type', e)
raise raise
end end
......
...@@ -27,8 +27,24 @@ module Geo ...@@ -27,8 +27,24 @@ module Geo
klass_name.camelize klass_name.camelize
end end
def log(message) def log_info(message)
Rails.logger.info "#{self.class.name}: #{message}" data = log_base_data(message)
Gitlab::Geo::Logger.info(data)
end
def log_error(message, error)
data = log_base_data(message)
data[:error] = error
Gitlab::Geo::Logger.error(data)
end
def log_base_data(message)
{
class: self.class.name,
object_type: object_type,
object_db_id: object_db_id,
message: message
}
end end
end end
end end
...@@ -21,8 +21,8 @@ module Geo ...@@ -21,8 +21,8 @@ module Geo
def uploader_klass def uploader_klass
"Gitlab::Geo::#{service_klass_name}Uploader".constantize "Gitlab::Geo::#{service_klass_name}Uploader".constantize
rescue NameError rescue NameError => e
log("Unknown file type: #{object_type}") log_error('Unknown file type', e)
raise raise
end end
end end
......
...@@ -20,10 +20,15 @@ module Geo ...@@ -20,10 +20,15 @@ module Geo
next unless node.enabled? next unless node.enabled?
notify_url = node.send(notify_url_method.to_sym) notify_url = node.send(notify_url_method.to_sym)
success, message = notify(notify_url, content) success, details = notify(notify_url, content)
unless success unless success
Rails.logger.error("GitLab failed to notify #{node.url} to #{notify_url} : #{message}") Gitlab::Geo::Logger.error(
class: self.class.name,
message: "GitLab failed to notify",
error: details,
node_url: node.url,
notify_url: notify_url)
queue.store_batched_data(projects) queue.store_batched_data(projects)
end end
end end
......
...@@ -10,7 +10,7 @@ module Geo ...@@ -10,7 +10,7 @@ module Geo
end end
def fetch_project_repository def fetch_project_repository
log('Fetching project repository') log_info('Fetching project repository')
update_registry(:repository, started_at: DateTime.now) update_registry(:repository, started_at: DateTime.now)
begin begin
...@@ -19,16 +19,16 @@ module Geo ...@@ -19,16 +19,16 @@ module Geo
update_registry(:repository, finished_at: DateTime.now) update_registry(:repository, finished_at: DateTime.now)
rescue Gitlab::Shell::Error, Geo::EmptyCloneUrlPrefixError => e rescue Gitlab::Shell::Error, Geo::EmptyCloneUrlPrefixError => e
Rails.logger.error("#{self.class.name}: Error syncing repository for project #{project.path_with_namespace}: #{e}") log_error("Error syncing repository", e)
rescue Gitlab::Git::Repository::NoRepository => e rescue Gitlab::Git::Repository::NoRepository => e
Rails.logger.error("#{self.class.name}: Error invalid repository for project #{project.path_with_namespace}: #{e}") log_error("Invalid repository", e)
log('Expiring caches') log_info('Expiring caches')
project.repository.after_create project.repository.after_create
end end
end end
def expire_repository_caches def expire_repository_caches
log('Expiring caches') log_info('Expiring caches')
project.repository.after_sync project.repository.after_sync
end end
......
module Geo module Geo
class RepositoryUpdateService class RepositoryUpdateService
include Gitlab::Geo::ProjectLogHelpers
attr_reader :project, :clone_url, :logger attr_reader :project, :clone_url, :logger
LEASE_TIMEOUT = 1.hour.freeze LEASE_TIMEOUT = 1.hour.freeze
...@@ -21,21 +23,21 @@ module Geo ...@@ -21,21 +23,21 @@ module Geo
project.repository.expire_content_cache project.repository.expire_content_cache
end end
rescue Gitlab::Shell::Error => e rescue Gitlab::Shell::Error => e
logger.error "#{self.class.name}: Error fetching repository for project #{project.path_with_namespace}: #{e}" log_error('Error fetching repository for project', e)
rescue Gitlab::Git::Repository::NoRepository => e rescue Gitlab::Git::Repository::NoRepository => e
logger.error "#{self.class.name}: Error invalid repository for project #{project.path_with_namespace}: #{e}" log_error('Error invalid repository', e)
logger.warn "#{self.class.name}: Invalidating cache for project #{project.path_with_namespace}" log_info('Invalidating cache for project')
project.repository.after_create project.repository.after_create
end end
private private
def try_obtain_lease def try_obtain_lease
log('Trying to obtain lease to sync repository') log_info('Trying to obtain lease to sync repository')
repository_lease = Gitlab::ExclusiveLease.new(lease_key, timeout: LEASE_TIMEOUT).try_obtain repository_lease = Gitlab::ExclusiveLease.new(lease_key, timeout: LEASE_TIMEOUT).try_obtain
unless repository_lease.present? unless repository_lease.present?
log('Could not obtain lease to sync repository') log_info('Could not obtain lease to sync repository')
return return
end end
...@@ -43,7 +45,7 @@ module Geo ...@@ -43,7 +45,7 @@ module Geo
begin begin
yield yield
ensure ensure
log('Releasing leases to sync repository') log_info('Releasing leases to sync repository')
Gitlab::ExclusiveLease.cancel(lease_key, repository_lease) Gitlab::ExclusiveLease.cancel(lease_key, repository_lease)
end end
end end
...@@ -51,9 +53,5 @@ module Geo ...@@ -51,9 +53,5 @@ module Geo
def lease_key def lease_key
@lease_key ||= "#{LEASE_KEY_PREFIX}:#{project.id}" @lease_key ||= "#{LEASE_KEY_PREFIX}:#{project.id}"
end end
def log(message)
logger.info("#{self.class.name}: #{message} for project #{project.path_with_namespace} (#{project.id})")
end
end end
end end
...@@ -9,7 +9,7 @@ module Geo ...@@ -9,7 +9,7 @@ module Geo
end end
def fetch_wiki_repository def fetch_wiki_repository
log('Fetching wiki repository') log_info('Fetching wiki repository')
update_registry(:wiki, started_at: DateTime.now) update_registry(:wiki, started_at: DateTime.now)
begin begin
...@@ -21,7 +21,7 @@ module Geo ...@@ -21,7 +21,7 @@ module Geo
Gitlab::Shell::Error, Gitlab::Shell::Error,
ProjectWiki::CouldNotCreateWikiError, ProjectWiki::CouldNotCreateWikiError,
Geo::EmptyCloneUrlPrefixError => e Geo::EmptyCloneUrlPrefixError => e
Rails.logger.error("#{self.class.name}: Error syncing wiki repository for project #{project.path_with_namespace}: #{e}") log_error("Error syncing wiki repository", e)
end end
end end
......
module Gitlab
module Geo
class Logger < ::Gitlab::JsonLogger
def self.file_name_noext
'geo'
end
end
end
end
module Gitlab
module Geo
module ProjectLogHelpers
def log_info(message)
data = base_log_data(message)
Gitlab::Geo::Logger.info(data)
end
def log_error(message, error)
data = base_log_data(message)
data[:error] = error
Gitlab::Geo::Logger.error(data)
end
private
def base_log_data(message)
{
class: self.class.name,
project_id: project.id,
project_path: project.path_with_namespace,
message: message
}
end
end
end
end
module Gitlab
class JsonLogger < ::Gitlab::Logger
def self.file_name_noext
raise NotImplementedError
end
def format_message(severity, timestamp, progname, message)
data = {}
data[:severity] = severity
data[:time] = timestamp.utc.iso8601(3)
case message
when String
data[:message] = message
when Hash
data.merge!(message)
end
data.to_json + "\n"
end
end
end
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment