Frage

Ich arbeite an einer Anwendung, die mit CronTriggers eines Gesamt Quarz-basierten Scheduler und „CycledJob“ run besteht. Der Zweck der Anwendung ist Eingaben von anderen E-Mail-Postfächern auf dem Herkunftsland basieren zu verarbeiten.

auf dem Land, dass es kommt aus (dh US, UK, FR, usw.) die Anwendung löst einen Job-Thread der jeweiligen Landes Verarbeitungszyklus zu laufen, so gäbe es eine UK Worker-Thread, einem für USA, Frankreich usw. Wenn die Ausgabe in log4j Formatierung, ich die Thread-Parameter verwenden, so ist es aussendet [ApplicationName_Worker-1], [ApplicationName_Worker-2] usw. Versuchen sie, wie ich könnte, ich kann nicht einen Weg finden, um die Fäden zu nennen da sie aus Quarz des Threadpools gezogen. Obwohl ich nur so weit gehen könnte als Quarz zu verlängern, würde Ich mag eine andere Lösung erarbeiten, statt mit der Standardbibliothek von Unordnung.

Hier ist das Problem: Wenn log4j verwenden, würde Ich mag alle Log-Einträge aus der US-Thread Ausgabe nur in US-Datei für jede der Land Fäden, ebenfalls haben. Mir ist es egal, ob sie in einem einheitlichen ConsoleAppender bleiben, ist die FileAppender Split, was ich nach hier. Ich weiß schon, wie mehrere Dateiappen zu spezifizieren und so, mein Problem ist, ich kann nicht auf Land unterscheiden. Es gibt mehr als 20 Klassen in der Anwendung, die auf der Ausführungskette sein kann, nur sehr wenige von denen ich mit dem Wissen zu belasten will einen zusätzlichen „Kontext“ Parameter durch jede Methode von vorbei ... Ich habe ein Strategie-Muster als eine Verlängerung log4j Wrapper-Klasse, aber wenn ich nicht jede Klasse in der Kette lassen kann wissen, welchen Thread es auf den Logger Anruf zu parametrieren, das scheint unmöglich. Ohne die Möglichkeit, den Faden zu nennen schafft auch eine Herausforderung (sonst wäre so einfach sein!).

Hier ist also die Frage: Was für eine vorgeschlagene Konzept würde viele untergeordneten Klassen in einer Anwendung zu ermöglichen, die jeweils für jeden anderen Thread verwendet werden, um die Eingabe zu verarbeiten, weiß, dass sie im Rahmen eines bestimmten Land Thread sind, wenn sie sich anmelden ?

Viel Glück Verständnis, und fragen Sie bitte klärende Fragen! Ich hoffe, dass jemand in der Lage ist, mir zu helfen einen angemessenen Weg finden, um diese zu bekämpfen. Alle Vorschläge willkommen.

War es hilfreich?

Lösung

An der Spitze der einzelnen Verarbeitungs-Thread des Landes, setzen Sie den Ländercode in Log4j des abgebildeten diagnostischen Kontext (MDC). Dieser verwendet eine Thread Variable, so dass Sie nicht explizit das Land nach oben und unten den Call-Stack übergeben. Dann erstellen Sie einen benutzerdefinierten Filter, der am MDC sieht, und alle Ereignisse herausfiltert, die nicht die aktuelle appender Ländercode enthalten.

In Ihrem 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);
  }
}
...

Schreiben Sie eine benutzerdefinierte Filter :

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; }

}

In Ihrem 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> 

Andere Tipps

Ich wünschte, ich könnte etwas hilfreicher als das sein, aber Sie können mit einigen Filter untersuchen wollen? Vielleicht ist Ihre Protokollierung konnte Ausgabe des Ländercode und Sie könnten Ihre Filter entsprechen, bezogen auf das?

Ein StringMatchFilter sollte wahrscheinlich in der Lage sein, es für Sie zu entsprechen.

kann nicht die unten stehende Adresse erhält richtig als Verbindung zu arbeiten, aber wenn man es betrachtet, es hat ein paar Sachen auf separaten Dateiprotokollierung mit Filter.

http: //mail-archives.apache. org / mod_mbox / logging-log4j-user / 200512.mbox / <1CC26C83B6E5AA49A9540FAC8D35158B01E2968E@pune.kaleconsultants.com> (entfernen Sie einfach den Raum vor dem>)

http: //logging.apache .org / log4j / 1.2 / apidocs / org / apache / log4j / spi / Filter.html

Warum nicht einfach anrufen Thread.setName (), wenn der Auftrag startet den Namen des Thread zu setzen? Wenn ein Zugriffsproblem ist, konfigurieren Quarz Ihren eigenen Thread-Pool zu verwenden.

kann ich völlig weg von der Unterseite sein auf meinem Verständnis von dem, was Sie zu erreichen versucht, aber ich werde einen Stich an der Lösung nehmen. Es klingt wie Sie eine separate Protokolldatei für jedes Land, für das Sie E-Mail-Verarbeitung sind. Basierend auf diesem Verständnis ist hier eine mögliche Lösung:

  1. Stellen Sie für jedes Land eine appender in Ihrer log4j Konfiguration auf, für die Sie separat (US Beispiel vorgesehen) protokollieren:

    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. Erstellen Sie einen Logger für jedes Land und jeder von ihnen an den entsprechenden appender (US Beispiel vorgesehen) richten:

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

  3. In Ihrem Code, erstellen Sie Ihren Logger basierte auf dem Land, für das die E-Mail verarbeitet wird:

    Logger Logger = Logger.getLogger ( "my-us-Logger");

  4. Sie fest, wie Sie Schritt 3 für die nachfolgenden Methodenaufrufe erreichen wird. Sie könnten Schritt 3 in jeder Klasse / Methode wiederholen; oder Sie können die Methodensignaturen ändern, um einen Logger als Eingabe zu akzeptieren; oder Sie könnten möglicherweise verwenden Thread die Logger zwischen den Methoden.

  5. passieren

Zusätzliche Informationen: Wenn Sie nicht das Protokoll Aussagen wollen gehen Mutterlogger (zum Beispiel der rootLogger), können Sie ihre additivity Flaggen auf false (US Beispiel vorgesehen) festgelegt:

log4j.additivity.my-us-logger=false
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top