有些问题会以非常明显的方式显现出来。还有一些人则隐藏在“在我的机器上运行正常”和“对每个人都正常”之间的空白地带。它牢牢地栖身于那个空隙之中。
症状似乎很简单:一些用户无法加载我们基于 HubSpot 的表单。原因也合情合理:浏览器隐私设置和跟踪拦截器介入,拒绝让任何类似跟踪器的东西通过。但当我们试图 衡量 这个问题时,却遇到了难题,原本看似可以快速解决的问题变得有趣得多。
我们通常会用来发现这些故障的工具——真实用户监控——却被破坏表单的相同保护措施所阻止。我们的 New Relic RUM 看起来像一个追踪器,因为,嗯,它 本来就是 一个追踪器。我们当时实际上是想在一个房间里安装烟雾探测器,但房间里的烟雾触发了一个会使烟雾探测器失效的装置。
本文详细介绍了我们如何解决这个悖论:通过我们自己的第一方域名代理 New Relic,使其不再看起来像第三方跟踪,处理子域名带来的复杂情况,保持遥测数据的清洁,并最终构建可靠的 HubSpot 故障检测机制;即使是完全无法加载的静默故障也能检测到。在此过程中,我们将介绍 CDN 和调度程序的配置、在快速开发环境中进行测试、通过 Cloud Manager 进行部署,以及将巧妙的变通方法转化为可靠指标的磨合期。
当您使用代理方法时,务必确保您有权根据您对最终用户和/或网站访问者可能承担的任何合同、监管或其他法律义务这样做。
让 New Relic 成为第一方
解决方案不是直接从 New Relic 的标准端点加载所有内容,而是通过我们自己的域代理所有内容。这会将请求从第三方转移到第一方,从而绕过大多数跟踪保护措施。
引入了两个终点:
/nr/agent/→ 为 New Relic 浏览器代理提供服务/nr/data/→ 接收信标(遥测)请求
硬编码代理值
在 New Relic 中配置第一方代理的最简单方法是将代理路径直接在NREUM.init中设置为静态字符串。您将assets指向提供 New Relic 代理脚本块的 URL,并将beacon指向接收遥测数据的 URL;两者都通过您自己的域而不是 New Relic 的 CDN 进行路由。
proxy: {
assets: 'www.arborydigital.com/nr/agent',
beacon: 'www.arborydigital.com/nr/data'
}
这很容易理解。路径一目了然,无需运行时逻辑,并且在代理初始化之前就已设置;因此无需担心配置是否能及时生效。只要你的服务器配置了这两条路由,并且正确地转发到 New Relic,它就能正常工作。对于仅使用单个域名且没有子域名流量的网站来说,这通常就足够了。
跨子域代理
当您的网站使用子域名(例如blog.arborydigital.com时,单个硬编码的代理路径是不够的。每个子域都从自己的源运行,浏览器安全规则意味着从blog.arborydigital.com到托管在www.arborydigital.com上的代理路径的请求在技术上是跨域请求。虽然这样做可能有效,但这违背了第一方代理的部分意义,即通过浏览器已经信任的同一来源发送遥测数据。
为了解决这个问题,可以在运行时动态设置代理配置。该脚本不会指向固定的域名,而是检查window.location.hostname来确定页面当前运行的源。如果该主机名与您的根域或其任何子域匹配,则代理端点将使用window.location.origin构建——这意味着blog.arborydigital.com将通过blog.arborydigital.com/nr-assets/和blog.arborydigital.com/nr-beacon路由其 New Relic 流量,而www.arborydigital.com使用其自己的等效路径。
这种方法要求每个子域都在服务器或 CDN 级别配置相应的代理路由。New Relic 代理配置(包括NREUM.info中的beacon和errorBeacon字段)也需要更新,以反映当前的主机名,以便代理知道在哪里报告数据。
ajax.deny_list
New Relic 浏览器代理配置为将所有遥测数据通过第一方代理blog.arborydigital.com/nr/data而不是 New Relic 自己的服务器bam.nr-data.net进行路由。这样可以避免针对已知 NR 结构域的阻断剂。
这样做的一个副作用是:NR 代理会监视页面上 所有 传出的 XHR/fetch 请求,并将它们捕获为 AJAX 事件;包括它自己发送到blog.arborydigital.com/nr/data信标调用。如果没有拒绝列表,NR 会将自己的遥测 POST 请求记录为 AJAX 事件,然后这些事件又会作为更多的遥测数据发送出去,从而用 NR 内部流量污染 AJAX 数据。
为了解决这个问题,避免你的数据速率像电影《阿基拉》里那样高得离谱,我们可以使用内置通配符来阻止这些信标调用。最终结果会是blog.arborydigital.com/nr/data/* 。实现此功能后,它会告诉 New Relic 在成功捕获浏览器数据时不要创建ajax条目。POST内的所有信息都将被保留,并且不再有冗余的 ajax 条目。
使用查询参数作为功能标志
将代理服务器置于?proxy=yes之后,可以在生产环境中测试行为,而不会影响其他访问者。URL 中缺少该参数的用户将完全绕过此限制,在这种情况下,New Relic 将不会触发。打开一个带有附加参数的标签页,在 DevTools 中确认请求正在通过您自己的域进行路由,一切检查完毕后,从脚本中删除该条件。之后,主机名检查将接管,代理将自动激活以处理所有流量。
实现 New Relic Agent
您可以通过以下方式找到 JavaScript 代码片段:
- 登录 New Relic One (one.newrelic.com)
- 导航至浏览器→添加数据→浏览器监控
- 选择应用程序(应用 ID)或创建一个新应用
- 选择使用 SPA 加载器的 复制/粘贴 部署方法。
- 复制生成的完整
<script>代码片段
当您将 RUM 脚本添加到存储库时,请确保它位于其自身的newrelic.js文件中,以便我们可以在内部调用它。 head.html
- 注意:
<script src="/scripts/newrelic.js"></script>必须是您初始化的第一个脚本,紧跟在任何meta标签之后。
完成此操作后,您需要将具体的代理设置添加到此字符串中。在生成的代码片段的NREUM.init块中,添加代理配置:
proxy: {
assets: 'www.arborydigital.com/nr/agent',
beacon: 'www.arborydigital.com/nr/data'
}
代理服务器布线(EDS/CDN 层)
代理本身位于 CDN 层。目标很简单:将传入的/nr/*请求转发到真正的 New Relic 端点。
源选择器必须排除/nr/agent/*和/nr/data/* ,这样这些请求就 不会 被路由到边缘交付服务源。相反,它们会流向默认的 AEM 发布源,Apache ProxyPass 规则会在那里执行。在你的cdn.yaml中,它看起来会像这样:
originSelectors:
rules:
- name: arbory-da
when:
allOf:
- reqProperty: path
like: /*
# ...existing exclusions...
- reqProperty: path
doesNotMatch: /nr/agent/*
- reqProperty: path
doesNotMatch: /nr/data/*
action:
type: selectOrigin
originName: arbory-da
您还需要编辑 VirtualHost ( .vhost ) 文件:
# New Relic Browser Agent Proxy
SSLProxyEngine on
# Proxy New Relic agent JS chunks (lazy-loaded scripts)
<Location "/nr/agent/">
ProxyPass "https://js-agent.newrelic.com/"
ProxyPassReverse "https://js-agent.newrelic.com/"
RewriteEngine Off
</Location>
# Proxy New Relic beacon/telemetry data
<Location "/nr/data/">
ProxyPass "https://bam.nr-data.net/"
ProxyPassReverse "https://bam.nr-data.net/"
RewriteEngine Off
</Location>
关键细节:
SSLProxyEngine on由于上游目标是 HTTPS,因此需要这样做。RewriteEngine Off防止 AEM 的默认重写规则干扰代理路径
检测 HubSpot 故障(即使页面完全加载不出来)
一旦 New Relic 被解除阻塞,下一个问题是 HubSpot 故障并不总是会抛出明显的错误;尤其是在脚本从未加载的情况下。
为了解决这个问题,增加了两条检测路径:
1. 脚本加载失败
检测 HubSpot 脚本何时完全无法加载:
script.onerror = () => {
reportError('HubSpot script failed to load');
};
2. 运行时故障
捕获脚本加载后的错误:
window.addEventListener('error', (e) => {
if (e.filename && e.filename.includes('hsforms')) {
reportError('HubSpot runtime error');
}
});
两者都汇入同一个报表功能:
function reportError(errorMsg) {
console.error(errorMsg);
if (window.newrelic) {
window.newrelic.noticeError(new Error(errorMsg));
}
}
验证其是否真的有效
所有线路连接完毕后,验证过程非常简单,但仍然很重要。测试应重点关注启用了严格跟踪保护/扩展程序的浏览器,在这些浏览器中,您应该会看到 HubSpot 表单无法加载,控制台中出现错误,并且这些相同的错误也会出现在 New Relic 中。在 DevTools 中,确认代理从/nr/agent/加载,并且信标发送到/nr/data/ ,没有向bam.nr-data.net等第三方域发送请求。在 New Relic 中,验证仪表板中是否显示错误,事件是否与触发的故障匹配,以及会话是否正在被记录。如果仍然缺少会话,则代理可能配置不正确。
使用快速开发环境 (RDE) 进行测试
如果您是我们的老读者,您可能还记得我写过一篇关于使用快速开发环境 (RDE) 测试 CDN 配置更改的文章。测试这款新朗姆酒时,我就是这么做的!
遵循最佳实践时,开发工作将在分支上进行。为了确保您的更改应用于分支而不是主分支,您需要对cdn.yaml进行额外的更改:
origins:
# ...existing code...
- name: arbory-da
domain: (BRANCH_NAME)--(rest of domain).aem.live
forwardHost: false
准备推送更改时,您需要用到两个主要命令:
aio aem:rde:install -t env-config ./config 这将推送您的/config的内容以及我们之前所做的排除项。
aio aem:rde:install -t dispatcher-config ./dispatcher/src 这将推送您的/src的内容——即调度程序配置.vhost中的更改。
由于 RDE 运行在与其他环境不同的域上,因此您需要指定一个新的 URL 来进行代理。否则将被视为第三方域名:
proxy: {
assets: 'your-rde-domain.aem.live/nr/agent',
beacon: 'your-rde-domain.aem.live/nr/data'
}
云管理器管道部署(开发+生产)
通过 Adobe Cloud Manager 部署此功能需要比一般代码更改更多的协调工作。代理行为取决于多个层(CDN、调度器和浏览器),所有这些层都需要在同一部署中保持一致。
部署流程
流水线执行将:
- 构建并验证应用程序
- 部署调度程序配置(包括
.vhost、过滤器和代理规则) - 部署CDN 配置(
cdn.yaml,包括源选择器) - 使缓存失效并将更改推广到整个环境
在此实现中,调度程序和 CDN 的变更紧密耦合。如果两者都不存在且一致,代理将无法正常工作。
所需更改(必须同时部署)
以下更新需要包含在同一次流水线运行中:
-
CDN(
cdn.yaml)- 从边缘交付路由中排除
/nr/agent/*和/nr/data/*
- 从边缘交付路由中排除
-
调度器(
.vhost)ProxyPass/ProxyPassReverse规则,适用于 New Relic 端点SSLProxyEngine on- 禁用代理路径的重写
-
调度员过滤器
- 显式允许规则
/nr/*
- 显式允许规则
如果其中任何一个缺失或不同步,请求要么会被错误路由,要么会被阻止,要么会回退到第三方端点。
烧伤期
现在代理已经配置和部署完毕,需要进行一段时间的测试,以确保一切运行正常。由于故障取决于用户的实际情况,例如隐私设置、扩展程序和网络行为,因此需要一些时间才能全面了解情况。
经过一段时间的验证,确认数据已正确摄取后,下一步是审查这些数据;验证错误率是否符合预期流量,确保覆盖所有环境,并改进任何差距(遗漏的事件、不一致的域或边缘情况阻塞)。由此,你可以开始将其视为可靠的指标,观察其随时间变化的趋势,并用它来量化真正的用户影响,而不是轶事报道。
最后想说的话
最初只是想“添加一些监控”,结果却变成了一次关于浏览器隐私模型、第一方代理、CDN 路由以及如何衡量那些天生就难以衡量的事物的微妙艺术的探索之旅。
核心见解值得牢记:当你试图观察的对象和你 用来 观察它的对象都被浏览器视为不受欢迎的对象时,你无法通过现成的工具来监控并摆脱困境。您需要更改浏览器对遥测数据的感知方式。通过我们的第一方域代理 New Relic 正是如此——将请求从第三方转移到第一方,绕过了障碍物,让我们真正看到了以前看不见的故障。
但代理人只是成功的一半。检测 HubSpot 故障,尤其是脚本从未加载的静默故障,需要仔细处理加载错误和运行时错误,并将所有错误都集中到一个报告路径中。这一切都毫无意义,直到数据在试用期内得到验证,真实的用户条件用证据取代了假设。
这样做的好处是能够用数据代替轶事。现在,我们不再只是说“有些用户反映表单无法加载”,而是有了可衡量、可追踪的信号,可以量化真实的用户影响。有时候,最有价值的解决方法并非直接解决问题,而是让你最终 看清 问题的解决方法。然后,你就可以开始着手改进它了。
故障排除
<https://https//...><https://> 包含在代理值中arborydigital.com/nr/agentNREUM.init.session_replay中的sampling_rate或进行错误测试以触发 100% 捕获newrelic 对象未定义newrelic.js是第一个<script> head.html作者简介
喜欢你听到的内容吗?对什么更适合自己有疑问吗?我们很乐意与您交流!联系我们