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.util.List;
20  import java.util.concurrent.Executor;
21  import java.util.concurrent.atomic.AtomicLong;
22  import javax.management.MBeanNotificationInfo;
23  import javax.management.Notification;
24  import javax.management.NotificationBroadcasterSupport;
25  import javax.management.ObjectName;
26  
27  import org.apache.logging.log4j.Level;
28  import org.apache.logging.log4j.status.StatusData;
29  import org.apache.logging.log4j.status.StatusListener;
30  import org.apache.logging.log4j.status.StatusLogger;
31  
32  /**
33   * Implementation of the {@code StatusLoggerAdminMBean} interface.
34   */
35  public class StatusLoggerAdmin extends NotificationBroadcasterSupport implements StatusListener, StatusLoggerAdminMBean {
36  
37      private final AtomicLong sequenceNo = new AtomicLong();
38      private final ObjectName objectName;
39      private final String contextName;
40      private Level level = Level.WARN;
41  
42      /**
43       * Constructs a new {@code StatusLoggerAdmin} with the {@code Executor} to
44       * be used for sending {@code Notification}s asynchronously to listeners.
45       * 
46       * @param contextName name of the LoggerContext under which to register this
47       *            StatusLoggerAdmin. Note that the StatusLogger may be
48       *            registered multiple times, once for each LoggerContext. In web
49       *            containers, each web application has its own LoggerContext and
50       *            by associating the StatusLogger with the LoggerContext, all
51       *            associated MBeans can be unloaded when the web application is
52       *            undeployed.
53       * @param executor used to send notifications asynchronously
54       */
55      public StatusLoggerAdmin(final String contextName, final Executor executor) {
56          super(executor, createNotificationInfo());
57          this.contextName = contextName;
58          try {
59              final String mbeanName = String.format(PATTERN, Server.escape(contextName));
60              objectName = new ObjectName(mbeanName);
61          } catch (final Exception e) {
62              throw new IllegalStateException(e);
63          }
64          StatusLogger.getLogger().registerListener(this);
65      }
66  
67      private static MBeanNotificationInfo createNotificationInfo() {
68          final String[] notifTypes = new String[] {//
69          NOTIF_TYPE_DATA, NOTIF_TYPE_MESSAGE };
70          final String name = Notification.class.getName();
71          final String description = "StatusLogger has logged an event";
72          return new MBeanNotificationInfo(notifTypes, name, description);
73      }
74  
75      @Override
76      public String[] getStatusDataHistory() {
77          final List<StatusData> data = getStatusData();
78          final String[] result = new String[data.size()];
79          for (int i = 0; i < result.length; i++) {
80              result[i] = data.get(i).getFormattedStatus();
81          }
82          return result;
83      }
84  
85      @Override
86      public List<StatusData> getStatusData() {
87          return StatusLogger.getLogger().getStatusData();
88      }
89  
90      @Override
91      public String getLevel() {
92          return this.level.name();
93      }
94  
95      @Override
96      public Level getStatusLevel() {
97          return this.level;
98      }
99  
100     @Override
101     public void setLevel(final String level) {
102         this.level = Level.toLevel(level, Level.ERROR);
103     }
104 
105     @Override
106     public String getContextName() {
107         return contextName;
108     }
109 
110     /*
111      * (non-Javadoc)
112      * 
113      * @see
114      * org.apache.logging.log4j.status.StatusListener#log(org.apache.logging
115      * .log4j.status.StatusData)
116      */
117     @Override
118     public void log(final StatusData data) {
119         final Notification notifMsg = new Notification(NOTIF_TYPE_MESSAGE, getObjectName(), nextSeqNo(), now(),
120                 data.getFormattedStatus());
121         sendNotification(notifMsg);
122 
123         final Notification notifData = new Notification(NOTIF_TYPE_DATA, getObjectName(), nextSeqNo(), now());
124         notifData.setUserData(data);
125         sendNotification(notifData);
126     }
127 
128     /**
129      * Returns the {@code ObjectName} of this mbean.
130      * 
131      * @return the {@code ObjectName}
132      * @see StatusLoggerAdminMBean#NAME
133      */
134     @Override
135     public ObjectName getObjectName() {
136         return objectName;
137     }
138 
139     private long nextSeqNo() {
140         return sequenceNo.getAndIncrement();
141     }
142 
143     private long now() {
144         return System.currentTimeMillis();
145     }
146 }