编写针对使用opentelemetry javaagent进行工具化的函数的单元测试

huangapple go评论86阅读模式
英文:

Writing unit tests for a function instrumented with opentelemetry javaagent

问题

以下是翻译好的部分:

"我已经将opentelemetry的javaagent添加到一个项目中,并使用它来对项目进行仪器化。是否有一种方法可以在单元测试中测试仪器化(例如创建的span)?

假设这是我的整个项目代码:

public class Main {
    public static void main(String[] args) {
        System.out.println(hello());
    }

    @WithSpan("hello")
    private static String hello() {
        return "Hello world!";
    }
}

如何测试调用hello()函数是否创建了一个hello span?"

英文:

I have added opentelemetry javaagent to a project and used it to instrument the project. Is there a way to test the instrumentation(for example created spans) in the unit tests?

Lets say this is my whole project code:

public class Main {
    public static void main(String[] args) {
        System.out.println(hello());
    }

    @WithSpan("hello")
    private static String hello() {
        return "Hello world!";
    }
}

How can I test that calling the hello() function creates a hello span?

答案1

得分: 3

为了编写单元测试,您可以使用AgentTestingExporterAccess来访问导出的跨度。您需要导入以下这些包:

<dependency>
    <groupId>io.opentelemetry.javaagent</groupId>
    <artifactId>opentelemetry-testing-common</artifactId>
    <version>1.23.0-alpha</version>
    <scope>test</scope>
</dependency>
<dependency>
    <groupId>io.opentelemetry.javaagent</groupId>
    <artifactId>opentelemetry-agent-for-testing</artifactId>
    <version>1.23.0-alpha</version>
    <scope>test</scope>
</dependency>

一个简单的单元测试可以像这样:

import io.opentelemetry.api.trace.SpanKind;
import io.opentelemetry.javaagent.testing.common.AgentTestingExporterAccess;

import static io.opentelemetry.api.common.AttributeKey.stringKey;

import io.opentelemetry.sdk.trace.data.StatusData;

public class MainTest {
    @Test
    public void testHello() {
        AgentTestingExporterAccess.reset();
        Main.hello(); // 这是一个创建跨度的函数
        var spans = AgentTestingExporterAccess.getExportedSpans();
        assertEquals(spans.get(0).getName(), "hello");
        assertEquals(spans.get(0).getKind(), SpanKind.INTERNAL);
        assertEquals(spans.get(0).getStatus(), StatusData.unset());
        assertEquals(spans.get(0).getAttributes().get(stringKey("service.name")), "search");
    }
}

请注意,要能够使用AgentTestingExporterAccess,您需要在运行测试时也使用java代理。如果在运行测试时未附加java代理,将会收到AgentTestingExporterAccess引发的异常,类似于以下内容:

java.lang.AssertionError: Error accessing fields with reflection.
...
Caused by: java.lang.NullPointerException
...

另一种方法是编写一个模拟服务器来捕获跨度。Opentelemetry在这里有一个示例。

英文:

To write unit tests you can access the exported spans with AgentTestingExporterAccess. You need to import these packages:

&lt;dependency&gt;
    &lt;groupId&gt;io.opentelemetry.javaagent&lt;/groupId&gt;
    &lt;artifactId&gt;opentelemetry-testing-common&lt;/artifactId&gt;
    &lt;version&gt;1.23.0-alpha&lt;/version&gt;
    &lt;scope&gt;test&lt;/scope&gt;
&lt;/dependency&gt;
&lt;dependency&gt;
    &lt;groupId&gt;io.opentelemetry.javaagent&lt;/groupId&gt;
    &lt;artifactId&gt;opentelemetry-agent-for-testing&lt;/artifactId&gt;
    &lt;version&gt;1.23.0-alpha&lt;/version&gt;
    &lt;scope&gt;test&lt;/scope&gt;
&lt;/dependency&gt;

A simple unit test can look like this:

import io.opentelemetry.api.trace.SpanKind;
import io.opentelemetry.javaagent.testing.common.AgentTestingExporterAccess;


import static io.opentelemetry.api.common.AttributeKey.stringKey;


import io.opentelemetry.sdk.trace.data.StatusData;


public class MainTest {
    @Test
    public void testHello() {
        AgentTestingExporterAccess.reset();
        Main.hello(); // This a function that creates a span
        var spans = AgentTestingExporterAccess.getExportedSpans();
        assertEquals(spans.get(0).getName(), &quot;hello&quot;);
        assertEquals(spans.get(0).getKind(), SpanKind.INTERNAL);
        assertEquals(spans.get(0).getStatus(), StatusData.unset());
        assertEquals(spans.get(0).getAttributes().get(stringKey(&quot;service.name&quot;)), &quot;search&quot;);
    }
}

Please note that to be able to use AgentTestingExporterAccess, you need to run your tests with the javaagent too. If the java agent is not attached when running the tests, you will get an exception from AgentTestingExporterAccess like this:

java.lang.AssertionError: Error accessing fields with reflection.
...
Caused by: java.lang.NullPointerException
...

Another way of doing this is to write a mock server and capture the spans. Opentelemetry has an example here

答案2

得分: 1

你可以选择将 OTEL 配置为将跟踪日志记录在有用的地方,比如临时文件。您可以按照这里描述的方式通过系统属性或环境变量进行设置:
https://github.com/open-telemetry/opentelemetry-java/blob/main/sdk-extensions/autoconfigure/README.md#logging-otlp-json-exporter

顺便说一下,我在 digma.ai 工作,我们正在开发一个免费的 IntelliJ 插件,具有一个非常酷的功能,可以用于启用/禁用测试的 OTEL,并分析结果。您还可以使用它来验证测试运行中记录的跟踪。

英文:

Alternatively, you can also set up OTEL to log the traces somewhere useful, like a temp file. You can set it up via a system property or environment variable as described here:
https://github.com/open-telemetry/opentelemetry-java/blob/main/sdk-extensions/autoconfigure/README.md#logging-otlp-json-exporter

BTW I work at digma.ai and we are developing a free IntelliJ plugin that has a really cool feature for enabling/disabling OTEL for tests and analyzing the results. You can also use it to validate which traces are being recorded by test runs.

huangapple
  • 本文由 发表于 2023年2月24日 04:11:42
  • 转载请务必保留本文链接:https://go.coder-hub.com/75549857.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定