【问题标题】:OSGI LoggerFactoryOSGI LoggerFactory
【发布时间】:2018-11-21 16:48:13
【问题描述】:

在我的 OSGI 工作中,我正在努力解决另一个看似简单的日志记录问题。

我们已经将日志记录到我们的包中并且它可以工作。我们实际上是在使用 pax-logging 服务来为我们完成繁重的工作。

import org.ops4j.pax.logging.PaxLoggingService;
import org.osgi.service.component.*;

@Component( immediate=true )
public class ComponentImpl implements TimeService {

    @Reference
    private PaxLoggingService logs;

    @Activate
    public void activate(ComponentContext ctx)
    {
        // deprecated legacy interface
        logs.log(PaxLoggingService.LOG_INFO, "Activate called at " + getTime());
        logs.log(PaxLoggingService.LOG_INFO, "Activated component " + ctx.getProperties().get("component.id"));
    }
}

但是有两件事困扰着我们。首先,直接使用public void log(int level, String message)方法一直是deprecated since OSGI v1.4。其次,我们更愿意通过 OSGI LogService 进行日志记录。

但是,这似乎并不那么容易。我们第一次尝试使用更新后的日志接口,您首先构建一个记录器实例,然后通过该接口进行记录,这会导致 Java AbstractMethodError:

@Component( immediate=true )
public class ComponentImpl implements TimeService {

    @Reference
    private PaxLoggingService logs;

    @Activate
    public void activate(ComponentContext ctx)
    {
        // fancy, new logging interface - throws exception
        Logger logger = logs.getLogger(ComponentImpl.class);
        logger.log(PaxLoggingService.LOG_INFO, "Activate called at " + getTime());
    }
}

运行时异常(这也发生在我们尝试 Apache Felix 的 LoggerService 实现时)

java.lang.AbstractMethodError: org.ops4j.pax.logging.service.internal.PaxLoggingServiceImpl$1ManagedPaxLoggingService.getLogger(Ljava/lang/Class;)Lorg/osgi/service/log/Logger;
        at com.foobar.baz.osgi.testservice.ComponentImpl.activate(ComponentImpl.java:31)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
        at java.lang.reflect.Method.invoke(Unknown Source)
        ...
        at org.apache.felix.framework.BundleImpl.start(BundleImpl.java:998)
        at aQute.launcher.Launcher.startBundles(Launcher.java:517)
        at aQute.launcher.Launcher.activate(Launcher.java:423)
        at aQute.launcher.Launcher.run(Launcher.java:301)
        at aQute.launcher.Launcher.main(Launcher.java:147)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
        at java.lang.reflect.Method.invoke(Unknown Source)
        at aQute.launcher.pre.EmbeddedLauncher.main(EmbeddedLauncher.java:47)

理想情况下,无论如何您都不想在activate() 中初始化记录器实例,而是由框架设置它。 OSGI spec shows an example of this in section 112.3.12

@Component
public class MyComponent {
  @Reference(service=LoggerFactory.class)
  private Logger logger;
  @Activate
  void activate(ComponentContext context) {
    logger.trace(“activating component id {}”,
      context.getProperties().get(“component.id”));
  }
}

不幸的是,该示例也不起作用。引用没有得到解决,因此捆绑包永远不会运行......我一直在搜索网络,但没有找到任何相关的东西。似乎大多数人不使用 OSGI 服务接口进行日志记录,而是使用 slf4j(或其他外观)代替; Pax 将以任何一种方式捕获日志条目。所以从技术上讲,它没有区别。

我认为我们的问题是没有人(PAX 和 Felix 都没有)实现过 OSGI LoggerFactory 接口......

  • 是否有 OSGI LogService 实现 实现 LoggerFactory?
  • 通过“隐式”通道(如导入 slf4j)而不是使用“显式”OSGI 接口登录是否有优势?

【问题讨论】:

    标签: osgi


    【解决方案1】:

    目前登录 OSGi 的最佳实践是使用 slf4j 作为前端。

    Logger log = LoggerFactory.getLogger(this.getClass());
    

    只需在您的课程中使用它。 Pax-Logging 为其提供了后端,它也可以与 logback 后端一起使用。

    OSGi R7 提供了一些改进的日志服务集成,但我认为这还没有在平台上广泛使用。

    使用@Reference 进行日志记录的优势在于,当您的日志记录后端可能尚不可用时,它可以消除启动时的计时问题。

    像上面这样集成 slf4j 的优点是它甚至适用于也需要在 OSGi 之外工作的混合 jar。

    【讨论】:

      【解决方案2】:
      • 到现在(2019 年 3 月),(至少)有(至少)Apache Felix Log 完全实现了 OSGi 日志记录 1.4。

      • 据我所知,显式使用 OSGi Logger 的最简单方法是通过 logging facade。声明一个记录器就像使用 slf4j 或 log4j 一样简单,并且不需要 SCR(或类似的)。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2019-05-09
        • 1970-01-01
        • 1970-01-01
        • 2016-04-20
        • 2019-04-23
        • 2015-11-30
        • 1970-01-01
        相关资源
        最近更新 更多