feat: experimental measurement protol reporting
This commit is contained in:
parent
0257299b5a
commit
0748249e1f
|
@ -1,18 +1,15 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
from __future__ import absolute_import
|
||||
|
||||
from six.moves.urllib.parse import urlencode
|
||||
import logging
|
||||
import threading
|
||||
|
||||
import requests
|
||||
|
||||
import ckan.plugins as p
|
||||
import ckan.plugins.toolkit as tk
|
||||
|
||||
from ckan.exceptions import CkanConfigurationException, CkanVersionException
|
||||
|
||||
from .. import helpers
|
||||
from .. import helpers, utils
|
||||
from ..logic import action, auth
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
@ -39,16 +36,8 @@ class AnalyticsPostThread(threading.Thread):
|
|||
def run(self):
|
||||
while True:
|
||||
# grabs host from queue
|
||||
data_dict = self.queue.get()
|
||||
|
||||
data = urlencode(data_dict)
|
||||
log.debug("Sending API event to Google Analytics: " + data)
|
||||
# send analytics
|
||||
requests.post(
|
||||
"http://www.google-analytics.com/collect",
|
||||
data,
|
||||
timeout=10,
|
||||
)
|
||||
data = self.queue.get()
|
||||
utils.send_event(data)
|
||||
# signals to queue job is done
|
||||
self.queue.task_done()
|
||||
|
||||
|
|
|
@ -1,9 +1,16 @@
|
|||
import ast
|
||||
import json
|
||||
import logging
|
||||
|
||||
import requests
|
||||
from six.moves.urllib.parse import urlencode
|
||||
import ckantoolkit as tk
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
DEFAULT_RESOURCE_URL_TAG = "/downloads/"
|
||||
DEFAULT_RECENT_VIEW_DAYS = 14
|
||||
EVENT_API = "CKAN API Request"
|
||||
|
||||
|
||||
def config_id():
|
||||
|
@ -26,6 +33,20 @@ def config_tracking_mode():
|
|||
return "ga"
|
||||
|
||||
|
||||
def config_measurement_protocol_client_id():
|
||||
return tk.config.get("googleanalytics.measurement_protocol.client_id")
|
||||
|
||||
|
||||
def config_measurement_protocol_client_secret():
|
||||
return tk.config.get("googleanalytics.measurement_protocol.client_secret")
|
||||
|
||||
|
||||
def config_measurement_protocol_api_whitelist():
|
||||
return tk.aslist(
|
||||
tk.config.get("googleanalytics.measurement_protocol.api_tracking_whitelist")
|
||||
)
|
||||
|
||||
|
||||
def config_account():
|
||||
return tk.config.get("googleanalytics.account")
|
||||
|
||||
|
@ -74,3 +95,75 @@ def config_recent_view_days():
|
|||
"googleanalytics.recent_view_days", DEFAULT_RECENT_VIEW_DAYS
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
def send_event(data):
|
||||
if isinstance(data, MeasurementProtocolData):
|
||||
if data["event"] != EVENT_API:
|
||||
log.warning("Only API event supported by Measurement Protocol at the moment")
|
||||
return
|
||||
|
||||
return _mp_api_handler({
|
||||
"action": data["object"],
|
||||
"payload": data["payload"],
|
||||
})
|
||||
|
||||
|
||||
return _ga_handler(data)
|
||||
|
||||
|
||||
class SafeJSONEncoder(json.JSONEncoder):
|
||||
def default(self, _):
|
||||
return None
|
||||
|
||||
|
||||
def _mp_api_handler(data_dict):
|
||||
whitelist = set(config_measurement_protocol_api_whitelist())
|
||||
if whitelist and data_dict["action"] not in whitelist:
|
||||
log.debug(
|
||||
"Skip sending %s API action to Google Analytics because it is not whitelisted",
|
||||
data_dict["action"]
|
||||
)
|
||||
return
|
||||
|
||||
log.debug(
|
||||
"Sending API event to Google Analytics using the Measurement Protocol: %s",
|
||||
data_dict
|
||||
)
|
||||
resp = requests.post(
|
||||
"https://www.google-analytics.com/mp/collect",
|
||||
params={
|
||||
"api_secret": config_measurement_protocol_client_secret(),
|
||||
"measurement_id": config_id()
|
||||
},
|
||||
data=json.dumps({
|
||||
"client_id": config_measurement_protocol_client_id(),
|
||||
"non_personalized_ads": False,
|
||||
"events":[{
|
||||
"name": data_dict["action"],
|
||||
"params": data_dict["payload"]
|
||||
}]
|
||||
}, cls=SafeJSONEncoder)
|
||||
)
|
||||
# breakpoint()
|
||||
if resp.status_code >= 300:
|
||||
log.error("Cannot post event: %s", resp)
|
||||
|
||||
|
||||
def _ga_handler(data_dict):
|
||||
data = urlencode(data_dict)
|
||||
log.debug("Sending API event to Google Analytics: %s", data)
|
||||
|
||||
requests.post(
|
||||
"http://www.google-analytics.com/collect",
|
||||
data,
|
||||
timeout=10,
|
||||
)
|
||||
|
||||
|
||||
class UniversalAnalyticsData(dict):
|
||||
pass
|
||||
|
||||
|
||||
class MeasurementProtocolData(dict):
|
||||
pass
|
||||
|
|
|
@ -12,6 +12,7 @@ import ckan.views.api as api
|
|||
import ckan.views.resource as resource
|
||||
|
||||
from ckan.common import g
|
||||
from . import utils
|
||||
|
||||
CONFIG_HANDLER_PATH = "googleanalytics.download_handler"
|
||||
|
||||
|
@ -30,7 +31,7 @@ def action(logic_function, ver=api.API_MAX_VERSION):
|
|||
id = request_data["q"]
|
||||
if "query" in request_data:
|
||||
id = request_data[u"query"]
|
||||
_post_analytics(g.user, "CKAN API Request", logic_function, "", id)
|
||||
_post_analytics(g.user, utils.EVENT_API, logic_function, "", id, request_data)
|
||||
except Exception as e:
|
||||
log.debug(e)
|
||||
pass
|
||||
|
@ -87,13 +88,24 @@ ga.add_url_rule(
|
|||
|
||||
|
||||
def _post_analytics(
|
||||
user, event_type, request_obj_type, request_function, request_id
|
||||
user, event_type,
|
||||
request_obj_type, request_function,
|
||||
request_id, request_payload=None
|
||||
):
|
||||
|
||||
from ckanext.googleanalytics.plugin import GoogleAnalyticsPlugin
|
||||
|
||||
if tk.config.get("googleanalytics.id"):
|
||||
data_dict = {
|
||||
if utils.config_measurement_protocol_client_id() and event_type == utils.EVENT_API:
|
||||
data_dict = utils.MeasurementProtocolData({
|
||||
"event": event_type,
|
||||
"object": event_type,
|
||||
"function": event_type,
|
||||
"id": request_id,
|
||||
"payload": request_payload,
|
||||
})
|
||||
else:
|
||||
data_dict = utils.UniversalAnalyticsData({
|
||||
"v": 1,
|
||||
"tid": tk.config.get("googleanalytics.id"),
|
||||
"cid": hashlib.md5(six.ensure_binary(tk.c.user)).hexdigest(),
|
||||
|
@ -105,5 +117,5 @@ def _post_analytics(
|
|||
"ec": event_type,
|
||||
"ea": request_obj_type + request_function,
|
||||
"el": request_id,
|
||||
}
|
||||
})
|
||||
GoogleAnalyticsPlugin.analytics_queue.put(data_dict)
|
||||
|
|
Loading…
Reference in New Issue