Sentry(v20.12.1) K8S 云原生架构探索,JavaScript Data Management(问题分组篇)

本文涉及的产品
容器服务 Serverless 版 ACK Serverless,952元额度 多规格
容器服务 Serverless 版 ACK Serverless,317元额度 多规格
简介: Sentry(v20.12.1) K8S 云原生架构探索,JavaScript Data Management(问题分组篇)

SDK Fingerprinting



在受支持的 SDK 中,可以覆盖 Sentry 的默认分组,该分组将 fingerprint 属性作为字符串数组传递。fingerprint 数组的长度不受限制。这类似于 fingerprint rules functionality,它总是可用的,并可以实现类似的结果。


Basic Example


在最基本的情况下,值直接传递:


function makeRequest(method, path, options) {
  return fetch(method, path, options).catch(function(err) {
    Sentry.withScope(function(scope) {
      // group errors together based on their request and response
      scope.setFingerprint([method, path, String(err.statusCode)]);
      Sentry.captureException(err);
    });
  });
}


您可以使用变量替换将动态值填充到通常在服务器上计算出的指纹中。例如,可以添加值 {{default}},以将整个正常生成的分组哈希添加到指纹中。这些值与服务器端指纹识别相同。有关更多信息,请参见 Variables。


Group Errors With Greater Granularity


您的应用程序查询远程过程调用模型(Remote Procedure Call Model, RPC)接口或外部应用程序编程接口(external application Programming interface, API)服务,因此堆栈跟踪通常是相同的(即使传出请求非常不同)。


以下示例将进一步分解 Sentry 将创建的默认组(用 {{default}} 表示),并考虑错误对象的一些属性:


class MyRPCError extends Error {
  constructor(message, functionName, errorCode) {
    super(message);
    // The name of the RPC function that was called (e.g. "getAllBlogArticles")
    this.functionName = functionName;
    // For example a HTTP status code returned by the server.
    this.errorCode = errorCode;
  }
}
Sentry.init({
  ...,
  beforeSend: function(event, hint) {
    const exception = hint.originalException;
    if (exception instanceof MyRPCError) {
      event.fingerprint = [
        '{{ default }}',
        String(exception.functionName),
        String(exception.errorCode)
      ];
    }
    return event;
  }
});


Group Errors More Aggressively


通用错误(例如数据库连接错误)具有许多不同的堆栈跟踪,并且从不在一起。

以下示例将通过从数组中省略 {{ default }} 来完全覆盖 Sentry 的分组:


class DatabaseConnectionError extends Error {}
Sentry.init({
  ...,
  beforeSend: function(event, hint) {
    const exception = hint.originalException;
    if (exception instanceof DatabaseConnectionError) {
      event.fingerprint = ['database-connection-error'];
    }
    return event;
  }
});


Fingerprint Rules



Fingerprint 规则(以前称为服务器端指纹)也配置了类似于 stack trace rules 的配置,但语法略有不同。匹配器(matchers)是相同的,但不是翻转标志(flipping flags),而是分配一个指纹,它完全覆盖默认分组。


这些规则可以在 Settings > Projects > [project] > Issue Grouping > Fingerprint Rules 中按项目设置。Group Settings 有输入字段,您可以在其中写入自定义指纹规则。该语法遵循 Discover queries 中的语法。如果要否定匹配,可以在表达式前面加上感叹号(!)。


所有值都匹配,并且在堆栈跟踪的情况下,将考虑所有帧。如果所有匹配项都匹配,则应用指纹。

Fingerprinting Config


# You can use comments to explain the rules.  Rules themselves follow the
# following syntax:
matcher:expression -> list of values
# The list of values can be hardcoded or substituted values.


下面是一个实际的示例,它将特定类型的异常组合在一起:


error.type:DatabaseUnavailable -> system-down
error.type:ConnectionError -> system-down
error.value:"connection error: *" -> connection-error, {{ transaction }}


Matchers


匹配器通常使用通配符语法。可以使用以下匹配器:

error.type

  • alias: type
  • 与异常类型(异常名称)匹配。匹配以区分大小写的形式进行。


error.type:ZeroDivisionError -> zero-division
error.type:ConnectionError -> connection-error


error.value

  • alias: value
  • 与异常值匹配。错误或异常通常具有易于理解的描述(值)。该匹配器允许不区分大小写的匹配。


error.value:"connection error (code: *)" -> connection-error
error.value:"could not connect (*)" -> connection-error


message

  • 匹配日志消息。它还会自动检查其他异常值,因为它们很难分开。匹配不区分大小写。


message:"system encountered a fatal problem: *" -> fatal-log


logger

  • 匹配 logger 的名称,这对于将 logger 的所有消息组合在一起非常有用。此匹配区分大小写。


logger:"com.myapp.mypackage.*" -> mypackage-logger


level

  • 在日志级别匹配。匹配不区分大小写。


logger:"com.myapp.FooLogger" level:"error" -> mylogger-error


tags.tag_name

  • 与标签 tag_name 的值匹配。这对于过滤某些类型的事件很有用。例如,您可以分离由特定服务器引起的事件:


tags.server_name:"canary-*.mycompany.internal" -> canary-events


stack.abs_path

  • alias: path
  • 在事件的路径上匹配,并且不区分大小写。它使用路径遍历语义,这意味着 * 不匹配斜杠,而 ** 匹配。请注意,此匹配器在 abs_pathfilename 上都匹配,因为 SDK 关于如何支持这些值可能会非常不一致。如果 glob 匹配这些值中的任何一个,则视为匹配。


stack.abs_path:"**/my-utils/*.js" -> my-utils, {{ error.type }}


stack.module

  • alias: module
  • stack.abs_path 类似,但是匹配模块名称。匹配区分大小写,并且会应用常规的规则(* 也匹配斜杠)。


stack.module:"*/my-utils/*" -> my-utils, {{ error.type }}


stack.function

  • alias: function
  • 检查堆栈跟踪中的任何函数是否与全局匹配。匹配区分大小写:


stack.function:"my_assertion_failed" -> my-assertion-failed


stack.package

  • alias: package
  • 与 frame 的 "package" 匹配。这通常是包含 frame 的 debug symbol/object file 的名称。如果有任何 frame 与该目标文件匹配,那么它将匹配。


stack.package:"**/libcurl.dylib" -> libcurl
stack.package:"**/libcurl.so" -> libcurl


family

  • 用于 "scope" 匹配器。存在以下族:用于任何类型的 JavaScript 事件的 javascript,用于任何类型的 Native 事件的 native。任何其他平台称为 other


family:native !stack.module:"myproject::*" -> not-from-my-project


app

  • 检查 frame 是否在应用程序内。与其他匹配器结合使用时特别有用。可能的值为 yesno


app:yes stack.function:"assert" -> assert


Combining Matchers


当多个匹配器组合在一起时,它们都需要匹配。在 frame 上运行的匹配器必须全部应用于同一 frame;否则,它们不被视为匹配项。


例如,如果在函数名称和模块名称上都匹配,则仅当 frame 同时在函数名称和模块名称上匹配时,才存在匹配项。一个frame 仅与函数名称匹配是不够的,即使另一个 frame 本身会与模块名称匹配也是如此。


# this matches if a frame exists with a specific function and module name
# and also a specific error type is thrown
error.type:ConnectionError stack.function:"connect" stack.module:"bot" -> bot-error


Variables


在 fingerprint 的右边,你可以使用常数值和变量。变量会被自动替换,并具有与匹配器相同的名称,但它们的填充方式可能不同。


变量用双花括号括起来({{variable_name}})。

{{ default }}

  • 这将填充正常分组操作将产生的默认 fingerprint。如果您想用其他方法细分一个已经存在的组,这将非常有用:


stack.function:"query_database" -> {{ default }}, {{ transaction }}


{{ transaction }}

  • 这会将 transaction 名称填写到 transaction 中。它将强制为每个 transaction 创建一个组:


error.type:"ApiError" -> api-error, {{ transaction }}


{{ error.type }}

  • alias: {{ type }}
  • 这将填写发生的错误的名称。使用 ·chained exceptions· 时,它将是最近抛出的错误。这将强制每个 ·transaction· 创建一个组:


stack.function:"evaluate_script" -> script-evaluation, {{ error.type }}


{{ stack.function }}

  • alias: {{ function }}
  • 这将填充 "crashing frame," 的功能名称,也称为应用程序代码的最上层 frame。


error.type:"ScriptError" -> script-evaluation, {{ stack.function }}


{{ stack.module }}

  • alias: {{ module }}
  • 这将填写"crashing frame,"的模块名称,也称为应用程序代码的最上层 frame。


error.type:"ScriptError" -> script-evaluation, {{ stack.module }}


{{ stack.package }}

  • alias: {{ package }}
  • 这将填写 "crashing frame," 的 package 名称(object file),也称为应用程序代码的最上层 frame。


stack.function:"assert" -> assertion, {{ stack.package }}


{{ logger }}

  • 这将填写引起事件的 logger 的名称。


message:"critical connection error*" -> connection-error, {{ logger }}


{{ level }}

  • 这将填充用于创建事件的日志级别的名称。


message:"connection error*" -> connection-error, {{ logger }}, {{ level }}


{{ tags.tag_name }}

  • 这会将 tag 的值填充到 fingerprint 中,例如,可以使用 fingerprint 按 server name 或类似名称拆分事件。


message:"connection error*" -> connection-error, {{ tags.server_name }}


Stack Trace Rules



如果使用堆栈跟踪进行分组,则堆栈跟踪规则(以前称为分组增强)会影响输入该算法的数据。可以在 Settings > Projects > [project] > Issue Grouping > Stack Trace Rules 下,针对每个项目配置这些规则。


每行都是一条规则;当所有表达式匹配时,一个或多个匹配表达式后跟一个或多个要执行的动作。所有规则在堆栈跟踪中的所有帧上从上到下执行。

堆栈跟踪规则的语法类似于:


matcher-name:expression other-matcher:expression ... action1 action2 ...


该语法遵循 Discover queries 中的语法。如果要否定匹配,可以在表达式前面加上感叹号(!)。

下面是一个实际的例子:


# mark all code in node modules not to be in app
stack.abs_path:**/node_modules/**         -app
# remove all generated javascript code from all grouping
stack.abs_path:**/generated/**.js         -group


Matchers


可以在一行中定义多个匹配器。下面的匹配器是可用的:

family

  • 匹配通用 platform family,目前包括 javascript, native 和 other。逗号分隔规则将它们应用于多个平台。


family:javascript stack.abs_path:**/generated/**  -group


stack.abs_path

  • alias: path
  • 该匹配器对堆栈跟踪中路径上的 Unix glob 行为不区分大小写。路径分隔符被标准化为 /。作为特殊规则,如果文件名是相对的,则它仍在 **/ 上匹配。


# match on all files under `project` with a `.c` extension
stack.abs_path:**/project/**.c` +app
# matches on vendor/foo without sub folders
stack.abs_path:**/vendor/foo/*.c` -app
# matches on `foo.c` as well as `foo/bar.c`.
stack.abs_path:**/*.gen.c` -group


stack.module

  • alias: module
  • Module 与 path 类似,但与 module 匹配。它不用于 Native,但用于 JavaScript、Python 和类似平台。匹配是区分大小写的,常规通配符是可用的。请注意,modules 不是 packages,这可能会让 Native 环境感到困惑。

stack.function

  • alias: function
  • 匹配堆栈跟踪中的函数,并且使用常规通配符区分大小写。


stack.function:myproject_* +app
stack.function:malloc      -group


stack.package

  • alias: package
  • 在堆栈跟踪中匹配 package。package 是包含 functionmodule 的容器。这是一个 .jar ,一个 .dylib 或类似的。匹配规则与 path 相同。例如,这通常是一个绝对路径。


stack.package:**/libcurl.dylib -group


app

  • stack trace frame 的应用内标记的当前状态匹配。yes 表示该 frame 是应用程序内 frame,no 表示不是。


Actions


有两种类型的 actions:标记(flag)和变量(variables)设置。

flag 标识在所有匹配器都匹配并使用以下前缀时采取的动作:


  • + 设置 flag
  • - 取消设置 flag
  • ^ 适用于匹配帧之上的帧(走向崩溃)。
  • v 适用于匹配帧下面的帧(远离崩溃)。

例如,-group ^-group 从组中移除匹配帧和它上面的所有帧。

  • app:在应用程序内标记或取消标记 frame
  • group:从分组中添加或删除 frame

variables:可以设置变量(variable=value)。当前只有一种:

  • max-frames:设置要分组的总帧数。默认值为 0,表示“所有帧”。如果设置为 3,则仅考虑前三个帧。

如果一行以 hash(#) 作为前缀,则它是一个注释并被忽略。


stack.abs_path:**/node_modules/** -group
stack.abs_path:**/app/utils/requestError.jsx -group
stack.abs_path:**src/getsentry/src/getsentry/** +app
family:native max-frames=3
stack.function:fetchSavedSearches v-group
stack.abs_path:**/app/views/**.jsx stack.function:fetchData ^-group
family:native stack.function:SpawnThread v-app -app
family:native stack.function:_NSRaiseError ^-group -app
family:native stack.function:std::* -app
family:native stack.function:core::* -app


Recommendations


这些建议将大大改善您的即用型分组体验。

Mark in-app Frames

为了主动改善您的体验,请帮助 Sentry 确定堆栈跟踪中的哪些帧是“应用程序内”(属于您自己的应用程序),哪些不是。SDK 定义了默认规则,但是在许多情况下,也可以在服务器上进行改进。特别是对于需要服务器端处理的语言(例如,Native C,C++ 或 JavaScript),最好在服务器上覆盖它。


stack.function:myapplication::* +app


你也可以通过标记其他帧 “not in-app” 来达到同样的效果。然而,如果是这种情况,你应该确保首先将所有帧设置为 “in-app”,以覆盖默认值:


app:no                   +app
stack.function:std::*    -app
stack.function:boost::*  -app


你需要强制所有帧首先在应用程序内,因为客户端 SDK 或早期处理可能已经设置了一些默认值。


Cut Stack Traces


在许多情况下,您要删除堆栈跟踪的顶部或底部。例如,许多代码库使用通用函数来生成错误。在这种情况下,错误机制将显示为堆栈跟踪的一部分。

例如,如果你使用 Rust,你可能想要删除一些与 panic 处理相关的 frames:


stack.function:std::panicking::begin_panic       ^-app -app ^-group
stack.function:core::panicking::begin_panic      ^-app -app ^-group


在这里,我们告诉系统从 begin-panic 到崩溃位置的所有 frame 都不是应用程序的一部分(包括 panic frame 本身)。在所有情况下,以上所有 frame 均与分组无关。

同样,您也可以删除堆栈跟踪的 base。如果您有不同的主循环来驱动应用程序,则此功能特别有用:


例如,如果你使用 Rust,你可能想要删除一些与 panic 处理相关的 frames:


stack.function:std::panicking::begin_panic       ^-app -app ^-group
stack.function:core::panicking::begin_panic      ^-app -app ^-group


这并不适用于所有的项目,但它可以很好地工作于许多崩溃的大型应用程序。默认的策略是考虑与分组相关的大多数堆栈跟踪。这意味着导致崩溃的每个不同的堆栈跟踪都将导致创建不同的组。如果你不想这样,你可以通过限制应该考虑的帧数来强制设置更大的组。


例如,如果堆栈跟踪中的任何帧都指向一个公共的外部库,你可以告诉系统只考虑 top N 帧:


# always only consider the top 1 frame for all native events
family:native max-frames=1
# if the bug is in proprietarymodule.so, only consider top 2 frames
family:native stack.package:**/proprietarymodule.so  max-frames=2
# these are functions we want to consider much more of the stack trace for
family:native stack.function:KnownBadFunction1  max-frames=5
family:native stack.function:KnownBadFunction2  max-frames=5


相关实践学习
通过Ingress进行灰度发布
本场景您将运行一个简单的应用,部署一个新的应用用于新的发布,并通过Ingress能力实现灰度发布。
容器应用与集群管理
欢迎来到《容器应用与集群管理》课程,本课程是“云原生容器Clouder认证“系列中的第二阶段。课程将向您介绍与容器集群相关的概念和技术,这些概念和技术可以帮助您了解阿里云容器服务ACK/ACK Serverless的使用。同时,本课程也会向您介绍可以采取的工具、方法和可操作步骤,以帮助您了解如何基于容器服务ACK Serverless构建和管理企业级应用。 学习完本课程后,您将能够: 掌握容器集群、容器编排的基本概念 掌握Kubernetes的基础概念及核心思想 掌握阿里云容器服务ACK/ACK Serverless概念及使用方法 基于容器服务ACK Serverless搭建和管理企业级网站应用
相关文章
|
3天前
|
Cloud Native 安全 数据安全/隐私保护
云原生架构下的微服务治理与挑战####
随着云计算技术的飞速发展,云原生架构以其高效、灵活、可扩展的特性成为现代企业IT架构的首选。本文聚焦于云原生环境下的微服务治理问题,探讨其在促进业务敏捷性的同时所面临的挑战及应对策略。通过分析微服务拆分、服务间通信、故障隔离与恢复等关键环节,本文旨在为读者提供一个关于如何在云原生环境中有效实施微服务治理的全面视角,助力企业在数字化转型的道路上稳健前行。 ####
|
5天前
|
运维 Kubernetes Cloud Native
云原生技术:容器化与微服务架构的完美结合
【10月更文挑战第37天】在数字化转型的浪潮中,云原生技术以其灵活性和高效性成为企业的新宠。本文将深入探讨云原生的核心概念,包括容器化技术和微服务架构,以及它们如何共同推动现代应用的发展。我们将通过实际代码示例,展示如何在Kubernetes集群上部署一个简单的微服务,揭示云原生技术的强大能力和未来潜力。
|
3天前
|
Cloud Native 安全 API
云原生架构下的微服务治理策略与实践####
—透过云原生的棱镜,探索微服务架构下的挑战与应对之道 本文旨在探讨云原生环境下,微服务架构所面临的关键挑战及有效的治理策略。随着云计算技术的深入发展,越来越多的企业选择采用云原生架构来构建和部署其应用程序,以期获得更高的灵活性、可扩展性和效率。然而,微服务架构的复杂性也带来了服务发现、负载均衡、故障恢复等一系列治理难题。本文将深入分析这些问题,并提出一套基于云原生技术栈的微服务治理框架,包括服务网格的应用、API网关的集成、以及动态配置管理等关键方面,旨在为企业实现高效、稳定的微服务架构提供参考路径。 ####
20 5
|
4天前
|
Kubernetes 负载均衡 Cloud Native
云原生架构下的微服务治理策略
随着云原生技术的不断成熟,微服务架构已成为现代应用开发的主流选择。本文探讨了在云原生环境下实施微服务治理的策略和方法,重点分析了服务发现、负载均衡、故障恢复和配置管理等关键技术点,以及如何利用Kubernetes等容器编排工具来优化微服务的部署和管理。文章旨在为开发者提供一套实用的微服务治理框架,帮助其在复杂的云环境中构建高效、可靠的分布式系统。
18 5
|
4天前
|
负载均衡 监控 Cloud Native
云原生架构下的微服务治理策略与实践####
在数字化转型浪潮中,企业纷纷拥抱云计算,而云原生架构作为其核心技术支撑,正引领着一场深刻的技术变革。本文聚焦于云原生环境下微服务架构的治理策略与实践,探讨如何通过精细化的服务管理、动态的流量调度、高效的故障恢复机制以及持续的监控优化,构建弹性、可靠且易于维护的分布式系统。我们将深入剖析微服务治理的核心要素,结合具体案例,揭示其在提升系统稳定性、扩展性和敏捷性方面的关键作用,为读者提供一套切实可行的云原生微服务治理指南。 ####
|
4天前
|
消息中间件 缓存 Cloud Native
云原生架构下的性能优化实践与挑战####
随着企业数字化转型的加速,云原生架构以其高度解耦、弹性伸缩和快速迭代的特性,成为现代软件开发的首选模式。本文深入探讨了云原生环境下性能优化的关键策略与面临的主要挑战,通过案例分析,揭示了如何有效利用容器化、微服务、动态调度等技术手段提升应用性能,同时指出了在复杂云环境中确保系统稳定性和高效性的难题,为开发者和架构师提供了实战指南。 ####
18 3
|
4天前
|
运维 Kubernetes Cloud Native
深入理解云原生架构:从理论到实践
【10月更文挑战第38天】本文将引导读者深入探索云原生技术的核心概念,以及如何将这些概念应用于实际的软件开发和运维中。我们将从云原生的基本定义出发,逐步展开其背后的设计哲学、关键技术组件,并以一个具体的代码示例来演示云原生应用的构建过程。无论你是云原生技术的初学者,还是希望深化理解的开发者,这篇文章都将为你提供有价值的见解和实操指南。
|
4天前
|
Kubernetes Cloud Native 持续交付
云原生技术在现代应用架构中的实践与思考
【10月更文挑战第38天】随着云计算的不断成熟和演进,云原生(Cloud-Native)已成为推动企业数字化转型的重要力量。本文从云原生的基本概念出发,深入探讨了其在现代应用架构中的实际应用,并结合代码示例,展示了云原生技术如何优化资源管理、提升系统弹性和加速开发流程。通过分析云原生的优势与面临的挑战,本文旨在为读者提供一份云原生转型的指南和启示。
18 3
|
4天前
|
运维 Kubernetes Cloud Native
云原生技术在现代应用架构中的实践与挑战####
本文深入探讨了云原生技术的核心概念、关键技术组件及其在实际项目中的应用案例,分析了企业在向云原生转型过程中面临的主要挑战及应对策略。不同于传统摘要的概述性质,本摘要强调通过具体实例揭示云原生技术如何促进应用的灵活性、可扩展性和高效运维,同时指出实践中需注意的技术债务、安全合规等问题,为读者提供一幅云原生技术实践的全景视图。 ####
|
5天前
|
监控 持续交付 Docker
Docker 容器化部署在微服务架构中的应用有哪些?
Docker 容器化部署在微服务架构中的应用有哪些?