OSGI LoggerFactory
OSGI LoggerFactory
在我的 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.PaxLoggingServiceImplManagedPaxLoggingService.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?
- 通过 'implicit' 通道(如导入 slf4j)而不是使用 'explicit' OSGI 接口登录是否有优势?
目前在 OSGi 中登录的最佳实践是使用 slf4j 作为前端。
Logger log = LoggerFactory.getLogger(this.getClass());
只需在 类 中使用它即可。 Pax-Logging 为其提供后端,它也可以与 logback 后端一起使用。
OSGi R7 提供了一些改进的日志服务集成,但我认为这在平台中尚未广泛使用。
使用@Reference 进行日志记录的优势在于,当您的日志记录后端可能尚不可用时,它可以消除启动时的计时问题。
像上面这样的 slf4j 集成的优点是它甚至适用于也需要在 OSGi 之外工作的混合 jar。
到现在(2019 年 3 月)有(至少)Apache Felix Log 完全实现了 OSGi Logging 1.4。
据我所知,明确使用 OSGi 记录器的最简单方法是通过此 logging facade。声明记录器与使用 slf4j 或 log4j 一样简单,它不需要 SCR(或类似的)。
在我的 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.PaxLoggingServiceImplManagedPaxLoggingService.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?
- 通过 'implicit' 通道(如导入 slf4j)而不是使用 'explicit' OSGI 接口登录是否有优势?
目前在 OSGi 中登录的最佳实践是使用 slf4j 作为前端。
Logger log = LoggerFactory.getLogger(this.getClass());
只需在 类 中使用它即可。 Pax-Logging 为其提供后端,它也可以与 logback 后端一起使用。
OSGi R7 提供了一些改进的日志服务集成,但我认为这在平台中尚未广泛使用。
使用@Reference 进行日志记录的优势在于,当您的日志记录后端可能尚不可用时,它可以消除启动时的计时问题。
像上面这样的 slf4j 集成的优点是它甚至适用于也需要在 OSGi 之外工作的混合 jar。
到现在(2019 年 3 月)有(至少)Apache Felix Log 完全实现了 OSGi Logging 1.4。
据我所知,明确使用 OSGi 记录器的最简单方法是通过此 logging facade。声明记录器与使用 slf4j 或 log4j 一样简单,它不需要 SCR(或类似的)。