View Javadoc

1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements. See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache license, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License. You may obtain a copy of the License at
8    *
9    *      http://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the license for the specific language governing permissions and
15   * limitations under the license.
16   */
17  package org.apache.logging.log4j.core.jmx;
18  
19  import java.io.IOException;
20  import java.util.List;
21  import java.util.concurrent.Executor;
22  import java.util.concurrent.atomic.AtomicLong;
23  
24  import javax.management.MBeanNotificationInfo;
25  import javax.management.Notification;
26  import javax.management.NotificationBroadcasterSupport;
27  import javax.management.ObjectName;
28  
29  import org.apache.logging.log4j.Level;
30  import org.apache.logging.log4j.status.StatusData;
31  import org.apache.logging.log4j.status.StatusListener;
32  import org.apache.logging.log4j.status.StatusLogger;
33  
34  /**
35   * Implementation of the {@code StatusLoggerAdminMBean} interface.
36   */
37  public class StatusLoggerAdmin extends NotificationBroadcasterSupport implements StatusListener, StatusLoggerAdminMBean {
38  
39      private final AtomicLong sequenceNo = new AtomicLong();
40      private final ObjectName objectName;
41      private final String contextName;
42      private Level level = Level.WARN;
43  
44      /**
45       * Constructs a new {@code StatusLoggerAdmin} with the {@code Executor} to
46       * be used for sending {@code Notification}s asynchronously to listeners.
47       * 
48       * @param contextName name of the LoggerContext under which to register this
49       *            StatusLoggerAdmin. Note that the StatusLogger may be
50       *            registered multiple times, once for each LoggerContext. In web
51       *            containers, each web application has its own LoggerContext and
52       *            by associating the StatusLogger with the LoggerContext, all
53       *            associated MBeans can be unloaded when the web application is
54       *            undeployed.
55       * @param executor used to send notifications asynchronously
56       */
57      public StatusLoggerAdmin(final String contextName, final Executor executor) {
58          super(executor, createNotificationInfo());
59          this.contextName = contextName;
60          try {
61              final String mbeanName = String.format(PATTERN, Server.escape(contextName));
62              objectName = new ObjectName(mbeanName);
63          } catch (final Exception e) {
64              throw new IllegalStateException(e);
65          }
66          StatusLogger.getLogger().registerListener(this);
67      }
68  
69      private static MBeanNotificationInfo createNotificationInfo() {
70          final String[] notifTypes = new String[] {//
71          NOTIF_TYPE_DATA, NOTIF_TYPE_MESSAGE };
72          final String name = Notification.class.getName();
73          final String description = "StatusLogger has logged an event";
74          return new MBeanNotificationInfo(notifTypes, name, description);
75      }
76  
77      @Override
78      public String[] getStatusDataHistory() {
79          final List<StatusData> data = getStatusData();
80          final String[] result = new String[data.size()];
81          for (int i = 0; i < result.length; i++) {
82              result[i] = data.get(i).getFormattedStatus();
83          }
84          return result;
85      }
86  
87      @Override
88      public List<StatusData> getStatusData() {
89          return StatusLogger.getLogger().getStatusData();
90      }
91  
92      @Override
93      public String getLevel() {
94          return this.level.name();
95      }
96  
97      @Override
98      public Level getStatusLevel() {
99          return this.level;
100     }
101 
102     @Override
103     public void setLevel(final String level) {
104         this.level = Level.toLevel(level, Level.ERROR);
105     }
106 
107     @Override
108     public String getContextName() {
109         return contextName;
110     }
111 
112     /*
113      * (non-Javadoc)
114      * 
115      * @see
116      * org.apache.logging.log4j.status.StatusListener#log(org.apache.logging
117      * .log4j.status.StatusData)
118      */
119     @Override
120     public void log(final StatusData data) {
121         final Notification notifMsg = new Notification(NOTIF_TYPE_MESSAGE, getObjectName(), nextSeqNo(), now(),
122                 data.getFormattedStatus());
123         sendNotification(notifMsg);
124 
125         final Notification notifData = new Notification(NOTIF_TYPE_DATA, getObjectName(), nextSeqNo(), now());
126         notifData.setUserData(data);
127         sendNotification(notifData);
128     }
129 
130     /**
131      * Returns the {@code ObjectName} of this mbean.
132      * 
133      * @return the {@code ObjectName}
134      * @see StatusLoggerAdminMBean#PATTERN
135      */
136     @Override
137     public ObjectName getObjectName() {
138         return objectName;
139     }
140 
141     private long nextSeqNo() {
142         return sequenceNo.getAndIncrement();
143     }
144 
145     private long now() {
146         return System.currentTimeMillis();
147     }
148 
149     @Override
150     public void close() throws IOException {
151         // nothing to close here
152     }
153 }