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();
  }
}


相关实践学习
深入解析Docker容器化技术
Docker是一个开源的应用容器引擎,让开发者可以打包他们的应用以及依赖包到一个可移植的容器中,然后发布到任何流行的Linux机器上,也可以实现虚拟化,容器是完全使用沙箱机制,相互之间不会有任何接口。Docker是世界领先的软件容器平台。开发人员利用Docker可以消除协作编码时“在我的机器上可正常工作”的问题。运维人员利用Docker可以在隔离容器中并行运行和管理应用,获得更好的计算密度。企业利用Docker可以构建敏捷的软件交付管道,以更快的速度、更高的安全性和可靠的信誉为Linux和Windows Server应用发布新功能。 在本套课程中,我们将全面的讲解Docker技术栈,从环境安装到容器、镜像操作以及生产环境如何部署开发的微服务应用。本课程由黑马程序员提供。 &nbsp; &nbsp; 相关的阿里云产品:容器服务 ACK 容器服务 Kubernetes 版(简称 ACK)提供高性能可伸缩的容器应用管理能力,支持企业级容器化应用的全生命周期管理。整合阿里云虚拟化、存储、网络和安全能力,打造云端最佳容器化应用运行环境。 了解产品详情: https://www.aliyun.com/product/kubernetes
相关文章
|
5月前
|
运维 Kubernetes Cloud Native
智联招聘 × 阿里云 ACK One:云端弹性算力颠覆传统 IDC 架构,打造春招技术新范式
在 2025 年春季招聘季的激战中,智联招聘凭借阿里云 ACK One 注册集群与弹性 ACS 算力的深度融合,成功突破传统 IDC 机房的算力瓶颈,以云上弹性架构支撑千万级用户的高并发访问,实现招聘服务效率与稳定性的双重跃升。
|
运维 Kubernetes Docker
利用Docker和Kubernetes构建微服务架构
利用Docker和Kubernetes构建微服务架构
|
存储 Kubernetes 调度
|
12月前
|
Kubernetes Cloud Native 持续交付
容器化、Kubernetes与微服务架构的融合
容器化、Kubernetes与微服务架构的融合
441 82
|
9月前
|
Kubernetes 监控 Serverless
基于阿里云Serverless Kubernetes(ASK)的无服务器架构设计与实践
无服务器架构(Serverless Architecture)在云原生技术中备受关注,开发者只需专注于业务逻辑,无需管理服务器。阿里云Serverless Kubernetes(ASK)是基于Kubernetes的托管服务,提供极致弹性和按需付费能力。本文深入探讨如何使用ASK设计和实现无服务器架构,涵盖事件驱动、自动扩展、无状态设计、监控与日志及成本优化等方面,并通过图片处理服务案例展示具体实践,帮助构建高效可靠的无服务器应用。
|
9月前
|
监控 Kubernetes Cloud Native
基于阿里云容器服务Kubernetes版(ACK)的微服务架构设计与实践
本文介绍了如何基于阿里云容器服务Kubernetes版(ACK)设计和实现微服务架构。首先概述了微服务架构的优势与挑战,如模块化、可扩展性及技术多样性。接着详细描述了ACK的核心功能,包括集群管理、应用管理、网络与安全、监控与日志等。在设计基于ACK的微服务架构时,需考虑服务拆分、通信、发现与负载均衡、配置管理、监控与日志以及CI/CD等方面。通过一个电商应用案例,展示了用户服务、商品服务、订单服务和支付服务的具体部署步骤。最后总结了ACK为微服务架构提供的强大支持,帮助应对各种挑战,构建高效可靠的云原生应用。
|
监控 持续交付 Docker
Docker容器化部署在微服务架构中的应用
Docker容器化部署在微服务架构中的应用
552 60
|
9月前
|
监控 Cloud Native Java
基于阿里云容器服务(ACK)的微服务架构设计与实践
本文介绍如何利用阿里云容器服务Kubernetes版(ACK)构建高可用、可扩展的微服务架构。通过电商平台案例,展示基于Java(Spring Boot)、Docker、Nacos等技术的开发、容器化、部署流程,涵盖服务注册、API网关、监控日志及性能优化实践,帮助企业实现云原生转型。
|
Kubernetes API 调度
【赵渝强老师】Kubernetes的体系架构
本文介绍了Kubernetes的体系架构及其核心组件。Kubernetes采用主从分布式架构,由master主节点和多个node工作节点组成。master节点负责集群管理和调度,运行API Server、scheduler、controller-manager等服务组件;node节点运行kubelet、kube-proxy和Docker容器守护进程,负责实际业务应用的运行。文章还简要介绍了Kubernetes的附加组件及其作用。
192 5
|
监控 持续交付 Docker
Docker 容器化部署在微服务架构中的应用有哪些?
Docker 容器化部署在微服务架构中的应用有哪些?

热门文章

最新文章

下一篇
oss云网关配置