Loading [MathJax]/jax/output/CommonHTML/config.js
前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >后端线上服务监控与报警方案

后端线上服务监控与报警方案

作者头像
后端技术探索
发布于 2018-08-09 07:58:34
发布于 2018-08-09 07:58:34
2.2K00
代码可运行
举报
文章被收录于专栏:后端技术探索后端技术探索
运行总次数:0
代码可运行

点击关注⬆️nginx⬆️,学习lnmp

一、背景

1、上线期间服务稳定性观察较困难

一个功能上线后,其实研发心里根本没底儿,不知道这个功能上线以后是不是真的没问题;有经验一些老同学还知道直接登录线上机器去tail -f php.error.log,但是对于新同学来说,基本就只能等着被通知服务故障。

退一步说,即便是能去线上去tail -f查看错误日志,但是线上是多集群部署的,服务器都特别多,研发不可能在每一台机器上都能看到日志;即便是有日志收集机器,也得在各个集群下分别tail -f,定位问题很不方便!

再退一步说,即便是在线上机器看到了php错误日志,也并没有足够多的信息辅助信息能够迅速定位出来,怎样的一次访问请求,导致了这个错误。因为php记录的日志一般都是这个格式:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
[22-Oct-2015 18:39:04 Asia/Shanghai] PHP Fatal error:  Call to a member function prepare() on null in /home/work/phplib/db/Database.class.php on line 238

2、平时线上服务稳定性无法察觉

真正线上出问题较多的,其实还是系统运行过程中;比如流量突然增加导致接口处理出错、所依赖的第三方服务宕掉导致的程序错误、网络原因导致接口不能正常工作,等等。因为平时系统运行中,大家不会有专门的人去线上日志机器一直tail -f进行观察,效率低,且不现实。

3、接口性能问题无人关注

一个接口,可能因为产品上的各种原因,研发会不停地往上面打补丁进行实现,很多情况下,会因为功能上线比较紧张,所以实现过程中忽略了接口性能。在一段时间内,一个接口的响应时间从100ms上升到300ms,接口可用性从99.99下降到90.00;也许在正常情况下,我们不会感知到逐渐改造后的接口对线上造成了什么影响,但其实不然,接口SLA非常重要!可是,这些信息我们通过什么样的方式才能得知呢,真正能提供这些信息的同学,并不多! 

4、谁来跟进已发现的问题

还有一些情况是,线上出了问题,且其他组的同学帮助定位到大致的问题范围,抛到研发群以后,没人主动响应;大家都会觉得我没改过这个东西,所以忽略了;于是一个线上问题就只能等着Leader来安排跟进,否则就石沉大海,长期影响用户使用。

综上,我们必须要有一套自动化的线上服务监控和预警方案,主动发现,及时跟进!

二、监控范围

为了能对线上服务状况了如指掌,我们需要监控的内容一定得是很全的,但一开始得有一个重点监控的范围,也是平时最容易出问题的地方:

  • 编码粗心导致的PHP Syntax/Parse Error
  • 程序代码中的PHP Fatal Error
  • 程序代码中的PHP Warning
  • 数据库访问导致的DB Error/Timeout等
  • 缓存系统Redis相关的错误
  • 缓存系统Memcache相关的错误
  • 线上接口的可用性监控
  • 线上接口的响应时间监控

三、实现方案【如何:采】

1、PHP相关错误监控

包括语法错误、以及运行期间的Fatal、Warning等,都可以借助PHP提供的register_sutdown_functionset_error_handler组合的形式来实现:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
/**
 * 统一截获并处理错误
 * @return bool
 */public static function registErrorHandler() {
    $e_types = array (
        E_ERROR   => 'PHP Fatal',
        E_WARNING => 'PHP Warning',
        E_PARSE   => 'PHP Parse Error',
        E_NOTICE  => 'PHP Notice'
    );
    register_shutdown_function(function () use ($e_types) {
        $error = error_get_last();        if ($error['type'] != E_NOTICE && !empty($error['message'])) {            $error['trace'] = self::getStackTrace();            self::error_handler($error);
        }
    });
    set_error_handler(function ($type, $message, $file, $line) use ($e_types) {
        if ($type != E_NOTICE && !empty($message)) {            $error = array (                'type'    => $type,                'message' => $message,                'file'    => $file,                'line'    => $line,                'trace'   => self::getStackTrace()
            );            self::error_handler($error);            // 被截获的错误,重新输出到错误文件
            error_log(($e_types[$type] ?: 'Unknown Problem') . ' :  ' . $message . ' in ' . $file . ' on line ' . $line . "\n");
        }
    }, E_ALL);
}

当然,这个需要在程序的入口处进行注册,保证每一次的程序执行,都能成功捕获错误:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
// 全局异常捕获MonitorManager::registErrorHandler();

通过这个方式,我们在业务层就能完全捕获接口执行过程中的任意错误。

2、DB、Memcache、Redis相关错误的监控

在各个SDK内部,将执行过程中的异常都向上抛出(throw new Exception),内容尽可能详细,包括:

  • DB错误
    • 具体的SQL
    • 具体的DB、Table
    • 错误栈
    • 对应的接口名称
    • 服务器IP
  • Memcache、Redis错误
    • 具体错误号(内容)
    • 出错的Memcache Key
    • 错误栈
    • 对应的接口名称
    • 服务器IP

同时,我们通过一个统一工具方法进行收集错误日志,下面说如何收集

四、实现方案【如何:集】

所有的错误不采取直接上报,因为这必然会直接影响当前接口的性能,所以采取队列方式进行收集,即:业务层或SDK中有错误产生时,统一通过一个工具方法进行收集,收集之后,将该错误内容直接入队列,另外开启一个队列实时消耗进程,将队列中的错误日志数据上报到服务器进行处理。

1、日志收集的工具方法

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
/**
 * 添加监控日志,日志会被异步收集到日志平台进行展示
 *
 * @param $type
 * @param $content
 */public static function collect($type, $content) {
    // 线上集群,并且开关处于打开状态,才进行收集
    if (Utilities::isOnlineCluster() && SwitchManager::getSwitch('collect', SwitchManager::SWITCH_MONITOR)) {        // 检查当前这种监控类型是否支持
        if (self::support($type) && !self::checkWhiteList($type, $content)) {            self::queueInstance()->enQueue(json_encode(array (                'type'    => $type,                'data'    => $content,                'cluster' => Utilities::getClusterName(),                'reqtime' => isset($_SERVER['REQUEST_TIME']) ? $_SERVER['REQUEST_TIME'] : time(),                'extinfo' => array (                    'domain'    => $_SERVER['SERVER_NAME'],                    'path'      => isset($_SERVER['QUERY_STRING']) ? str_replace('?' . $_SERVER['QUERY_STRING'], '', $_SERVER['REQUEST_URI']) : 'script',                    'userAgent' => isset($_SERVER['HTTP_USER_AGENT']) ? $_SERVER['HTTP_USER_AGENT'] : '',                    'referer'   => isset($_SERVER['HTTP_REFERER']) ? $_SERVER['HTTP_REFERER'] : '',                    'serverIp'  => Utilities::getServerPhpIP(),                    'reqData'   => json_encode($_REQUEST, true)
                )
            ), true));
        }
    }
}

从上面的方法可看出,除了具体的错误日志,我们还一并收集了一些非常重要的辅助信息,比如当前集群、出问题的域名、对应接口、userAgent、请求参数、接口从哪儿来的等等。

2、队列实时消耗脚本

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
<?phpnamespace Mlservice\Script\Monitor;use Framework\Libs\Monitor\MonitorManager;use Framework\Libs\Util\Utilities;/**
 * 从MC队列中,将各种错误日志上报到日志平台进行汇总监控、报警等
 * Class Collect
 * @package Mlservice\Script\Monitor
 * @author  xianliezhao
 */class Collect extends \Framework\FrameworkScript {
    private $limit = 5;    private $interval = 600;    public function run() {
        // 检查脚本可执行
        $this->checkCluster();        $start = time();        while (true) {            $index = 0;            $params = array ();            while (true) {                $index++;                $item = MonitorManager::queueInstance()->deQueue();                if (!empty($item)) {                    $params[] = $item;
                } else {                    // 如果数据为空,则10分钟清理一次队列,做一次初始化,且自杀进程
                    if (time() - $start > $this->interval) {
                        MonitorManager::queueInstance()->makeEmpty();                        exit(0);
                    }                    break;
                }                if ($index >= $this->limit) {                    break;
                }
            }            // 发送到服务器,统一收集
            if (!empty($params)) {
                Utilities::apiRequest('bizfe', 'feapi/monitor/mon/collect', $params);
            } else {
                sleep(1);
            }
        }
    }
}

队列消耗机制做的很简单,不需要采集到所有的错误,只要保证线上有错误了,我们能第一时间得知,即可。 日志每最多收集满5条就上报一次,通过HTTP请求方式,上报到bizfe::/feapi/monitor/mon/collect

五、实现方案【如何:处理】

1、数据采用MongoDB存储

对于这种内容和结构灵活多变的数据,采用MongoDB存储再合适不过了,只需要定义一个简单的一级表结构即可:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
/**
 * 错误日志采集的表结构
 * @type {*|Model}
 */var monModel = connection.model('monitor', new Schema({
    type: String,
    cluster: String,
    product: String,
    data: Object,
    extinfo: Object,
    reqtime: Number
}, {
    autoIndex: true}));

2、数据保存策略

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
/**
 * 对数据进行加工,然后保存日志到db,批量保存成功以后再进行报警检测
 * @param messageModel
 */function save(messageModel) {
    return function (reqParams, callback) {
        var params = [];        for (var i in reqParams) {            var item = JSON.parse(reqParams[i]);            // 忽略来自标准环境的任何错误
            if (item.extinfo.domain.indexOf('rdlab') > 0) {                continue;
            }            // 从域名中记录下出问题的模块名称
            item.product = item.extinfo.domain.split('\.')[0];
            item = cleanParams(messageModel, item);
            params.push(item);
        }        var count = params.length;        if (count == 0) {
            callback();
        }        var saveData = [];        var done = 0;        // 批量保存
        params.forEach(function (item) {
            new messageModel(item).save(function (err, product, effectRows) {
                !err && (item._id = product._id);
                saveData.push(item);                if (++done == count) {                    // 当所有的错误日志都进入db成功以后,开始进行报警检测(内存中会维护一个错误池)
                    alarm.addAndCheckPool(saveData);                    if (err) {
                        callback(err, null);
                    } else {
                        callback(null, {error_code: 0, data: {}});
                    }
                }
            });
        });
    };
}

3、报警检测机制

通过alarm.addAndCheckPool会在内存中维护一个日志错误池,只需要开启一个子进程每秒检测错误池中的数据,进行阈值检测即可。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
/**
 * 每秒检测一次,各个错误类型只要达到邮件或者短信的最大阈值,则进行报警
 */var doAlarm = function () {
    var INTERVAL_TIME = 1000;    // 启用监控
    if (!alarmListenIng) {
        alarmListenIng = true;
    } else {        return false;
    }

    setInterval(function () {
        // 遍历所有类型,判断是否进行报警
        Object.keys(cachePool).forEach(function (type) {

            // 当前时间
            var nowTime = (new Date()).getTime();            // 控制每分钟最多只能报警N次
            var alarmCount = cachePool[type]['alarmCount'];            if (alarmCount === undefined) {
                initCacheByType(type, 1);
            } else {                var lastMtime = cachePool[type]['lastMtime'];                if ((nowTime - lastMtime) / 1000 > 60) {                    // 超过1分钟,直接进行数据重新初始化
                    initCacheByType(type, 1);
                } else if (alarmCount >= cachePool[type]['alarmCpm']) {                    // 如果每分钟的报警次数超过阈值,就不报警了
                    return false;
                }
            }            // 控制每N秒内报警一次
            var lastAlarmTime = cachePool[type]['lastAlarmTime'];            if (lastAlarmTime === undefined) {
                cachePool[type]['lastAlarmTime'] = nowTime;
            } else if (Math.ceil((nowTime - lastAlarmTime) / 1000) >= cachePool[type]['timeInterval']) {
                cachePool[type]['lastAlarmTime'] = nowTime;                // 这种情况下,才表明需要报警
                if (cachePool[type]['alarms'] && cachePool[type]['alarms']['total'] >= cachePool[type]['maxNumForMail']) {
                    cachePool[type]['type'] = type;
                    cachePool[type]['alarmCount'] += 1;                    var theAlarmData = cachePool[type];
                    theAlarmData.theTime = Math.ceil((nowTime - lastAlarmTime) / 1000) || 1;                    // 邮件报警
                    sendEmail(buildEmailAlarmContent(theAlarmData));                    // 如果是出错量比设定的短信阈值还大,则短信报警
                    if (cachePool[type]['maxNumForSms'] <= cachePool[type]['alarms']['total']) {
                        sendSmsMessage(buildSmsAlarmContent(theAlarmData));
                    }                    // 清空
                    initCacheByType(type, 0);
                }
            }
        });
    }, INTERVAL_TIME);
};

当然,各种错误的不同阈值为了日后的维护,也抽离成配置单独管理,更为合适:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
    /**
     * 报警阈值设定
     */
    alarmLimits: {
        db_log: {
            timeInterval: 3, // 每隔3s监控一次
            maxNumForMail: 10, // 邮件报警阈值
            maxNumForSms: 50, // 短信报警阈值
            alarmCpm: 5 // 表示每分钟最多报警5次
        },
        redis_log: {
            timeInterval: 3,
            maxNumForMail: 10,
            maxNumForSms: 50,
            alarmCpm: 5
        },
        mc_log: {
            timeInterval: 3,
            maxNumForMail: 5,
            maxNumForSms: 20,
            alarmCpm: 5
        },
        mq_error: {
            timeInterval: 3,
            maxNumForMail: 10,
            maxNumForSms: 30,
            alarmCpm: 5
        },
        php_error: {
            timeInterval: 3,
            maxNumForMail: 5,
            maxNumForSms: 20,
            alarmCpm: 5
        },
        php_warning: {
            timeInterval: 3,
            maxNumForMail: 10,
            maxNumForSms: 50,
            alarmCpm: 5
        }
    }

六、接收报警

按照这套流程下来,线上只要出任何错误,都会被实时上报到日志服务器,以php_error为例,每隔3秒检测一次,如果累积出现5次错误,则采取邮件方式进行报警,如果累积出现20次错误,则可理解为错误较严重,进行短信报警!

对于不同类型的错误报警,会发送给不同的接收人,抄送给大组,保证该次报警一定不会被忽略。同时提供一个Web平台,对日志进行分析展现,可查询某个错误的详细信息,快速分析出问题出现在什么地方;一般情况下,通过该平台的日志详情页,可以一眼就判断出来该错误应该采取什么方式去修复。

七、接口可用性与响应时间监控

1、数据来源分析

这部分的数据,可以直接从Nginx日志中进行提取,首先,我们可以来看看一条完整的Nginx日志包含的内容:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
[x.x.x.x] [-] [23/Oct/2015:14:59:59 +0800] [GET /goods/goods_info?goods_id=276096349&fields=platform_type%2Cgoods_id%2Cgoods_param%2Cgoods_detail%2Cshop_id%2Cfirst_sort_id%2Csize%2Cgoods_desc HTTP/1.1] [200] [1957] [xxx.com/share/goods_details] [Snake Connect] [-] [0.010] [y.y.y.y:9999] [0.010] [-] [uid:0;ip:0.0.0.0;v:0;master:0;is_mob:0]

基本就是这个格式:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
[$remote_addr] [$remote_user] [$time_local] [$request] [$status] [$body_bytes_sent] [$http_referer] [$http_user_agent] [$http_user_agent] [$http_x_forwarded_for] [$request_time] [$upstream_addr] [$upstream_response_time] [$request_body]

当然,Nginx日志收集的格式,是可以在Nginx配置文件中进行自定义的,具体看业务层需要怎么分析。

基于上面已经产生的这个日志,我们可以通过这几个数据来做接口性能监控

  • $request 具体的接口名称
  • $status 该请求对应的执行状态(200:成功;499:超时;502:服务挂了;500:可能是有Fatal...),通过这个信息来衡量接口的可用性
  • $request_time 一个接口的完整执行时间,通过这个值来衡量接口的响应时间

2、监控对象以及数据采集

对于需要监控的对象,可以通过白名单的方式,指定对某些接口进行监控,但是这样不够灵活,尤其是一个服务下的接口在不断增加,经常更新监控的接口列表,维护成本较高。

还有比较智能的方法,就是根据某个接口的访问量,取前N个进行监控,比如可以通过这样的方式来获取监控接口列表:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
# 日期date_time=$(date -d "-1 hours" "+%Y%m%d%H")# 文件位置file_name="/home/service/nginx/log/xxx.mlservice.access.${date_time}.log"# 获取监控列表api_list=$(awk '{print $6}' ${file_name} | grep -v 'your_filter_api_here' | sed -e "s/\?.*//" -e "s/^\///" | tr '[A-Z]' '[a-z]' | sort | uniq -c | sort -nr | head -n 20 | awk '{print $2}') ;

这里的api_list就是是动态获取到的监控对象了,结果形如:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
goods/goods_info
goods/campaign_info
inventory/get_skuinfo
inventory/set_inventory
campaign/update_campaign
campaign/goods_info
inventory/spu_set
inventory/inventory_decr
...

对于数据的采集,就可以直接通过上面的监控对象,利用grep提取所有相关的数据,然后通过awk逐条进行分析,最终得出平均值,输出结果。而对数据结果的上报,直接通过curl方式发送到bizfe平台进行统一存储以及集中展现。

3、几张效果图片

1)、报警邮件
2)、平台中展现所有监控日志
3)、错误详情
4)、平台中展现接口性能

八、结语

线上服务出现任何问题,作为一线研发,都应该第一时间知道出了什么问题、问题出在哪儿、大致的影响范围是什么、大致如何修复等。绝对不是等着用户来反馈了,我们才被动的去找用户报的问题,如何复现?

当然,我们也不能成为监控报警的重度患者,凡事也得有个度,如果线上不管是什么样的log都通过报警的方式发出来,就真成了扰民了!

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2015-12-22,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 nginx 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
一文搞懂得物前端监控
得物的服务端监控是比较全面和有效的,除了上报原始日志数据,还通过数据分析制定线上告警机制,调用链路分析,而针对前端项目这一块,还是不够全面的。对前端线上问题感应不及时,靠人肉发现,没有告警机制等问题,所以就有个前端监控这个项目。前端监控也确实很有必要,我们需要对线上的页面有个全面的把控,而至于怎么做监控,做数据上报,以及数据分析,如何针对监控数据分析出有用的核心链路的告警等也能有个全面的认识。本文主要是介绍得物针对监控做了哪些事情以及对前端底层监控手段做个总结。
得物技术
2023/12/13
7800
一文搞懂得物前端监控
服务稳定性及应用防护方案
日志收集推荐使用Elastic Stack协议栈,可以满足收集海量日志需求,而且便于后续分析、报表、报警操作
三杯水Plus
2018/11/14
1.1K0
一条502报警引发的胡思乱想
就在安心养神的时候, 同事转给了我一条nginx 502的报警, 赶紧去线上一顿排查。
用户2825413
2019/07/16
6590
一条502报警引发的胡思乱想
从0到1搭建前端监控平台,面试必备的亮点项目
常常会苦恼,平常做的项目很普通,没啥亮点;面试中也经常会被问到:做过哪些亮点项目吗?
前端老道
2023/02/27
3.7K0
从0到1搭建前端监控平台,面试必备的亮点项目
【升职加薪秘籍】我在服务监控方面的实践(6)-业务维度的mysql监控
在上一节我们是讲解了如何对应用服务进行监控,这一节我将会介绍如何对mysql进行监控,在传统监控mysql(对mysql整体服务质量的监控)的情况下,建立对表级别的监控,以及长事务,复杂sql的监控,并能定位到具体代码。
蓝胖子的编程梦
2023/12/04
3790
【升职加薪秘籍】我在服务监控方面的实践(6)-业务维度的mysql监控
目前为止整理最全的前端监控体系搭建篇(长文预警)
PV(page view) 是页面浏览量,UV(Unique visitor)用户访问量。PV 只要访问一次页面就算一次,UV 同一天内多次访问只算一次。
前端达人
2022/04/18
12.3K1
目前为止整理最全的前端监控体系搭建篇(长文预警)
转 前端代码异常日志收集与监控
☞ 收集日志的方法 平时收集日志的手段,可以归类为两个方面,一个是逻辑中的错误判断,为主动判断;一个是利用语言给我们提供的捷径,暴力式获取错误信息,如 try..catch 和 window.onerror。 1. 主动判断 我们在一些运算之后,得到一个期望的结果,然而结果不是我们想要的 // test.js function calc(){ // code... return val; } if(calc() !== "someVal"){ Reporter.send({ positi
jojo
2018/05/03
1.3K0
转                                        前端代码异常日志收集与监控
web前端监控的三个方面探讨
以 init 为程序的入口,代码中所有同步执行出现的错误都会被捕获,这种方式也可以很好的避免程序刚跑起来就挂。
smy
2018/08/01
1.2K0
web前端监控的三个方面探讨
应用性能前端监控,字节跳动这些年经验都在这了
随着用户数量的不断增长,对于站点体验衡量的的需求也日益紧迫,用户会将产品和他们每天使用的体验最好的 Web 站点进行比较。想着手优化,则必须先有相关的监控数据,才能对症下药。
ssh_晨曦时梦见兮
2022/03/07
1.3K0
应用性能前端监控,字节跳动这些年经验都在这了
针对业务日志的监控报警设置
需求说明:对线上业务日志进行监控,当日志中出现的ERROR条数超过30条时立即报警! 监控脚本部署到qd-inf-logcollector01服务器上了(需要提前做好qd-inf-logcollector01到业务部署机器的ssh无密码信任关系) 1)qd-inf-logcollector01 机器上的操作记录: [root@qd-inf-logcollector01 ~]$ cd /app/script/ [root@qd-inf-logcollector01 script]$ ll total 37
洗尽了浮华
2018/01/23
1.8K0
后端服务(nginx部署)<status code 500>的一次排查经历
本文介绍狼厂同事一次解决服务端接口报 http status 500错误的过程。问题不复杂,但是问题的起因在实际工作中并不多见,并且涉及多个知识点。
后端技术探索
2019/07/19
5.3K0
沉淀了3年的自研前端错误监控系统,打通你的脉络
这篇文章是我的好朋友广胤所写,里面记录了我们2018年探索的前端监控体系的历程,由于在建设完后的我离职了,后续也没有继续能和广胤一起更进一步的探索,还是有一些些遗憾。还记得我第一次进入「兑吧」的时候,我就在简历里描述了错误监控之类的项目,其实当时我并没有在一个公司进行过实践,这大概是之前在网易的时候,闲来没事,进行的自我探索。然后进入「兑吧」后,没想到当时公司正好缺少这一块的基建,于是 TL 就让我和广胤负责了这块项目,也是这次经历让我从实习阶段就正式踏入了前端基础建设的道路,还是非常感谢这一次的机会,让我从单一的业务开发人员,转化到了结构型开发人员。记得在开发的项目的那一个月中,除了吃饭,或者和广胤讨论项目的进度问题,近乎一种忘我的开发状态。
秋风的笔记
2021/07/30
1.1K0
干货满满!如何做好前端日志和异常监控的思考
在研发过程中,日志是非常重要的一环,它可以帮助我们快速定位问题,解决问题。在前端开发中,日志也是非常重要的一环,它可以帮助我们快速定位问题,解决问题。本文将介绍前端日志的规范和最佳实践。但是我们经常看到一些项目日志打得满天飞,但是到了真正定位问题的时候,发现日志并没有什么卵用。这是因为日志打得不规范,不规范的日志是没有意义的。所以我们需要规范日志的打印,才能让日志发挥最大的作用。
老码小张
2024/03/20
1.5K1
干货满满!如何做好前端日志和异常监控的思考
2019腾讯广告算法大赛方案分享(初赛冠军)
bettenW/Tencent2019_Finals_Rank1st​github.com
Coggle数据科学
2019/09/12
1.8K0
2019腾讯广告算法大赛方案分享(初赛冠军)
前端错误捕获方案总结
本文主要摘抄自:https://juejin.cn/post/7172072612430872584#heading-10,主要用来记录和学习,也推荐大家看看原博主的文章。
蓓蕾心晴
2022/12/30
1.7K0
前端错误捕获方案总结
小程序的日志系统与监控分析
在开发小程序的过程中,日志系统和监控分析工具是不可或缺的组件。无论是调试、性能监控,还是排查生产环境中的问题,良好的日志系统都能为开发者提供重要的信息支持。而监控系统则能够帮助开发者实时掌握小程序的健康状态,及时发现潜在问题,从而确保系统的稳定性和用户的良好体验。
LucianaiB
2025/01/28
1300
【前端监控】监控数据都有什么
用户的账号信息。如果是QQ 登陆,就是QQ 号,微信登陆就是 微信uin(不是微信号),或者你们公司自己登录体系下的账号
神仙朱
2021/09/10
1.5K0
【前端监控】监控数据都有什么
Zabbix 3.4监控Zookeeper3.4(附脚本模板)
zookeeper监控要点系统监控 这个监控linux系统以及修改linux服务器参数即可 内存使用量 ZooKeeper应当完全运行在内存中,不能使用到SWAP。Java Heap大小不能超过可用内存。 Swap使用量 使用Swap会降低ZooKeeper的性能,设置vm.swappiness = 0 网络带宽占用 如果发现ZooKeeper性能降低关注下网络带宽占用情况和丢包情况,通常情况下ZooKeeper是20%写入80%读入 磁盘使用量 ZooKeeper数据目录使用情况需要注意 磁盘I/O ZooKeeper的磁盘写入是异步的,所以不会存在很大的I/O请求,如果ZooKeeper和其他I/O密集型服务公用应该关注下磁盘I/O情况
星哥玩云
2022/07/19
5400
SourceMap 与前端异常监控
我们从事 Web 开发工作中,异常监控系统已经是我们朝夕相处的好助手,但是这些异常处理工具通常都是建立在 Web 生态,或者是假定运行在浏览器环境下的,但是当我们需要给一套跨端系统搭建一套类似的异常监控系统,并且期望该系统兼容 Web 生态,现有的工具很可能就不满足我们的需求了,因此我们需要考虑一套完整的异常监控系统整个链路将会涉及到哪些工具链,以及如何修改这些工具链来适配我们的跨端系统。
用户4456933
2021/07/12
2.3K0
SourceMap 与前端异常监控
监控平台前端SDK开发实践
背景 监控是提高故障处理能力和保障服务质量必需的一环,它需要负责的内容包括:及时上报错误、收集有效信息、提供故障排查依据。 及时上报错误:发生线上问题后,经由运营或者产品反馈到开发人员,其中流转过程可能是几分钟甚至几十分钟,这段时间可能直接导致公司的经济损失。如果有一个监控系统,在线上出现问题时,监控系统能够第一时间报警,并且通知到开发人员,那开发人员就可以第一时间修复上线,使公司损失最小化。 收集有效信息:特别是移动时代,定位一个问题时,需要很多用户信息(如用户手机版本、网络情况、操作流程等)。如果没有监
美团技术团队
2018/03/13
1.9K0
监控平台前端SDK开发实践
推荐阅读
相关推荐
一文搞懂得物前端监控
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验