Pergunta

Eu estou trabalhando em um aplicativo que consiste de um programador baseado em Quartz geral e "CycledJob" executado usando CronTriggers. O objetivo da aplicação é para entradas de processo de diferentes caixas de entrada de e-mail com base no país de origem.

Com base no país que vem de (ou seja, US, UK, FR, etc.) os gatilhos de aplicação um segmento de trabalho para executar ciclo de processamento de cada país, para que houvesse um segmento de trabalho do Reino Unido, um para EUA, França , etc. ao formatar a saída para log4j, estou usando o parâmetro de linha, por isso emite [ApplicationName_Worker-1], [ApplicationName_Worker-2] etc. Por mais que tentasse, não consigo encontrar uma maneira de nomear os tópicos uma vez que está puxado para fora de Piscinas fio de quartzo. Embora eu poderia ir tão longe como para estender Quartz, eu gostaria de encontrar uma solução diferente em vez de mexer com a biblioteca padrão.

Aqui está o problema: Ao usar log4j, eu gostaria de ter todos os itens de registro da saída de rosca dos EUA para um US único arquivo, da mesma forma para cada um dos tópicos país. Eu não me importo se eles ficar em um ConsoleAppender unificada, a divisão FileAppender é o que eu estou atrás aqui. Eu já sei como especificar várias appenders arquivos e tal, o meu problema é que eu não pode diferenciar com base no país. Há mais de 20 classes dentro do aplicativo que pode estar na cadeia de execução, muito poucos dos quais eu quero fardo com o conhecimento de passar um parâmetro extra "contexto" através do método CADA ... Eu considerei um padrão Estratégia estendendo uma log4j classe de mensagens publicitárias, mas a menos que eu posso deixar todas as classes no saber cadeia qual thread é para parametrizar a chamada logger, que parece impossível. Sem ser capaz de nomear o segmento também cria um desafio (ou então isso seria fácil!).

Então aqui vai a pergunta: O que seria uma abordagem sugerida para permitir que muitas classes subalternas em um aplicativo que são cada usada para cada segmento diferente para processar o know entrada que eles estão dentro do contexto de um segmento determinado país quando estão logging ?

Boa sorte entendimento, e por favor perguntas esclarecedoras! Espero que alguém é capaz de me ajudar a descobrir uma maneira decente para enfrentar isso. Todas as sugestões bem-vindos.

Foi útil?

Solução

No topo do segmento de processamento de cada país, colocar o código do país em contexto de diagnóstico mapeada de Log4j (MDC). Isto usa uma variável ThreadLocal de modo que você não tem que passar o país para cima e para baixo da pilha de chamadas explicitamente. Em seguida, crie um filtro personalizado que olha para o MDC, e filtra todos os eventos que não contêm código de país do appender atual.

Em seu Job:

...
public static final String MDC_COUNTRY = "com.y.foo.Country";
public void execute(JobExecutionContext context)
  /* Just guessing that you have the country in your JobContext. */
  MDC.put(MDC_COUNTRY, context.get(MDC_COUNTRY));
  try {
    /* Perform your job here. */
    ...
  } finally {
    MDC.remove(MDC_COUNTRY);
  }
}
...

Escrever um costume :

package com.y.log4j;

import org.apache.log4j.spi.LoggingEvent;

/**
 * This is a general purpose filter. If its "value" property is null, 
 * it requires only that the specified key be set in the MDC. If its 
 * value is not null, it further requires that the value in the MDC 
 * is equal.
 */
public final class ContextFilter extends org.apache.log4j.spi.Filter {

  public int decide(LoggingEvent event) {
    Object ctx = event.getMDC(key);
    if (value == null)
      return (ctx != null) ? NEUTRAL : DENY;
    else
      return value.equals(ctx) ? NEUTRAL : DENY;
  }

  private String key;
  private String value;

  public void setContextKey(String key) { this.key = key; }
  public String getContextKey() { return key; }
  public void setValue(String value) { this.value = value; }
  public String getValue() { return value; }

}

Em seu log4j.xml:

<appender name="fr" class="org.apache.log4j.FileAppender">
  <param name="file" value="france.log"/>
  ...
  <filter class="com.y.log4j.ContextFilter">
    <param name="key" value="com.y.foo.Country" />
    <param name="value" value="fr" />
  </filter>
</appender> 

Outras dicas

Eu gostaria de poder ser um pouco mais útil do que isso, mas você pode querer investigar usando alguns filtros? Talvez o seu logging poderia saída o código do país e você poderia coincidir com o filtro baseado em que?

A StringMatchFilter provavelmente deve ser capaz de combiná-lo para você.

Não foi possível obter o endereço abaixo para funcionar corretamente como um link, mas se você olhar para ele, ele tem algumas coisas sobre a exploração madeireira arquivo separado usando filtros.

http: //mail-archives.apache. org / mod_mbox / logging-log4j-user / 200512.mbox / <1CC26C83B6E5AA49A9540FAC8D35158B01E2968E@pune.kaleconsultants.com> (basta remover o espaço antes do>)

http: //logging.apache org / log4j / 1,2 / apidocs / org / Apache / log4j / SPI / Filter.html

Por que não apenas chamar Thread.setName () quando o trabalho começa a definir o nome do tópico? Se houver um problema de acesso, configure quartzo usar seu próprio pool de threads.

Eu posso estar completamente fora da base no meu entendimento do que você está tentando realizar, mas vou tomar uma facada em solução. Parece que você quer um arquivo de log separado para cada país para o qual você está processando e-mail. Com base nessa compreensão, aqui está uma solução possível:

  1. Configurar uma appender em sua configuração log4j para cada país para o qual deseja fazer logon separadamente (exemplo US fornecido):

    log4j.appender.usfile = org.apache.log4j.FileAppender

    log4j.appender.usfile.File = us.log

    log4j.appender.usfile.layout = org.apache.log4j.PatternLayout

    = log4j.appender.usfile.layout.ConversionPattern% m% n

  2. Criar um logger para cada país e direcionar cada um deles para o appender apropriado (exemplo US fornecido):

    log4j.logger.my-us-logger = debug, usfile

  3. Em seu código, criar seu Logger baseados no país para o qual o e-mail está sendo processado:

    Logger logger = Logger.getLogger ( "minha-us-logger");

  4. Determine como você irá realizar o passo 3 para as chamadas de método subsequentes. Você pode repetir o passo 3 em cada classe / método; ou você pode modificar as assinaturas de método para aceitar um Logger como entrada; ou você poderia usar ThreadLocal para passar o Logger entre os métodos.

Informações adicionais: Se você não quer que as declarações de log vai madeireiros de origem (por exemplo, o rootLogger), você pode definir suas bandeiras aditividade para false (US exemplo fornecido):

log4j.additivity.my-us-logger=false
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top