> 文档中心 > 微服务架构统一异常监控Sentry

微服务架构统一异常监控Sentry

Sentry

  • 基本介绍
  • 简单使用
  • Java项目应用
    • 简单demo
    • 项目实战

基本介绍

Sentry 是一个开源的实时错误报告工具,支持 web 前后端、移动应用以及游戏,支持 Python、OC、Java、Go、Node、Django、RoR 等主流编程语言和框架 ,还提供了 GitHub、Slack、Trello 等常见开发工具的集成。
Senty是专门用来干异常日志监控的,它的核心就是围绕异常日志来建模和设计的,它有很多的异常日志监控特性,包括智能错误分析,归类汇总,自动分配告警到相关团队等等,这些虽然理论上ELK也能实现,但是实现成本比较高。
Sentry是一个应用监控系统,可以用于前后端各种技术栈的线上监控和错误分析。

简单使用

首先打开Sentry 的官网sentry官网,并且进行一系列的注册,创建一个组织,这里我创建一个组织,命名叫做ah
在这里插入图片描述

创建项目
在这里插入图片描述
在这里插入图片描述
获取dsn

在这里插入图片描述

Java项目应用

      io.sentry     sentry     5.7.3 

简单demo

配置Sentry

@SpringBootApplicationpublic class ThriftRpcApplication {    public static void main(String[] args) { SpringApplication.run(ThriftRpcApplication.class, args); Sentry.init(options -> {     options.setDsn("https://90cd056919fxxxxxxxxxxxxxxxxx954c6186db4@o1207430.ingest.sentry.io/6340908"); });    }}
@RestController@Api(value = "测试", tags = "测试")@RequestMapping("/tt")public class Controller {    /     * 方法会发生500错误     *     * @return     */    @GetMapping("/helloworld")    @ApiOperation("ceshi")    public String helloworld() { try {     int x = 1 / 0; } catch (Exception e) {     Sentry.captureException(e); } return "Hello World!";    }    @GetMapping("/test")    @ApiOperation("tt")    public String test() { try {     System.out.println("测试代码");     throw  new Exception("测试错误。。。。"); } catch (Exception e) {     Sentry.captureException(e); } return "Hello World!";    }}

错误如下
在这里插入图片描述
在这里插入图片描述

项目实战

全局异常拦截类

@ControllerAdvice@RestControllerpublic class GlobalExceptionHandler {    private static Logger logger = LoggerFactory.getLogger(GlobalExceptionHandler.class);    @ExceptionHandler(BusinessException.class)    @ResponseBody    public ResultModel businessExceptionHandler(BusinessException e, ServletRequest request) { Sentry.captureException(e); ContentCachingRequestWrapper wrapper = (ContentCachingRequestWrapper) request; logger.error("error in \nurl :{} \ncode:{} \nmsg:{} \nparams:{}\n body:{}", ((ContentCachingRequestWrapper) request).getRequestURI(), e.getErrorCode(), e.getMsg(), JSON.toJSONString(request.getParameterMap()), StringUtils.toEncodedString(wrapper.getContentAsByteArray(), Charset.forName(wrapper.getCharacterEncoding()))); return ResultModel.error(e.getErrorCode(), e.getMsg());    }    @ExceptionHandler(MethodArgumentNotValidException.class)    @ResponseBody    public ResultModel methodArgumentNotValidHandler(MethodArgumentNotValidException e, ServletRequest request) { ContentCachingRequestWrapper wrapper = (ContentCachingRequestWrapper) request; String message = e.getBindingResult().getAllErrors().get(0).getDefaultMessage(); logger.error("error in \nurl :{} \nmsg:{} \nparams:{}\n body:{}", ((ContentCachingRequestWrapper) request).getRequestURI(), message, JSON.toJSONString(request.getParameterMap()), StringUtils.toEncodedString(wrapper.getContentAsByteArray(), Charset.forName(wrapper.getCharacterEncoding()))); Sentry.captureException(e); return ResultModel.error(ErrorCode.FAIL.getCode(), message);    }    @ExceptionHandler(MissingServletRequestParameterException.class)    @ResponseBody    public ResultModel methodArgumentNotValidHandler(MissingServletRequestParameterException e, ServletRequest request) { ContentCachingRequestWrapper wrapper = (ContentCachingRequestWrapper) request; String message = e.getMessage(); logger.error("error in \nurl :{} \nmsg:{} \nparams:{}\n body:{}", ((ContentCachingRequestWrapper) request).getRequestURI(), message, JSON.toJSONString(request.getParameterMap()), StringUtils.toEncodedString(wrapper.getContentAsByteArray(), Charset.forName(wrapper.getCharacterEncoding()))); Sentry.captureException(e); return ResultModel.error(ErrorCode.FAIL.getCode(), "必填参数为空");    }    @ExceptionHandler(IllegalArgumentException.class)    @ResponseBody    public ResultModel illegalArgumentHandler(IllegalArgumentException e, ServletRequest request) { ContentCachingRequestWrapper wrapper = (ContentCachingRequestWrapper) request; logger.error("error in \nurl :{} \nmsg:{} \nparams:{}\n body:{}", ((ContentCachingRequestWrapper) request).getRequestURI(), e.getMessage(), JSON.toJSONString(request.getParameterMap()), StringUtils.toEncodedString(wrapper.getContentAsByteArray(), Charset.forName(wrapper.getCharacterEncoding()))); Sentry.captureException(e); return ResultModel.error(ErrorCode.FAIL.getCode(), e.getMessage() );    }    @ExceptionHandler(Exception.class)    @ResponseBody    public ResultModel exceptionHandler(Exception e, ServletRequest request) { ContentCachingRequestWrapper wrapper = (ContentCachingRequestWrapper) request; logger.error("error in \nurl :{} \nparams:{}\nbody:{}", ((ContentCachingRequestWrapper) request).getRequestURI(), JSON.toJSONString(request.getParameterMap()), StringUtils.toEncodedString(wrapper.getContentAsByteArray(), Charset.forName(wrapper.getCharacterEncoding()))); logger.error("程序运行出现异常!", e); Sentry.captureException(e); return ResultModel.error(ErrorCode.UNDEFINED);    }    @ExceptionHandler(HttpMessageNotReadableException.class)    @ResponseBody    public ResultModel exceptionHandler(HttpMessageNotReadableException e, ServletRequest request) { ContentCachingRequestWrapper wrapper = (ContentCachingRequestWrapper) request; logger.error("error in \nurl :{} \nparams:{}\nbody:{}", ((ContentCachingRequestWrapper) request).getRequestURI(), JSON.toJSONString(request.getParameterMap()), StringUtils.toEncodedString(wrapper.getContentAsByteArray(), Charset.forName(wrapper.getCharacterEncoding()))); logger.error("程序运行出现异常!", e); Sentry.captureException(e); return ResultModel.error(ErrorCode.PARAM_ERROR.getCode(), "json格式错误:" + e.getLocalizedMessage());    }}

错误码接口

public interface IErrorCode {    long getCode();    String getMessage();}

错误码类

public enum ErrorCode implements IErrorCode {    /     * 成功     */    SUCCESS(0L, "成功"),    /     * 失败     */    FAIL(1L, "失败"),    /     * 参数异常     */    PARAM_ERROR(2L, "参数异常"),    /     * 服务连接异常     */    CONNECTION_ERROR(3L, "服务连接异常"),    /     * 未明确定义名称异常     */    UNDEFINED(10001, "未明确定义名称异常"),    ;    private long code;    private String message;    ErrorCode(long code, String message) { this.code = code; this.message = message;    }    @Override    public long getCode() { return code;    }    @Override    public String getMessage() { return message;    }}

返回对象封装

@Datapublic class ResultModel implements Serializable {    /     * 返回错误码     */    @ApiModelProperty(value="返回错误码数")    private long code = ErrorCode.SUCCESS.getCode();    /     * 返回错误信息     */    @ApiModelProperty(value="返回错误信息")    private String message = ErrorCode.SUCCESS.getMessage();    /     * 数据     */    @ApiModelProperty(value="数据")    private T data;    @ApiModelProperty(value="时间戳")    private long timestamp = System.currentTimeMillis();    /是否加密/    @ApiModelProperty(value="是否加密")    private boolean encryption = false;    /加密数据/    @ApiModelProperty(value="加密数据")    private String ciphertext;    public ResultModel(long code, T data, String message) { super(); this.code = code; this.message = message; this.data = data;    }    public ResultModel(long code, String message) { super(); this.code = code; this.message = message;    }    public ResultModel(ErrorCode errorCode) { super(); this.code = errorCode.getCode(); this.message = errorCode.getMessage();    }    public ResultModel() {    }    public ResultModel(T data) { this.data = data;    }    public static  ResultModel error(ErrorCode errorCode){ return new ResultModel(errorCode);    }    public static  ResultModel  error(long errorCode,String msg){ return new ResultModel(errorCode,msg);    }    public static  ResultModel error(long errorCode, String msg, T data){ return new ResultModel(errorCode,data,msg);    }    public static  ResultModel fail(){ return new ResultModel(ErrorCode.FAIL);    }    public static  ResultModel succ(){ return new ResultModel(ErrorCode.SUCCESS);    }    public static  ResultModel succ(T data){ return new ResultModel(data);    }}

业务异常类

import lombok.Getter;import lombok.Setter;import lombok.ToString;@Getter@Setter@ToStringpublic class BusinessException extends RuntimeException {    / 异常码 */    private Long errorCode = ErrorCode.UNDEFINED.getCode();    / 对用户友好的错误信息 */    private String msg;    public BusinessException(Long errorCode, String message) { super(message); this.errorCode = errorCode; this.msg = message;    }    public BusinessException(String message) { super(message); this.msg = message;    }    public BusinessException(IErrorCode errorCode) { super(errorCode.getMessage()); this.errorCode = errorCode.getCode(); this.msg = errorCode.getMessage();    }}

项目使用

/     * 方法会发生500错误     *     * @return     */    @GetMapping("/helloworld")    @ApiOperation("ceshi")    public String helloworld() { try {     int x = 1 / 0; } catch (Exception e) {     throw new BusinessException(e.getMessage()); } return "Hello World!";    }

Sentry显示如下
在这里插入图片描述

51银饰网