You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@storm.apache.org by bo...@apache.org on 2015/10/05 23:01:07 UTC

[35/37] storm git commit: Merge remote-tracking branch 'apache/master' into storm-820-agg-stats-on-nimbus

Merge remote-tracking branch 'apache/master' into storm-820-agg-stats-on-nimbus


Project: http://git-wip-us.apache.org/repos/asf/storm/repo
Commit: http://git-wip-us.apache.org/repos/asf/storm/commit/2d59aed8
Tree: http://git-wip-us.apache.org/repos/asf/storm/tree/2d59aed8
Diff: http://git-wip-us.apache.org/repos/asf/storm/diff/2d59aed8

Branch: refs/heads/master
Commit: 2d59aed83950c280ad1a6a0aacefcd2fa2017d26
Parents: f641a80 9ac9eb5
Author: Derek Dagit <de...@yahoo-inc.com>
Authored: Mon Oct 5 15:43:38 2015 -0500
Committer: Derek Dagit <de...@yahoo-inc.com>
Committed: Mon Oct 5 15:43:38 2015 -0500

----------------------------------------------------------------------
 CHANGELOG.md                                    |    1 +
 bin/storm.py                                    |   35 +-
 conf/defaults.yaml                              |    3 +
 docs/DYNAMIC_LOG_LEVEL_SETTINGS.md              |   41 +
 docs/images/dynamic_log_level_settings_1.png    |  Bin 0 -> 93689 bytes
 docs/images/dynamic_log_level_settings_2.png    |  Bin 0 -> 78785 bytes
 .../storm/starter/MultipleLoggerTopology.java   |  105 ++
 storm-core/src/clj/backtype/storm/cluster.clj   |   28 +-
 .../backtype/storm/command/set_log_level.clj    |   75 +
 .../src/clj/backtype/storm/daemon/nimbus.clj    |   45 +-
 .../clj/backtype/storm/daemon/supervisor.clj    |    2 +
 .../src/clj/backtype/storm/daemon/worker.clj    |  107 +-
 storm-core/src/clj/backtype/storm/ui/core.clj   |   55 +-
 storm-core/src/jvm/backtype/storm/Config.java   |    7 +
 .../jvm/backtype/storm/generated/LogConfig.java |  475 +++++
 .../jvm/backtype/storm/generated/LogLevel.java  |  836 +++++++++
 .../storm/generated/LogLevelAction.java         |   65 +
 .../jvm/backtype/storm/generated/Nimbus.java    | 1700 +++++++++++++++++-
 .../auth/authorizer/SimpleACLAuthorizer.java    |    4 +-
 storm-core/src/py/storm/Nimbus-remote           |   14 +
 storm-core/src/py/storm/Nimbus.py               |  356 ++++
 storm-core/src/py/storm/ttypes.py               |  213 +++
 storm-core/src/storm.thrift                     |   37 +
 storm-core/src/ui/public/css/style.css          |    8 +
 storm-core/src/ui/public/js/script.js           |   20 +
 .../templates/topology-page-template.html       |   68 +
 storm-core/src/ui/public/topology.html          |  149 +-
 .../test/clj/backtype/storm/nimbus_test.clj     |   56 +-
 .../test/clj/backtype/storm/supervisor_test.clj |    4 +
 .../test/clj/backtype/storm/worker_test.clj     |  179 +-
 30 files changed, 4670 insertions(+), 18 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/storm/blob/2d59aed8/storm-core/src/clj/backtype/storm/daemon/nimbus.clj
----------------------------------------------------------------------
diff --cc storm-core/src/clj/backtype/storm/daemon/nimbus.clj
index 789190c,19870f1..70bd197
--- a/storm-core/src/clj/backtype/storm/daemon/nimbus.clj
+++ b/storm-core/src/clj/backtype/storm/daemon/nimbus.clj
@@@ -36,13 -36,10 +36,13 @@@
              ExecutorInfo InvalidTopologyException Nimbus$Iface Nimbus$Processor SubmitOptions TopologyInitialStatus
              KillOptions RebalanceOptions ClusterSummary SupervisorSummary TopologySummary TopologyInfo
              ExecutorSummary AuthorizationException GetInfoOptions NumErrorsChoice
-             ComponentPageInfo TopologyPageInfo])
 -            LogConfig LogLevel LogLevelAction])
++            ComponentPageInfo TopologyPageInfo LogConfig LogLevel LogLevelAction])
    (:import [backtype.storm.daemon Shutdownable])
    (:use [backtype.storm util config log timer zookeeper])
 -  (:require [backtype.storm [cluster :as cluster] [stats :as stats] [converter :as converter]])
 +  (:require [backtype.storm [cluster :as cluster]
 +                            [converter :as converter]
 +                            [stats :as stats]
 +                            [tuple :as tuple]])
    (:require [clojure.set :as set])
    (:import [backtype.storm.daemon.common StormBase Assignment])
    (:use [backtype.storm.daemon common])

http://git-wip-us.apache.org/repos/asf/storm/blob/2d59aed8/storm-core/src/clj/backtype/storm/ui/core.clj
----------------------------------------------------------------------
diff --cc storm-core/src/clj/backtype/storm/ui/core.clj
index 49a94b4,4cd9046..5fa487f
--- a/storm-core/src/clj/backtype/storm/ui/core.clj
+++ b/storm-core/src/clj/backtype/storm/ui/core.clj
@@@ -32,10 -32,8 +32,11 @@@
              ExecutorStats ExecutorSummary ExecutorInfo TopologyInfo SpoutStats BoltStats
              ErrorInfo ClusterSummary SupervisorSummary TopologySummary
              Nimbus$Client StormTopology GlobalStreamId RebalanceOptions
 -            KillOptions GetInfoOptions NumErrorsChoice DebugOptions
 +            KillOptions GetInfoOptions NumErrorsChoice DebugOptions TopologyPageInfo
 +            TopologyStats CommonAggregateStats ComponentAggregateStats
 +            ComponentType BoltAggregateStats SpoutAggregateStats
-             ExecutorAggregateStats SpecificAggregateStats ComponentPageInfo])
++            ExecutorAggregateStats SpecificAggregateStats ComponentPageInfo
+             LogConfig LogLevel LogLevelAction])
    (:import [backtype.storm.security.auth AuthUtils ReqContext])
    (:import [backtype.storm.generated AuthorizationException])
    (:import [backtype.storm.security.auth AuthUtils])
@@@ -723,49 -972,58 +725,69 @@@
  (defn component-page
    [topology-id component window include-sys? user secure?]
    (thrift/with-configured-nimbus-connection nimbus
 -    (let [window (if window window ":all-time")
 -          summ (.getTopologyInfo ^Nimbus$Client nimbus topology-id)
 -          topology (.getTopology ^Nimbus$Client nimbus topology-id)
 -          topology-conf (from-json (.getTopologyConf ^Nimbus$Client nimbus topology-id))
 -          type (component-type topology component)
 -          summs (component-task-summs summ topology component)
 -          spec (cond (= type :spout) (spout-stats window summ component summs include-sys? secure?)
 -                     (= type :bolt) (bolt-stats window summ component summs include-sys? secure?))
 -          errors (component-errors (get (.get_errors summ) component) topology-id secure?)
 -          component->debug (.get_component_debug summ)
 -          debug-options (get component->debug component (get component->debug topology-id))]
 -      (merge
 -        {"user" user
 -         "id" component
 -         "encodedId" (url-encode component)
 -         "name" (.get_name summ)
 -         "executors" (count summs)
 -         "tasks" (sum-tasks summs)
 -         "topologyId" topology-id
 -         "topologyStatus" (.get_status summ)
 -         "encodedTopologyId" (url-encode topology-id)
 -         "window" window
 -         "componentType" (name type)
 -         "windowHint" (window-hint window)
 -         "debug" (if (not-nil? debug-options) (.is_enable debug-options) false)
 -         "samplingPct" (if (not-nil? debug-options) (.get_samplingpct debug-options) 10)
 -         "eventLogLink" (event-log-link topology-id summ topology component secure?)}
 -       spec errors))))
 +    (let [window (or window ":all-time")
 +          window-hint (window-hint window)
 +          comp-page-info (.getComponentPageInfo ^Nimbus$Client nimbus
 +                                                topology-id
 +                                                component
 +                                                window
 +                                                include-sys?)
 +          topology-conf (from-json (.getTopologyConf ^Nimbus$Client nimbus
 +                                                     topology-id))
 +          msg-timeout (topology-conf TOPOLOGY-MESSAGE-TIMEOUT-SECS)
 +          [debugEnabled
 +           samplingPct] (if-let [debug-opts (.get_debug_options comp-page-info)]
 +                          [(.is_enable debug-opts)
 +                           (.get_samplingpct debug-opts)])]
 +      (assoc
 +       (unpack-component-page-info comp-page-info
 +                                   topology-id
 +                                   window
 +                                   include-sys?
 +                                   secure?)
 +       "user" user
 +       "id" component
 +       "encodedId" (url-encode component)
 +       "name" (.get_topology_name comp-page-info)
 +       "executors" (.get_num_executors comp-page-info)
 +       "tasks" (.get_num_tasks comp-page-info)
 +       "topologyId" topology-id
 +       "topologyStatus" (.get_topology_status comp-page-info)
 +       "encodedTopologyId" (url-encode topology-id)
 +       "window" window
 +       "componentType" (-> comp-page-info .get_component_type str lower-case)
 +       "windowHint" window-hint
 +       "debug" (or debugEnabled false)
 +       "samplingPct" (or samplingPct 10)
 +       "eventLogLink" (event-log-link topology-id
 +                                      component
 +                                      (.get_eventlog_host comp-page-info)
 +                                      (.get_eventlog_port comp-page-info)
 +                                      secure?)))))
  
+ (defn- level-to-dict [level]
+   (if level
+     (let [timeout (.get_reset_log_level_timeout_secs level)
+           timeout-epoch (.get_reset_log_level_timeout_epoch level)
+           target-level (.get_target_log_level level)
+           reset-level (.get_reset_log_level level)]
+           {"target_level" (.toString (Level/toLevel target-level))
+            "reset_level" (.toString (Level/toLevel reset-level))
+            "timeout" timeout
+            "timeout_epoch" timeout-epoch})))
+ 
+ (defn log-config [topology-id]
+   (thrift/with-configured-nimbus-connection
+     nimbus
+     (let [log-config (.getLogConfig ^Nimbus$Client nimbus topology-id)
+           named-logger-levels (into {}
+                                 (for [[key val] (.get_named_logger_level log-config)]
+                                   [(str key) (level-to-dict val)]))]
+       {"namedLoggerLevels" named-logger-levels})))
+ 
  (defn topology-config [topology-id]
    (thrift/with-configured-nimbus-connection nimbus
 -     (from-json (.getTopologyConf ^Nimbus$Client nimbus topology-id))))
 +    (from-json (.getTopologyConf ^Nimbus$Client nimbus topology-id))))
  
  (defn topology-op-response [topology-id op]
    {"topologyOperation" op,

http://git-wip-us.apache.org/repos/asf/storm/blob/2d59aed8/storm-core/src/jvm/backtype/storm/generated/LogConfig.java
----------------------------------------------------------------------
diff --cc storm-core/src/jvm/backtype/storm/generated/LogConfig.java
index 0000000,318ed86..1420db4
mode 000000,100644..100644
--- a/storm-core/src/jvm/backtype/storm/generated/LogConfig.java
+++ b/storm-core/src/jvm/backtype/storm/generated/LogConfig.java
@@@ -1,0 -1,475 +1,475 @@@
+ /**
+  * Licensed to the Apache Software Foundation (ASF) under one
+  * or more contributor license agreements.  See the NOTICE file
+  * distributed with this work for additional information
+  * regarding copyright ownership.  The ASF licenses this file
+  * to you under the Apache License, Version 2.0 (the
+  * "License"); you may not use this file except in compliance
+  * with the License.  You may obtain a copy of the License at
+  *
+  * http://www.apache.org/licenses/LICENSE-2.0
+  *
+  * Unless required by applicable law or agreed to in writing, software
+  * distributed under the License is distributed on an "AS IS" BASIS,
+  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  * See the License for the specific language governing permissions and
+  * limitations under the License.
+  */
+ /**
+  * Autogenerated by Thrift Compiler (0.9.2)
+  *
+  * DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING
+  *  @generated
+  */
+ package backtype.storm.generated;
+ 
+ import org.apache.thrift.scheme.IScheme;
+ import org.apache.thrift.scheme.SchemeFactory;
+ import org.apache.thrift.scheme.StandardScheme;
+ 
+ import org.apache.thrift.scheme.TupleScheme;
+ import org.apache.thrift.protocol.TTupleProtocol;
+ import org.apache.thrift.protocol.TProtocolException;
+ import org.apache.thrift.EncodingUtils;
+ import org.apache.thrift.TException;
+ import org.apache.thrift.async.AsyncMethodCallback;
+ import org.apache.thrift.server.AbstractNonblockingServer.*;
+ import java.util.List;
+ import java.util.ArrayList;
+ import java.util.Map;
+ import java.util.HashMap;
+ import java.util.EnumMap;
+ import java.util.Set;
+ import java.util.HashSet;
+ import java.util.EnumSet;
+ import java.util.Collections;
+ import java.util.BitSet;
+ import java.nio.ByteBuffer;
+ import java.util.Arrays;
+ import javax.annotation.Generated;
+ import org.slf4j.Logger;
+ import org.slf4j.LoggerFactory;
+ 
+ @SuppressWarnings({"cast", "rawtypes", "serial", "unchecked"})
 -@Generated(value = "Autogenerated by Thrift Compiler (0.9.2)", date = "2015-9-24")
++@Generated(value = "Autogenerated by Thrift Compiler (0.9.2)", date = "2015-10-5")
+ public class LogConfig implements org.apache.thrift.TBase<LogConfig, LogConfig._Fields>, java.io.Serializable, Cloneable, Comparable<LogConfig> {
+   private static final org.apache.thrift.protocol.TStruct STRUCT_DESC = new org.apache.thrift.protocol.TStruct("LogConfig");
+ 
+   private static final org.apache.thrift.protocol.TField NAMED_LOGGER_LEVEL_FIELD_DESC = new org.apache.thrift.protocol.TField("named_logger_level", org.apache.thrift.protocol.TType.MAP, (short)2);
+ 
+   private static final Map<Class<? extends IScheme>, SchemeFactory> schemes = new HashMap<Class<? extends IScheme>, SchemeFactory>();
+   static {
+     schemes.put(StandardScheme.class, new LogConfigStandardSchemeFactory());
+     schemes.put(TupleScheme.class, new LogConfigTupleSchemeFactory());
+   }
+ 
+   private Map<String,LogLevel> named_logger_level; // optional
+ 
+   /** The set of fields this struct contains, along with convenience methods for finding and manipulating them. */
+   public enum _Fields implements org.apache.thrift.TFieldIdEnum {
+     NAMED_LOGGER_LEVEL((short)2, "named_logger_level");
+ 
+     private static final Map<String, _Fields> byName = new HashMap<String, _Fields>();
+ 
+     static {
+       for (_Fields field : EnumSet.allOf(_Fields.class)) {
+         byName.put(field.getFieldName(), field);
+       }
+     }
+ 
+     /**
+      * Find the _Fields constant that matches fieldId, or null if its not found.
+      */
+     public static _Fields findByThriftId(int fieldId) {
+       switch(fieldId) {
+         case 2: // NAMED_LOGGER_LEVEL
+           return NAMED_LOGGER_LEVEL;
+         default:
+           return null;
+       }
+     }
+ 
+     /**
+      * Find the _Fields constant that matches fieldId, throwing an exception
+      * if it is not found.
+      */
+     public static _Fields findByThriftIdOrThrow(int fieldId) {
+       _Fields fields = findByThriftId(fieldId);
+       if (fields == null) throw new IllegalArgumentException("Field " + fieldId + " doesn't exist!");
+       return fields;
+     }
+ 
+     /**
+      * Find the _Fields constant that matches name, or null if its not found.
+      */
+     public static _Fields findByName(String name) {
+       return byName.get(name);
+     }
+ 
+     private final short _thriftId;
+     private final String _fieldName;
+ 
+     _Fields(short thriftId, String fieldName) {
+       _thriftId = thriftId;
+       _fieldName = fieldName;
+     }
+ 
+     public short getThriftFieldId() {
+       return _thriftId;
+     }
+ 
+     public String getFieldName() {
+       return _fieldName;
+     }
+   }
+ 
+   // isset id assignments
+   private static final _Fields optionals[] = {_Fields.NAMED_LOGGER_LEVEL};
+   public static final Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> metaDataMap;
+   static {
+     Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> tmpMap = new EnumMap<_Fields, org.apache.thrift.meta_data.FieldMetaData>(_Fields.class);
+     tmpMap.put(_Fields.NAMED_LOGGER_LEVEL, new org.apache.thrift.meta_data.FieldMetaData("named_logger_level", org.apache.thrift.TFieldRequirementType.OPTIONAL, 
+         new org.apache.thrift.meta_data.MapMetaData(org.apache.thrift.protocol.TType.MAP, 
+             new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRING), 
+             new org.apache.thrift.meta_data.StructMetaData(org.apache.thrift.protocol.TType.STRUCT, LogLevel.class))));
+     metaDataMap = Collections.unmodifiableMap(tmpMap);
+     org.apache.thrift.meta_data.FieldMetaData.addStructMetaDataMap(LogConfig.class, metaDataMap);
+   }
+ 
+   public LogConfig() {
+   }
+ 
+   /**
+    * Performs a deep copy on <i>other</i>.
+    */
+   public LogConfig(LogConfig other) {
+     if (other.is_set_named_logger_level()) {
+       Map<String,LogLevel> __this__named_logger_level = new HashMap<String,LogLevel>(other.named_logger_level.size());
+       for (Map.Entry<String, LogLevel> other_element : other.named_logger_level.entrySet()) {
+ 
+         String other_element_key = other_element.getKey();
+         LogLevel other_element_value = other_element.getValue();
+ 
+         String __this__named_logger_level_copy_key = other_element_key;
+ 
+         LogLevel __this__named_logger_level_copy_value = new LogLevel(other_element_value);
+ 
+         __this__named_logger_level.put(__this__named_logger_level_copy_key, __this__named_logger_level_copy_value);
+       }
+       this.named_logger_level = __this__named_logger_level;
+     }
+   }
+ 
+   public LogConfig deepCopy() {
+     return new LogConfig(this);
+   }
+ 
+   @Override
+   public void clear() {
+     this.named_logger_level = null;
+   }
+ 
+   public int get_named_logger_level_size() {
+     return (this.named_logger_level == null) ? 0 : this.named_logger_level.size();
+   }
+ 
+   public void put_to_named_logger_level(String key, LogLevel val) {
+     if (this.named_logger_level == null) {
+       this.named_logger_level = new HashMap<String,LogLevel>();
+     }
+     this.named_logger_level.put(key, val);
+   }
+ 
+   public Map<String,LogLevel> get_named_logger_level() {
+     return this.named_logger_level;
+   }
+ 
+   public void set_named_logger_level(Map<String,LogLevel> named_logger_level) {
+     this.named_logger_level = named_logger_level;
+   }
+ 
+   public void unset_named_logger_level() {
+     this.named_logger_level = null;
+   }
+ 
+   /** Returns true if field named_logger_level is set (has been assigned a value) and false otherwise */
+   public boolean is_set_named_logger_level() {
+     return this.named_logger_level != null;
+   }
+ 
+   public void set_named_logger_level_isSet(boolean value) {
+     if (!value) {
+       this.named_logger_level = null;
+     }
+   }
+ 
+   public void setFieldValue(_Fields field, Object value) {
+     switch (field) {
+     case NAMED_LOGGER_LEVEL:
+       if (value == null) {
+         unset_named_logger_level();
+       } else {
+         set_named_logger_level((Map<String,LogLevel>)value);
+       }
+       break;
+ 
+     }
+   }
+ 
+   public Object getFieldValue(_Fields field) {
+     switch (field) {
+     case NAMED_LOGGER_LEVEL:
+       return get_named_logger_level();
+ 
+     }
+     throw new IllegalStateException();
+   }
+ 
+   /** Returns true if field corresponding to fieldID is set (has been assigned a value) and false otherwise */
+   public boolean isSet(_Fields field) {
+     if (field == null) {
+       throw new IllegalArgumentException();
+     }
+ 
+     switch (field) {
+     case NAMED_LOGGER_LEVEL:
+       return is_set_named_logger_level();
+     }
+     throw new IllegalStateException();
+   }
+ 
+   @Override
+   public boolean equals(Object that) {
+     if (that == null)
+       return false;
+     if (that instanceof LogConfig)
+       return this.equals((LogConfig)that);
+     return false;
+   }
+ 
+   public boolean equals(LogConfig that) {
+     if (that == null)
+       return false;
+ 
+     boolean this_present_named_logger_level = true && this.is_set_named_logger_level();
+     boolean that_present_named_logger_level = true && that.is_set_named_logger_level();
+     if (this_present_named_logger_level || that_present_named_logger_level) {
+       if (!(this_present_named_logger_level && that_present_named_logger_level))
+         return false;
+       if (!this.named_logger_level.equals(that.named_logger_level))
+         return false;
+     }
+ 
+     return true;
+   }
+ 
+   @Override
+   public int hashCode() {
+     List<Object> list = new ArrayList<Object>();
+ 
+     boolean present_named_logger_level = true && (is_set_named_logger_level());
+     list.add(present_named_logger_level);
+     if (present_named_logger_level)
+       list.add(named_logger_level);
+ 
+     return list.hashCode();
+   }
+ 
+   @Override
+   public int compareTo(LogConfig other) {
+     if (!getClass().equals(other.getClass())) {
+       return getClass().getName().compareTo(other.getClass().getName());
+     }
+ 
+     int lastComparison = 0;
+ 
+     lastComparison = Boolean.valueOf(is_set_named_logger_level()).compareTo(other.is_set_named_logger_level());
+     if (lastComparison != 0) {
+       return lastComparison;
+     }
+     if (is_set_named_logger_level()) {
+       lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.named_logger_level, other.named_logger_level);
+       if (lastComparison != 0) {
+         return lastComparison;
+       }
+     }
+     return 0;
+   }
+ 
+   public _Fields fieldForId(int fieldId) {
+     return _Fields.findByThriftId(fieldId);
+   }
+ 
+   public void read(org.apache.thrift.protocol.TProtocol iprot) throws org.apache.thrift.TException {
+     schemes.get(iprot.getScheme()).getScheme().read(iprot, this);
+   }
+ 
+   public void write(org.apache.thrift.protocol.TProtocol oprot) throws org.apache.thrift.TException {
+     schemes.get(oprot.getScheme()).getScheme().write(oprot, this);
+   }
+ 
+   @Override
+   public String toString() {
+     StringBuilder sb = new StringBuilder("LogConfig(");
+     boolean first = true;
+ 
+     if (is_set_named_logger_level()) {
+       sb.append("named_logger_level:");
+       if (this.named_logger_level == null) {
+         sb.append("null");
+       } else {
+         sb.append(this.named_logger_level);
+       }
+       first = false;
+     }
+     sb.append(")");
+     return sb.toString();
+   }
+ 
+   public void validate() throws org.apache.thrift.TException {
+     // check for required fields
+     // check for sub-struct validity
+   }
+ 
+   private void writeObject(java.io.ObjectOutputStream out) throws java.io.IOException {
+     try {
+       write(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(out)));
+     } catch (org.apache.thrift.TException te) {
+       throw new java.io.IOException(te);
+     }
+   }
+ 
+   private void readObject(java.io.ObjectInputStream in) throws java.io.IOException, ClassNotFoundException {
+     try {
+       read(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(in)));
+     } catch (org.apache.thrift.TException te) {
+       throw new java.io.IOException(te);
+     }
+   }
+ 
+   private static class LogConfigStandardSchemeFactory implements SchemeFactory {
+     public LogConfigStandardScheme getScheme() {
+       return new LogConfigStandardScheme();
+     }
+   }
+ 
+   private static class LogConfigStandardScheme extends StandardScheme<LogConfig> {
+ 
+     public void read(org.apache.thrift.protocol.TProtocol iprot, LogConfig struct) throws org.apache.thrift.TException {
+       org.apache.thrift.protocol.TField schemeField;
+       iprot.readStructBegin();
+       while (true)
+       {
+         schemeField = iprot.readFieldBegin();
+         if (schemeField.type == org.apache.thrift.protocol.TType.STOP) { 
+           break;
+         }
+         switch (schemeField.id) {
+           case 2: // NAMED_LOGGER_LEVEL
+             if (schemeField.type == org.apache.thrift.protocol.TType.MAP) {
+               {
 -                org.apache.thrift.protocol.TMap _map510 = iprot.readMapBegin();
 -                struct.named_logger_level = new HashMap<String,LogLevel>(2*_map510.size);
 -                String _key511;
 -                LogLevel _val512;
 -                for (int _i513 = 0; _i513 < _map510.size; ++_i513)
++                org.apache.thrift.protocol.TMap _map626 = iprot.readMapBegin();
++                struct.named_logger_level = new HashMap<String,LogLevel>(2*_map626.size);
++                String _key627;
++                LogLevel _val628;
++                for (int _i629 = 0; _i629 < _map626.size; ++_i629)
+                 {
 -                  _key511 = iprot.readString();
 -                  _val512 = new LogLevel();
 -                  _val512.read(iprot);
 -                  struct.named_logger_level.put(_key511, _val512);
++                  _key627 = iprot.readString();
++                  _val628 = new LogLevel();
++                  _val628.read(iprot);
++                  struct.named_logger_level.put(_key627, _val628);
+                 }
+                 iprot.readMapEnd();
+               }
+               struct.set_named_logger_level_isSet(true);
+             } else { 
+               org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
+             }
+             break;
+           default:
+             org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
+         }
+         iprot.readFieldEnd();
+       }
+       iprot.readStructEnd();
+       struct.validate();
+     }
+ 
+     public void write(org.apache.thrift.protocol.TProtocol oprot, LogConfig struct) throws org.apache.thrift.TException {
+       struct.validate();
+ 
+       oprot.writeStructBegin(STRUCT_DESC);
+       if (struct.named_logger_level != null) {
+         if (struct.is_set_named_logger_level()) {
+           oprot.writeFieldBegin(NAMED_LOGGER_LEVEL_FIELD_DESC);
+           {
+             oprot.writeMapBegin(new org.apache.thrift.protocol.TMap(org.apache.thrift.protocol.TType.STRING, org.apache.thrift.protocol.TType.STRUCT, struct.named_logger_level.size()));
 -            for (Map.Entry<String, LogLevel> _iter514 : struct.named_logger_level.entrySet())
++            for (Map.Entry<String, LogLevel> _iter630 : struct.named_logger_level.entrySet())
+             {
 -              oprot.writeString(_iter514.getKey());
 -              _iter514.getValue().write(oprot);
++              oprot.writeString(_iter630.getKey());
++              _iter630.getValue().write(oprot);
+             }
+             oprot.writeMapEnd();
+           }
+           oprot.writeFieldEnd();
+         }
+       }
+       oprot.writeFieldStop();
+       oprot.writeStructEnd();
+     }
+ 
+   }
+ 
+   private static class LogConfigTupleSchemeFactory implements SchemeFactory {
+     public LogConfigTupleScheme getScheme() {
+       return new LogConfigTupleScheme();
+     }
+   }
+ 
+   private static class LogConfigTupleScheme extends TupleScheme<LogConfig> {
+ 
+     @Override
+     public void write(org.apache.thrift.protocol.TProtocol prot, LogConfig struct) throws org.apache.thrift.TException {
+       TTupleProtocol oprot = (TTupleProtocol) prot;
+       BitSet optionals = new BitSet();
+       if (struct.is_set_named_logger_level()) {
+         optionals.set(0);
+       }
+       oprot.writeBitSet(optionals, 1);
+       if (struct.is_set_named_logger_level()) {
+         {
+           oprot.writeI32(struct.named_logger_level.size());
 -          for (Map.Entry<String, LogLevel> _iter515 : struct.named_logger_level.entrySet())
++          for (Map.Entry<String, LogLevel> _iter631 : struct.named_logger_level.entrySet())
+           {
 -            oprot.writeString(_iter515.getKey());
 -            _iter515.getValue().write(oprot);
++            oprot.writeString(_iter631.getKey());
++            _iter631.getValue().write(oprot);
+           }
+         }
+       }
+     }
+ 
+     @Override
+     public void read(org.apache.thrift.protocol.TProtocol prot, LogConfig struct) throws org.apache.thrift.TException {
+       TTupleProtocol iprot = (TTupleProtocol) prot;
+       BitSet incoming = iprot.readBitSet(1);
+       if (incoming.get(0)) {
+         {
 -          org.apache.thrift.protocol.TMap _map516 = new org.apache.thrift.protocol.TMap(org.apache.thrift.protocol.TType.STRING, org.apache.thrift.protocol.TType.STRUCT, iprot.readI32());
 -          struct.named_logger_level = new HashMap<String,LogLevel>(2*_map516.size);
 -          String _key517;
 -          LogLevel _val518;
 -          for (int _i519 = 0; _i519 < _map516.size; ++_i519)
++          org.apache.thrift.protocol.TMap _map632 = new org.apache.thrift.protocol.TMap(org.apache.thrift.protocol.TType.STRING, org.apache.thrift.protocol.TType.STRUCT, iprot.readI32());
++          struct.named_logger_level = new HashMap<String,LogLevel>(2*_map632.size);
++          String _key633;
++          LogLevel _val634;
++          for (int _i635 = 0; _i635 < _map632.size; ++_i635)
+           {
 -            _key517 = iprot.readString();
 -            _val518 = new LogLevel();
 -            _val518.read(iprot);
 -            struct.named_logger_level.put(_key517, _val518);
++            _key633 = iprot.readString();
++            _val634 = new LogLevel();
++            _val634.read(iprot);
++            struct.named_logger_level.put(_key633, _val634);
+           }
+         }
+         struct.set_named_logger_level_isSet(true);
+       }
+     }
+   }
+ 
+ }
+ 

http://git-wip-us.apache.org/repos/asf/storm/blob/2d59aed8/storm-core/src/jvm/backtype/storm/generated/Nimbus.java
----------------------------------------------------------------------
diff --cc storm-core/src/jvm/backtype/storm/generated/Nimbus.java
index e54491c,1d0114e..4632059
--- a/storm-core/src/jvm/backtype/storm/generated/Nimbus.java
+++ b/storm-core/src/jvm/backtype/storm/generated/Nimbus.java
@@@ -51,7 -51,7 +51,7 @@@ import org.slf4j.Logger
  import org.slf4j.LoggerFactory;
  
  @SuppressWarnings({"cast", "rawtypes", "serial", "unchecked"})
- @Generated(value = "Autogenerated by Thrift Compiler (0.9.2)", date = "2015-9-28")
 -@Generated(value = "Autogenerated by Thrift Compiler (0.9.2)", date = "2015-9-24")
++@Generated(value = "Autogenerated by Thrift Compiler (0.9.2)", date = "2015-10-5")
  public class Nimbus {
  
    public interface Iface {

http://git-wip-us.apache.org/repos/asf/storm/blob/2d59aed8/storm-core/src/jvm/backtype/storm/security/auth/authorizer/SimpleACLAuthorizer.java
----------------------------------------------------------------------
diff --cc storm-core/src/jvm/backtype/storm/security/auth/authorizer/SimpleACLAuthorizer.java
index c76d9a5,e332a13..c77d201
--- a/storm-core/src/jvm/backtype/storm/security/auth/authorizer/SimpleACLAuthorizer.java
+++ b/storm-core/src/jvm/backtype/storm/security/auth/authorizer/SimpleACLAuthorizer.java
@@@ -44,18 -44,7 +44,20 @@@ public class SimpleACLAuthorizer implem
  
      protected Set<String> _userCommands = new HashSet<String>(Arrays.asList("submitTopology", "fileUpload", "getNimbusConf", "getClusterInfo"));
      protected Set<String> _supervisorCommands = new HashSet<String>(Arrays.asList("fileDownload"));
 -    protected Set<String> _topoCommands = new HashSet<String>(Arrays.asList("killTopology","rebalance","activate","deactivate","getTopologyConf","getTopology","getUserTopology","getTopologyInfo","uploadNewCredentials","setLogConfig","getLogConfig"));
 +    protected Set<String> _topoCommands = new HashSet<String>(Arrays.asList(
 +            "killTopology",
 +            "rebalance",
 +            "activate",
 +            "deactivate",
 +            "getTopologyConf",
 +            "getTopology",
 +            "getUserTopology",
 +            "getTopologyInfo",
 +            "getTopologyPageInfo",
 +            "getComponentPageInfo",
-             "uploadNewCredentials"));
++            "uploadNewCredentials",
++            "setLogConfig",
++            "getLogConfig"));
  
      protected Set<String> _admins;
      protected Set<String> _supervisors;

http://git-wip-us.apache.org/repos/asf/storm/blob/2d59aed8/storm-core/src/py/storm/Nimbus-remote
----------------------------------------------------------------------

http://git-wip-us.apache.org/repos/asf/storm/blob/2d59aed8/storm-core/src/py/storm/Nimbus.py
----------------------------------------------------------------------

http://git-wip-us.apache.org/repos/asf/storm/blob/2d59aed8/storm-core/src/py/storm/ttypes.py
----------------------------------------------------------------------
diff --cc storm-core/src/py/storm/ttypes.py
index 0bde213,1881858..d365566
--- a/storm-core/src/py/storm/ttypes.py
+++ b/storm-core/src/py/storm/ttypes.py
@@@ -7672,6 -6365,202 +7689,202 @@@ class GetInfoOptions
    def __ne__(self, other):
      return not (self == other)
  
+ class LogLevel:
+   """
+   Attributes:
+    - action
+    - target_log_level
+    - reset_log_level_timeout_secs
+    - reset_log_level_timeout_epoch
+    - reset_log_level
+   """
+ 
+   thrift_spec = (
+     None, # 0
+     (1, TType.I32, 'action', None, None, ), # 1
+     (2, TType.STRING, 'target_log_level', None, None, ), # 2
+     (3, TType.I32, 'reset_log_level_timeout_secs', None, None, ), # 3
+     (4, TType.I64, 'reset_log_level_timeout_epoch', None, None, ), # 4
+     (5, TType.STRING, 'reset_log_level', None, None, ), # 5
+   )
+ 
+   def __init__(self, action=None, target_log_level=None, reset_log_level_timeout_secs=None, reset_log_level_timeout_epoch=None, reset_log_level=None,):
+     self.action = action
+     self.target_log_level = target_log_level
+     self.reset_log_level_timeout_secs = reset_log_level_timeout_secs
+     self.reset_log_level_timeout_epoch = reset_log_level_timeout_epoch
+     self.reset_log_level = reset_log_level
+ 
+   def read(self, iprot):
+     if iprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None and fastbinary is not None:
+       fastbinary.decode_binary(self, iprot.trans, (self.__class__, self.thrift_spec))
+       return
+     iprot.readStructBegin()
+     while True:
+       (fname, ftype, fid) = iprot.readFieldBegin()
+       if ftype == TType.STOP:
+         break
+       if fid == 1:
+         if ftype == TType.I32:
+           self.action = iprot.readI32();
+         else:
+           iprot.skip(ftype)
+       elif fid == 2:
+         if ftype == TType.STRING:
+           self.target_log_level = iprot.readString().decode('utf-8')
+         else:
+           iprot.skip(ftype)
+       elif fid == 3:
+         if ftype == TType.I32:
+           self.reset_log_level_timeout_secs = iprot.readI32();
+         else:
+           iprot.skip(ftype)
+       elif fid == 4:
+         if ftype == TType.I64:
+           self.reset_log_level_timeout_epoch = iprot.readI64();
+         else:
+           iprot.skip(ftype)
+       elif fid == 5:
+         if ftype == TType.STRING:
+           self.reset_log_level = iprot.readString().decode('utf-8')
+         else:
+           iprot.skip(ftype)
+       else:
+         iprot.skip(ftype)
+       iprot.readFieldEnd()
+     iprot.readStructEnd()
+ 
+   def write(self, oprot):
+     if oprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and self.thrift_spec is not None and fastbinary is not None:
+       oprot.trans.write(fastbinary.encode_binary(self, (self.__class__, self.thrift_spec)))
+       return
+     oprot.writeStructBegin('LogLevel')
+     if self.action is not None:
+       oprot.writeFieldBegin('action', TType.I32, 1)
+       oprot.writeI32(self.action)
+       oprot.writeFieldEnd()
+     if self.target_log_level is not None:
+       oprot.writeFieldBegin('target_log_level', TType.STRING, 2)
+       oprot.writeString(self.target_log_level.encode('utf-8'))
+       oprot.writeFieldEnd()
+     if self.reset_log_level_timeout_secs is not None:
+       oprot.writeFieldBegin('reset_log_level_timeout_secs', TType.I32, 3)
+       oprot.writeI32(self.reset_log_level_timeout_secs)
+       oprot.writeFieldEnd()
+     if self.reset_log_level_timeout_epoch is not None:
+       oprot.writeFieldBegin('reset_log_level_timeout_epoch', TType.I64, 4)
+       oprot.writeI64(self.reset_log_level_timeout_epoch)
+       oprot.writeFieldEnd()
+     if self.reset_log_level is not None:
+       oprot.writeFieldBegin('reset_log_level', TType.STRING, 5)
+       oprot.writeString(self.reset_log_level.encode('utf-8'))
+       oprot.writeFieldEnd()
+     oprot.writeFieldStop()
+     oprot.writeStructEnd()
+ 
+   def validate(self):
+     if self.action is None:
+       raise TProtocol.TProtocolException(message='Required field action is unset!')
+     return
+ 
+ 
+   def __hash__(self):
+     value = 17
+     value = (value * 31) ^ hash(self.action)
+     value = (value * 31) ^ hash(self.target_log_level)
+     value = (value * 31) ^ hash(self.reset_log_level_timeout_secs)
+     value = (value * 31) ^ hash(self.reset_log_level_timeout_epoch)
+     value = (value * 31) ^ hash(self.reset_log_level)
+     return value
+ 
+   def __repr__(self):
+     L = ['%s=%r' % (key, value)
+       for key, value in self.__dict__.iteritems()]
+     return '%s(%s)' % (self.__class__.__name__, ', '.join(L))
+ 
+   def __eq__(self, other):
+     return isinstance(other, self.__class__) and self.__dict__ == other.__dict__
+ 
+   def __ne__(self, other):
+     return not (self == other)
+ 
+ class LogConfig:
+   """
+   Attributes:
+    - named_logger_level
+   """
+ 
+   thrift_spec = (
+     None, # 0
+     None, # 1
+     (2, TType.MAP, 'named_logger_level', (TType.STRING,None,TType.STRUCT,(LogLevel, LogLevel.thrift_spec)), None, ), # 2
+   )
+ 
+   def __init__(self, named_logger_level=None,):
+     self.named_logger_level = named_logger_level
+ 
+   def read(self, iprot):
+     if iprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None and fastbinary is not None:
+       fastbinary.decode_binary(self, iprot.trans, (self.__class__, self.thrift_spec))
+       return
+     iprot.readStructBegin()
+     while True:
+       (fname, ftype, fid) = iprot.readFieldBegin()
+       if ftype == TType.STOP:
+         break
+       if fid == 2:
+         if ftype == TType.MAP:
+           self.named_logger_level = {}
 -          (_ktype457, _vtype458, _size456 ) = iprot.readMapBegin()
 -          for _i460 in xrange(_size456):
 -            _key461 = iprot.readString().decode('utf-8')
 -            _val462 = LogLevel()
 -            _val462.read(iprot)
 -            self.named_logger_level[_key461] = _val462
++          (_ktype561, _vtype562, _size560 ) = iprot.readMapBegin()
++          for _i564 in xrange(_size560):
++            _key565 = iprot.readString().decode('utf-8')
++            _val566 = LogLevel()
++            _val566.read(iprot)
++            self.named_logger_level[_key565] = _val566
+           iprot.readMapEnd()
+         else:
+           iprot.skip(ftype)
+       else:
+         iprot.skip(ftype)
+       iprot.readFieldEnd()
+     iprot.readStructEnd()
+ 
+   def write(self, oprot):
+     if oprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and self.thrift_spec is not None and fastbinary is not None:
+       oprot.trans.write(fastbinary.encode_binary(self, (self.__class__, self.thrift_spec)))
+       return
+     oprot.writeStructBegin('LogConfig')
+     if self.named_logger_level is not None:
+       oprot.writeFieldBegin('named_logger_level', TType.MAP, 2)
+       oprot.writeMapBegin(TType.STRING, TType.STRUCT, len(self.named_logger_level))
 -      for kiter463,viter464 in self.named_logger_level.items():
 -        oprot.writeString(kiter463.encode('utf-8'))
 -        viter464.write(oprot)
++      for kiter567,viter568 in self.named_logger_level.items():
++        oprot.writeString(kiter567.encode('utf-8'))
++        viter568.write(oprot)
+       oprot.writeMapEnd()
+       oprot.writeFieldEnd()
+     oprot.writeFieldStop()
+     oprot.writeStructEnd()
+ 
+   def validate(self):
+     return
+ 
+ 
+   def __hash__(self):
+     value = 17
+     value = (value * 31) ^ hash(self.named_logger_level)
+     return value
+ 
+   def __repr__(self):
+     L = ['%s=%r' % (key, value)
+       for key, value in self.__dict__.iteritems()]
+     return '%s(%s)' % (self.__class__.__name__, ', '.join(L))
+ 
+   def __eq__(self, other):
+     return isinstance(other, self.__class__) and self.__dict__ == other.__dict__
+ 
+   def __ne__(self, other):
+     return not (self == other)
+ 
  class DRPCRequest:
    """
    Attributes:

http://git-wip-us.apache.org/repos/asf/storm/blob/2d59aed8/storm-core/src/storm.thrift
----------------------------------------------------------------------

http://git-wip-us.apache.org/repos/asf/storm/blob/2d59aed8/storm-core/src/ui/public/templates/topology-page-template.html
----------------------------------------------------------------------
diff --cc storm-core/src/ui/public/templates/topology-page-template.html
index 0d8fbb7,f0cc822..817a7ab
--- a/storm-core/src/ui/public/templates/topology-page-template.html
+++ b/storm-core/src/ui/public/templates/topology-page-template.html
@@@ -366,5 -362,73 +366,73 @@@
      <input {{killStatus}} onclick="confirmAction('{{encodedId}}', '{{name}}', 'kill', true, 30, 'wait time in seconds')" type="button" value="Kill" class="btn btn-default">
      <input {{startDebugStatus}} onclick="confirmAction('{{encodedId}}', '{{name}}', 'debug/enable', true, {{currentSamplingPct}}, 'sampling percentage', 'debug')" type="button" value="Debug" class="btn btn-default">
      <input {{stopDebugStatus}} onclick="confirmAction('{{encodedId}}', '{{name}}', 'debug/disable', false, 0, 'sampling percentage', 'stop debugging')" type="button" value="Stop Debug" class="btn btn-default">
+     <input type="button" {{logLevel}} value="Change Log Level" onclick="toggleChangeLogLevel()" class="btn btn-default">
    </p>
+   <!-- 
+     Contents of topology-change-log-level-template will be added to the div below
+     once user clicks on "Change Log Level"
+   -->
+   <div id="change-log-level" style="display:none"></div>
  </script>
+ 
+ <script id="log-level-and-timeout" type="text/html" class="partials">
+     <tr id="logger-{{loggerId}}" class="{{cls}}">
+         {{#loggerName}}
+           <td>{{loggerName}}</td>
+           <input type="hidden" id="loggerName-{{loggerId}}" value="{{loggerName}}"/>
+           <input type="hidden" id="loggerRemove-{{loggerId}}" value="false"/>
+         {{/loggerName}}
+ 
+         {{#isNew}}
+           <td>
+             <input type="text" id="loggerName-{{loggerId}}" placeholder="com.your.organization.LoggerName"/>
+           </td>
+         {{/isNew}}
+ 
+         <td>
+             <select id="loggerLevel-{{loggerId}}">
+                 {{#levels}} 
+                     <option value="{{name}}" {{levelSelected}}>{{name}}</option>
+                 {{/levels}}
+             </select>
+         </td>
+         <td>
+             <input type="text" class="timeout_input" id="loggerTimeout-{{loggerId}}" placeholder="30" value="{{timeout}}"/> 
+         </td>
+         <td>
+             {{absoluteTimeout}}
+         </td>
+         <td>
+             {{#isNew}}
+                 <input type="button" value="Add" name="clear" onClick='sendLoggerLevel({{loggerId}})' class="btn btn-secondary"/>
+             {{/isNew}}
+             {{#loggerName}}
+                 <input type="button" value="Apply" name="clear" onClick='sendLoggerLevel({{loggerId}})' class="btn btn-secondary"/>
+                 {{#canClear}}
+                     <input type="button" value="Clear" name="clear" onClick='clearLoggerLevel({{loggerId}})' class="btn btn-secondary"/>
+                 {{/canClear}}
+             {{/loggerName}}
+         </td>
+     </tr>
+ </script>
+ 
+ <script id="topology-change-log-level-template" type="text/html">
+   <div id="change-log-level">
+       <h3>Change Log Level</h3>
+       Modify the logger levels for topology. Note that applying a setting restarts the timer in the workers. To configure the root logger, use the name ROOT. 
+       <table class="table table-striped compact">
+           <thead>
+               <tr>
+                   <th class="header">Logger</th>
+                   <th class="header">Level</th>
+                   <th class="header">Timeout (sec)</th>
+                   <th class="header">Expires at</th>
+                   <th class="header">Actions</th>
+               </tr>
+           </thead>
+       {{#loggers}}
+           {{ > log-level-and-timeout }}
+       {{/loggers}}
+       </table>
+   </div>
 -</script>
++</script>