Sentry(v20.12.1) K8S 云原生架构探索,JavaScript 性能监控之管理 Transactions

简介: Sentry(v20.12.1) K8S 云原生架构探索,JavaScript 性能监控之管理 Transactions

Automatic Instrumentation



要自动捕获 transactions,必须首先在应用程序中启用跟踪。

@sentry/tracing 包提供了一个 BrowserTracing 集成,以添加 automatic instrumentation 来监视浏览器应用程序的性能。


What Automatic Instrumentation Provides


BrowserTracing 集成为每个页面 load 和 navigation 事件创建一个新 transaction,并为在打开这些 transactions 时发生的每个 XMLHttpRequestfetch 请求创建一个 child span。进一步了解 traces, transactions, and spans。


Enable Automatic Instrumentation


要启用此自动跟踪,请在 SDK 配置选项中包含 BrowserTracing 集成。(请注意,使用 ESM 模块时,主要的 @sentry/* import 必须先于 @sentry/tracing import。)

配置完成后,在 sentry.io 中查看 transactions 时,您将同时看到 pageloadnavigation

ESM


// If you're using one of our integration packages, like `@sentry/react` or `@sentry/angular`,
// substitute its name for `@sentry/browser` here
import * as Sentry from "@sentry/browser";
import { Integrations as TracingIntegrations } from "@sentry/tracing"; // Must import second
Sentry.init({
  dsn: "https://examplePublicKey@o0.ingest.sentry.io/0",
  integrations: [
    new Integrations.BrowserTracing({
      tracingOrigins: ["localhost", "my-site-url.com", /^\//],
      // ... other options
    }),
  ],
  // We recommend adjusting this value in production, or using tracesSampler
  // for finer control
  tracesSampleRate: 1.0,
});


CDN


Sentry.init({
  dsn: "https://examplePublicKey@o0.ingest.sentry.io/0",
  integrations: [
    new Sentry.Integrations.BrowserTracing({
      tracingOrigins: ["localhost", "my-site-url.com", /^\//],
      // ... other options
    }),
  ],
  // We recommend adjusting this value in production, or using tracesSampler
  // for finer control
  tracesSampleRate: 1.0,
});


Configuration Options


您可以将许多不同的选项传递给 BrowserTracing 集成(作为 {optionName: value} 形式的对象),但是它具有合理的默认值。有关所有可能的选项,请参见 TypeDocs。


tracingOrigins


tracingOrigins 的默认值是 ['localhost', /^\//]。JavaScript SDK 将 sentry-trace header 附加到其目标包含列表中的字符串或匹配列表中的正则表达式的所有传出的 XHR/fetch 请求。如果您的前端向另一个域发出请求,则需要在其中添加它,以将 sentry-trace header 传播到后端服务,这是将 transactions 链接在一起作为单个跟踪的一部分所必需的。tracingOrigins 选项与整个请求 URL 匹配,而不仅仅是域。使用更严格的正则表达式来匹配 URL 的某些部分,可以确保请求不用不必要地附加 sentry-trace header。


例如:

  • 前端应用程序是从 example.com 提供的
  • 后端服务由 api.example.com 提供
  • 前端应用程序对后端进行 API 调用
  • 因此,该选项需要这样配置:new Integrations.BrowserTracing({tracingOrigins: ['api.example.com']})
  • 现在,向 api.example.com 发出的 XHR/fetch 请求将获得附加的 sentry-trace header


Sentry.init({
  dsn: "https://examplePublicKey@o0.ingest.sentry.io/0",
  integrations: [
    new Integrations.BrowserTracing({
      tracingOrigins: ["localhost", "my-site-url.com"],
    }),
  ],
  // We recommend adjusting this value in production, or using tracesSampler
  // for finer control
  tracesSampleRate: 1.0,
});


您将需要配置您的 Web 服务器 CORS 以允许 sentry-trace header。该配置可能类似于 "Access-Control-Allow-Headers: sentry-trace",但是该配置取决于您的设置。如果您不允许使用 sentry-trace header,则该请求可能会被阻止。


beforeNavigate

对于 pageloadnavigation transactions,BrowserTracing 集成使用浏览器的 window.location API 生成 transaction 名称。要自定义 pageloadnavigation transactions 的名称,您可以向 BrowserTracing 集成提供 beforeNavigate 选项。该选项允许您修改 transaction 名称以使其更通用,例如,名为 GET /users/12312012GET /users/11212012 的 transactions 都可以重命名为 GET /users/:userid,以便他们可以在一起。


import * as Sentry from "@sentry/browser";
import { Integrations } from "@sentry/tracing";
Sentry.init({
  dsn: "https://examplePublicKey@o0.ingest.sentry.io/0",
  integrations: [
    new Integrations.BrowserTracing({
      beforeNavigate: context => {
        return {
          ...context,
          // You could use your UI's routing library to find the matching
          // route template here. We don't have one right now, so do some basic
          // parameter replacements.
          name: location.pathname
            .replace(/\d+/g, "<digits>")
            .replace(/[a-f0-9]{32}/g, "<hash>"),
        };
      },
    }),
  ],
  // We recommend adjusting this value in production, or using tracesSampler
  // for finer control
  tracesSampleRate: 1.0,
});


shouldCreateSpanForRequest

此函数可用于过滤掉不需要的 spans,例如 XHR 的运行状况检查或类似的检查。默认情况下,shouldCreateSpanForRequest 已经过滤掉了除了 tracingOrigins 中定义的内容以外的所有内容。


import * as Sentry from "@sentry/browser";
import { Integrations } from "@sentry/tracing";
Sentry.init({
  dsn: "https://examplePublicKey@o0.ingest.sentry.io/0",
  integrations: [
    new Integrations.BrowserTracing({
      shouldCreateSpanForRequest: url => {
        // Do not create spans for outgoing requests to a `/health/` endpoint
        return !url.match(/\/health\/?$/);
      },
    }),
  ],
  // We recommend adjusting this value in production, or using tracesSampler
  // for finer control
  tracesSampleRate: 1.0,
});


Manual Instrumentation


要手动捕获 transactions,必须首先在应用程序中启用跟踪。

要手动 instrument 代码的某些区域,可以创建 transactions 来捕获它们。

这对于所有 JavaScript SDK(后端和前端)均有效,并且独立于 ExpressHttpBrowserTracing 集成而工作。


const transaction = Sentry.startTransaction({ name: "test-transaction" });
const span = transaction.startChild({ op: "functionX" }); // This function returns a Span
// functionCallX
span.finish(); // Remember that only finished spans will be sent with the transaction
transaction.finish(); // Finishing the transaction will send it to Sentry


例如,如果要为页面上的用户交互创建 transaction,请执行以下操作:


// Let's say this function is invoked when a user clicks on the checkout button of your shop
shopCheckout() {
  // This will create a new Transaction for you
  const transaction = Sentry.startTransaction('shopCheckout');
  // set the transaction on the scope so it picks up any errors
  hub.configureScope(scope => scope.setSpan(transaction));
  // Assume this function makes an xhr/fetch call
  const result = validateShoppingCartOnServer();
  const span = transaction.startChild({
    data: {
      result
    },
    op: 'task',
    description: `processing shopping cart result`,
  });
  processAndValidateShoppingCart(result);
  span.finish();
  transaction.finish();
}


这个例子将发送一个 transaction shopCheckout 到 Sentry。交易将包含一个 task span,该 span 衡量 processAndValidateShoppingCart 花费了多长时间。最后,对 transaction.finish() 的调用将完成transaction 并将其发送给 Sentry。


在为异步操作创建 spans 时,您还可以利用 Promises。但是请记住,必须在调用 transaction.finish() 之前将其 span 包含在事务中。


例如:


function processItem(item, transaction) {
  const span = transaction.startChild({
    op: "http",
    description: `GET /items/:item-id`,
  });
  return new Promise((resolve, reject) => {
    http.get(`/items/${item.id}`, response => {
      response.on("data", () => {});
      response.on("end", () => {
        span.setTag("http.status_code", response.statusCode);
        span.setData("http.foobarsessionid", getFoobarSessionid(response));
        span.finish();
        resolve(response);
      });
    });
  });
}


Connect Backend and Frontend Transactions



要将后端和前端 transactions 连接到单个一致的跟踪中,Sentry 使用 trace_id 值,该值在前端和后端之间传播。根据情况,此 ID 可以在请求 header 或 HTML <meta> 标记中传输。以这种方式链接 transactions 使您可以在 Sentry UI 中在它们之间进行导航,因此您可以更好地了解系统的不同部分如何相互影响。您可以在我们的分布式跟踪文档中了解有关此模型的更多信息。


Pageload


在前端和后端都启用跟踪并利用自动前端 instrumentation 功能时,可以将前端上自动生成的 pageload transaction 与后端上的为页面服务提供请求的 transaction 相连接。因为在浏览器中运行的 JavaScript 代码无法读取当前页面的响应 headers,所以 trace_id 必须在响应本身中传输,尤其是在从后端发送的 HTML <head> 中的 <meta> 标签中。


<html>
  <head>
    <meta name="sentry-trace" content="{{ span.toTraceparent() }}" />
    <!-- ... -->
  </head>
</html>


name 属性必须是字符串 "sentry-trace"content 属性必须由后端的 Sentry SDK 使用 span.toTraceparent()(或等效项,取决于后端平台)生成。这保证了将为每个请求生成一个新的唯一值。


span 引用是为 HTML 提供服务的 transaction,或其任何 child spans。它定义了 pageload transaction 的父级。


一旦数据被包含在 <meta> 标签中,我们的 BrowserTracing 集成将自动获取数据并将其链接到在 pageload 时生成的 transaction。(请注意,它不会链接到自动生成的 navigation transactions,即不需要重新加载整个页面的 transaction。每个 transaction 都是后端不同请求 transaction 的结果,因此应具有唯一的 trace_id。)


Navigation and Other XHR Requests


加载页面后,它发出的任何请求(以及后端产生的任何请求)都通过请求 header 链接。

就像上面讨论的 <meta> 标签一样,标题的名称是 sentry-trace,其值是通过调用 span.toTraceparent()(或等效的)来获得的,其中 span 是相关 transaction 或其任何子项。


Sentry 的所有与跟踪相关的集成(BrowserTracingHttpExpress)都会针对它们生成的所有 transactions 和 spans 自动生成或拾取并传播此 header。在手动创建 transaction 或 span 的任何情况下,您都可以自己附加和读取 header,这样做很有意义。


Control Data Truncation


当前,每个标签的最大字符数限制为200个字符。超过200个字符限制的标签将被截断,丢失潜在的重要信息。要保留此数据,您可以将数据拆分为多个标签。

例如,一个200多个字符标记的请求:


https://empowerplant.io/api/0/projects/ep/setup_form/?user_id=314159265358979323846264338327&tracking_id=EasyAsABC123OrSimpleAsDoReMi&product_name=PlantToHumanTranslator&product_id=161803398874989484820458683436563811772030917980576


上面200个字符以上的请求将被截断为:


https://empowerplant.io/api/0/projects/ep/setup_form/?user_id=314159265358979323846264338327&tracking_id=EasyAsABC123OrSimpleAsDoReMi&product_name=PlantToHumanTranslator&product_id=1618033988749894848


相反,使用 span.set_tagspan.set_data 会使用结构化元数据保留此查询的详细信息。这可以通过 baseUrlendpointparameters 完成:


const baseUrl = "https://empowerplant.io";
const endpoint = "/api/0/projects/ep/setup_form";
const parameters = {
  user_id: 314159265358979323846264338327,
  tracking_id: "EasyAsABC123OrSimpleAsDoReMi",
  product_name: PlantToHumanTranslator,
  product_id: 161803398874989484820458683436563811772030917980576,
};
const span = transaction.startChild({
  op: "request",
  description: "setup form",
});
span.setTag("baseUrl", baseUrl);
span.setTag("endpoint", endpoint);
span.setData("parameters", parameters);
// you may also find some parameters to be valuable as tags
span.setData("user_id", parameters.user_id);
http.get(`${base_url}/${endpoint}/`, (data = parameters));


Group Transactions


Sentry 捕获 transactions 时,将为它们分配一个 transaction 名称。该名称通常由 Sentry SDK 根据您使用的框架集成自动生成。如果您无法利用自动 transaction 生成(或想要自定义 transaction 名称的生成方式),则可以使用,在使用配置初始化 SDK 时注册的全局事件处理器。


在 node.js 应用程序中执行此操作的示例:


import { addGlobalEventProcessor } from "@sentry/node";
addGlobalEventProcessor(event => {
  // if event is a transaction event
  if (event.type === "transaction") {
    event.transaction = sanitizeTransactionName(event.transaction);
  }
  return event;
});


对于使用 BrowserTracing 集成的浏览器 JavaScript 应用程序,beforeNavigate 选项可用于根据 URL 更好地将 navigation/pageload transactions 分组在一起。


import * as Sentry from "@sentry/browser";
import { Integrations } from "@sentry/tracing";
Sentry.init({
  // ...
  integrations: [
    new Integrations.BrowserTracing({
      beforeNavigate: context => {
        return {
          ...context,
          // You could use your UI's routing library to find the matching
          // route template here. We don't have one right now, so do some basic
          // parameter replacements.
          name: location.pathname
            .replace(/\d+/g, "<digits>")
            .replace(/[a-f0-9]{32}/g, "<hash>"),
        };
      },
    }),
  ],
});


Retrieve an Active Transaction


如果要将 Spans 附加到已在进行中的 transaction 中,例如在对 transaction 进行分组时,可以使用 Sentry.getCurrentHub().getScope().getTransaction()。当 scope 中有正在运行的 transaction 时,此函数将返回一个 Transaction 对象,否则它将返回 undefined。如果您使用的是 BrowserTracing 集成,则默认情况下,我们会将 transaction 附加到 Scope,因此您可以执行以下操作:


function myJsFunction() {
  const transaction = Sentry.getCurrentHub()
    .getScope()
    .getTransaction();
  if (transaction) {
    let span = transaction.startChild({
      op: "encode",
      description: "parseAvatarImages",
    });
    // Do something
    span.finish();
  }
}


相关实践学习
通过Ingress进行灰度发布
本场景您将运行一个简单的应用,部署一个新的应用用于新的发布,并通过Ingress能力实现灰度发布。
容器应用与集群管理
欢迎来到《容器应用与集群管理》课程,本课程是“云原生容器Clouder认证“系列中的第二阶段。课程将向您介绍与容器集群相关的概念和技术,这些概念和技术可以帮助您了解阿里云容器服务ACK/ACK Serverless的使用。同时,本课程也会向您介绍可以采取的工具、方法和可操作步骤,以帮助您了解如何基于容器服务ACK Serverless构建和管理企业级应用。 学习完本课程后,您将能够: 掌握容器集群、容器编排的基本概念 掌握Kubernetes的基础概念及核心思想 掌握阿里云容器服务ACK/ACK Serverless概念及使用方法 基于容器服务ACK Serverless搭建和管理企业级网站应用
相关文章
|
24天前
|
运维 Cloud Native 持续交付
深入理解云原生架构及其在现代企业中的应用
随着数字化转型的浪潮席卷全球,企业正面临着前所未有的挑战与机遇。云计算技术的迅猛发展,特别是云原生架构的兴起,正在重塑企业的IT基础设施和软件开发模式。本文将深入探讨云原生的核心概念、关键技术以及如何在企业中实施云原生策略,以实现更高效的资源利用和更快的市场响应速度。通过分析云原生架构的优势和面临的挑战,我们将揭示它如何助力企业在激烈的市场竞争中保持领先地位。
|
22天前
|
Kubernetes Cloud Native 微服务
探索云原生技术:容器化与微服务架构的融合之旅
本文将带领读者深入了解云原生技术的核心概念,特别是容器化和微服务架构如何相辅相成,共同构建现代软件系统。我们将通过实际代码示例,探讨如何在云平台上部署和管理微服务,以及如何使用容器编排工具来自动化这一过程。文章旨在为开发者和技术决策者提供实用的指导,帮助他们在云原生时代中更好地设计、部署和维护应用。
|
22天前
|
运维 Cloud Native 持续交付
云原生技术深度探索:重塑现代IT架构的无形之力####
本文深入剖析了云原生技术的核心概念、关键技术组件及其对现代IT架构变革的深远影响。通过实例解析,揭示云原生如何促进企业实现敏捷开发、弹性伸缩与成本优化,为数字化转型提供强有力的技术支撑。不同于传统综述,本摘要直接聚焦于云原生技术的价值本质,旨在为读者构建一个宏观且具体的技术蓝图。 ####
|
25天前
|
弹性计算 运维 Cloud Native
云原生架构的崛起与未来展望
在数字化转型的浪潮中,云原生架构凭借其高效、灵活和可扩展的特性,正逐渐成为企业IT战略的核心。本文旨在探讨云原生架构的定义、关键特性、实施优势以及面临的挑战,同时展望未来的发展趋势。通过深入分析,我们期望为读者提供一个关于云原生架构全面而深入的视角,助力企业在云计算时代做出更明智的决策。
33 3
|
26天前
|
Cloud Native API 持续交付
云原生时代的微服务架构设计
随着云计算的蓬勃发展,云原生概念逐渐成为IT行业的热点。本文将通过深入浅出的方式,介绍在云原生环境下,如何设计一个高效、可扩展的微服务架构。文章不仅涉及理论概念,还将结合实际代码示例,帮助读者理解微服务架构的核心要素和设计原则,以及如何在云平台上实现这些设计。
|
29天前
|
Cloud Native 持续交付 云计算
云原生技术在现代IT架构中的转型力量####
本文深入剖析了云原生技术的精髓,探讨其在现代IT架构转型中的关键作用与实践路径。通过具体案例分析,展示了云原生如何赋能企业实现更高效的资源利用、更快的迭代速度以及更强的系统稳定性,为读者提供了一套可借鉴的实施框架与策略。 ####
24 0
|
1月前
|
消息中间件 运维 Cloud Native
云原生架构下的微服务优化策略####
本文深入探讨了云原生环境下微服务架构的优化路径,针对服务拆分、通信效率、资源管理及自动化运维等核心环节提出了具体的优化策略。通过案例分析与最佳实践分享,旨在为开发者提供一套系统性的解决方案,以应对日益复杂的业务需求和快速变化的技术挑战,助力企业在云端实现更高效、更稳定的服务部署与运营。 ####
|
22天前
|
Cloud Native API 持续交付
云原生架构下的微服务治理策略与实践####
本文旨在探讨云原生环境下微服务架构的治理策略,通过分析当前面临的挑战,提出一系列实用的解决方案。我们将深入讨论如何利用容器化、服务网格(Service Mesh)等先进技术手段,提升微服务系统的可管理性、可扩展性和容错能力。此外,还将分享一些来自一线项目的经验教训,帮助读者更好地理解和应用这些理论到实际工作中去。 ####
36 0
|
23天前
|
Cloud Native 持续交付 云计算
云原生架构的崛起:企业数字化转型的加速器
在当今快速发展的技术环境中,企业正面临着前所未有的变革压力。本文深入探讨了云原生架构如何成为推动企业数字化转型的关键力量。通过分析其核心概念、优势以及实施策略,本文旨在为读者提供对云原生技术的全面理解,展示其在现代企业中不可或缺的作用。
26 0
|
29天前
|
Cloud Native 持续交付 云计算
云计算的转型之路:探索云原生架构的崛起与实践####
随着企业数字化转型加速,云原生架构以其高效性、灵活性和可扩展性成为现代IT基础设施的核心。本文深入探讨了云原生技术的关键要素,包括容器化、微服务、持续集成/持续部署(CI/CD)及无服务器架构等,并通过案例分析展示了这些技术如何助力企业实现敏捷开发、快速迭代和资源优化。通过剖析典型企业的转型经历,揭示云原生架构在应对市场变化、提升业务竞争力方面的巨大潜力。 ####
34 0