微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

使用 ByteBuddy 检测另一个 Java 代理

如何解决使用 ByteBuddy 检测另一个 Java 代理

我使用 Elastic APM Agent 作为 Java 代理来监控 Spring Boot 微服务中各种方法的使用情况。这一切都很好,我们能够在 Kibana 中绘制各种指标。不幸的是,它没有做的是始终如一地将相同的标签附加到事务中的所有跨度,例如发出原始请求的用户的详细信息。

为了解决这个问题,我想我可以使用 ByteBuddy(我以前从未使用过)来包装 APM Span 类的任何用法并将该信息(因为它很容易从 ThreadLocal 获得)附加到每个实例。但是,我在访问位于 APM Java 代理中的 Span 类时遇到问题,使用以下代码我得到以下日志,其中似乎无法找到 Span 类...

        Instrumentation instrumentation = ByteBuddyAgent.install();
        new AgentBuilder.Default()
                .with(debuggingListener)
                .ignore(ElementMatchers.nameStartsWith("net.bytebuddy."))
                .type(ElementMatchers.named("co.elastic.apm.agent.impl.transaction.Span"),ElementMatchers.isBootstrapClassLoader())
                .transform((builder,type,classLoader,module) -> builder.visit(Advice.to(SpanAdvice.class).on(ElementMatchers.hasMethodName("start"))))
                .installOn(instrumentation);
[Byte Buddy] disCOVERY co.elastic.apm.agent.impl.transaction.Transaction [null,unnamed module @758a34ce,loaded=false]
[Byte Buddy] IGnorE co.elastic.apm.agent.impl.transaction.Transaction [null,loaded=false]
[Byte Buddy] COMPLETE co.elastic.apm.agent.impl.transaction.Transaction [null,loaded=false]
[Byte Buddy] disCOVERY co.elastic.apm.agent.impl.transaction.Transaction$1 [null,loaded=false]
[Byte Buddy] IGnorE co.elastic.apm.agent.impl.transaction.Transaction$1 [null,loaded=false]
[Byte Buddy] COMPLETE co.elastic.apm.agent.impl.transaction.Transaction$1 [null,loaded=false]
[Byte Buddy] disCOVERY co.elastic.apm.agent.impl.transaction.AbstractSpan$ChildDurationTimer [null,loaded=false]
[Byte Buddy] IGnorE co.elastic.apm.agent.impl.transaction.AbstractSpan$ChildDurationTimer [null,loaded=false]
[Byte Buddy] COMPLETE co.elastic.apm.agent.impl.transaction.AbstractSpan$ChildDurationTimer [null,loaded=false]
[Byte Buddy] disCOVERY co.elastic.apm.agent.impl.transaction.SpanCount [null,loaded=false]
[Byte Buddy] IGnorE co.elastic.apm.agent.impl.transaction.SpanCount [null,loaded=false]
[Byte Buddy] COMPLETE co.elastic.apm.agent.impl.transaction.SpanCount [null,loaded=false]
[Byte Buddy] disCOVERY co.elastic.apm.agent.impl.transaction.TraceState$TextTracestateAppender [null,loaded=false]
[Byte Buddy] IGnorE co.elastic.apm.agent.impl.transaction.TraceState$TextTracestateAppender [null,loaded=false]
[Byte Buddy] COMPLETE co.elastic.apm.agent.impl.transaction.TraceState$TextTracestateAppender [null,loaded=false]

我已经尝试将 ByteBuddy 用于我自己的类,并且一切正常,但我对哪个类加载器加载了什么以及如何将 ByteBuddy 指向它们感到非常困惑。

解决方法

如果目标是将标签附加到多个跨度的事务,那么使用 public APIs from the Elastic APM for Java 是更好的选择,而不是使用 ByteBuddy 检测 JVM。您将有更多的自由来做自己想做的事,而无需依赖黑客。仅供参考,用于 Java 的 Elastic APM 代理已经使用额外的字节码检测 JVM,因此您正在执行的操作可能会因此变得更加混乱。

或者,您也可以使用 OpenTracing Bridge 在交易中设置标签。

,

免责声明:这个答案暂时是一个存根。

您应该首先尝试探索一种更规范的做事方式,就像 Ricardo 建议的那样。如果由于某种原因不起作用,那么我们可以探索检测您的代理类的方法 - 不是因为我认为这是一个好主意,而是因为它在技术上很有趣。

基本上,在您的 ByteBuddy 代理激活之前,我们必须确定您要检测的类是否已经加载。然后您将不得不使用类重新转换而不是重新定义。您必须确保您应用的建议可以完成其工作,而无需更改有关方法签名和字段的类结构。

import pretty_midi

midi_file = pretty_midi.PrettyMIDI(initial_tempo=120.0)
prog = pretty_midi.instrument_name_to_program('Pad 1 (new age)')
track = pretty_midi.Instrument(program=prog)

note = pretty_midi.Note(velocity=100,pitch=70,start=0,end=2)
track.notes.append(note)

note = pretty_midi.Note(velocity=100,pitch=71,start=2,end=4)
track.notes.append(note)

midi_file.initial_tempo = 200 // not work
midi_file.write('tmp/chord.mid')

您还需要确保通知和 ByteBuddy 对其他代理的类加载器可见,例如通过将两者都放在引导类路径上。但是,让我们不要超越自己。请先了解 Ricardo 的想法。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。