Python Event Tracking System
This challenge asks you to build a foundational event tracking system in Python. Event tracking is crucial for understanding user behavior, monitoring application performance, and debugging issues. You will implement a system that can record and retrieve events with associated metadata.
Problem Description
You need to create a Python class, EventTracker, that can:
- Record Events: Accept events with a type (string) and an optional dictionary of metadata.
- Retrieve Events: Allow retrieval of all recorded events or events filtered by their type.
- Count Events: Provide a way to count the total number of events or the number of events of a specific type.
Key Requirements:
- The
EventTrackerclass should maintain an internal storage for all recorded events. - Each recorded event should store its type and its metadata.
- The system should handle events with identical types.
- The metadata associated with an event can be an empty dictionary.
Expected Behavior:
- When an event is recorded, it should be added to the tracker's internal storage.
- Retrieving all events should return a list of all recorded events.
- Retrieving events by type should return a list containing only events of that specified type.
- Counting all events should return the total number of recorded events.
- Counting events by type should return the number of events matching the specified type.
Edge Cases to Consider:
- Recording an event with no metadata.
- Retrieving events when no events have been recorded.
- Retrieving events of a type that has not been recorded.
- Counting events of a type that has not been recorded.
Examples
Example 1:
tracker = EventTracker()
tracker.record_event("page_view", {"url": "/home", "user_id": "user123"})
tracker.record_event("click", {"element_id": "cta-button", "user_id": "user123"})
tracker.record_event("page_view", {"url": "/about", "user_id": "user456"})
all_events = tracker.get_all_events()
print(f"All events: {all_events}")
page_views = tracker.get_events_by_type("page_view")
print(f"Page views: {page_views}")
click_count = tracker.count_events_by_type("click")
print(f"Click count: {click_count}")
Output:
All events: [{'type': 'page_view', 'metadata': {'url': '/home', 'user_id': 'user123'}}, {'type': 'click', 'metadata': {'element_id': 'cta-button', 'user_id': 'user123'}}, {'type': 'page_view', 'metadata': {'url': '/about', 'user_id': 'user456'}}]
Page views: [{'type': 'page_view', 'metadata': {'url': '/home', 'user_id': 'user123'}}, {'type': 'page_view', 'metadata': {'url': '/about', 'user_id': 'user456'}}]
Click count: 1
Explanation:
The record_event method is used three times to store different events. get_all_events returns all three. get_events_by_type("page_view") filters and returns only the "page_view" events. count_events_by_type("click") returns the number of "click" events.
Example 2:
tracker = EventTracker()
tracker.record_event("login") # No metadata
tracker.record_event("logout", {}) # Empty metadata
print(f"Total events: {tracker.count_all_events()}")
print(f"Login events: {tracker.get_events_by_type('login')}")
Output:
Total events: 2
Login events: [{'type': 'login', 'metadata': {}}]
Explanation:
This example demonstrates recording events with no metadata (implicitly an empty dictionary) and with an explicitly empty dictionary. Both are handled correctly.
Example 3: Edge Case - No Events Recorded
tracker = EventTracker()
print(f"All events: {tracker.get_all_events()}")
print(f"Events of type 'error': {tracker.get_events_by_type('error')}")
print(f"Total events: {tracker.count_all_events()}")
print(f"Error count: {tracker.count_events_by_type('error')}")
Output:
All events: []
Events of type 'error': []
Total events: 0
Error count: 0
Explanation:
When no events are recorded, all retrieval and counting methods should gracefully return empty lists or zero counts.
Constraints
- The event type will always be a string.
- Metadata will always be a dictionary. It can be empty.
- The
EventTrackerclass should be able to handle at least 10,000 events without significant performance degradation. - No external libraries beyond Python's standard library are permitted.
Notes
- Consider how you will store the events. A list of dictionaries or custom objects would be suitable.
- Think about the structure of each recorded event – what information must it contain?
- The
record_eventmethod should accept both an event type and its metadata. If metadata is not provided by the caller, it should default to an empty dictionary. - The
get_events_by_typemethod should return a new list of events, not a reference to the internal storage, to prevent accidental modification.