Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,43 @@ def get_host_slowlog(
return {"slowlog_entries": host_slows, "total_count": len(host_slows)}


def get_instance_slowlog(
host: str,
port: int,
immute_domain: str,
start_time: timezone.datetime,
end_time: timezone.datetime,
) -> List[Dict]:
cluster_obj = Cluster.objects.get(immute_domain=immute_domain)
machine_obj = Machine.objects.get(bk_cloud_id=cluster_obj.bk_cloud_id, ip=host)

host_slows = []
if machine_obj.access_layer == AccessLayer.PROXY.value:
host_slows = _get_slowlog(
get_query_params(
immute_domain=immute_domain,
role="proxy",
start_time=start_time,
end_time=end_time,
host=host,
port=port,
)
)
else:
host_slows = _get_slowlog(
get_query_params(
immute_domain=immute_domain,
role="redis_master",
start_time=start_time,
end_time=end_time,
host=host,
port=port,
)
)

return {"slowlog_entries": host_slows, "total_count": len(host_slows)}


def _get_slowlog(
query_params: Dict,
) -> Dict:
Expand Down Expand Up @@ -195,13 +232,16 @@ def get_query_params(
end_time: timezone.datetime,
role=None,
host=None,
port=None,
) -> Dict:

query_parts = [f'__ext.cluster_domain:"{immute_domain}"']
if role:
query_parts.append(f'__ext.instance_role:"{role}"')
if host:
query_parts.append(f'__ext.instance_host:"{host}"')
if port:
query_parts.append(f'__ext.instance_port:"{port}"')

query_params = {
"indices": f"{env.DBA_APP_BK_BIZ_ID}_bklog.redis_slowlog",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,13 +43,13 @@ class RedisEntrySerializer(RedisBaseInstanceSerializer):


class RedisTopoInputSerializer(serializers.Serializer):
immute_domain = serializers.CharField(help_text=_("集群域名"))
cluster_domain = serializers.CharField(help_text=_("集群域名"))


class RedisHostInputSerializer(serializers.Serializer):
"""Redis主机列表序列化器"""

hosts = serializers.ListField(
ips = serializers.ListField(
child=serializers.IPAddressField(protocol="both"), help_text=_("主机IP地址列表"), required=True
)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ class RedisInstanceInputSerializer(serializers.Serializer):
"""Redis实例输入序列化器"""

redis_addr = serializers.CharField(help_text=_("实例地址"))
immute_domain = serializers.CharField(help_text=_("集群域名"))
cluster_domain = serializers.CharField(help_text=_("集群域名"))


# ==================== 输出序列化器 ====================
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ class RedisClusertAlarmInputSerializer(serializers.Serializer):

start_time = serializers.DateTimeField(help_text=_("开始时间"))
end_time = serializers.DateTimeField(help_text=_("结束时间"))
immute_domain = serializers.CharField(help_text=_("集群域名"))
cluster_domain = serializers.CharField(help_text=_("集群域名"))

def validate(self, attrs):
"""验证时间参数"""
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,18 +16,28 @@ class RedisSlowlogInputSerializer(serializers.Serializer):

start_time = serializers.DateTimeField(help_text=_("开始时间"))
end_time = serializers.DateTimeField(help_text=_("结束时间"))
immute_domain = serializers.CharField(help_text=_("集群域名"))
cluster_domain = serializers.CharField(help_text=_("集群域名"))


class RedisSlowlog4HostInputSerializer(serializers.Serializer):
"""Redis慢查询输入序列化器"""

start_time = serializers.DateTimeField(help_text=_("开始时间"))
end_time = serializers.DateTimeField(help_text=_("结束时间"))
immute_domain = serializers.CharField(help_text=_("集群域名"))
cluster_domain = serializers.CharField(help_text=_("集群域名"))
ip = serializers.CharField(help_text=_("主机IP"))


class RedisSlowlog4InstInputSerializer(serializers.Serializer):
"""Redis慢查询输入序列化器"""

start_time = serializers.DateTimeField(help_text=_("开始时间"))
end_time = serializers.DateTimeField(help_text=_("结束时间"))
cluster_domain = serializers.CharField(help_text=_("集群域名"))
host = serializers.CharField(help_text=_("主机IP"))
port = serializers.IntegerField(help_text=_("实例端口"))


class RedisSlowlogEntrySerializer(serializers.Serializer):
"""Redis慢查询日志条目"""

Expand Down
4 changes: 4 additions & 0 deletions dbm-ui/backend/dbm_aiagent/mcp_tools/redis/views/job.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
from backend.db_meta.enums import InstanceInnerRole
from backend.db_meta.models import Cluster
from backend.db_services.redis.util import is_have_proxy, is_redis_cluster_protocal
from backend.dbm_aiagent.mcp_tools.common.auth_parser.base import auth_parse_clusters
from backend.dbm_aiagent.mcp_tools.common.impl.job import exec_cluster_query_net_tcp_cmd, get_job_exec_status
from backend.dbm_aiagent.mcp_tools.constants import DBMMCPTags, DBMMcpTools
from backend.dbm_aiagent.mcp_tools.decorators import mcp_tools_api_decorator
Expand All @@ -32,6 +33,7 @@
)
from backend.dbm_aiagent.mcp_tools.views import McpToolsViewSet
from backend.iam_app.handlers.drf_perm.base import DBManagePermission
from backend.iam_app.handlers.drf_perm.mcp import McpClusterManagePermission


class RedisJobMcpToolsViewSet(McpToolsViewSet):
Expand Down Expand Up @@ -92,6 +94,8 @@ def get_redis_source_access(self, request, *args, **kwargs):
description=str(_("""根据关键字,实时获取对应关键字的请求情况""")),
request_slz=GetRedisSourceAccessByKeyInputSerializer,
response_slz=GetRedisSourceAccessByKeyOutputSerializer,
permission_classes=[McpClusterManagePermission],
mcp_auth_parser=auth_parse_clusters,
tags=[DBMMCPTags.READ],
mcp=[DBMMcpTools.REDIS_JOB],
name_prefix="redis_job",
Expand Down
10 changes: 10 additions & 0 deletions dbm-ui/backend/dbm_aiagent/mcp_tools/redis/views/metrics.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
from django.utils.translation import gettext_lazy as _
from rest_framework.response import Response

from backend.dbm_aiagent.mcp_tools.common.auth_parser.base import auth_parse_clusters
from backend.dbm_aiagent.mcp_tools.constants import DBMMCPTags, DBMMcpTools
from backend.dbm_aiagent.mcp_tools.decorators import mcp_tools_api_decorator
from backend.dbm_aiagent.mcp_tools.redis.impl.redis_metrics import MetricsInstanceRole, MetricType, query_redis_metrics
Expand All @@ -22,6 +23,7 @@
)
from backend.dbm_aiagent.mcp_tools.views import McpToolsViewSet
from backend.iam_app.handlers.drf_perm.base import DBManagePermission
from backend.iam_app.handlers.drf_perm.mcp import McpClusterManagePermission

logger = logging.getLogger("root")

Expand Down Expand Up @@ -97,6 +99,8 @@ def _query_metrics_by_type(self, request, metric_type: MetricType, *args, **kwar
),
request_slz=RedisMetricsInputSerializer,
response_slz=RedisMetricsOutputSerializer,
permission_classes=[McpClusterManagePermission],
mcp_auth_parser=auth_parse_clusters,
tags=[DBMMCPTags.READ],
mcp=[DBMMcpTools.REDIS_METRICS],
name_prefix="redis_metrics",
Expand All @@ -115,6 +119,8 @@ def query_cpu(self, request, *args, **kwargs):
),
request_slz=RedisMetricsInputSerializer,
response_slz=RedisMetricsOutputSerializer,
permission_classes=[McpClusterManagePermission],
mcp_auth_parser=auth_parse_clusters,
tags=[DBMMCPTags.READ],
mcp=[DBMMcpTools.REDIS_METRICS],
name_prefix="redis_metrics",
Expand All @@ -133,6 +139,8 @@ def query_memory(self, request, *args, **kwargs):
),
request_slz=RedisMetricsInputSerializer,
response_slz=RedisMetricsOutputSerializer,
permission_classes=[McpClusterManagePermission],
mcp_auth_parser=auth_parse_clusters,
tags=[DBMMCPTags.READ],
mcp=[DBMMcpTools.REDIS_METRICS],
name_prefix="redis_metrics",
Expand All @@ -151,6 +159,8 @@ def query_connections(self, request, *args, **kwargs):
),
request_slz=RedisMetricsInputSerializer,
response_slz=RedisMetricsOutputSerializer,
permission_classes=[McpClusterManagePermission],
mcp_auth_parser=auth_parse_clusters,
tags=[DBMMCPTags.READ],
mcp=[DBMMcpTools.REDIS_METRICS],
name_prefix="redis_metrics",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
from django.utils.translation import gettext_lazy as _
from rest_framework.response import Response

from backend.dbm_aiagent.mcp_tools.common.auth_parser.base import auth_parse_bizs, auth_parse_clusters
from backend.dbm_aiagent.mcp_tools.constants import DBMMCPTags, DBMMcpTools
from backend.dbm_aiagent.mcp_tools.decorators import mcp_tools_api_decorator
from backend.dbm_aiagent.mcp_tools.redis.impl.redis_alarms import get_alarms_flat, get_cluster_alarms
Expand All @@ -22,18 +23,21 @@
RedisClusertAlarmOutputSerializer,
)
from backend.dbm_aiagent.mcp_tools.views import McpToolsViewSet
from backend.iam_app.handlers.drf_perm.base import RejectPermission
from backend.iam_app.handlers.drf_perm.base import DBManagePermission
from backend.iam_app.handlers.drf_perm.mcp import McpClusterManagePermission

logger = logging.getLogger("flow")


class RedisQueryALARMMcpToolsViewSet(McpToolsViewSet):
default_permission_class = [RejectPermission()]
default_permission_class = [DBManagePermission()]

@mcp_tools_api_decorator(
description=str(_("查询获取集群时间范围内告警列表")),
request_slz=RedisClusertAlarmInputSerializer,
response_slz=RedisClusertAlarmOutputSerializer,
permission_classes=[McpClusterManagePermission],
mcp_auth_parser=auth_parse_clusters,
tags=[DBMMCPTags.READ],
mcp=[DBMMcpTools.REDIS_QUERY_ALARM],
name_prefix="redis_query_alarm",
Expand All @@ -42,14 +46,16 @@ def fetch_cluster_alarms(self, request, *args, **kwargs):
"""获取集群时间范围内告警信息"""
start_time = self.get_param("start_time")
end_time = self.get_param("end_time")
immute_domain = self.get_param("immute_domain")
immute_domain = self.get_param("cluster_domain")

return Response(get_cluster_alarms(immute_domain=immute_domain, start_time=start_time, end_time=end_time))

@mcp_tools_api_decorator(
description=str(_("查询某个业务在时间范围内告警信息,按集群汇总")),
request_slz=RedisAppAlarmInputSerializer,
response_slz=RedisAppAlarmOutputSerializer,
permission_classes=[McpClusterManagePermission],
mcp_auth_parser=auth_parse_bizs,
tags=[DBMMCPTags.READ],
mcp=[DBMMcpTools.REDIS_QUERY_ALARM],
name_prefix="redis_query_alarm",
Expand Down
45 changes: 40 additions & 5 deletions dbm-ui/backend/dbm_aiagent/mcp_tools/redis/views/query_log.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,23 +12,30 @@
from django.utils.translation import gettext_lazy as _
from rest_framework.response import Response

from backend.dbm_aiagent.mcp_tools.common.auth_parser.base import auth_parse_clusters
from backend.dbm_aiagent.mcp_tools.constants import DBMMCPTags, DBMMcpTools
from backend.dbm_aiagent.mcp_tools.decorators import mcp_tools_api_decorator
from backend.dbm_aiagent.mcp_tools.redis.impl.redis_slowlog import get_cluster_slowlog_static, get_host_slowlog
from backend.dbm_aiagent.mcp_tools.redis.impl.redis_slowlog import (
get_cluster_slowlog_static,
get_host_slowlog,
get_instance_slowlog,
)
from backend.dbm_aiagent.mcp_tools.redis.serializers.redis_log import (
RedisSlowClusterStaticSerializer,
RedisSlowlog4HostInputSerializer,
RedisSlowlog4InstInputSerializer,
RedisSlowlogInputSerializer,
RedisSlowlogResponseSerializer,
)
from backend.dbm_aiagent.mcp_tools.views import McpToolsViewSet
from backend.iam_app.handlers.drf_perm.base import RejectPermission
from backend.iam_app.handlers.drf_perm.base import DBManagePermission
from backend.iam_app.handlers.drf_perm.mcp import McpClusterManagePermission

logger = logging.getLogger("root")


class RedisQueryLogMcpToolsViewSet(McpToolsViewSet):
default_permission_class = [RejectPermission()]
default_permission_class = [DBManagePermission()]

@mcp_tools_api_decorator(
description=str(
Expand All @@ -39,6 +46,8 @@ class RedisQueryLogMcpToolsViewSet(McpToolsViewSet):
),
request_slz=RedisSlowlogInputSerializer,
response_slz=RedisSlowClusterStaticSerializer,
permission_classes=[McpClusterManagePermission],
mcp_auth_parser=auth_parse_clusters,
tags=[DBMMCPTags.READ],
mcp=[DBMMcpTools.REDIS_QUERY_LOG],
name_prefix="redis_query_log",
Expand All @@ -47,7 +56,7 @@ def get_cluster_slowlog_statics(self, request, *args, **kwargs):
"""获取集群时间范围内慢查询日志统计数据"""
start_time = self.get_param("start_time")
end_time = self.get_param("end_time")
immute_domain = self.get_param("immute_domain")
immute_domain = self.get_param("cluster_domain")

return Response(
get_cluster_slowlog_static(immute_domain=immute_domain, start_time=start_time, end_time=end_time)
Expand All @@ -57,6 +66,8 @@ def get_cluster_slowlog_statics(self, request, *args, **kwargs):
description=str(_("查询某台机器上的慢查询日志(slowlog),包括执行时间、命令内容等。可用于分析Redis性能问题和慢查询优化")),
request_slz=RedisSlowlog4HostInputSerializer,
response_slz=RedisSlowlogResponseSerializer,
permission_classes=[McpClusterManagePermission],
mcp_auth_parser=auth_parse_clusters,
tags=[DBMMCPTags.READ],
mcp=[DBMMcpTools.REDIS_QUERY_LOG],
name_prefix="redis_query_log",
Expand All @@ -66,8 +77,32 @@ def fetch_host_slowlog(self, request, *args, **kwargs):
start_time = self.get_param("start_time")
end_time = self.get_param("end_time")
ip = self.get_param("ip")
immute_domain = self.get_param("immute_domain")
immute_domain = self.get_param("cluster_domain")

return Response(
get_host_slowlog(immute_domain=immute_domain, start_time=start_time, end_time=end_time, host=ip)
)

@mcp_tools_api_decorator(
description=str(_("查询某个实例的慢查询日志(slowlog),包括执行时间、命令内容等。可用于分析Redis性能问题和慢查询优化")),
request_slz=RedisSlowlog4InstInputSerializer,
response_slz=RedisSlowlogResponseSerializer,
permission_classes=[McpClusterManagePermission],
mcp_auth_parser=auth_parse_clusters,
tags=[DBMMCPTags.READ],
mcp=[DBMMcpTools.REDIS_QUERY_LOG],
name_prefix="redis_query_log",
)
def fetch_instance_slowlog(self, request, *args, **kwargs):
"""获取某个实例上时间范围内慢查询日志"""
start_time = self.get_param("start_time")
end_time = self.get_param("end_time")
host = self.get_param("host")
port = self.get_param("port")
immute_domain = self.get_param("cluster_domain")

return Response(
get_instance_slowlog(
immute_domain=immute_domain, start_time=start_time, end_time=end_time, host=host, port=port
)
)
Loading