当前位置: 首页 > 知识库问答 >
问题:

使用OTEL Java agent,如何在不使用@WithSpan的情况下创建新上下文

许自强
2023-03-14

opentelemetry javaagent all(版本0.17.0和1.0.1)是向Java应用程序添加跟踪信息的起点。自动仪表工作得很好。

我的一些应用程序无法自动检测。对于应用程序的这一部分,我首先使用span向代码中的有趣点添加注释。

现在,我已经达到了使用span注释进行简单注释的极限。然而,我的应用程序的底层框架允许我注册在特定点调用的回调,例如,我可以提供在客户端连接/断开连接时通知的处理程序。

我想我需要的是在Foo时开始一个新的跨度。调用onConnect(),并将其设置为对应于每个请求的Span的父级。

public class Foo {

    void onConnect() {
        // called when a client connects to my app
        // Here I want to create a Span that will be the parent of the Span created in
        // Foo.processEachRequest().
    }

    @WithSpan
    public void processEachRequest() {
        // works, but since it is called for each request... each span is in a separate Trace
    }

    void onDisconnect() {
        // called when the client disconnects from my app
        // Here I can end the parent Span.
    }
}

其他想法——没有成功:

1-显而易见的解决方案是将@SusSpan注释添加到底层框架中。出于各种原因,这不会是一种切实可行的前进方式。

2-下一个选择可能是搜索一种方法来告诉javaagent我的底层框架中的方法。(New Relic代理可以做这样的事情。)无论如何,这似乎不是开放遥测代理的功能。

所以,我剩下的就是寻找一种使用回调实现这一点的方法,如上所述。有没有办法做到这一点?

共有1个答案

秦炜
2023-03-14

这应该可以通过手动检测您的代码来实现。您将使用OpenTelem计的Tracer接口,如OpenTelem计Java文档中所述。

这应该给你一个大致的想法:

public class Foo {
    private Span parentSpan; // you might need a Map/List/Stack here

    void onConnect() {
        Tracer tracer =
                openTelemetry.getTracer("instrumentation-library-name", "1.0.0");
        Span span = tracer.spanBuilder("my span").startSpan();
        this.parentSpan = span; // might need to store span per request/client/connection-id
    }

    public void processEachRequest() {
        final Span parent = this.lookupParentSpan();
        if (parent != null) {
            try (Scope scope = span.makeCurrent()) {
              yourLogic();
            } catch (Throwable t) {
              span.setStatus(StatusCode.ERROR, "error message");
              throw t;
            }
        } else {
            yourLogic();
        }
    }

    void onDisconnect() {
        final Span parent = this.lookupParentSpan();
        if (parent != null) {
            parent.end();
        }
    }

    private Span lookupParentSpan() {
        // you probably want to lookup the span by client or connection id from a (weak) map
        return this.parentSpan;
    }
}

注意:您必须保证跨度始终处于末端且不会泄漏。确保正确地确定范围并最终调用Span#end()。

 类似资料:
  • 本文向大家介绍如何在不使用HTML的情况下创建网站?,包括了如何在不使用HTML的情况下创建网站?的使用技巧和注意事项,需要的朋友参考一下 如果您不了解HTML或CSS,并且想创建一个网站,那么不用担心,您可以轻松创建网站,而无需编写一行HTML代码。 以下是一些无需编写任何HTML或代码行即可构建网站的方法: 网站构造函数 当您购买网站托管计划时,托管公司将为您提供免费的网站构建器选项,以轻松创

  • 问题内容: 在XCode 6中创建一个新项目不允许禁用Storyboard。您只能选择Swift或Objective-C,而不能使用Core Data。 我尝试删除情节提要,并从项目中删除主情节提要,然后从didFinishLaunching手动设置窗口 在AppDelegate中,我有以下内容: 但是,XCode给我一个错误: 类“ AppDelegate”没有初始化程序 有人成功吗? 问题答案

  • 更新我的DDMS后,我意识到每当我想创建一个新项目时,一个名为appcompatv7的支持库都会自动添加到我的项目窗口中。 这个库添加了一些我以前从未使用过的feauters。我只想创建一个简单的android项目,其中包含一个空白活动和一个activity_main.xml.但是这个库还添加了一个名为activity_fragment.xml的xml文件 那么,如何在不使用这个支持库的情况下创建

  • 问题内容: 我已经在我的一个Web应用程序中使用了Django ORM,对此我感到非常满意。现在,我有了一个新的需求,它需要数据库,而Django则没有其他要求。我不想花更多的时间来学习另一个像sqlalchemy的ORM。 我想我仍然可以 创建模型,但是如果没有模型,该如何迁移和同步呢? 问题答案: 有关如何加载应用程序的Django 1.11文档 对于最新的Django版本,项目结构为- 您仍

  • 我正在开发一个企业应用程序,管理员在其中创建新用户(没有注册表单)。我正在使用Firebase Auth,它在很多方面都很棒,但我在我的用例中遇到了一个问题。当您使用时,由此创建的用户将自动登录。当管理员创建用户帐户时,这显然不起作用。有没有办法避免这种行为?谢了。

  • 问题内容: 如果我要使用DefaultServeMux(我将其指定为ListenAndServe的第二个参数来指定),那么我可以访问,您可以在Go Wiki的以下示例中看到该: 在当前代码中,我无法使用DefaultServeMux,即我将自定义处理程序传递给ListenAndServe 因此,我没有内置的代码。但是,我必须将一些授权代码修改为需要类似的授权代码。例如,如果我一直在使用Defaul