【问题标题】:Apache Felix OSGi logging with LogbackApache Felix OSGi 使用 Logback 进行日志记录
【发布时间】:2016-01-14 22:18:01
【问题描述】:

我当前的应用程序使用Logback 进行日志记录。我使用 Apache Felix 部署了一个 OSGi 框架,该框架允许在运行时动态注册包。 Felix 设置如下:

    ...

    //System.out.println("Building OSGi Framework");
    FrameworkFactory frameworkFactory = ServiceLoader.load(FrameworkFactory.class).iterator().next();
    Map<String, String> config = new HashMap<>();

    // specify the class loader
    config.put(Constants.FRAMEWORK_BUNDLE_PARENT, Constants.FRAMEWORK_BUNDLE_PARENT_FRAMEWORK);

    // specify the osgi cache directory
    config.put(Constants.FRAMEWORK_STORAGE, appConfig.getOsgiCacheDir());

    // make sure the cache is cleaned
    config.put(Constants.FRAMEWORK_STORAGE_CLEAN, Constants.FRAMEWORK_STORAGE_CLEAN_ONFIRSTINIT);

    // expose api
    config.put(Constants.FRAMEWORK_SYSTEMPACKAGES_EXTRA, "list.of.packages.to.export");

    // more properties available at: http://felix.apache.org/documentation/subprojects/apache-felix-service-component-runtime.html
    config.put("ds.showtrace", "false");
    config.put("ds.showerrors", "true");
    config.put("felix.fileinstall.dir", appConfig.getActiveOsgiExtDir());
    config.put("felix.fileinstall.tmpdir", appConfig.getTempOsgiExtDir());
    config.put("felix.fileinstall.bundles.startTransient","true");
    config.put("felix.fileinstall.poll","5000");
    config.put("felix.fileinstall.bundles.new.start", "true");

    LOG.debug("OSGi config: " + config.toString());

    framework = frameworkFactory.newFramework(config);

    try {
        framework.init();
        FrameworkEvent event;

        do {
            framework.start();
    ...

唯一的问题是 Felix 似乎没有日志记录。当捆绑包由于某种原因无法加载时,我不明白为什么!我知道我可以在包中使用以下内容来获取父记录器:

ServiceReference ref = bundleContext.getServiceReference(LogService.class.getName());
if (ref != null) {
    LogService log = (LogService) bundleContext.getService(ref);
    ...
   }

但是,我首先不明白如何让 felix 使用 logback 作为记录器。

【问题讨论】:

  • 您无需登录即可找出捆绑软件无法启动的原因。只需从 shell 显式启动它并观察那里的错误消息。
  • 你的绝对正确。但是,我通常需要能够执行日志记录,并且捆绑包能够将其日志记录传递给主应用程序框架。

标签: java logging osgi apache-felix blueprint-osgi


【解决方案1】:

我猜你使用Apache Felix Log 在你的 OSGi 容器中有一个 LogService。 Apache Felix Log 实现了 OSGi 企业规范的“101 日志服务规范”章节。

LogService 的基本实现会将记录的条目存储一段时间,但不会将它们写入任何地方。您可以通过LogReaderServiceLogListener查询记录的条目。

另一方面,您可以通过将 slf4j-api 和 slf4j-logback 添加到 OSGi 容器的方式来使用 Logback。通过这样做,通过 slf4j-api 类记录的所有内容都将由 logback 记录。

如果我的猜测是正确的,osgi-loglistener-slf4j 捆绑包可以帮助您。这个包除了为环境中的每个 LogReaderService 注册一个 LogListener 之外什么都不做,并将它捕获的每个日志条目转发到 slf4j-api。该捆绑包可在maven-central上获得

如果您不想使用 slf4j API,您可以编写一个类似的包,将日志从 LogReaderService 转发到 Logback。如果您检查我链接的捆绑包的来源,您会发现它只用几行代码实现。

【讨论】:

  • 我实际上认为你是 100% 正确的。但是,我目前无法让 osgi-loglistener-slf4j 无错误地注册。修复后会更新。
  • Unable to resolve org.everit.osgi.loglistener.slf4j [3](R 3.0): missing requirement [org.everit.osgi.loglistener.slf4j [3](R 3.0)] osgi.wiring.package; (&amp;(osgi.wiring.package=org.osgi.service.log)(version&gt;=1.3.0)(!(version&gt;=2.0.0))) Unresolved requirements: [[org.everit.osgi.loglistener.slf4j [3](R 3.0)] osgi.wiring.package; (&amp;(osgi.wiring.package=org.osgi.service.log)(version&gt;=1.3.0)(!(version&gt;=2.0.0)))]
  • 这有点奇怪。我猜你使用了 org.osgi.service.log 包中的 LogService 类。它是另一个 LogService 类吗?如果示例代码中没有导入包部分,我无法确定。如果是来自这个包,你的容器中包含什么版本的包?
  • 确保在使用 org.everit.osgi.loglistener.slf4j 时还安装了 Apache Felix Log 包 felix.apache.org/documentation/subprojects/…>,它提供了 org.osgi.service.log 包。跨度>