From b746fa912e91b51afcfd642a704f2e78893f5e21 Mon Sep 17 00:00:00 2001 From: Dries Peeters Date: Thu, 16 Apr 2026 16:23:54 +0200 Subject: [PATCH] chore(analytics): remove dead PostHog feature-flag module Delete app/utils/posthog_features.py. It was unused by routes, and is_posthog_enabled() always returned False, so flags never activated and the API was misleading. Document the real model: deployment behavior uses environment variables and app/config.py; per-user UI preferences stay on the user record. Refresh PostHog monitoring guides and README accordingly, update the incomplete-implementations note, and soften posthog_segmentation wording so it does not imply an in-app PostHog flag layer. --- README.md | 3 +- app/utils/posthog_features.py | 269 ------------------ app/utils/posthog_segmentation.py | 3 +- docs/INCOMPLETE_IMPLEMENTATIONS_ANALYSIS.md | 15 +- .../monitoring/POSTHOG_ADVANCED_FEATURES.md | 219 ++------------ .../POSTHOG_ENHANCEMENTS_SUMMARY.md | 144 ++-------- .../monitoring/POSTHOG_QUICK_REFERENCE.md | 118 +------- 7 files changed, 52 insertions(+), 719 deletions(-) delete mode 100644 app/utils/posthog_features.py diff --git a/README.md b/README.md index d8c9e273..4e79fc2e 100644 --- a/README.md +++ b/README.md @@ -801,11 +801,12 @@ TimeTracker includes **optional** analytics and monitoring features to help impr #### 4. **Product Analytics** (Optional - Grafana OTLP) - Tracks feature usage and user behavior patterns with advanced features: - **Person Properties**: Role, auth method, login history - - **Feature Flags**: Gradual rollouts, A/B testing, kill switches - **Group Analytics**: Segment by version, platform, deployment - **Rich Context**: Browser, device, environment on every event - **Sink config:** Set `GRAFANA_OTLP_ENDPOINT` and `GRAFANA_OTLP_TOKEN` +**Rollouts and kill switches** in this application are not driven by remote PostHog feature flags. Use **environment variables** and [`app/config.py`](app/config.py) (for example `DEMO_MODE`, `ALLOW_SELF_REGISTER`, `ENABLE_TELEMETRY`, `SINGLE_ACTIVE_TIMER`). **Per-user UI visibility** preferences are stored on the user record in the database, not in PostHog. + #### 5. **Installation Telemetry** (Optional, Anonymous) - Sends anonymous installation data via Grafana OTLP with: - Anonymized fingerprint (SHA-256 hash, cannot be reversed) diff --git a/app/utils/posthog_features.py b/app/utils/posthog_features.py deleted file mode 100644 index f52d4742..00000000 --- a/app/utils/posthog_features.py +++ /dev/null @@ -1,269 +0,0 @@ -""" -PostHog Feature Flags and Advanced Features - -This module provides utilities for using PostHog's advanced features: -- Feature flags (for A/B testing and gradual rollouts) -- Experiments -- Feature enablement checks -- Remote configuration -""" - -import os -from functools import wraps -from typing import Any, Dict, Optional - -from flask import request - - -def is_posthog_enabled() -> bool: - """Legacy feature-flag hook; disabled after Grafana cutover.""" - return False - - -def get_feature_flag(user_id: Any, flag_key: str, default: bool = False) -> bool: - """ - Check if a feature flag is enabled for a user. - - Args: - user_id: The user ID (internal ID, not PII) - flag_key: The feature flag key in PostHog - default: Default value if PostHog is not configured - - Returns: - True if feature is enabled, False otherwise - """ - if not is_posthog_enabled(): - return default - - return default - - -def get_feature_flag_payload(user_id: Any, flag_key: str) -> Optional[Dict[str, Any]]: - """ - Get the payload for a feature flag (for remote configuration). - - Example usage: - config = get_feature_flag_payload(user.id, "new-dashboard-config") - if config: - theme = config.get("theme", "light") - features = config.get("features", []) - - Args: - user_id: The user ID - flag_key: The feature flag key - - Returns: - Dict with payload data, or None if not available - """ - if not is_posthog_enabled(): - return None - - return None - - -def get_all_feature_flags(user_id: Any) -> Dict[str, Any]: - """ - Get all feature flags for a user. - - Returns a dictionary of flag_key -> enabled/disabled - - Args: - user_id: The user ID - - Returns: - Dict of feature flags - """ - if not is_posthog_enabled(): - return {} - - return {} - - -def feature_flag_required(flag_key: str, redirect_to: Optional[str] = None): - """ - Decorator to require a feature flag for a route. - - Usage: - @app.route('/beta-feature') - @feature_flag_required('beta-features') - def beta_feature(): - return "This is a beta feature!" - - Args: - flag_key: The feature flag key to check - redirect_to: URL to redirect to if flag is disabled (optional) - """ - - def decorator(f): - @wraps(f) - def decorated_function(*args, **kwargs): - from flask import abort, redirect, url_for - from flask_login import current_user - - if not current_user.is_authenticated: - # Can't check feature flags for anonymous users - if redirect_to: - return redirect(redirect_to) - abort(403) - - if not get_feature_flag(current_user.id, flag_key): - # Feature not enabled for this user - if redirect_to: - return redirect(redirect_to) - abort(403) - - return f(*args, **kwargs) - - return decorated_function - - return decorator - - -def get_active_experiments(user_id: Any) -> Dict[str, str]: - """ - Get active experiments and their variants for a user. - - This can be used for A/B testing and tracking which - variants users are seeing. - - Args: - user_id: The user ID - - Returns: - Dict of experiment_key -> variant - """ - flags = get_all_feature_flags(user_id) - - # Filter for experiments (flags that have variants) - experiments = {} - for flag_key, value in flags.items(): - if isinstance(value, str) and value not in ["true", "false"]: - # This is likely a multivariate flag (experiment) - experiments[flag_key] = value - - return experiments - - -def inject_feature_flags_to_frontend(user_id: Any) -> Dict[str, Any]: - """ - Get feature flags formatted for frontend injection. - - This can be used to inject feature flags into JavaScript - for frontend feature toggling. - - Usage in template: - - - Args: - user_id: The user ID - - Returns: - Dict of feature flags safe for frontend use - """ - if not is_posthog_enabled(): - return {} - - try: - flags = get_all_feature_flags(user_id) - # Convert to boolean values for frontend - return {key: bool(value) for key, value in flags.items()} - except Exception: - return {} - - -def override_feature_flag(user_id: Any, flag_key: str, value: bool): - """ - Override a feature flag for testing purposes. - - Note: This only works in development/testing environments. - - Args: - user_id: The user ID - flag_key: The feature flag key - value: The value to set - """ - if os.getenv("FLASK_ENV") not in ["development", "testing"]: - # Only allow overrides in dev/test - return - - try: - # Store override in session or cache - # This is a placeholder - implement based on your needs - pass - except Exception: - pass - - -def track_feature_flag_interaction(user_id: Any, flag_key: str, action: str, properties: Optional[Dict] = None): - """ - Track when users interact with features controlled by feature flags. - - This helps measure the impact of features and experiments. - - Args: - user_id: The user ID - flag_key: The feature flag key - action: The action taken (e.g., "clicked", "viewed", "completed") - properties: Additional properties to track - """ - from app import track_event - - event_properties = {"feature_flag": flag_key, "action": action, **(properties or {})} - - track_event(user_id, "feature_interaction", event_properties) - - -# Predefined feature flags for common use cases -class FeatureFlags: - """ - Centralized feature flag keys for the application. - - Define your feature flags here to avoid typos and enable autocomplete. - """ - - # Beta features - BETA_FEATURES = "beta-features" - NEW_DASHBOARD = "new-dashboard" - ADVANCED_REPORTS = "advanced-reports" - - # Experiments - TIMER_UI_EXPERIMENT = "timer-ui-experiment" - ONBOARDING_FLOW = "onboarding-flow" - - # Rollout features - NEW_ANALYTICS_PAGE = "new-analytics-page" - BULK_OPERATIONS = "bulk-operations" - - # Kill switches (for emergency feature disabling) - ENABLE_EXPORTS = "enable-exports" - ENABLE_API = "enable-api" - ENABLE_WEBSOCKETS = "enable-websockets" - - # Premium features (if you have paid tiers) - CUSTOM_REPORTS = "custom-reports" - API_ACCESS = "api-access" - INTEGRATIONS = "integrations" - - -# Example usage helper -def is_feature_enabled_for_request(flag_key: str, default: bool = False) -> bool: - """ - Check if a feature is enabled for the current request's user. - - Convenience function for use in templates and view functions. - - Args: - flag_key: The feature flag key - default: Default value if user not authenticated - - Returns: - True if feature is enabled - """ - from flask_login import current_user - - if not current_user.is_authenticated: - return default - - return get_feature_flag(current_user.id, flag_key, default) diff --git a/app/utils/posthog_segmentation.py b/app/utils/posthog_segmentation.py index cd8a8f9b..1c7d8468 100644 --- a/app/utils/posthog_segmentation.py +++ b/app/utils/posthog_segmentation.py @@ -20,9 +20,8 @@ def identify_user_with_segments(user_id: Any, user) -> None: This sets person properties in PostHog that can be used for: - Creating cohorts - - Targeting feature flags + - Analytics segmentation - Analyzing behavior by segment - - A/B testing Args: user_id: User ID diff --git a/docs/INCOMPLETE_IMPLEMENTATIONS_ANALYSIS.md b/docs/INCOMPLETE_IMPLEMENTATIONS_ANALYSIS.md index 363a5a61..306aa341 100644 --- a/docs/INCOMPLETE_IMPLEMENTATIONS_ANALYSIS.md +++ b/docs/INCOMPLETE_IMPLEMENTATIONS_ANALYSIS.md @@ -115,14 +115,9 @@ This document provides a comprehensive analysis of incomplete implementations, m #### 2.2 Telemetry (`app/utils/telemetry.py`) - **Status:** Implementation appears complete. -#### 2.3 PostHog Features (`app/utils/posthog_features.py`) -- **Line 202-205**: Placeholder implementations - ```python - # This is a placeholder - implement based on your needs - pass - ``` - **Impact:** PostHog feature flags may not be fully functional. - **Priority:** Low +#### 2.3 PostHog server-side feature flags (removed) + +The dedicated PostHog feature-flag helper under `app/utils/` was **removed**. Remote PostHog feature-flag evaluation is not part of this application; deployment behavior is controlled with **environment variables** and `app/config.py` instead. #### 2.4 Environment Validation (`app/utils/env_validation.py`) - **Line 14**: `pass` statement @@ -456,10 +451,6 @@ This document provides a comprehensive analysis of incomplete implementations, m - Implement info toast notifications - **Estimated Effort:** 1-2 hours -4. **PostHog Feature Flags** (`app/utils/posthog_features.py:202`) - - Complete PostHog feature flag implementation - - **Estimated Effort:** 4-6 hours - --- ## Testing Recommendations diff --git a/docs/admin/monitoring/POSTHOG_ADVANCED_FEATURES.md b/docs/admin/monitoring/POSTHOG_ADVANCED_FEATURES.md index 6235de97..57a8b5b7 100644 --- a/docs/admin/monitoring/POSTHOG_ADVANCED_FEATURES.md +++ b/docs/admin/monitoring/POSTHOG_ADVANCED_FEATURES.md @@ -4,14 +4,15 @@ This guide explains how to leverage PostHog's advanced features in TimeTracker f ## ๐Ÿ“Š What's Included -TimeTracker now uses these PostHog features: +TimeTracker uses these PostHog-related analytics capabilities where configured: 1. **Person Properties** - Track user and installation characteristics 2. **Group Analytics** - Segment by version, platform, etc. -3. **Feature Flags** - Gradual rollouts and A/B testing -4. **Identify Calls** - Rich user profiles in PostHog -5. **Enhanced Event Properties** - Contextual data for better analysis -6. **Group Identification** - Cohort analysis by installation type +3. **Identify Calls** - Rich user profiles in PostHog +4. **Enhanced Event Properties** - Contextual data for better analysis +5. **Group Identification** - Cohort analysis by installation type + +**Server-side feature gates** (rollouts, kill switches, route guards) are **not** implemented via PostHog in this codebase. Use environment variables and [`app/config.py`](../../../app/config.py) instead. ## ๐ŸŽฏ Person Properties @@ -102,109 +103,19 @@ Installations are automatically grouped by: - "How many Linux installations are active?" - "Which Python versions are most common on Windows?" -## ๐Ÿš€ Feature Flags +## ๐Ÿงช Experiments and measurement -### Basic Usage +There is no in-app PostHog feature-flag or variant API. To compare behaviors, implement variants in your own code (for example driven by `app.config`) and **distinguish them in analytics** with explicit properties on `track_event` calls (see below). -Check if a feature is enabled: +### Track meaningful actions ```python -from app.utils.posthog_features import get_feature_flag +from app import track_event -if get_feature_flag(user.id, "new-dashboard"): - return render_template("dashboard_v2.html") -else: - return render_template("dashboard.html") -``` - -### Route Protection - -Require a feature flag for entire routes: - -```python -from app.utils.posthog_features import feature_flag_required - -@app.route('/beta/advanced-analytics') -@feature_flag_required('beta-features') -def advanced_analytics(): - return render_template("analytics_beta.html") -``` - -### Remote Configuration - -Use feature flag payloads for configuration: - -```python -from app.utils.posthog_features import get_feature_flag_payload - -config = get_feature_flag_payload(user.id, "dashboard-config") -if config: - theme = config.get("theme", "light") - widgets = config.get("enabled_widgets", []) -``` - -### Frontend Feature Flags - -Inject flags into JavaScript: - -```python -# In your view function -from app.utils.posthog_features import inject_feature_flags_to_frontend - -@app.route('/dashboard') -def dashboard(): - feature_flags = inject_feature_flags_to_frontend(current_user.id) - return render_template("dashboard.html", feature_flags=feature_flags) -``` - -```html - - -``` - -### Predefined Feature Flags - -Use the `FeatureFlags` class to avoid typos: - -```python -from app.utils.posthog_features import FeatureFlags - -if get_feature_flag(user.id, FeatureFlags.ADVANCED_REPORTS): - # Enable advanced reports - pass -``` - -## ๐Ÿงช A/B Testing & Experiments - -### Track Experiment Variants - -```python -from app.utils.posthog_features import get_active_experiments - -experiments = get_active_experiments(user.id) -# {"timer-ui-experiment": "variant-b"} - -if experiments.get("timer-ui-experiment") == "variant-b": - # Show variant B - pass -``` - -### Track Feature Interactions - -```python -from app.utils.posthog_features import track_feature_flag_interaction - -track_feature_flag_interaction( +track_event( user.id, - "new-dashboard", - "clicked_export_button", - {"export_type": "csv", "rows": 100} + "export.completed", + {"export_type": "csv", "rows": 100, "experiment_variant": "b"}, ) ``` @@ -269,41 +180,6 @@ Event: timer.started Breakdown: Hour of day ``` -## ๐ŸŽจ Setting Up Feature Flags in PostHog - -### 1. Create a Feature Flag - -1. Go to PostHog โ†’ Feature Flags -2. Click "New feature flag" -3. Set key (e.g., `new-dashboard`) -4. Configure rollout: - - **Boolean**: On/off for everyone - - **Percentage**: Gradual rollout (e.g., 10% of users) - - **Person properties**: Target specific users - - **Groups**: Target specific platforms/versions - -### 2. Target Specific Users - -**Example: Enable for admins only** -``` -Match person properties: - is_admin = true -``` - -**Example: Enable for Docker installations** -``` -Match group properties: - deployment_method = "docker" -``` - -### 3. Gradual Rollout - -1. Start at 0% (disabled) -2. Roll out to 10% (testing) -3. Increase to 50% (beta) -4. Increase to 100% (full release) -5. Remove flag from code - ## ๐Ÿ” Person Properties for Segmentation ### Available Person Properties @@ -360,81 +236,40 @@ Person properties: 4. **Timer Usage** - `timer.started` events over time 5. **Export Activity** - `export.csv` events by user cohort -## ๐Ÿšจ Kill Switches +## ๐Ÿšจ Kill switches and rollouts (application) -Use feature flags as emergency kill switches: +To disable or limit behavior for **all users** of an installation, use **configuration**: environment variables and [`app/config.py`](../../../app/config.py). That requires a deploy or config change, which is the supported model for this codebase. -```python -from app.utils.posthog_features import get_feature_flag, FeatureFlags +## ๐Ÿง‘โ€๐Ÿ’ป Development best practices -@app.route('/api/export') -def api_export(): - if not get_feature_flag(current_user.id, FeatureFlags.ENABLE_EXPORTS, default=True): - abort(503, "Exports temporarily disabled") - - # Proceed with export -``` +### 1. Centralize deployment toggles -**Benefits:** -- Instantly disable problematic features -- No deployment needed -- Can target specific user segments -- Helps during incidents +Add booleans or strings to `Config` in `app/config.py` and read them from the environment with safe defaults. -## ๐Ÿง‘โ€๐Ÿ’ป Development Best Practices +### 2. Default to safe values -### 1. Define Flags Centrally +Prefer secure or conservative defaults for production (for example registration off unless explicitly enabled). -```python -# In app/utils/posthog_features.py -class FeatureFlags: - MY_NEW_FEATURE = "my-new-feature" -``` +### 3. Document env vars -### 2. Default to Safe Values +When you add a new toggle, document the variable in deployment or admin docs so operators know how to set it. -```python -# Default to False for new features -if get_feature_flag(user.id, "risky-feature", default=False): - # Enable risky feature -``` +### 4. Test behavior -### 3. Clean Up Old Flags +Test both branches of a toggle in unit tests by patching `current_app.config` or the setting your view reads. -Once a feature is fully rolled out: -1. Remove the flag check from code -2. Delete the flag in PostHog -3. Document in release notes - -### 4. Test Flag Behavior - -```python -def test_feature_flag(): - with mock.patch('app.utils.posthog_features.get_feature_flag') as mock_flag: - mock_flag.return_value = True - # Test with flag enabled - - mock_flag.return_value = False - # Test with flag disabled -``` - -## ๐Ÿ“š Additional Resources +## ๐Ÿ“š Additional resources - **PostHog Docs**: https://posthog.com/docs -- **Feature Flags**: https://posthog.com/docs/feature-flags - **Group Analytics**: https://posthog.com/docs/data/group-analytics - **Person Properties**: https://posthog.com/docs/data/persons - **Experiments**: https://posthog.com/docs/experiments -## ๐ŸŽ‰ Benefits Summary +## ๐ŸŽ‰ Benefits summary -Using these PostHog features, you can now: +With the analytics integration, you can: โœ… **Segment users** by role, auth method, platform, version -โœ… **Gradually roll out** features to test with small groups -โœ… **A/B test** different UI variations -โœ… **Kill switches** for emergency feature disabling -โœ… **Remote config** without deploying code changes โœ… **Cohort analysis** to understand user behavior โœ… **Track updates** and version adoption patterns โœ… **Monitor health** of different installation types diff --git a/docs/admin/monitoring/POSTHOG_ENHANCEMENTS_SUMMARY.md b/docs/admin/monitoring/POSTHOG_ENHANCEMENTS_SUMMARY.md index 218a6db5..d7053fd1 100644 --- a/docs/admin/monitoring/POSTHOG_ENHANCEMENTS_SUMMARY.md +++ b/docs/admin/monitoring/POSTHOG_ENHANCEMENTS_SUMMARY.md @@ -111,48 +111,7 @@ posthog.group_identify( - โœ… Understand deployment patterns - โœ… Correlate issues with specific configurations -### 4. **Feature Flags System** ๐Ÿšฉ - -**What:** Complete feature flag utilities for gradual rollouts and A/B testing. - -**New File:** `app/utils/posthog_features.py` - -**Features:** -- `get_feature_flag()` - Check if feature is enabled -- `get_feature_flag_payload()` - Remote configuration -- `get_all_feature_flags()` - Get all flags for a user -- `feature_flag_required()` - Decorator for route protection -- `inject_feature_flags_to_frontend()` - Frontend integration -- `track_feature_flag_interaction()` - Track feature usage -- `FeatureFlags` class - Centralized flag definitions - -**Example Usage:** -```python -from app.utils.posthog_features import get_feature_flag, feature_flag_required - -# Simple check -if get_feature_flag(user.id, "new-dashboard"): - return render_template("dashboard_v2.html") - -# Route protection -@app.route('/beta/feature') -@feature_flag_required('beta-features') -def beta_feature(): - return "Beta!" - -# Frontend injection -feature_flags = inject_feature_flags_to_frontend(user.id) -return render_template("app.html", feature_flags=feature_flags) -``` - -**Benefits:** -- โœ… Gradual feature rollouts (0% โ†’ 10% โ†’ 50% โ†’ 100%) -- โœ… A/B testing different UI variations -- โœ… Emergency kill switches -- โœ… Target features to specific user segments -- โœ… Remote configuration without deployment - -### 5. **Automatic User Identification on Login** ๐Ÿ” +### 4. **Automatic User Identification on Login** ๐Ÿ” **What:** Users are automatically identified when they log in (both local and OIDC). @@ -191,23 +150,17 @@ return render_template("app.html", feature_flags=feature_flags) - Added `identify_user()` calls on OIDC login - Set person properties on every login -### New Files -4. **`app/utils/posthog_features.py`** (NEW) - - Complete feature flag system - - Predefined flag constants - - Helper functions and decorators - ### Documentation -5. **`POSTHOG_ADVANCED_FEATURES.md`** (NEW) +4. **`POSTHOG_ADVANCED_FEATURES.md`** (NEW) - Complete guide to all features - Usage examples and best practices - PostHog query examples -6. **`POSTHOG_ENHANCEMENTS_SUMMARY.md`** (THIS FILE) +5. **`POSTHOG_ENHANCEMENTS_SUMMARY.md`** (THIS FILE) - Summary of all changes ### Tests -7. **`tests/test_telemetry.py`** +6. **`tests/test_telemetry.py`** - Updated to match enhanced property names ## ๐Ÿš€ What You Can Do Now @@ -217,61 +170,26 @@ return render_template("app.html", feature_flags=feature_flags) - Group installations by version, platform, deployment method - Build cohorts for targeted analysis -### 2. **Gradual Rollouts** -```python -# In PostHog: Create flag "new-timer-ui" at 10% -if get_feature_flag(user.id, "new-timer-ui"): - # Show new UI to 10% of users - pass -``` +### 2. **Deployment toggles (not PostHog)** -### 3. **A/B Testing** -```python -experiments = get_active_experiments(user.id) -if experiments.get("onboarding-flow") == "variant-b": - # Show variant B - pass -``` +Rollouts, kill switches, and route-level gates use **environment variables** and [`app/config.py`](../../../app/config.py), not a PostHog feature-flag module. -### 4. **Emergency Kill Switches** -```python -if not get_feature_flag(user.id, "enable-exports", default=True): - abort(503, "Exports temporarily disabled") -``` - -### 5. **Remote Configuration** -```python -config = get_feature_flag_payload(user.id, "dashboard-config") -theme = config.get("theme", "light") -widgets = config.get("enabled_widgets", []) -``` - -### 6. **Frontend Feature Flags** -```html - -``` - -### 7. **Version Analytics** +### 3. **Version Analytics** - Track how many installations are on each version - Identify installations that need updates - Measure update adoption speed -### 8. **Platform Analytics** +### 4. **Platform Analytics** - Compare behavior across Linux, Windows, macOS - Identify platform-specific issues - Optimize for most common platforms -### 9. **User Behavior Analysis** +### 5. **User Behavior Analysis** - Filter events by user role - Analyze admin vs regular user behavior - Track feature adoption by user segment -### 10. **Installation Health** +### 6. **Installation Health** - Monitor active installations (telemetry.health events) - Track deployment methods (Docker vs native) - Geographic distribution via timezone @@ -317,24 +235,7 @@ Compare to: All users ## ๐ŸŽจ Setting Up in PostHog -### 1. **Create Feature Flags** - -Go to PostHog โ†’ Feature Flags โ†’ New feature flag - -**Example: Gradual Rollout** -- Key: `new-dashboard` -- Rollout: 10% of users -- Increase over time: 10% โ†’ 50% โ†’ 100% - -**Example: Admin Only** -- Key: `admin-tools` -- Condition: Person property `is_admin` = `true` - -**Example: Docker Users** -- Key: `docker-optimizations` -- Condition: Person property `deployment_method` = `docker` - -### 2. **Create Cohorts** +### 1. **Create Cohorts** **Docker Admins:** ``` @@ -351,7 +252,7 @@ Events: telemetry.install within last 30 days ``` -### 3. **Build Dashboards** +### 2. **Build Dashboards** **Installation Health:** - Active installations (last 24h) @@ -388,7 +289,7 @@ pytest tests/test_telemetry.py -v No linter errors: ```bash -pylint app/utils/telemetry.py app/utils/posthog_features.py +pylint app/utils/telemetry.py # โœ… No errors ``` @@ -405,14 +306,10 @@ With these enhancements, you now have: โœ… **World-class product analytics** with person properties โœ… **Group analytics** for cohort analysis -โœ… **Feature flags** for gradual rollouts & A/B testing -โœ… **Kill switches** for emergency feature control -โœ… **Remote configuration** without deployments โœ… **Rich context** on every event โœ… **Installation tracking** with version/platform groups โœ… **User segmentation** by role, auth, platform โœ… **Automatic identification** on login -โœ… **Frontend integration** for client-side flags โœ… **Comprehensive docs** and examples โœ… **Production-ready** with tests passing @@ -424,20 +321,11 @@ With these enhancements, you now have: POSTHOG_HOST=https://app.posthog.com ``` -2. **Create Feature Flags** in PostHog dashboard +2. **Build Dashboards** for your metrics -3. **Build Dashboards** for your metrics +3. **Analyze Data** in PostHog to make data-driven decisions -4. **Start Using Flags** in your code: - ```python - from app.utils.posthog_features import FeatureFlags, get_feature_flag - - if get_feature_flag(user.id, FeatureFlags.NEW_DASHBOARD): - # New feature! - pass - ``` - -5. **Analyze Data** in PostHog to make data-driven decisions +4. **Gate features in the app** using `app/config.py` and environment variables when you need deploy-time toggles --- diff --git a/docs/admin/monitoring/POSTHOG_QUICK_REFERENCE.md b/docs/admin/monitoring/POSTHOG_QUICK_REFERENCE.md index cab5db00..a7ec13c1 100644 --- a/docs/admin/monitoring/POSTHOG_QUICK_REFERENCE.md +++ b/docs/admin/monitoring/POSTHOG_QUICK_REFERENCE.md @@ -38,49 +38,9 @@ identify_user(user.id, { }) ``` -### Check Feature Flag -```python -from app.utils.posthog_features import get_feature_flag +### Application toggles (server-side) -if get_feature_flag(user.id, "new-feature"): - # Enable feature - pass -``` - -### Protect Route with Flag -```python -from app.utils.posthog_features import feature_flag_required - -@app.route('/beta/feature') -@feature_flag_required('beta-access') -def beta_feature(): - return "Beta!" -``` - -### Get Flag Payload (Remote Config) -```python -from app.utils.posthog_features import get_feature_flag_payload - -config = get_feature_flag_payload(user.id, "app-config") -if config: - theme = config.get("theme", "light") -``` - -### Inject Flags to Frontend -```python -from app.utils.posthog_features import inject_feature_flags_to_frontend - -@app.route('/dashboard') -def dashboard(): - flags = inject_feature_flags_to_frontend(current_user.id) - return render_template("dashboard.html", feature_flags=flags) -``` - -```html - -``` +TimeTracker does **not** ship a PostHog-backed feature-flag API. Enable or restrict behavior with **environment variables** and [`app/config.py`](../../../app/config.py) (for example `DEMO_MODE`, `ALLOW_SELF_REGISTER`, `ENABLE_TELEMETRY`). Per-user UI options live on the user model in the database. ## ๐Ÿ“Š Person Properties @@ -100,39 +60,6 @@ def dashboard(): - `timezone` - Installation timezone - `first_seen_version` - Original version (set once) -## ๐ŸŽฏ Feature Flag Examples - -### Gradual Rollout -``` -Key: new-ui -Rollout: 10% โ†’ 25% โ†’ 50% โ†’ 100% -``` - -### Target Admins Only -``` -Key: admin-tools -Condition: is_admin = true -``` - -### Platform Specific -``` -Key: linux-optimizations -Condition: current_platform = "Linux" -``` - -### Version Specific -``` -Key: v3-features -Condition: current_version >= "3.0.0" -``` - -### Kill Switch -``` -Key: enable-exports -Default: true -Use in code: default=True -``` - ## ๐Ÿ“ˆ Useful PostHog Queries ### Active Users by Role @@ -187,16 +114,6 @@ Compare: All platforms ## ๐Ÿงช Testing -### Mock Feature Flags -```python -from unittest.mock import patch - -def test_with_feature_enabled(): - with patch('app.utils.posthog_features.get_feature_flag', return_value=True): - # Test with feature enabled - pass -``` - ### Mock Track Events ```python @patch('app.track_event') @@ -212,36 +129,7 @@ def test_event_tracking(mock_track): - **Analytics Docs**: [docs/analytics.md](docs/analytics.md) - **PostHog Docs**: https://posthog.com/docs -## ๐ŸŽฏ Predefined Feature Flags - -```python -from app.utils.posthog_features import FeatureFlags - -# Beta features -FeatureFlags.BETA_FEATURES -FeatureFlags.NEW_DASHBOARD -FeatureFlags.ADVANCED_REPORTS - -# Experiments -FeatureFlags.TIMER_UI_EXPERIMENT -FeatureFlags.ONBOARDING_FLOW - -# Rollouts -FeatureFlags.NEW_ANALYTICS_PAGE -FeatureFlags.BULK_OPERATIONS - -# Kill switches -FeatureFlags.ENABLE_EXPORTS -FeatureFlags.ENABLE_API -FeatureFlags.ENABLE_WEBSOCKETS - -# Premium -FeatureFlags.CUSTOM_REPORTS -FeatureFlags.API_ACCESS -FeatureFlags.INTEGRATIONS -``` - --- -**Quick Tip:** Start with small rollouts (10%) and gradually increase as you gain confidence! +**Quick Tip:** Use person properties and cohorts in PostHog for analysis; gate behavior in the app with config and env vars.