Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

HDX-9798 add page view for /docs + fix tests #88

Merged
merged 3 commits into from
May 9, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
from fastapi import Request, BackgroundTasks

from hdx_hapi.config.config import get_config
from hdx_hapi.endpoints.middleware.util.util import track_api_call
from hdx_hapi.endpoints.middleware.util.util import track_api_call, track_page_view

import logging

Expand All @@ -26,6 +26,11 @@ async def mixpanel_tracking_middleware(request: Request, call_next):
else:
logger.warning('HDX_MIXPANEL_TOKEN environment variable is not set.')

if request.url.path.startswith('/docs'):
if CONFIG.HDX_MIXPANEL_TOKEN:
background_tasks.add_task(track_page_view, request, response)
else:
logger.warning('HDX_MIXPANEL_TOKEN environment variable is not set.')
response.background = background_tasks

return response
33 changes: 31 additions & 2 deletions hdx_hapi/endpoints/middleware/util/util.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@

logger = logging.getLogger(__name__)


async def track_api_call(request: Request, response: Response):
current_url = str(request.url)
endpoint = request.url.path
Expand Down Expand Up @@ -44,19 +45,47 @@ async def track_api_call(request: Request, response: Response):
'$os': ua_os,
'$browser': ua_browser,
'$browser_version': ua_browser_version,
'$current_url': current_url
'$current_url': current_url,
}
await send_mixpanel_event('api call', distinct_id, mixpanel_dict)


async def track_page_view(request: Request, response: Response):
current_url = str(request.url)
user_agent_string = request.headers.get('user-agent', '')
ip_address = request.headers.get('HTTP_X_REAL_IP', '')
response_code = response.status_code
distinct_id = HashCodeGenerator({'ip': ip_address, 'ua': user_agent_string}).compute_hash()
event_time = time.time()
ua_dict = useragent.Parse(user_agent_string)
ua_os = ua_dict.get('os', {}).get('family')
ua_browser = ua_dict.get('user_agent', {}).get('family')
ua_browser_version = ua_dict.get('user_agent', {}).get('major')

page_view_dict = {
'page title': 'HAPI - OpenAPI Docs',
'time': event_time,
'server side': True,
'response code': response_code,
'user agent': user_agent_string,
'ip': ip_address,
'$os': ua_os,
'$browser': ua_browser,
'$browser_version': ua_browser_version,
'$current_url': current_url,
}
await send_mixpanel_event('page view', distinct_id, page_view_dict)


async def send_mixpanel_event(event_name: str, distinct_id: str, event_data: dict):
mixpanel.track(distinct_id, event_name, event_data)
mixpanel.track(distinct_id, event_name, event_data)


class HashCodeGenerator(object):
"""
Works only on simple dictionaries (not nested). At least the specified fields need to not be nested.
"""

def __init__(self, src_dict, field_list=None):
if not field_list and src_dict:
field_list = list(src_dict.keys())
Expand Down
11 changes: 5 additions & 6 deletions tests/test_analytics/test_api_call_tracking.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@ async def test_tracking_endpoint_success():
'hdx_hapi.endpoints.middleware.util.util.HashCodeGenerator.compute_hash',
return_value='123456',
):

async with AsyncClient(app=app, base_url=TEST_BASE_URL) as ac:
headers = {
'User-Agent': TEST_USER_AGENT,
Expand Down Expand Up @@ -49,17 +48,17 @@ async def test_tracking_endpoint_success():
'$current_url': f'{TEST_BASE_URL}/api/v1/themes/3w?admin_level=1&output_format=json',
}

send_mixpanel_event_patch.assert_called_once_with(
'api call', '123456', expected_mixpanel_dict
), 'Parameters do not match the expected ones'
(
send_mixpanel_event_patch.assert_called_once_with('api call', '123456', expected_mixpanel_dict),
'Parameters do not match the expected ones',
)


@pytest.mark.asyncio
async def test_docs_page_not_tracked():
with patch('hdx_hapi.endpoints.middleware.util.util.send_mixpanel_event') as send_mixpanel_event_patch:

async with AsyncClient(app=app, base_url=TEST_BASE_URL) as ac:
response = await ac.get('/docs')

assert response.status_code == 200
assert send_mixpanel_event_patch.call_count == 0, 'Docs page should not be tracked as an API call'
assert send_mixpanel_event_patch.call_count > 0, 'Docs page should be tracked as a page view'
7 changes: 3 additions & 4 deletions tests/test_endpoints/test_endpoints_vs_encode_identifier.py
Original file line number Diff line number Diff line change
Expand Up @@ -52,12 +52,11 @@ async def test_encode_identifier(event_loop, refresh_db, enable_hapi_identifier_
# testing the encode identifier endpoint
endpoint_router = '/api/v1/encode_identifier'

# it should not be important if app_identifier is passed or not to the endpoint
async with AsyncClient(app=app, base_url='http://test') as ac:
response = await ac.get(endpoint_router)
assert response.status_code == 200
assert response.status_code == 422

async with AsyncClient(app=app, base_url='http://test', params=query_parameters) as ac:
response = await ac.get(endpoint_router)
assert response.status_code == 200
response_items = response.json()
assert len(response_items) > 0
assert response.status_code == 422
Loading