如何在 Karaf 的容器初始化期间记录 Blueprint (Aries) 创建的对象的初始化?

Posted

技术标签:

【中文标题】如何在 Karaf 的容器初始化期间记录 Blueprint (Aries) 创建的对象的初始化?【英文标题】:How can I log initialization of objects created by Blueprint (Aries) during container initialization in Karaf? 【发布时间】:2019-11-25 03:11:52 【问题描述】:

读完之后,我觉得我明白了,现在我感到困惑。以下是我的期望和我所做的:

我希望登录到 Karaf,重新加载我的包,然后运行 ​​log:tail 并最终看到如下日志消息:

13:28:47.265 INFO [Blueprint] You just created a class called: MyClass.

使用的技术: - 由 Apache Karaf 实现的 OSGI 容器 - 白羊座实现的蓝图

    我的 OSGI 包从 Karaf 导入 pax 记录器

    org.slf4j.*; provider=paxlogging

据我了解,这意味着对 Karaf 的单例记录器的引用将在运行时提供给我的应用程序,该应用程序仅使用 API。

    我的类使用SLF4J接口,所以我的项目中存在依赖slf4j-api:slf4j-api:1.7.26

    存在一个类

类服务于模型

public class MyClass 
  private static final Logger LOGGER = LoggerFactory.getLogger(MyClass.class);
  public MyClass() 
    LOGGER.info("You just created a class called: ", this);
  
  @Override
  public String toString()  return "MyClass" ;

我只是遵循 OSGI LoggerFactory 的规范:

此 API 的使用者不得实现此类型https://osgi.org/specification/osgi.cmpn/7.0.0/service.log.html#org.osgi.service.log.LoggerFactory

    白羊座创造了一个:

蓝图 XML

<?xml version="1.0" encoding="UTF-8" ?>
<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xsi:schemaLocation="http://www.osgi.org/xmlns/blueprint/v1.0.0 http://www.osgi.org/xmlns/blueprint/v1.0.0/blueprint.xsd">

<description>
    A sample Blueprint XML to demonstrate 
    the initialization procedure in the hopes of reproducing a problem.
</description>

<bean id="myclass1" class=com.stack.MyClass/>
</blueprint>

相关

How handle different logging solutions in OSGi (Apache Felix) Activating an OSGI LogListener before other services?

【问题讨论】:

【参考方案1】:

在 karaf 中启用 slf4j 登录不需要特殊处理。 只需像您一样登录您的 java 代码,然后让 maven bundle 插件为您创建一个包导入(无需特殊配置)。

指向 OSGi R7 日志服务规范的链接是即将到来的日志标准化。基本上,该规范允许将记录器作为 OSGi 服务注入。这在技术上比 karaf(实际上是 pax-logging)今天所做的更干净。 在 karaf,此规范尚未实施。

【讨论】:

@Schneider 我喜欢你在***.com/q/28882345/1236128 的评论。我想你可能误读了我的问题。我有所有的设置(除了我使用 Gradle biz.aQute.bnd 插件)。不记录早期创建的对象。我需要知道如何解决这个问题。我的猜测是,我需要尽早查询服务管理器并获取对 pax 日志记录的参考(尚不确定如何执行此操作)。 啊..它是关于不丢失日志条目。您可以将 org.osgi.service.log.LogService 注入到蓝图上下文中。 Pax 日志记录提供此服务,它将确保您的代码仅在 pax 日志记录准备好时执行。 Appeciated,但文档指出 LogService 已被弃用,取而代之的是 LoggerFactory 或 Loggers。 osgi.org/specification/osgi.cmpn/7.0.0/service.log.html 您只能将 LogService 用作一种标记服务,让您的蓝图上下文等待它准备好。您不会使用 LogService 来记录内容。 Pax 日志还实现了一些其他接口,但我给了你一个日志服务,因为它背后有一个规范......所以你不需要依赖 pax 日志特定的接口。 API 在依赖项中应该足够好。如果日志记录适用于某些线程,那么您的依赖关系是正确的。如果您没有看到所有日志,那么这可能是 pax 日志记录中的错误。【参考方案2】:

想通了:

捆绑包中编译的 SLF4J API 是故事的一部分。其余部分由 org.ops4j.pax.logging.pax-logging-api 在 Karaf / Felix 中提供。这东西在后台做事:

    设置自己的单例记录器工厂。 立即启用 SLF4J API 支持并记录一条消息。 其中一个单例记录器工厂是 SLF4J API 创建记录器所需的,Slf4jLoggerFactory。它持有对PaxLoggingManager 对象(Slf4jLoggerFactory.setPaxLoggingManager(manager),其中经理是new OSGIPaxLoggingManager(bundleContext))的静态引用。此单例中的方法getLogger 返回一个new Slf4jLogger(name, paxLogger) 对象(其中名称通常是类名,而paxLogger 来自FallbackLogFactory.createFallbackLog(FrameworkUtil.getBundle(Logger.class), name)m_paxLogging.getLogger(name, Slf4jLogger.SLF4J_FQCN)。Slf4jLogger

因此,有必要绑定到这个特定的Slf4jLoggerFactory(实现ILoggerFactory),以便捆绑包中的所有类在调用getLogger(class) 时都能获得正确的引用。 Aries Blueprint 的问题似乎在于它懒惰地将 SLF4J API 绑定到headers org.ops4j.pax.logging.pax-logging-api 提供的实现。因此,我按照 Christian Schneider 的建议在 Blueprint 中创建了一个***引用,强制 Blueprint 等待 Pax Manager 准备好:

 <reference id="logService" interface="org.osgi.service.log.LogService" availability="mandatory" activation="eager"/>

那么其他高层管理者可以通过depends-on来依赖这个:

<bean id="MyRegistry" class="com.foo.MyRegistry" scope="singleton" factory-method="getSingletonInstance" depends-on="logService">

当然,我需要在我的 OSGI MANIFEST.MF 中添加以下内容

Import-Package:
org.slf4j;version="[1.7.0,2.0.0)",
org.osgi.service.log,

【讨论】:

以上是关于如何在 Karaf 的容器初始化期间记录 Blueprint (Aries) 创建的对象的初始化?的主要内容,如果未能解决你的问题,请参考以下文章

Karaf 容器、Rest WS 和 Spring 安全性

无法从 Karaf 2.2.0 OSGi 容器中的根上下文运行 WAR

OSGi 容器 - Equinox 与 Apache Karaf 中的 Apache Felix

osgi+camel+karaf运行环境搭建

关于Karaf Container 4.0.7

如何绕过karaf中的默认aries jndi查找