【问题标题】:How to setup a logger in an OSGi Enterprise Application on WebSphere?如何在 WebSphere 上的 OSGi 企业应用程序中设置记录器?
【发布时间】:2013-11-05 00:49:10
【问题描述】:

我对如何在 Java EE OSGi 环境中正确设置记录器感到很困惑。以下是我的要求:

  • 每个 EBA(捆绑包分组)只有 1 个日志文件
  • 每个应用程序服务器有多个日志文件(由于多个 EBA)
  • 不想执行 ClassLoader 魔术(如果我使用的库可以执行此操作,我只是不想编写它)
  • 必须在一天结束时轮换日志文件,并且一次只能维护 7 个日志文件
  • 最好不需要为每个 EBA 创建日志包。如果我告诉他们为每个应用程序编写自己的日志互操作性,其他开发人员都不会接受。
  • 必须与 WebSphere Application Server 8.5.5 一起使用

首先,我尝试像其他 Java EE 应用程序一样在 log4j 之上使用 SLF4j,但是找不到我的 log4j.properties。我尝试了导入 SLF4j 的变体,但也遇到了将其加载到 1 个捆绑包中阻止它加载到另一个捆绑包中的问题。

接下来我查看了 PAX 记录器,但它似乎是全局记录,而不是每个 EBA。

尝试使用 OSGi LogService 会阻止我的包部署到 WebSphere,而且我不确定如何才能让它满足我的要求。

我现在可以看到的唯一选择是编写我自己的包来保存包的注册表 -> 日志文件(在客户端类上使用 FrameworkUtil.getBundle)并在其中实现完整的日志记录框架.如果这有类加载器隔离问题,那么可能会推送到 EJB 来进行实际的日志记录。我真的希望这不是我唯一的解决方案。

谁能指点我一些可以帮助我的文档??

谢谢!

【问题讨论】:

    标签: java logging websphere osgi aries


    【解决方案1】:

    人们普遍对日志服务感到困惑......日志服务不存储任何日志,它只是充当调度程序。我理解这种混乱,因为日志服务被要求在初始启动时有一个小缓冲区,并提供一个 API 来获取缓冲区。

    对于您想要的,您应该添加一个带有日志读取器服务的日志侦听器。使用声明式服务,您想要的很容易。这是一个实现您的要求的组件:

    @Component(provide = {}, immediate = true) public class Logger extends Thread
        implements LogListener {
      final BlockingQueue<LogEntry> queue = new ArrayBlockingQueue<LogEntry>(1000);
      File root;
    
      @Reference void setLR(LogReaderService lr) {
        lr.addLogListener(this);
      }
    
      @Activate void activate(BundleContext context, Map<String,Object> props) {
        if ( props.containsKey("root"))
          root = new File((String) props.get("root"));
        else
          root = context.getDataFile("logs");
        root.mkdirs();
        start();
      }
    
      @Deactivate void deactivate() {
        interrupt();
      }
    
      @Override public void logged(LogEntry entry) {
        queue.offer(entry); // ignore full silently
      }
    
      public void run() {
        while (true)
          try {
            LogEntry entry = queue.take();
            File file = getPath(entry);
    
            if (file.isFile()) {
              long days = TimeUnit.MILLISECONDS.toDays(System.currentTimeMillis()
                  - file.lastModified());
              if (days > 2) file.delete();
            }
    
            try (OutputStream raf = new FileOutputStream(file, true)) {
              String s = String.format("%tT [%03d] %s%n", entry.getTime(), entry
                  .getBundle().getBundleId(), entry.getMessage());
              raf.write(s.getBytes("UTF-8"));
            }
    
          } catch (InterruptedException ie) {
            return;
          } catch (Exception e) {
            throw new RuntimeException(e);
          }
      }
    
      private File getPath(LogEntry entry) {
        long rollover = TimeUnit.MILLISECONDS.toDays(System.currentTimeMillis()) % 7;
        String eba = "eba"; // fill in eba from entry.getBundle()?
        return new File(root, "log-" + eba + "-" + rollover + ".msg");
      }
    }
    

    这当然可以做得更有效率,但这留作练习。

    【讨论】:

    • 看来编写我自己的解决方案并为每个捆绑包保留日志文件的注册表是最佳选择?我有点失望,没有更好的解决方案,但您让我在实施方面领先一步。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-07-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多