jjzjj

Elasticsearch:使用 Elastic APM 监控 Android 应用程序(一)

Elastic 中国社区官方博客 2024-04-28 原文

作者:Alexander WertCesar Munoz

人们通过私人和专业的移动应用程序在智能手机上处理越来越多的事情。 拥有成千上万甚至数百万的用户,确保出色的性能和可靠性是移动应用程序和相关后端服务的提供商和运营商面临的主要挑战。 了解移动应用程序的行为、崩溃的发生和类型、响应时间慢的根本原因以及后端问题对用户的实际影响是管理移动应用程序和相关后端服务性能的关键。

Elastic 推出了适用于 Android 应用程序的应用程序性能监控 (APM) 代理,允许开发人员跟踪其应用程序的关键方面,从崩溃和 HTTP 请求到屏幕渲染时间和端到端分布式跟踪。 所有这些都有助于解决移动应用程序、相应后端服务及其交互的问题和性能缺陷。 Elastic APM Android 代理会自动检测你的应用程序及其依赖项,因此你可以简单地将代理 “即插即用” 到你的应用程序中,而不必担心对代码库进行太多更改。

Elastic APM Android 代理是在 OpenTelemetry 之上从头开发的,OpenTelemetry 是一种开放标准和可观察性框架。 开发人员将能够充分利用其功能,以及庞大而活跃的社区提供的支持。 如果你熟悉 OpenTelemetry 并且你的应用程序已经使用 OpenTelemetry 进行检测,那么你可以在切换到 Elastic APM Android Agent 时简单地重用它。 但如果情况并非如此,请不要担心 —— 代理被配置为自动处理常见的可追踪场景,而无需深入研究 OpenTelemetry API 的细节。

[相关文章:添加免费和开放的 Elastic APM 作为 Elastic 可观察性部署的一部分]

使用 Elastic APM 监控 Android 应用程序

怎么运行的

Elastic APM Android Agent 是 SDK 和 Gradle 插件的组合。 SDK 包含实用程序,可让你初始化和配置代理的行为,以及准备和初始化 OpenTelemetry SDK。 你可以使用 SDK 以编程方式配置和初始化代理,特别是高级和特殊用例。

在大多数情况下,不需要编程配置和初始化。 相反,你可以使用提供的 Gradle 插件来配置代理并自动检测你的应用程序。 Gradle 插件在后台使用 Byte Buddy 和官方 Android Gradle 插件 API,通过应用程序及其依赖项类的编译时转换,自动将检测代码注入你的应用程序。

在配置并启用 Elastic Android APM 代理 Gradle 插件的情况下编译你的应用程序将使你的 Android 应用程序在运行时报告跟踪数据、指标以及不同的事件和日志。

在 Android 应用程序中使用 Elastic APM 代理

通过一个简单的演示应用程序,我们将按照 “设置代理” 指南中提到的步骤来设置 Elastic Android APM 代理。

先决条件

对于此示例,你将需要以下内容:

  • 启用了 APM 的 Elastic Stack(我们推荐使用 Elastic 的 Cloud 产品。免费试用。)
  • Java 11+
  • Android Studio
  • Android 模拟器、AVD 设备

你还需要一种方法将应用程序的信号推送到 Elastic。 因此,你将需要 Elastic APM 的秘密令牌(secret token),稍后你将在我们的示例应用程序中配置该令牌。

我们示例的测试项目

为了展示包括分布式跟踪在内的端到端场景,在此示例中,我们将检测一个简单的天气应用程序,该应用程序包含两个 Android UI 片段和一个基于 Spring Boot 的简单本地后端服务。

第一个片段将有一个包含一些城市名称的下拉列表以及一个将你带到第二个片段的按钮,你将在其中看到所选城市的当前温度。 如果你在第一个屏幕上选择了一个非欧洲城市,那么当你前往第二个屏幕时,你会从(本地)后端收到一个错误。 这是为了演示如何在 Elastic APM 中捕获和关联网络和后端错误。

应用 Elastic APM 代理插件

在下文中,我们将解释从头开始为 Android 应用程序设置 Elastic APM Android 代理所需的所有步骤。 如果你想跳过这些说明并立即查看代理的运行情况,请使用该存储库的主分支并仅应用步骤 (3.b),然后再继续下一节(“设置本地后端服务”)。

1. 克隆示例应用程序库并在 Android Studio 中打开它。
2. 切换到 uninstrumented 的 repo 分支,从一个空白的、未检测的 Android 应用程序开始。 你可以运行此命令切换到未检测的分支:

git checkout uninstrumented

3. 按照 Elastic APM Android Agent 的设置指南进行操作:

将 co.elastic.apm.android 插件添加到 app/build.gradle 文件(请确保使用该插件的最新版本,你可以在此处找到该插件)。

通过在 app/build.gradle 文件的 “elasticAPM” 部分中提供 “serverUrl” 和 “secretToken” 来配置代理与 Elastic APM 后端的连接。

// Android app's build.gradle file
plugins {
    //...
    id "co.elastic.apm.android" version "[latest_version]"
}

//...

elasticApm {
    // Minimal configuration
    serverUrl = "https://your.elastic.apm.endpoint"

    // Optional
    serviceName = "weather-sample-app" 
    serviceVersion = "0.0.1" 
    secretToken = "your Elastic APM secret token" 
}

4. 唯一实际需要更改的代码是一行代码,用于在 Application.onCreate 方法中初始化 Elastic APM Android 代理。 此示例应用程序的应用程序类位于 app/src/main/java/co/elastic/apm/android/sample/MyApp.kt。

package co.elastic.apm.android.sample

import android.app.Application
import co.elastic.apm.android.sdk.ElasticApmAgent

class MyApp : Application() {

    override fun onCreate() {
        super.onCreate()
        ElasticApmAgent.initialize(this)
    }
}

请记住,对于此示例,我们不会更改代理的默认配置 —— 如果你想了解有关如何更改的更多信息,请查看代理的运行时配置指南。

在启动我们的 Android 天气应用程序之前,我们需要配置并启动本地天气后端服务,如下一节所述。

设置本地后端服务

代理提供的关键功能之一是分布式跟踪,它允许你查看 HTTP 事务的完整端到端故事,从我们的移动应用程序开始并遍历应用程序使用的检测后端服务。 Elastic APM 将以一个分布式跟踪的形式向你展示全貌,这对于解决问题非常方便,尤其是与高延迟和后端错误相关的问题。

作为示例应用程序的一部分,我们将启动一个简单的本地后端服务来处理我们应用程序的 HTTP 请求。 后端服务使用 Elastic APM Java 代理进行检测,以收集自己的 APM 数据并将其发送到 Elastic APM,使其能够将移动交互与后端请求的处理相关联。

为了配置本地服务器,我们需要在 backend/src/main/resources/elasticapm.properties 文件中设置我们的 Elastic APM 端点和秘密令牌(与上一步中我们的 Android 应用程序使用的相同):

service_name=weather-backend
application_packages=co.elastic.apm.android.sample
server_url=YOUR_ELASTIC_APM_URL
secret_token=YOUR_ELASTIC_APM_SECRET_TOKEN

启动演示

我们的示例应用程序将为代理当前支持的框架获得自动检测,这意味着我们将看到屏幕渲染跨度以及开箱即用的 OkHttp 请求。 对于当前不支持的框架,你可以应用手动检测来丰富你的 APM 数据(请参阅下面的 “手动检测”)。

我们准备启动演示。 (该 demo 旨在使用 Android 模拟器在本地环境中执行。)因此,我们需要:

  1. 在位于示例项目根目录的终端中使用此命令启动后端服务:./gradlew bootRun(如果你使用的是 Windows,则为 gradlew.bat bootRun)。 或者,你可以从 Android Studio 启动后端服务。
  2. 在 Android 模拟器(来自 Android Studio)中启动天气示例应用程序。

一切运行后,我们需要在应用程序中四处导航以生成一些我们希望在 Elastic APM 中观察到的负载。 因此,选择一个城市,单击 “Next” 并重复多次。 请确保至少选择 New York 一次。 你会看到天气预报对纽约这个城市不起作用。 下面,我们将使用 Elastic APM 来找出选择纽约时出现的问题。

初看 APM 结果

让我们打开 Kibana 并导航到 Observability 解决方案。

在 Services 导航项下,你应该看到两个服务的列表:我们的 Android 应用 weather-sample-app 和相应的后端服务 weather-backend。 单击 Service map 选项卡以查看这些服务与任何外部服务之间依赖关系的可视化。

单击 weather-sample-app 以深入了解 Android 应用程序的仪表板。 移动应用程序的服务视图在发布此博文时处于技术预览(technical preview)阶段,但你已经可以在该屏幕上看到有关该应用程序的深入信息。 你会看到所选时间范围内的活动会话数量、weather-sample-app 发出的 HTTP 请求数量、请求的地理分布以及设备型号、操作系统版本、网络连接类型和应用程序的细分等信息 版本。 (有关崩溃和应用程序加载时间的信息正在开发中。)

为了演示的目的,我们保持这个演示简单,所以数据不那么多样化,也相当有限。 但是,当你监控使用次数较多且设备型号、操作系统版本等方面更加多样化的移动应用程序时,此类数据特别有用。当你可以使用这些属性进行过滤和分组你的 APM 数据时,故障排除和性能问题变得更加容易 。 你可以使用顶部的快速过滤器来执行此操作,并查看指标如何根据你的选择被采用。

 

现在,让我们看看如何处理单个用户交互,包括对后端服务的下游调用。 在 Transactions 选项卡(顶部)下,我们看到不同的端到端 transaction 组,包括 FirstFragment 和 SecondFragment 的两个 transactions。

让我们深入研究 SecondFragment - 查看出现的 transaction,以查看此 transaction 组的指标(例如,延迟、吞吐量)以及单个用户交互的调用瀑布视图。 正如我们在下面的屏幕截图中看到的,在视图创建之后,该片段向 10.0.2.2 执行 HTTP GET 请求,这需要大约 130 毫秒。 在同一个瀑布中,我们看到 HTTP 调用由 weather-backend 服务处理,它本身对 api.open-meteo.com 进行 HTTP 调用。

 现在,当查看纽约被选为城市的请求的瀑布视图时,我们看到后端服务发生错误,这解释了为什么预测对 New York 不起作用。 通过单击红色的查看相关错误标记,你将获得错误的详细信息和问题的实际根本原因。

天气后端的异常消息指出 “This service can only retrieve geo locations for European cities!” 这就是选择 New York 作为城市的问题。

手动检测

如前所述,Elastic APM Android Agent 代表你为受支持的框架执行一系列自动检测; 但是,在某些情况下,你可能希望根据应用的用例获得额外的检测。 对于这些情况,你已经了解了 OpenTelemetry API,它是 Elastic APM Android 代理的基础。 OpenTelemetry Java SDK 包含用于创建自定义 spans、 metrics 和 logs 的工具,并且由于它是 Elastic APM Android 代理的基础,因此你无需在项目中添加任何额外依赖项也无需配置任何内容即可使用它及将你的自定义信号连接到你自己的 Elastic 环境,就像代理为你做的那样。

开始的方法是像这样获取 OpenTelemetry 的实例:

OpenTelemetry openTelemetry = GlobalOpenTelemetry.get();

然后你可以按照 OpenTelemetry Java 文档中的说明创建自定义信号。 有关创建自定义 span 的示例,请参见以下示例:

OpenTelemetry openTelemetry = GlobalOpenTelemetry.get();
Tracer tracer = openTelemetry.getTracer("instrumentation-library-name", "1.0.0");
Span span = tracer.spanBuilder("my span").startSpan();

// Make the span the current span
try (Scope ss = span.makeCurrent()) {
  // In this scope, the span is the current/active span
} finally {
    span.end();
}

结论

在这篇博文中,我们演示了如何使用 Elastic APM Android 代理在基于 Android 的移动应用程序中实现端到端的可观察性。 设置代理只需几分钟,所提供的见解可让你分析应用的性能及其对后端服务的依赖性。 有了 Elastic APM Android Agent,你可以利用 Elastic 丰富的 APM 功能以及各种可能性,通过自定义检测和自定义仪表板来自定义你的分析工作流程。

你好奇吗? 然后自己试试。 在 Elastic Cloud 上注册免费试用,使用本博客中所述的 Elastic APM Android 代理丰富你的 Android 应用程序,并探索 Elastic 的可观察性解决方案中的数据。

原文:Monitoring Android applications with Elastic APM | Elastic Blog

有关Elasticsearch:使用 Elastic APM 监控 Android 应用程序(一)的更多相关文章

  1. ruby - 如何使用 Nokogiri 的 xpath 和 at_xpath 方法 - 2

    我正在学习如何使用Nokogiri,根据这段代码我遇到了一些问题:require'rubygems'require'mechanize'post_agent=WWW::Mechanize.newpost_page=post_agent.get('http://www.vbulletin.org/forum/showthread.php?t=230708')puts"\nabsolutepathwithtbodygivesnil"putspost_page.parser.xpath('/html/body/div/div/div/div/div/table/tbody/tr/td/div

  2. ruby - 使用 RubyZip 生成 ZIP 文件时设置压缩级别 - 2

    我有一个Ruby程序,它使用rubyzip压缩XML文件的目录树。gem。我的问题是文件开始变得很重,我想提高压缩级别,因为压缩时间不是问题。我在rubyzipdocumentation中找不到一种为创建的ZIP文件指定压缩级别的方法。有人知道如何更改此设置吗?是否有另一个允许指定压缩级别的Ruby库? 最佳答案 这是我通过查看ruby​​zip内部创建的代码。level=Zlib::BEST_COMPRESSIONZip::ZipOutputStream.open(zip_file)do|zip|Dir.glob("**/*")d

  3. ruby - 为什么我可以在 Ruby 中使用 Object#send 访问私有(private)/ protected 方法? - 2

    类classAprivatedeffooputs:fooendpublicdefbarputs:barendprivatedefzimputs:zimendprotecteddefdibputs:dibendendA的实例a=A.new测试a.foorescueputs:faila.barrescueputs:faila.zimrescueputs:faila.dibrescueputs:faila.gazrescueputs:fail测试输出failbarfailfailfail.发送测试[:foo,:bar,:zim,:dib,:gaz].each{|m|a.send(m)resc

  4. ruby-on-rails - 使用 Ruby on Rails 进行自动化测试 - 最佳实践 - 2

    很好奇,就使用ruby​​onrails自动化单元测试而言,你们正在做什么?您是否创建了一个脚本来在cron中运行rake作业并将结果邮寄给您?git中的预提交Hook?只是手动调用?我完全理解测试,但想知道在错误发生之前捕获错误的最佳实践是什么。让我们理所当然地认为测试本身是完美无缺的,并且可以正常工作。下一步是什么以确保他们在正确的时间将可能有害的结果传达给您? 最佳答案 不确定您到底想听什么,但是有几个级别的自动代码库控制:在处理某项功能时,您可以使用类似autotest的内容获得关于哪些有效,哪些无效的即时反馈。要确保您的提

  5. ruby - 在 Ruby 中使用匿名模块 - 2

    假设我做了一个模块如下:m=Module.newdoclassCendend三个问题:除了对m的引用之外,还有什么方法可以访问C和m中的其他内容?我可以在创建匿名模块后为其命名吗(就像我输入“module...”一样)?如何在使用完匿名模块后将其删除,使其定义的常量不再存在? 最佳答案 三个答案:是的,使用ObjectSpace.此代码使c引用你的类(class)C不引用m:c=nilObjectSpace.each_object{|obj|c=objif(Class===objandobj.name=~/::C$/)}当然这取决于

  6. ruby - 使用 ruby​​ 和 savon 的 SOAP 服务 - 2

    我正在尝试使用ruby​​和Savon来使用网络服务。测试服务为http://www.webservicex.net/WS/WSDetails.aspx?WSID=9&CATID=2require'rubygems'require'savon'client=Savon::Client.new"http://www.webservicex.net/stockquote.asmx?WSDL"client.get_quotedo|soap|soap.body={:symbol=>"AAPL"}end返回SOAP异常。检查soap信封,在我看来soap请求没有正确的命名空间。任何人都可以建议我

  7. ruby - 在 Ruby 程序执行时阻止 Windows 7 PC 进入休眠状态 - 2

    我需要在客户计算机上运行Ruby应用程序。通常需要几天才能完成(复制大备份文件)。问题是如果启用sleep,它会中断应用程序。否则,计算机将持续运行数周,直到我下次访问为止。有什么方法可以防止执行期间休眠并让Windows在执行后休眠吗?欢迎任何疯狂的想法;-) 最佳答案 Here建议使用SetThreadExecutionStateWinAPI函数,使应用程序能够通知系统它正在使用中,从而防止系统在应用程序运行时进入休眠状态或关闭显示。像这样的东西:require'Win32API'ES_AWAYMODE_REQUIRED=0x0

  8. python - 如何使用 Ruby 或 Python 创建一系列高音调和低音调的蜂鸣声? - 2

    关闭。这个问题是opinion-based.它目前不接受答案。想要改进这个问题?更新问题,以便editingthispost可以用事实和引用来回答它.关闭4年前。Improvethisquestion我想在固定时间创建一系列低音和高音调的哔哔声。例如:在150毫秒时发出高音调的蜂鸣声在151毫秒时发出低音调的蜂鸣声200毫秒时发出低音调的蜂鸣声250毫秒的高音调蜂鸣声有没有办法在Ruby或Python中做到这一点?我真的不在乎输出编码是什么(.wav、.mp3、.ogg等等),但我确实想创建一个输出文件。

  9. ruby-on-rails - 'compass watch' 是如何工作的/它是如何与 rails 一起使用的 - 2

    我在我的项目目录中完成了compasscreate.和compassinitrails。几个问题:我已将我的.sass文件放在public/stylesheets中。这是放置它们的正确位置吗?当我运行compasswatch时,它不会自动编译这些.sass文件。我必须手动指定文件:compasswatchpublic/stylesheets/myfile.sass等。如何让它自动运行?文件ie.css、print.css和screen.css已放在stylesheets/compiled。如何在编译后不让它们重新出现的情况下删除它们?我自己编译的.sass文件编译成compiled/t

  10. ruby - 将差异补丁应用于字符串/文件 - 2

    对于具有离线功能的智能手机应用程序,我正在为Xml文件创建单向文本同步。我希望我的服务器将增量/差异(例如GNU差异补丁)发送到目标设备。这是计划:Time=0Server:hasversion_1ofXmlfile(~800kiB)Client:hasversion_1ofXmlfile(~800kiB)Time=1Server:hasversion_1andversion_2ofXmlfile(each~800kiB)computesdeltaoftheseversions(=patch)(~10kiB)sendspatchtoClient(~10kiBtransferred)Cl

随机推荐