File size: 7,168 Bytes
eebf5c4
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
"""

Feature Flags System

Allows dynamic toggling of application modules and features

"""
from typing import Dict, Any
import json
from pathlib import Path
from datetime import datetime
import logging

logger = logging.getLogger(__name__)


class FeatureFlagManager:
    """Manage application feature flags"""

    DEFAULT_FLAGS = {
        "enableWhaleTracking": True,
        "enableMarketOverview": True,
        "enableFearGreedIndex": True,
        "enableNewsFeed": True,
        "enableSentimentAnalysis": True,
        "enableMlPredictions": False,  # Disabled by default (requires HF setup)
        "enableProxyAutoMode": True,
        "enableDefiProtocols": True,
        "enableTrendingCoins": True,
        "enableGlobalStats": True,
        "enableProviderRotation": True,
        "enableWebSocketStreaming": True,
        "enableDatabaseLogging": True,
        "enableRealTimeAlerts": False,  # New feature - not yet implemented
        "enableAdvancedCharts": True,
        "enableExportFeatures": True,
        "enableCustomProviders": True,
        "enablePoolManagement": True,
        "enableHFIntegration": True,
    }

    def __init__(self, storage_path: str = "data/feature_flags.json"):
        """

        Initialize feature flag manager



        Args:

            storage_path: Path to persist feature flags

        """
        self.storage_path = Path(storage_path)
        self.flags = self.DEFAULT_FLAGS.copy()
        self.load_flags()

    def load_flags(self):
        """Load feature flags from storage"""
        try:
            if self.storage_path.exists():
                with open(self.storage_path, 'r', encoding='utf-8') as f:
                    saved_flags = json.load(f)
                # Merge saved flags with defaults (in case new flags were added)
                self.flags.update(saved_flags.get('flags', {}))
                logger.info(f"Loaded feature flags from {self.storage_path}")
            else:
                # Create storage directory if it doesn't exist
                self.storage_path.parent.mkdir(parents=True, exist_ok=True)
                self.save_flags()
                logger.info("Initialized default feature flags")
        except Exception as e:
            logger.error(f"Error loading feature flags: {e}")
            self.flags = self.DEFAULT_FLAGS.copy()

    def save_flags(self):
        """Save feature flags to storage"""
        try:
            self.storage_path.parent.mkdir(parents=True, exist_ok=True)
            data = {
                'flags': self.flags,
                'last_updated': datetime.now().isoformat()
            }
            with open(self.storage_path, 'w', encoding='utf-8') as f:
                json.dump(data, f, indent=2)
            logger.info("Feature flags saved successfully")
        except Exception as e:
            logger.error(f"Error saving feature flags: {e}")

    def get_all_flags(self) -> Dict[str, bool]:
        """Get all feature flags"""
        return self.flags.copy()

    def get_flag(self, flag_name: str) -> bool:
        """

        Get a specific feature flag value



        Args:

            flag_name: Name of the flag



        Returns:

            bool: Flag value (defaults to False if not found)

        """
        return self.flags.get(flag_name, False)

    def set_flag(self, flag_name: str, value: bool) -> bool:
        """

        Set a feature flag value



        Args:

            flag_name: Name of the flag

            value: New value (True/False)



        Returns:

            bool: Success status

        """
        try:
            self.flags[flag_name] = bool(value)
            self.save_flags()
            logger.info(f"Feature flag '{flag_name}' set to {value}")
            return True
        except Exception as e:
            logger.error(f"Error setting feature flag: {e}")
            return False

    def update_flags(self, updates: Dict[str, bool]) -> bool:
        """

        Update multiple flags at once



        Args:

            updates: Dictionary of flag name -> value pairs



        Returns:

            bool: Success status

        """
        try:
            for flag_name, value in updates.items():
                self.flags[flag_name] = bool(value)
            self.save_flags()
            logger.info(f"Updated {len(updates)} feature flags")
            return True
        except Exception as e:
            logger.error(f"Error updating feature flags: {e}")
            return False

    def reset_to_defaults(self) -> bool:
        """Reset all flags to default values"""
        try:
            self.flags = self.DEFAULT_FLAGS.copy()
            self.save_flags()
            logger.info("Feature flags reset to defaults")
            return True
        except Exception as e:
            logger.error(f"Error resetting feature flags: {e}")
            return False

    def is_enabled(self, flag_name: str) -> bool:
        """

        Check if a feature is enabled (alias for get_flag)



        Args:

            flag_name: Name of the flag



        Returns:

            bool: True if enabled, False otherwise

        """
        return self.get_flag(flag_name)

    def get_enabled_features(self) -> Dict[str, bool]:
        """Get only enabled features"""
        return {k: v for k, v in self.flags.items() if v is True}

    def get_disabled_features(self) -> Dict[str, bool]:
        """Get only disabled features"""
        return {k: v for k, v in self.flags.items() if v is False}

    def get_flag_count(self) -> Dict[str, int]:
        """Get count of enabled/disabled flags"""
        enabled = sum(1 for v in self.flags.values() if v)
        disabled = len(self.flags) - enabled
        return {
            'total': len(self.flags),
            'enabled': enabled,
            'disabled': disabled
        }

    def get_feature_info(self) -> Dict[str, Any]:
        """Get comprehensive feature flag information"""
        counts = self.get_flag_count()
        return {
            'flags': self.flags,
            'counts': counts,
            'enabled_features': list(self.get_enabled_features().keys()),
            'disabled_features': list(self.get_disabled_features().keys()),
            'storage_path': str(self.storage_path),
            'last_loaded': datetime.now().isoformat()
        }


# Global instance
feature_flags = FeatureFlagManager()


# Convenience functions
def is_feature_enabled(flag_name: str) -> bool:
    """Check if a feature is enabled"""
    return feature_flags.is_enabled(flag_name)


def get_all_feature_flags() -> Dict[str, bool]:
    """Get all feature flags"""
    return feature_flags.get_all_flags()


def set_feature_flag(flag_name: str, value: bool) -> bool:
    """Set a feature flag"""
    return feature_flags.set_flag(flag_name, value)


def update_feature_flags(updates: Dict[str, bool]) -> bool:
    """Update multiple feature flags"""
    return feature_flags.update_flags(updates)