Add /health endpoint that returns last_process timestamp, fix issue #6009
This commit is contained in:
parent
451eca51c8
commit
bf62fc9b25
@ -100,6 +100,8 @@ class FreqtradeBot(LoggingMixin):
|
|||||||
self._exit_lock = Lock()
|
self._exit_lock = Lock()
|
||||||
LoggingMixin.__init__(self, logger, timeframe_to_seconds(self.strategy.timeframe))
|
LoggingMixin.__init__(self, logger, timeframe_to_seconds(self.strategy.timeframe))
|
||||||
|
|
||||||
|
self.last_process = datetime.utcfromtimestamp(0.0)
|
||||||
|
|
||||||
def notify_status(self, msg: str) -> None:
|
def notify_status(self, msg: str) -> None:
|
||||||
"""
|
"""
|
||||||
Public method for users of this class (worker, etc.) to send notifications
|
Public method for users of this class (worker, etc.) to send notifications
|
||||||
@ -187,6 +189,7 @@ class FreqtradeBot(LoggingMixin):
|
|||||||
self.enter_positions()
|
self.enter_positions()
|
||||||
|
|
||||||
Trade.commit()
|
Trade.commit()
|
||||||
|
self.last_process = datetime.utcnow()
|
||||||
|
|
||||||
def process_stopped(self) -> None:
|
def process_stopped(self) -> None:
|
||||||
"""
|
"""
|
||||||
|
@ -382,3 +382,7 @@ class BacktestResponse(BaseModel):
|
|||||||
class SysInfo(BaseModel):
|
class SysInfo(BaseModel):
|
||||||
cpu_pct: List[float]
|
cpu_pct: List[float]
|
||||||
ram_pct: float
|
ram_pct: float
|
||||||
|
|
||||||
|
|
||||||
|
class Health(BaseModel):
|
||||||
|
last_process: datetime
|
||||||
|
@ -14,12 +14,12 @@ from freqtrade.rpc import RPC
|
|||||||
from freqtrade.rpc.api_server.api_schemas import (AvailablePairs, Balances, BlacklistPayload,
|
from freqtrade.rpc.api_server.api_schemas import (AvailablePairs, Balances, BlacklistPayload,
|
||||||
BlacklistResponse, Count, Daily,
|
BlacklistResponse, Count, Daily,
|
||||||
DeleteLockRequest, DeleteTrade, ForceBuyPayload,
|
DeleteLockRequest, DeleteTrade, ForceBuyPayload,
|
||||||
ForceBuyResponse, ForceSellPayload, Locks, Logs,
|
ForceBuyResponse, ForceSellPayload, Health,
|
||||||
OpenTradeSchema, PairHistory, PerformanceEntry,
|
Locks, Logs, OpenTradeSchema, PairHistory,
|
||||||
Ping, PlotConfig, Profit, ResultMsg, ShowConfig,
|
PerformanceEntry, Ping, PlotConfig, Profit,
|
||||||
Stats, StatusMsg, StrategyListResponse,
|
ResultMsg, ShowConfig, Stats, StatusMsg,
|
||||||
StrategyResponse, SysInfo, Version,
|
StrategyListResponse, StrategyResponse, SysInfo,
|
||||||
WhitelistResponse)
|
Version, WhitelistResponse)
|
||||||
from freqtrade.rpc.api_server.deps import get_config, get_exchange, get_rpc, get_rpc_optional
|
from freqtrade.rpc.api_server.deps import get_config, get_exchange, get_rpc, get_rpc_optional
|
||||||
from freqtrade.rpc.rpc import RPCException
|
from freqtrade.rpc.rpc import RPCException
|
||||||
|
|
||||||
@ -290,3 +290,8 @@ def list_available_pairs(timeframe: Optional[str] = None, stake_currency: Option
|
|||||||
@router.get('/sysinfo', response_model=SysInfo, tags=['info'])
|
@router.get('/sysinfo', response_model=SysInfo, tags=['info'])
|
||||||
def sysinfo():
|
def sysinfo():
|
||||||
return RPC._rpc_sysinfo()
|
return RPC._rpc_sysinfo()
|
||||||
|
|
||||||
|
|
||||||
|
@router.get('/health', response_model=Health, tags=['info'])
|
||||||
|
def health(rpc: RPC = Depends(get_rpc)):
|
||||||
|
return rpc._health()
|
||||||
|
@ -1030,3 +1030,8 @@ class RPC:
|
|||||||
"cpu_pct": psutil.cpu_percent(interval=1, percpu=True),
|
"cpu_pct": psutil.cpu_percent(interval=1, percpu=True),
|
||||||
"ram_pct": psutil.virtual_memory().percent
|
"ram_pct": psutil.virtual_memory().percent
|
||||||
}
|
}
|
||||||
|
|
||||||
|
def _health(self) -> Dict[str, str]:
|
||||||
|
return {
|
||||||
|
'last_process': str(self._freqtrade.last_process)
|
||||||
|
}
|
||||||
|
@ -113,7 +113,7 @@ class Telegram(RPCHandler):
|
|||||||
r'/stopbuy$', r'/reload_config$', r'/show_config$',
|
r'/stopbuy$', r'/reload_config$', r'/show_config$',
|
||||||
r'/logs$', r'/whitelist$', r'/blacklist$', r'/bl_delete$',
|
r'/logs$', r'/whitelist$', r'/blacklist$', r'/bl_delete$',
|
||||||
r'/weekly$', r'/weekly \d+$', r'/monthly$', r'/monthly \d+$',
|
r'/weekly$', r'/weekly \d+$', r'/monthly$', r'/monthly \d+$',
|
||||||
r'/forcebuy$', r'/edge$', r'/help$', r'/version$']
|
r'/forcebuy$', r'/edge$', r'/health$', r'/help$', r'/version$']
|
||||||
# Create keys for generation
|
# Create keys for generation
|
||||||
valid_keys_print = [k.replace('$', '') for k in valid_keys]
|
valid_keys_print = [k.replace('$', '') for k in valid_keys]
|
||||||
|
|
||||||
@ -173,6 +173,7 @@ class Telegram(RPCHandler):
|
|||||||
CommandHandler(['blacklist_delete', 'bl_delete'], self._blacklist_delete),
|
CommandHandler(['blacklist_delete', 'bl_delete'], self._blacklist_delete),
|
||||||
CommandHandler('logs', self._logs),
|
CommandHandler('logs', self._logs),
|
||||||
CommandHandler('edge', self._edge),
|
CommandHandler('edge', self._edge),
|
||||||
|
CommandHandler('health', self._health),
|
||||||
CommandHandler('help', self._help),
|
CommandHandler('help', self._help),
|
||||||
CommandHandler('version', self._version),
|
CommandHandler('version', self._version),
|
||||||
]
|
]
|
||||||
@ -1282,6 +1283,7 @@ class Telegram(RPCHandler):
|
|||||||
"*/logs [limit]:* `Show latest logs - defaults to 10` \n"
|
"*/logs [limit]:* `Show latest logs - defaults to 10` \n"
|
||||||
"*/count:* `Show number of active trades compared to allowed number of trades`\n"
|
"*/count:* `Show number of active trades compared to allowed number of trades`\n"
|
||||||
"*/edge:* `Shows validated pairs by Edge if it is enabled` \n"
|
"*/edge:* `Shows validated pairs by Edge if it is enabled` \n"
|
||||||
|
"*/health* `Show latest process timestamp - defaults to 1970-01-01 00:00:00` \n"
|
||||||
|
|
||||||
"_Statistics_\n"
|
"_Statistics_\n"
|
||||||
"------------\n"
|
"------------\n"
|
||||||
@ -1309,6 +1311,20 @@ class Telegram(RPCHandler):
|
|||||||
|
|
||||||
self._send_msg(message, parse_mode=ParseMode.MARKDOWN)
|
self._send_msg(message, parse_mode=ParseMode.MARKDOWN)
|
||||||
|
|
||||||
|
@authorized_only
|
||||||
|
def _health(self, update: Update, context: CallbackContext) -> None:
|
||||||
|
"""
|
||||||
|
Handler for /health
|
||||||
|
Shows the last process timestamp
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
health = self._rpc._health()
|
||||||
|
message = f"Last process: `{health['last_process']}`"
|
||||||
|
logger.debug(message)
|
||||||
|
self._send_msg(message)
|
||||||
|
except RPCException as e:
|
||||||
|
self._send_msg(str(e))
|
||||||
|
|
||||||
@authorized_only
|
@authorized_only
|
||||||
def _version(self, update: Update, context: CallbackContext) -> None:
|
def _version(self, update: Update, context: CallbackContext) -> None:
|
||||||
"""
|
"""
|
||||||
|
@ -1272,3 +1272,12 @@ def test_rpc_edge_enabled(mocker, edge_conf) -> None:
|
|||||||
assert ret[0]['Winrate'] == 0.66
|
assert ret[0]['Winrate'] == 0.66
|
||||||
assert ret[0]['Expectancy'] == 1.71
|
assert ret[0]['Expectancy'] == 1.71
|
||||||
assert ret[0]['Stoploss'] == -0.02
|
assert ret[0]['Stoploss'] == -0.02
|
||||||
|
|
||||||
|
|
||||||
|
def test_rpc_health(mocker, default_conf) -> None:
|
||||||
|
mocker.patch('freqtrade.rpc.telegram.Telegram', MagicMock())
|
||||||
|
|
||||||
|
freqtradebot = get_patched_freqtradebot(mocker, default_conf)
|
||||||
|
rpc = RPC(freqtradebot)
|
||||||
|
ret = rpc._health()
|
||||||
|
assert ret['last_process'] == '1970-01-01 00:00:00'
|
||||||
|
@ -1442,3 +1442,13 @@ def test_api_backtesting(botclient, mocker, fee, caplog, tmpdir):
|
|||||||
assert result['status'] == 'reset'
|
assert result['status'] == 'reset'
|
||||||
assert not result['running']
|
assert not result['running']
|
||||||
assert result['status_msg'] == 'Backtest reset'
|
assert result['status_msg'] == 'Backtest reset'
|
||||||
|
|
||||||
|
|
||||||
|
def test_health(botclient):
|
||||||
|
ftbot, client = botclient
|
||||||
|
|
||||||
|
rc = client_get(client, f"{BASE_URI}/health")
|
||||||
|
|
||||||
|
assert_response(rc)
|
||||||
|
ret = rc.json()
|
||||||
|
assert ret['last_process'] == '1970-01-01T00:00:00'
|
||||||
|
Loading…
Reference in New Issue
Block a user