Как настроить регистратор в корпоративном приложении OSGi на WebSphere?

Я совершенно не понимаю, как правильно настроить регистратор в среде Java EE OSGi. Вот мои требования:

  • Только 1 файл журнала на EBA (группировка пакетов)
  • Несколько файлов журналов на сервер приложений (из-за нескольких EBA)
  • Не хочу выполнять магию ClassLoader (это нормально, если библиотека, которую я использую, делает это, я просто не хочу ее писать)
  • Необходимо чередовать файл журнала в конце дня и одновременно поддерживать только 7 файлов журнала.
  • Предпочтительно не требуется создавать пакет журналов для каждого EBA. Ни один другой разработчик не купится, если я попрошу их написать собственное взаимодействие для ведения журналов для каждого приложения.
  • Должен работать с WebSphere Application Server 8.5.5.

Сначала я попытался использовать SLF4j поверх log4j, как это делают другие наши приложения Java EE, однако ничто не смогло найти мои log4j.properties. Я пробовал варианты импорта SLF4j, а также имел проблемы, когда загрузка его в 1 пакете мешала его загрузке в другом.

Затем я заглянул в регистратор PAX, но, похоже, он ведет глобальный журнал, а не для EBA.

Попытка использовать OSGi LogService препятствует развертыванию моего пакета в WebSphere, плюс я не знаю, как я могу заставить его соответствовать моим требованиям.

Я нахожусь в точке, где единственный вариант, который я вижу, - это написать свой собственный пакет, который хранит реестр для пакета → файл журнала (используя FrameworkUtil.getBundle в клиентском классе) и реализует в нем полную структуру ведения журнала. Если у этого есть проблемы с изоляцией загрузчика классов, возможно, нажмите на EJB для фактического ведения журнала. Я действительно надеюсь, что это не единственное решение.

Может ли кто-нибудь указать мне на какую-то документацию, которая мне поможет??

Спасибо!


person Craig    schedule 25.10.2013    source источник


Ответы (1)


Люди вообще путаются в Log Service... Log Service не хранит никаких логов, он просто выполняет роль диспетчера. Я понимаю путаницу, поскольку служба журналов обязана иметь небольшой буфер для первоначального запуска и предоставляет 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");
  }
}

Это, конечно, можно было бы сделать немного эффективнее, но это остается в качестве упражнения.

person Peter Kriens    schedule 27.10.2013
comment
Таким образом, кажется, что написание моего собственного решения и сохранение реестра для файла журнала для каждого пакета - лучший вариант? Я немного разочарован тем, что нет лучшего решения, но что вы дали мне преимущество в реализации. - person Craig; 27.10.2013