MonkeyCode实现日记分析体系:从日记网络到实时告警

[复制链接]
发表于 3 小时前 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?立即注册

×
日记是体系的黑匣子

线上出标题,第一反应就是看日记。但日记散落在各台服务器,grep查起来慢,关键错误被沉没在海量日记里……
这篇文章用MonkeyCode构建一个完备的日记分析体系:网络→存储→分析→告警,全流程主动化。
体系架构
  1. [应用服务器] --Fluentd--> [Kafka] --> [Logstash] --> [Elasticsearch] --> [Kibana]
  2.                                                     |
  3.                                                     --> [告警服务] --> [Slack/企微]
复制代码
给MonkeyCode的Prompt
  1. 构建日志日志分析系统,要求:
  2. 1. 日志日志收集:Fluentd配置(收集Nginx、应用日志日志
  3. 2. 消息队列:Kafka(解耦收集和处理)
  4. 3. 日志处理:Logstash(解析、过滤、转换)
  5. 4. 存储:Elasticsearch(索引、搜索)
  6. 5. 可视化:Kibana仪表板
  7. 6. 告警规则:错误率、响应时间、异常关键字
  8. 7. 告警通知:Webhook发送到Slack
  9. 日志格式:JSON(包含timestamp, level, service, message, trace_id)
复制代码
1. Fluentd设置
  1. # fluentd/fluent.conf - MonkeyCode生成
  2. # Nginx访问日志
  3. <source>
  4.   @type tail
  5.   path /var/log/nginx/access.log
  6.   pos_file /var/log/td-agent/nginx-access.log.pos
  7.   tag nginx.access
  8.   format nginx
  9. </source>
  10. # Nginx错误日志
  11. <source>
  12.   @type tail
  13.   path /var/log/nginx/error.log
  14.   pos_file /var/log/td-agent/nginx-error.log.pos
  15.   tag nginx.error
  16.   format regexp
  17.   expression /^\d{4}/\d{2}/\d{2} \d{2}:\d{2}:\d{2} \[(\w+)\] (\d+#\d+): (.*)$/
  18. </source>
  19. # 应用JSON日志
  20. <source>
  21.   @type tail
  22.   path /var/log/app/*.log
  23.   pos_file /var/log/td-agent/app.log.pos
  24.   tag app
  25.   format json
  26.   time_key timestamp
  27.   time_format %Y-%m-%dT%H:%M:%S.%NZ
  28. </source>
  29. # 发送到Kafka
  30. <match **>
  31.   @type kafka2
  32.   
  33.   brokers kafka1:9092,kafka2:9092,kafka3:9092
  34.   topic_key topic
  35.   default_topic logs
  36.   
  37.   <format>
  38.     @type json
  39.   </format>
  40.   
  41.   <buffer>
  42.     @type file
  43.     path /var/log/td-agent/buffer
  44.     flush_interval 5s
  45.     chunk_limit_size 16MB
  46.     queue_limit_length 1024
  47.   </buffer>
  48. </match>
复制代码
2. Kafka设置
  1. # kafka/docker-compose.yml
  2. version: '3.8'
  3. services:
  4.   zookeeper:
  5.     image: confluentinc/cp-zookeeper:7.3.0
  6.     environment:
  7.       ZOOKEEPER_CLIENT_PORT: 2181
  8.       ZOOKEEPER_TICK_TIME: 2000
  9.     volumes:
  10.       - zookeeper-data:/var/lib/zookeeper/data
  11.   kafka:
  12.     image: confluentinc/cp-kafka:7.3.0
  13.     depends_on:
  14.       - zookeeper
  15.     ports:
  16.       - "9092:9092"
  17.     environment:
  18.       KAFKA_BROKER_ID: 1
  19.       KAFKA_ZOOKEEPER_CONNECT: zookeeper:2181
  20.       KAFKA_ADVERTISED_LISTENERS: PLAINTEXT://kafka:9092
  21.       KAFKA_OFFSETS_TOPIC_REPLICATION_FACTOR: 1
  22.       KAFKA_LOG_RETENTION_HOURS: 24
  23.       KAFKA_LOG_SEGMENT_BYTES: 1073741824
  24.       KAFKA_RETENTION_CHECK_INTERVAL_MS: 300000
  25.     volumes:
  26.       - kafka-data:/var/lib/kafka/data
  27. volumes:
  28.   zookeeper-data:
  29.   kafka-data:
复制代码
3. Logstash管道
  1. # logstash/pipeline/logs.conf - MonkeyCode生成
  2. input {
  3.   kafka {
  4.     bootstrap_servers => "kafka1:9092,kafka2:9092"
  5.     topics => ["logs"]
  6.     group_id => "logstash"
  7.     consumer_threads => 4
  8.     decorate_events => true
  9.   }
  10. }
  11. filter {
  12.   # 解析Nginx访问日志
  13.   if "nginx.access" in [tags] {
  14.     grok {
  15.       match => { "message" => "%{COMBINEDAPACHELOG}" }
  16.     }
  17.     date {
  18.       match => [ "timestamp", "dd/MMM/yyyy:HH:mm:ss Z" ]
  19.     }
  20.    
  21.     # 提取响应时间
  22.     grok {
  23.       match => { "message" => "rt=(?<response_time>\d+\.\d+)" }
  24.     }
  25.    
  26.     # 地理位置解析
  27.     geoip {
  28.       source => "clientip"
  29.       target => "geoip"
  30.     }
  31.    
  32.     # User-Agent解析
  33.     useragent {
  34.       source => "agent"
  35.       target => "useragent"
  36.     }
  37.   }
  38.   
  39.   # 解析应用JSON日志
  40.   if [level] {
  41.     # 标准化日志级别
  42.     mutate {
  43.       replace => { "log_level" => "%{level}" }
  44.     }
  45.    
  46.     # 错误日志特殊处理
  47.     if [level] == "ERROR" or [level] == "FATAL" {
  48.       mutate {
  49.         add_tag => ["error"]
  50.       }
  51.       
  52.       # 提取异常栈(如果有)
  53.       if [exception] {
  54.         grok {
  55.           match => { "exception" => "(?<exception_class>\w+\.\w+Exception): (?<exception_message>.*)" }
  56.         }
  57.       }
  58.     }
  59.   }
  60.   
  61.   # 添加服务标识
  62.   mutate {
  63.     add_field => { "environment" => "production" }
  64.     add_field => { "hostname" => "%{host}" }
  65.   }
  66.   
  67.   # 移除不需要的字段
  68.   mutate {
  69.     remove_field => [ "agent", "auth" ]
  70.   }
  71. }
  72. output {
  73.   # 输出到Elasticsearch
  74.   elasticsearch {
  75.     hosts => ["http://elasticsearch:9200"]
  76.     index => "logs-%{[service]}-%{+YYYY.MM.dd}"
  77.     template_name => "logs"
  78.     template_overwrite => true
  79.   }
  80.   
  81.   # 错误日志同时发送到告警主题
  82.   if "error" in [tags] {
  83.     kafka {
  84.       bootstrap_servers => "kafka1:9092"
  85.       topic_id => "alerts"
  86.     }
  87.   }
  88. }
复制代码
4. Elasticsearch索引模板
  1. // elasticsearch/templates/logs.json
  2. {
  3.   "index_patterns": ["logs-*"],
  4.   "settings": {
  5.     "number_of_shards": 3,
  6.     "number_of_replicas": 1,
  7.     "refresh_interval": "5s"
  8.   },
  9.   "mappings": {
  10.     "properties": {
  11.       "@timestamp": { "type": "date" },
  12.       "level": { "type": "keyword" },
  13.       "service": { "type": "keyword" },
  14.       "trace_id": { "type": "keyword" },
  15.       "message": { "type": "text", "analyzer": "standard" },
  16.       "exception": { "type": "text", "index": false },
  17.       "hostname": { "type": "keyword" },
  18.       "environment": { "type": "keyword" },
  19.       "response_time": { "type": "float" },
  20.       "status": { "type": "integer" },
  21.       "request": {
  22.         "properties": {
  23.           "method": { "type": "keyword" },
  24.           "path": { "type": "keyword" },
  25.           "params": { "type": "object", "enabled": false }
  26.         }
  27.       },
  28.       "user": {
  29.         "properties": {
  30.           "id": { "type": "keyword" },
  31.           "ip": { "type": "ip" }
  32.         }
  33.       },
  34.       "geoip": {
  35.         "properties": {
  36.           "country": { "type": "keyword" },
  37.           "city": { "type": "keyword" },
  38.           "location": { "type": "geo_point" }
  39.         }
  40.       }
  41.     }
  42.   }
  43. }
复制代码
5. 告警服务
  1. # alert_service.py - MonkeyCode生成
  2. import json
  3. import requests
  4. import time
  5. from kafka import KafkaConsumer
  6. from elasticsearch import Elasticsearch
  7. from datetime import datetime, timedelta
  8. from dataclasses import dataclass
  9. from typing import List, Dict, Any
  10. import logging
  11. logging.basicConfig(level=logging.INFO)
  12. logger = logging.getLogger(__name__)
  13. @dataclass
  14. class AlertRule:
  15.     name: str
  16.     condition: dict  # ES查询条件
  17.     threshold: int
  18.     time_window: int  # 秒
  19.     severity: str  # critical/warning/info
  20.     channels: List[str]  # ['slack', 'wechat']
  21. class AlertService:
  22.     """日志告警服务"""
  23.    
  24.     def __init__(self, es_hosts: list, kafka_servers: list):
  25.         self.es = Elasticsearch(es_hosts)
  26.         self.consumer = KafkaConsumer(
  27.             'alerts',
  28.             bootstrap_servers=kafka_servers,
  29.             value_deserializer=lambda m: json.loads(m.decode('utf-8'))
  30.         )
  31.         self.alert_rules = self._load_rules()
  32.         self.alert_cooldown = {}  # 防止重复告警
  33.    
  34.     def _load_rules(self) -> List[AlertRule]:
  35.         """加载告警规则"""
  36.         return [
  37.             # 规则1:5分钟内错误超过100次
  38.             AlertRule(
  39.                 name='high_error_rate',
  40.                 condition={'term': {'level': 'ERROR'}},
  41.                 threshold=100,
  42.                 time_window=300,
  43.                 severity='critical',
  44.                 channels=['slack', 'wechat']
  45.             ),
  46.             # 规则2:5分钟内500响应超过50次
  47.             AlertRule(
  48.                 name='high_500_rate',
  49.                 condition={'term': {'status': 500}},
  50.                 threshold=50,
  51.                 time_window=300,
  52.                 severity='critical',
  53.                 channels=['slack']
  54.             ),
  55.             # 规则3:P99响应时间超过2秒
  56.             AlertRule(
  57.                 name='slow_response',
  58.                 condition={'range': {'response_time': {'gt': 2}}},
  59.                 threshold=10,
  60.                 time_window=60,
  61.                 severity='warning',
  62.                 channels=['slack']
  63.             ),
  64.             # 规则4:特定异常出现
  65.             AlertRule(
  66.                 name='critical_exception',
  67.                 condition={'match': {'exception_class': 'OutOfMemoryError'}},
  68.                 threshold=1,
  69.                 time_window=60,
  70.                 severity='critical',
  71.                 channels=['slack', 'wechat']
  72.             ),
  73.         ]
  74.    
  75.     def check_rules(self):
  76.         """检查所有告警规则"""
  77.         now = datetime.utcnow()
  78.         
  79.         for rule in self.alert_rules:
  80.             # 冷却期检查(避免重复告警)
  81.             if rule.name in self.alert_cooldown:
  82.                 if now < self.alert_cooldown[rule.name]:
  83.                     continue
  84.             
  85.             # 构建ES查询
  86.             query = {
  87.                 "query": {
  88.                     "bool": {
  89.                         "must": [
  90.                             rule.condition,
  91.                             {"range": {"@timestamp": {"gte": f"now-{rule.time_window}s"}}}
  92.                         ]
  93.                     }
  94.                 },
  95.                 "size": 0
  96.             }
  97.             
  98.             # 执行查询
  99.             result = self.es.search(index="logs-*", body=query)
  100.             count = result['hits']['total']['value']
  101.             
  102.             # 判断是否触发
  103.             if count >= rule.threshold:
  104.                 self._send_alert(rule, count)
  105.                 # 设置冷却期(5分钟内不重复告警)
  106.                 self.alert_cooldown[rule.name] = now + timedelta(minutes=5)
  107.    
  108.     def _send_alert(self, rule: AlertRule, count: int):
  109.         """发送告警"""
  110.         alert_data = {
  111.             "rule_name": rule.name,
  112.             "severity": rule.severity,
  113.             "count": count,
  114.             "threshold": rule.threshold,
  115.             "time_window": f"{rule.time_window}秒",
  116.             "timestamp": datetime.utcnow().isoformat()
  117.         }
  118.         
  119.         logger.warning(f"Alert triggered: {rule.name}, count={count}")
  120.         
  121.         if 'slack' in rule.channels:
  122.             self._send_to_slack(alert_data)
  123.         
  124.         if 'wechat' in rule.channels:
  125.             self._send_to_wechat(alert_data)
  126.    
  127.     def _send_to_slack(self, alert: dict):
  128.         """发送到Slack"""
  129.         webhook_url = "https://hooks.slack.com/services/YOUR/WEBHOOK/URL"
  130.         
  131.         color = {
  132.             'critical': 'danger',
  133.             'warning': 'warning',
  134.             'info': '#439FE0'
  135.         }.get(alert['severity'], 'warning')
  136.         
  137.         payload = {
  138.             "attachments": [{
  139.                 "color": color,
  140.                 "title": f"🚨 Alert: {alert['rule_name']}",
  141.                 "fields": [
  142.                     {"title": "严重程度", "value": alert['severity'], "short": True},
  143.                     {"title": "触发次数", "value": str(alert['count']), "short": True},
  144.                     {"title": "阈值", "value": str(alert['threshold']), "short": True},
  145.                     {"title": "时间窗口", "value": alert['time_window'], "short": True},
  146.                 ],
  147.                 "footer": alert['timestamp']
  148.             }]
  149.         }
  150.         
  151.         try:
  152.             requests.post(webhook_url, json=payload, timeout=5)
  153.         except Exception as e:
  154.             logger.error(f"Failed to send Slack alert: {e}")
  155.    
  156.     def _send_to_wechat(self, alert: dict):
  157.         """发送到企业微信"""
  158.         webhook_url = "https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=YOUR_KEY"
  159.         
  160.         payload = {
  161.             "msgtype": "markdown",
  162.             "markdown": {
  163.                 "content": f"""
  164. ## 🚨 告警通知
  165. **规则**: {alert['rule_name']}
  166. **严重程度**: {alert['severity']}
  167. **触发次数**: {alert['count']}
  168. **阈值**: {alert['threshold']}
  169. **时间窗口**: {alert['time_window']}
  170. **时间**: {alert['timestamp']}
  171. """
  172.             }
  173.         }
  174.         
  175.         try:
  176.             requests.post(webhook_url, json=payload, timeout=5)
  177.         except Exception as e:
  178.             logger.error(f"Failed to send WeChat alert: {e}")
  179.    
  180.     def run(self):
  181.         """主循环"""
  182.         logger.info("Alert service started")
  183.         
  184.         while True:
  185.             try:
  186.                 self.check_rules()
  187.                 time.sleep(30)  # 每30秒检查一次
  188.             except KeyboardInterrupt:
  189.                 break
  190.             except Exception as e:
  191.                 logger.error(f"Error in alert loop: {e}")
  192.                 time.sleep(60)
  193. if __name__ == '__main__':
  194.     service = AlertService(
  195.         es_hosts=['http://elasticsearch:9200'],
  196.         kafka_servers=['kafka1:9092']
  197.     )
  198.     service.run()
复制代码
6. Kibana仪表板设置
  1. // kibana/dashboard.json
  2. {
  3.   "version": "8.0.0",
  4.   "objects": [
  5.     {
  6.       "id": "logs-overview",
  7.       "type": "dashboard",
  8.       "attributes": {
  9.         "title": "Logs Overview",
  10.         "panelsJSON": [
  11.           {
  12.             "id": "error-count",
  13.             "type": "visualization",
  14.             "gridData": {"x": 0, "y": 0, "w": 6, "h": 4},
  15.             "panelConfig": {
  16.               "visType": "metric",
  17.               "aggs": [
  18.                 {"id": "1", "type": "count", "schema": "metric"}
  19.               ],
  20.               "filters": [
  21.                 {"query": "level:ERROR", "label": "Errors"}
  22.               ]
  23.             }
  24.           },
  25.           {
  26.             "id": "response-time-percentiles",
  27.             "type": "visualization",
  28.             "gridData": {"x": 6, "y": 0, "w": 6, "h": 4},
  29.             "panelConfig": {
  30.               "visType": "line",
  31.               "aggs": [
  32.                 {"id": "1", "type": "percentiles", "field": "response_time", "percents": [50, 95, 99]}
  33.               ]
  34.             }
  35.           },
  36.           {
  37.             "id": "top-services",
  38.             "type": "visualization",
  39.             "gridData": {"x": 0, "y": 4, "w": 6, "h": 4},
  40.             "panelConfig": {
  41.               "visType": "pie",
  42.               "aggs": [
  43.                 {"id": "1", "type": "terms", "field": "service", "size": 10}
  44.               ]
  45.             }
  46.           },
  47.           {
  48.             "id": "error-trend",
  49.             "type": "visualization",
  50.             "gridData": {"x": 6, "y": 4, "w": 6, "h": 4},
  51.             "panelConfig": {
  52.               "visType": "area",
  53.               "aggs": [
  54.                 {"id": "1", "type": "count"},
  55.                 {"id": "2", "type": "date_histogram", "field": "@timestamp", "interval": "1h"}
  56.               ],
  57.               "filters": [
  58.                 {"query": "level:ERROR"}
  59.               ]
  60.             }
  61.           }
  62.         ]
  63.       }
  64.     }
  65.   ]
  66. }
复制代码
7. 日记查询工具
  1. # log_query.py - MonkeyCode生成
  2. from elasticsearch import Elasticsearch
  3. from datetime import datetime, timedelta
  4. from typing import List, Dict, Any, Optional
  5. import json
  6. class LogQuery:
  7.     """日志查询工具"""
  8.    
  9.     def __init__(self, es_hosts: list):
  10.         self.es = Elasticsearch(es_hosts)
  11.    
  12.     def search(self, query: str, service: str = None, level: str = None,
  13.                start_time: datetime = None, end_time: datetime = None,
  14.                size: int = 100) -> List[Dict]:
  15.         """通用搜索"""
  16.         must = []
  17.         
  18.         # 关键字搜索
  19.         if query:
  20.             must.append({"match": {"message": query}})
  21.         
  22.         # 服务过滤
  23.         if service:
  24.             must.append({"term": {"service": service}})
  25.         
  26.         # 日志级别过滤
  27.         if level:
  28.             must.append({"term": {"level": level}})
  29.         
  30.         # 时间范围
  31.         time_range = {}
  32.         if start_time:
  33.             time_range["gte"] = start_time.isoformat()
  34.         if end_time:
  35.             time_range["lte"] = end_time.isoformat()
  36.         if time_range:
  37.             must.append({"range": {"@timestamp": time_range}})
  38.         
  39.         # 执行查询
  40.         body = {
  41.             "query": {"bool": {"must": must}} if must else {"match_all": {}},
  42.             "size": size,
  43.             "sort": [{"@timestamp": {"order": "desc"}}]
  44.         }
  45.         
  46.         result = self.es.search(index="logs-*", body=body)
  47.         
  48.         return [hit["_source"] for hit in result["hits"]["hits"]]
  49.    
  50.     def get_by_trace_id(self, trace_id: str) -> List[Dict]:
  51.         """根据trace_id查询完整链路"""
  52.         body = {
  53.             "query": {"term": {"trace_id": trace_id}},
  54.             "size": 1000,
  55.             "sort": [{"@timestamp": {"order": "asc"}}]
  56.         }
  57.         
  58.         result = self.es.search(index="logs-*", body=body)
  59.         return [hit["_source"] for hit in result["hits"]["hits"]]
  60.    
  61.     def get_error_context(self, log_id: str, before: int = 10, after: int = 10) -> List[Dict]:
  62.         """获取错误日志上下文"""
  63.         # 先找到目标日志
  64.         target = self.es.get(index="logs-*", id=log_id)
  65.         target_time = target["_source"]["@timestamp"]
  66.         hostname = target["_source"]["hostname"]
  67.         
  68.         # 查询前后的日志
  69.         body = {
  70.             "query": {
  71.                 "bool": {
  72.                     "must": [
  73.                         {"term": {"hostname": hostname}},
  74.                         {"range": {
  75.                             "@timestamp": {
  76.                                 "gte": datetime.fromisoformat(target_time) - timedelta(minutes=5),
  77.                                 "lte": datetime.fromisoformat(target_time) + timedelta(minutes=5)
  78.                             }
  79.                         }}
  80.                     ]
  81.                 }
  82.             },
  83.             "size": before + after + 1,
  84.             "sort": [{"@timestamp": {"order": "asc"}}]
  85.         }
  86.         
  87.         result = self.es.search(index="logs-*", body=body)
  88.         return [hit["_source"] for hit in result["hits"]["hits"]]
  89.    
  90.     def stats_by_service(self, time_range: str = "1h") -> Dict:
  91.         """按服务统计日志数量"""
  92.         body = {
  93.             "query": {"range": {"@timestamp": {"gte": f"now-{time_range}"}}},
  94.             "size": 0,
  95.             "aggs": {
  96.                 "by_service": {
  97.                     "terms": {"field": "service", "size": 20},
  98.                     "aggs": {
  99.                         "by_level": {
  100.                             "terms": {"field": "level"}
  101.                         }
  102.                     }
  103.                 }
  104.             }
  105.         }
  106.         
  107.         result = self.es.search(index="logs-*", body=body)
  108.         
  109.         stats = {}
  110.         for bucket in result["aggregations"]["by_service"]["buckets"]:
  111.             service = bucket["key"]
  112.             stats[service] = {
  113.                 "total": bucket["doc_count"],
  114.                 "by_level": {
  115.                     b["key"]: b["doc_count"]
  116.                     for b in bucket["by_level"]["buckets"]
  117.                 }
  118.             }
  119.         
  120.         return stats
  121. # 使用示例
  122. query = LogQuery(['http://localhost:9200'])
  123. # 搜索最近1小时的错误日志
  124. errors = query.search(
  125.     query="OutOfMemoryError",
  126.     level="ERROR",
  127.     start_time=datetime.utcnow() - timedelta(hours=1)
  128. )
  129. # 查询trace_id链路
  130. trace_logs = query.get_by_trace_id("abc-123-def")
  131. # 按服务统计
  132. stats = query.stats_by_service("1h")
  133. for service, data in stats.items():
  134.     print(f"{service}: {data}")
复制代码
8. Docker Compose一键摆设
  1. # docker-compose.yml - MonkeyCode生成
  2. version: '3.8'
  3. services:
  4.   elasticsearch:
  5.     image: docker.elastic.co/elasticsearch/elasticsearch:8.11.0
  6.     environment:
  7.       - discovery.type=single-node
  8.       - xpack.security.enabled=false
  9.       - "ES_JAVA_OPTS=-Xms512m -Xmx512m"
  10.     ports:
  11.       - "9200:9200"
  12.     volumes:
  13.       - es-data:/usr/share/elasticsearch/data
  14.     healthcheck:
  15.       test: ["CMD", "curl", "-f", "http://localhost:9200/_cluster/health"]
  16.       interval: 10s
  17.       timeout: 5s
  18.       retries: 5
  19.   kibana:
  20.     image: docker.elastic.co/kibana/kibana:8.11.0
  21.     depends_on:
  22.       elasticsearch:
  23.         condition: service_healthy
  24.     ports:
  25.       - "5601:5601"
  26.     environment:
  27.       - ELASTICSEARCH_HOSTS=http://elasticsearch:9200
  28.   logstash:
  29.     image: docker.elastic.co/logstash/logstash:8.11.0
  30.     depends_on:
  31.       - elasticsearch
  32.     volumes:
  33.       - ./logstash/pipeline:/usr/share/logstash/pipeline
  34.     ports:
  35.       - "5044:5044"
  36.   alert-service:
  37.     build: ./alert-service
  38.     depends_on:
  39.       - elasticsearch
  40.       - kafka
  41.     environment:
  42.       - ES_HOSTS=http://elasticsearch:9200
  43.       - KAFKA_SERVERS=kafka:9092
  44. volumes:
  45.   es-data:
复制代码
用MonkeyCode天生日记分析体系的关键是:把日记流从产生到告警的完备链路形貌清楚。ELK技能栈成熟但设置复杂,AI天生的设置文件可以节省大量时间,但告警规则必要根据业务特点调优。

免责声明:如果侵犯了您的权益,请联系站长及时删除侵权内容,谢谢合作!qidao123.com:ToB企服之家,中国第一个企服评测及软件市场,开放入驻,技术点评得现金.
回复

使用道具 举报

登录后关闭弹窗

登录参与点评抽奖  加入IT实名职场社区
去登录
快速回复 返回顶部 返回列表