import time from datetime import datetime, timedelta import uuid from urllib import parse from django.views.generic import View from django.http import HttpResponse, JsonResponse from django.http.request import validate_host, split_domain_port from django.conf import settings from django.utils.decorators import method_decorator from django.views.decorators.cache import never_cache from pingcap_sso.user_behavior_track import report_event from pingcap_sso.utils.requests import get_client_agent, get_client_ip from pingcap_sso.user_behavior_track.models import TrackEvent class EventView(View): TRACK_ID_COOKIE_NAME = '_track_id' TRACK_USER_OPENID_COOKIE_NAME = 'uid' TRACK_EVENTS = { 'pageview': '访问了页面', 'event': '触发自定义事件' } def dispatch(self, request, *args, **kwargs): origin = request.META.get('HTTP_ORIGIN') host = None if origin: host = parse.urlparse(origin).hostname else: host = request.get_host() # host is not exist in header if user visit page at file:///index.html if not host: return JsonResponse({'detail': 'invalid host'}, status=400) if not validate_host( split_domain_port(host)[0], settings.TRUSTED_HOSTS): return JsonResponse({'detail': 'invalid host'}, status=400) track_id = request.COOKIES.get(self.TRACK_ID_COOKIE_NAME) or self._generate_tack_id() uid = None cookie_uid = request.COOKIES.get(self.TRACK_USER_OPENID_COOKIE_NAME) query_uid = request.GET.get('uid') if request.user.is_authenticated: uid = request.user.openid elif cookie_uid: uid = cookie_uid else: uid = query_uid response = super(EventView, self).dispatch( request, host, track_id, uid, *args, **kwargs) response.set_cookie( self.TRACK_ID_COOKIE_NAME, track_id, expires=datetime.utcnow() + timedelta(days=730), domain=settings.SESSION_COOKIE_DOMAIN ) return response @method_decorator(never_cache) def get(self, request, host, track_id, uid, *args, **kwargs): data = request.GET dl = data.get('dl') # document.location.href dr = data.get('dr') # document.referrer dt = data.get('dt') # document.title ts = data.get('ts') # 客户端时间戳 ul = data.get('ul') # navigator.language sr = data.get('sr') # 屏幕宽度 version = data.get('v') # 事件版本号 event = data.get('e') # 事件类型 if not dl: return JsonResponse({'detail': 'invalid payload'}, status=400) if event not in self.TRACK_EVENTS: return JsonResponse({'detail': 'invalid events'}, status=400) _url_parse = parse.urlparse(dl) pure_url = '{}://{}{}'.format(_url_parse.scheme, _url_parse.netloc, _url_parse.path) utm = dict(parse.parse_qsl(_url_parse.query)) utm_source = utm.get('utm_source') utm_medium = utm.get('utm_medium') utm_campaign = utm.get('utm_campaign') event_desc = self.TRACK_EVENTS[event] if event == 'pageview': if host == 'docs.pingcap.com': event_desc = '浏览了文档' elif host == 'forms.pingcap.com': event_desc = '打开了表单' description = '{event} [{title}]({url})'.format( event=event_desc, title=dt, url=dl) event_type = 'site.{}.{}'.format( host.replace('.', '#'), event ) event_body = { 'dl': dl, 'dr': dr, 'ts': ts, 'ul': ul, 'dt': dt, 'sr': sr, 'e': event, 'v': version, 'pure_url': pure_url } report_event( openid=uid, event_type=event_type, event_body=event_body, track_id=track_id, user_agent=get_client_agent(request), ip=get_client_ip(request), pure_url=pure_url[:255], utm_source=utm_source[:64] if utm_source else None, utm_medium=utm_medium[:64] if utm_medium else None, utm_campaign=utm_campaign[:64] if utm_campaign else None, description=description, source=TrackEvent.SOURCE_BROWSER ) return HttpResponse() def _generate_tack_id(self): return '{}.{}'.format(uuid.uuid1(), int(time.time()))