如何创建电报机器人以监视Python中的正常运行时间(第1部分:即时指标)
#python #web3 #linux #telegram

''
大家好!几年来,我一直在Python为我自己写各种“助手”电报机器人,这些电报机器人为我处理各种小型日常任务 - 通知我有关某些内容,检查服务正常运行时间,从电报频道和聊天中转发有趣的内容等等。

>

这很方便,因为手机总是在手头,并且能够在服务器上修复某些东西,甚至不打开我的笔记本电脑会给我特别的乐趣。

通常,我积累了许多我想与dev.to读者分享的不同小型项目模板。

我会马上说,这些示例可能是其应用程序“原样”的利基市场,但是我将标记那些地方,通过将几行代码更改为自己,您将能够重新使用项目的大多数开发。

>

我几天前完成了这个特定的项目,这已经给我带来了很多好处。我在Web3基础架构提供商Chainstack.com上工作,处理用于索引来自EVM区块链智能合约的数据的服务。

和开发的服务质量在很大程度上取决于如何“井”在线检索数据的节点。

我花了很多时间尝试使用基础设施部门使用的现成工具,例如Grafana,Better Pustime等,但是由于我对系统的内部构件不感兴趣,因此我的主要重点是入口和退出的指标,我决定写下我自己的机器人,这将有以下内容:

>>>>>>>>>>/p>>

>

>:

>

>

>:

>:

>:

>:

>

>
  • 应我的要求,它将访问服务,检查指标,并向我发送有关当前情况的简短报告。
  • 根据我的其他要求,它会给我发送有关最近X小时发生的事情的图表。
  • 在特殊情况下,它会给我发送一条通知,说当时正在发生某些事情。

在本文中,我将重点介绍第一部分,即根据要求收到指标。

我们将需要一个新的虚拟环境进行工作。

cd ~ 
virtualenv -p python3.8 up_env  # crete a virtualenv
source ~/up_env/bin/activate  # activate the virtualenl

安装依赖项:

pip install python-telegram-bot
pip install "python-telegram-bot[job-queue]" --pre
pip install --upgrade python-telegram-bot==13.6.0  # the code was written before version 20, so here the version is explicitly specified

pip install numpy # needed for the median value function
pip install web3 # needed for requests to nodes (replace with what you need)

带有functions functions.py的文件(您可以使用类实现它,但是由于示例很短,因此我不打算将其分为模块,但是多线程库需要将函数移至单独的文件)。导入依赖性:

import numpy as np
import multiprocessing

from web3 import Web3 #  add those libraries needed for your task

描述检查状态的函数。就我而言,它涉及通过预先选择的公共节点进行循环,检索其最后一个块,取出中位数以滤除任何偏差,然后检查我们自己的节点针对此中位数。

服务状态检查功能(您可以用自己的替换):

# Helper function that checks a single node
def get_last_block_once(rpc):
    try:
        w3 = Web3(Web3.HTTPProvider(rpc))
        block_number = w3.eth.block_number
        if isinstance(block_number, int):
            return block_number
        else:
            return None
    except Exception as e:
        print(f'{rpc} - {repr(e)}')
        return None


# Main function to check the status of the service that will be called
def check_service():
    # pre-prepared list of reference nodes
    # for any network, it can be found on the website https://chainlist.org/
    list_of_public_nodes = [
        'https://polygon.llamarpc.com',
        'https://polygon.rpc.blxrbdn.com',
        'https://polygon.blockpi.network/v1/rpc/public',
        'https://polygon-mainnet.public.blastapi.io',
        'https://rpc-mainnet.matic.quiknode.pro',
        'https://polygon-bor.publicnode.com',
        'https://poly-rpc.gateway.pokt.network',
        'https://rpc.ankr.com/polygon',
        'https://polygon-rpc.com'
    ]

    # parallel processing of requests to all nodes
    with multiprocessing.Pool(processes=len(list_of_public_nodes)) as pool:
        results = pool.map(get_last_block_once, list_of_public_nodes)
        last_blocks = [b for b in results if b is not None and isinstance(b, int)]

    # define the maximum and median value of the current block
    med_val = int(np.median(last_blocks))
    max_val = int(np.max(last_blocks))
    # determine the number of nodes with the maximum and median value
    med_support = np.sum([1 for x in last_blocks if x == med_val])
    max_support = np.sum([1 for x in last_blocks if x == max_val])

    return max_val, max_support, med_val, med_support

bot的下一个重要文件是uptime_bot.py。我们从上面的文件导入库和函数,并设置必要的常数:

import telegram
from telegram.ext import Updater, CommandHandler, Filters

from functions import get_last_block_once, check_service

# Here one can to set a limited circle of bot users, 
# listing the usernames of the users

ALLOWED_USERS = ['your_telegram_account', 'someone_else']
# The address of the node that I am monitoring (also a public node in this case)
OBJECT_OF_CHECKING = 'https://polygon-mainnet.chainstacklabs.com'
# Threshold for highlighting critical lag
THRESHOLD = 5

接下来,让我们描述一个从机器人UI发出命令时将调用的函数。

def start(update, context):
    """Send a message when the command /start is issued."""

    try:
        # Get the user
        user = update.effective_user

        # Filter out bots
        if user.is_bot:
            return

        # Check if the user is allowed
        username = str(user.username)
        if username not in ALLOWED_USERS:
            return
    except Exception as e:
        print(f'{repr(e)}')
        return

    # Call the main function to check the network status
    max_val, max_support, med_val, med_support = check_service()
    # Call the function to check the status of the specified node
    last_block = get_last_block_once(OBJECT_OF_CHECKING)

    # Create the message to send to Telegram
    message = ""

    # Information about the state of the nodes in the public network (median, maximum, and number of nodes)
    message += f"Public median block number {med_val} (on {med_support}) RPCs\n"
    message += f"Public maximum block number +{max_val - med_val} (on {max_support}) PRCs\n"

     # Compare with the threshold
    if last_block is not None:
        out_text = str(last_block - med_val) if last_block - med_val < 0 else '+' + str(last_block - med_val)

        if abs(last_block - med_val) > THRESHOLD:
            message += f"The node block number shift ⚠️<b>{out_text}</b>⚠️"
        else:
            message += f"The node block number shift {out_text}"
    else: # Exception processing if a node has not responded
        message += f"The node has ⚠️<b>not responded</b>⚠️"

    # Send the message to the user
    context.bot.send_message(chat_id=user.id, text=message, parse_mode="HTML")

现在,剩下的就是添加初始化机器人的部分,并连接处理程序功能:

token = "xxx"  # Bot token obtained from BotFather

# set up the bot
bot = telegram.Bot(token=token)
updater = Updater(token=token, use_context=True)
dispatcher = updater.dispatcher

# bind the handler function
dispatcher.add_handler(CommandHandler("start", start, filters=Filters.chat_type.private))

# run the bot
updater.start_polling()

最后,您可以使用:
在便宜的VPS服务器上运行代码

source ~/up_env/bin/activate
python uptime_bot.py

配置SystemD单元文件后。

结果,机器人的工作看起来像这样。

  1. 如果一切都很好:

''

  1. 如果滞后太大,则如下:

''

在以下文章中,我将描述如何实施其余两个任务:

  1. 在请求上检索图形,显示最后X小时发生的事件。

  2. 接收一个警报,指示当前正在发生某些事情并需要采取行动。

项目的源代码可在github repository中找到。如果您发现本教程有帮助,请随时在github上给它一颗星星,我很感激