Logger for geocoder metrics
This commit is contained in:
parent
0b4d1bb17f
commit
ac1627b5c5
@ -146,6 +146,18 @@ class InternalGeocoderConfig(ServiceConfig):
|
|||||||
def service_type(self):
|
def service_type(self):
|
||||||
return 'geocoder_internal'
|
return 'geocoder_internal'
|
||||||
|
|
||||||
|
@property
|
||||||
|
def is_high_resolution(self):
|
||||||
|
return False
|
||||||
|
|
||||||
|
@property
|
||||||
|
def cost_per_hit(self):
|
||||||
|
return 0
|
||||||
|
|
||||||
|
@property
|
||||||
|
def geocoding_quota(self):
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
class GeocoderConfig(ServiceConfig):
|
class GeocoderConfig(ServiceConfig):
|
||||||
|
|
||||||
@ -168,6 +180,7 @@ class GeocoderConfig(ServiceConfig):
|
|||||||
USERNAME_KEY = 'username'
|
USERNAME_KEY = 'username'
|
||||||
ORGNAME_KEY = 'orgname'
|
ORGNAME_KEY = 'orgname'
|
||||||
PERIOD_END_DATE = 'period_end_date'
|
PERIOD_END_DATE = 'period_end_date'
|
||||||
|
LOG_PATH = '/var/log/postgresql/geocodings.log'
|
||||||
|
|
||||||
def __init__(self, redis_connection, username, orgname=None,
|
def __init__(self, redis_connection, username, orgname=None,
|
||||||
heremaps_app_id=None, heremaps_app_code=None):
|
heremaps_app_id=None, heremaps_app_code=None):
|
||||||
@ -256,7 +269,10 @@ class GeocoderConfig(ServiceConfig):
|
|||||||
|
|
||||||
@property
|
@property
|
||||||
def geocoding_quota(self):
|
def geocoding_quota(self):
|
||||||
return self._geocoding_quota
|
if self.heremaps_geocoder:
|
||||||
|
return self._geocoding_quota
|
||||||
|
else:
|
||||||
|
return None
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def soft_geocoding_limit(self):
|
def soft_geocoding_limit(self):
|
||||||
@ -273,3 +289,18 @@ class GeocoderConfig(ServiceConfig):
|
|||||||
@property
|
@property
|
||||||
def heremaps_app_code(self):
|
def heremaps_app_code(self):
|
||||||
return self._heremaps_app_code
|
return self._heremaps_app_code
|
||||||
|
|
||||||
|
@property
|
||||||
|
def is_high_resolution(self):
|
||||||
|
return True
|
||||||
|
|
||||||
|
@property
|
||||||
|
def cost_per_hit(self):
|
||||||
|
if self.heremaps_geocoder:
|
||||||
|
return 1
|
||||||
|
else:
|
||||||
|
return 0
|
||||||
|
|
||||||
|
@property
|
||||||
|
def log_path(self):
|
||||||
|
return self.LOG_PATH
|
||||||
|
@ -0,0 +1,74 @@
|
|||||||
|
|
||||||
|
import abc
|
||||||
|
import json
|
||||||
|
import re
|
||||||
|
|
||||||
|
|
||||||
|
class LoggerFactory:
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def build(self, service_config):
|
||||||
|
if re.match('geocoder_*', service_config.service_type):
|
||||||
|
return GeocoderLogger(service_config)
|
||||||
|
else:
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
|
class Logger(object):
|
||||||
|
__metaclass__ = abc.ABCMeta
|
||||||
|
|
||||||
|
def __init__(self, file_path):
|
||||||
|
self._file_path = file_path
|
||||||
|
|
||||||
|
def dump_to_file(self, data):
|
||||||
|
with open(self._file_path, 'a') as logfile:
|
||||||
|
json.dump(data, logfile)
|
||||||
|
|
||||||
|
@abc.abstractproperty
|
||||||
|
def log(self, **data):
|
||||||
|
raise NotImplementedError('log method must be defined')
|
||||||
|
|
||||||
|
|
||||||
|
class GeocoderLogger(Logger):
|
||||||
|
|
||||||
|
def __init__(self, service_config):
|
||||||
|
super(GeocoderLogger, self).__init__(service_config.log_path)
|
||||||
|
self._service_config = service_config
|
||||||
|
|
||||||
|
def log(self, **data):
|
||||||
|
dump_data = self._dump_data(**data)
|
||||||
|
self.dump_to_file(dump_data)
|
||||||
|
|
||||||
|
def _dump_data(self, **data):
|
||||||
|
if data['success']:
|
||||||
|
cost = self._service_config.cost_per_hit
|
||||||
|
failed_rows = 0
|
||||||
|
successful_rows = 1
|
||||||
|
else:
|
||||||
|
cost = 0
|
||||||
|
failed_rows = 1
|
||||||
|
successful_rows = 0
|
||||||
|
|
||||||
|
if self._service_config.is_high_resolution:
|
||||||
|
kind = 'high-resolution'
|
||||||
|
else:
|
||||||
|
kind = 'internal'
|
||||||
|
|
||||||
|
return {
|
||||||
|
"batched": False,
|
||||||
|
"cache_hits": 0, # Always 0 because no cache involved
|
||||||
|
# https://github.com/CartoDB/cartodb/blob/master/app/models/geocoding.rb#L208-L211
|
||||||
|
"cost": cost,
|
||||||
|
"created_at": datetime.now().isoformat(),
|
||||||
|
"failed_rows": failed_rows,
|
||||||
|
"geocoder_type": self._service_config.service_type,
|
||||||
|
"kind": kind,
|
||||||
|
"processable_rows": 1,
|
||||||
|
"processed_rows": successful_rows,
|
||||||
|
"real_rows": successful_rows,
|
||||||
|
"success": data['success'],
|
||||||
|
"successful_rows": successful_rows,
|
||||||
|
"used_credits": 0,
|
||||||
|
"username": self._service_config.username,
|
||||||
|
"organization": self._service_config.organization
|
||||||
|
}
|
@ -1,19 +1,20 @@
|
|||||||
from user import UserMetricsService
|
from user import UserMetricsService
|
||||||
|
from log import LoggerFactory
|
||||||
from datetime import date
|
from datetime import date
|
||||||
import re
|
import re
|
||||||
|
|
||||||
|
|
||||||
class QuotaService:
|
class QuotaService:
|
||||||
""" Class to manage all the quota operation for
|
""" Class to manage all the quota operation for
|
||||||
the Geocoder SQL API Extension """
|
the Dataservices SQL API Extension """
|
||||||
|
|
||||||
def __init__(self, user_service_config, redis_connection):
|
def __init__(self, user_service_config, redis_connection):
|
||||||
self._user_service_config = user_service_config
|
self._user_service_config = user_service_config
|
||||||
# TODO First step to extract to a factory if needed in the future
|
|
||||||
self._quota_checker = QuotaChecker(user_service_config,
|
self._quota_checker = QuotaChecker(user_service_config,
|
||||||
redis_connection)
|
redis_connection)
|
||||||
self._user_service = UserMetricsService(
|
self._user_service = UserMetricsService(self._user_service_config,
|
||||||
self._user_service_config, redis_connection)
|
redis_connection)
|
||||||
|
self._logger = LoggerFactory.build(user_service_config)
|
||||||
|
|
||||||
def check_user_quota(self):
|
def check_user_quota(self):
|
||||||
return self._quota_checker.check()
|
return self._quota_checker.check()
|
||||||
@ -22,16 +23,19 @@ class QuotaService:
|
|||||||
self._user_service.increment_service_use(
|
self._user_service.increment_service_use(
|
||||||
self._user_service_config.service_type, "success_responses",
|
self._user_service_config.service_type, "success_responses",
|
||||||
amount=amount)
|
amount=amount)
|
||||||
|
self._log_service_process("success")
|
||||||
|
|
||||||
def increment_empty_service_use(self, amount=1):
|
def increment_empty_service_use(self, amount=1):
|
||||||
self._user_service.increment_service_use(
|
self._user_service.increment_service_use(
|
||||||
self._user_service_config.service_type, "empty_responses",
|
self._user_service_config.service_type, "empty_responses",
|
||||||
amount=amount)
|
amount=amount)
|
||||||
|
self._log_service_process("empty")
|
||||||
|
|
||||||
def increment_failed_service_use(self, amount=1):
|
def increment_failed_service_use(self, amount=1):
|
||||||
self._user_service.increment_service_use(
|
self._user_service.increment_service_use(
|
||||||
self._user_service_config.service_type, "fail_responses",
|
self._user_service_config.service_type, "fail_responses",
|
||||||
amount=amount)
|
amount=amount)
|
||||||
|
self._log_service_process("fail")
|
||||||
|
|
||||||
def increment_total_service_use(self, amount=1):
|
def increment_total_service_use(self, amount=1):
|
||||||
self._user_service.increment_service_use(
|
self._user_service.increment_service_use(
|
||||||
@ -43,6 +47,13 @@ class QuotaService:
|
|||||||
self._user_service_config.service_type, "isolines_generated",
|
self._user_service_config.service_type, "isolines_generated",
|
||||||
amount=amount)
|
amount=amount)
|
||||||
|
|
||||||
|
def _log_service_process(self, event):
|
||||||
|
if self._logger:
|
||||||
|
if event is 'success' or event is 'empty':
|
||||||
|
self._logger.log(success=True)
|
||||||
|
elif event is 'empty':
|
||||||
|
self._logger.log(success=False)
|
||||||
|
|
||||||
|
|
||||||
class QuotaChecker:
|
class QuotaChecker:
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user