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

简介: 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搭建和管理企业级网站应用
相关文章
|
19天前
|
运维 Cloud Native 持续交付
深入理解云原生架构及其在现代企业中的应用
随着数字化转型的浪潮席卷全球,企业正面临着前所未有的挑战与机遇。云计算技术的迅猛发展,特别是云原生架构的兴起,正在重塑企业的IT基础设施和软件开发模式。本文将深入探讨云原生的核心概念、关键技术以及如何在企业中实施云原生策略,以实现更高效的资源利用和更快的市场响应速度。通过分析云原生架构的优势和面临的挑战,我们将揭示它如何助力企业在激烈的市场竞争中保持领先地位。
|
17天前
|
Kubernetes Cloud Native 微服务
探索云原生技术:容器化与微服务架构的融合之旅
本文将带领读者深入了解云原生技术的核心概念,特别是容器化和微服务架构如何相辅相成,共同构建现代软件系统。我们将通过实际代码示例,探讨如何在云平台上部署和管理微服务,以及如何使用容器编排工具来自动化这一过程。文章旨在为开发者和技术决策者提供实用的指导,帮助他们在云原生时代中更好地设计、部署和维护应用。
|
26天前
|
Cloud Native Devops 云计算
云计算的未来:云原生架构与微服务的革命####
【10月更文挑战第21天】 随着企业数字化转型的加速,云原生技术正迅速成为IT行业的新宠。本文深入探讨了云原生架构的核心理念、关键技术如容器化和微服务的优势,以及如何通过这些技术实现高效、灵活且可扩展的现代应用开发。我们将揭示云原生如何重塑软件开发流程,提升业务敏捷性,并探索其对企业IT架构的深远影响。 ####
42 3
|
28天前
|
Cloud Native 持续交付 云计算
云原生架构的演进与挑战
随着云计算技术的不断发展,云原生架构已成为企业数字化转型的重要支撑。本文深入探讨了云原生架构的概念、发展历程、核心技术以及面临的挑战,旨在为读者提供一个全面了解云原生架构的视角。通过分析Kubernetes、Docker等关键技术的应用,以及微服务、持续集成/持续部署(CI/CD)等实践案例,本文揭示了云原生架构在提高应用开发效率、降低运维成本、增强系统可扩展性等方面的显著优势。同时,也指出了云原生架构在安全性、复杂性管理等方面所面临的挑战,并提出了相应的解决策略。
|
16天前
|
运维 Cloud Native 持续交付
云原生技术深度探索:重塑现代IT架构的无形之力####
本文深入剖析了云原生技术的核心概念、关键技术组件及其对现代IT架构变革的深远影响。通过实例解析,揭示云原生如何促进企业实现敏捷开发、弹性伸缩与成本优化,为数字化转型提供强有力的技术支撑。不同于传统综述,本摘要直接聚焦于云原生技术的价值本质,旨在为读者构建一个宏观且具体的技术蓝图。 ####
|
19天前
|
弹性计算 运维 Cloud Native
云原生架构的崛起与未来展望
在数字化转型的浪潮中,云原生架构凭借其高效、灵活和可扩展的特性,正逐渐成为企业IT战略的核心。本文旨在探讨云原生架构的定义、关键特性、实施优势以及面临的挑战,同时展望未来的发展趋势。通过深入分析,我们期望为读者提供一个关于云原生架构全面而深入的视角,助力企业在云计算时代做出更明智的决策。
31 3
|
21天前
|
Cloud Native API 持续交付
云原生时代的微服务架构设计
随着云计算的蓬勃发展,云原生概念逐渐成为IT行业的热点。本文将通过深入浅出的方式,介绍在云原生环境下,如何设计一个高效、可扩展的微服务架构。文章不仅涉及理论概念,还将结合实际代码示例,帮助读者理解微服务架构的核心要素和设计原则,以及如何在云平台上实现这些设计。
|
29天前
|
Kubernetes Cloud Native Docker
云原生之旅:从传统架构到容器化服务的演变
随着技术的快速发展,云计算已经从简单的虚拟化服务演进到了更加灵活和高效的云原生时代。本文将带你了解云原生的概念、优势以及如何通过容器化技术实现应用的快速部署和扩展。我们将以一个简单的Python Web应用为例,展示如何利用Docker容器进行打包和部署,进而探索Kubernetes如何管理这些容器,确保服务的高可用性和弹性伸缩。
|
23天前
|
Cloud Native 持续交付 云计算
云原生技术在现代IT架构中的转型力量####
本文深入剖析了云原生技术的精髓,探讨其在现代IT架构转型中的关键作用与实践路径。通过具体案例分析,展示了云原生如何赋能企业实现更高效的资源利用、更快的迭代速度以及更强的系统稳定性,为读者提供了一套可借鉴的实施框架与策略。 ####
24 0
|
26天前
|
消息中间件 运维 Cloud Native
云原生架构下的微服务优化策略####
本文深入探讨了云原生环境下微服务架构的优化路径,针对服务拆分、通信效率、资源管理及自动化运维等核心环节提出了具体的优化策略。通过案例分析与最佳实践分享,旨在为开发者提供一套系统性的解决方案,以应对日益复杂的业务需求和快速变化的技术挑战,助力企业在云端实现更高效、更稳定的服务部署与运营。 ####