From d13cfe2dc9beda8fc4fda6fa6536d87b9ce514a1 Mon Sep 17 00:00:00 2001 From: Kishor Patil Date: Thu, 24 Sep 2015 14:22:37 +0000 Subject: [PATCH 1/5] Adding thrift changes for Dynamic Logging --- .../backtype/storm/generated/LogConfig.java | 475 +++++ .../backtype/storm/generated/LogLevel.java | 836 ++++++++ .../storm/generated/LogLevelAction.java | 65 + .../jvm/backtype/storm/generated/Nimbus.java | 1700 ++++++++++++++++- storm-core/src/py/storm/Nimbus-remote | 14 + storm-core/src/py/storm/Nimbus.py | 359 +++- storm-core/src/py/storm/ttypes.py | 213 +++ storm-core/src/storm.thrift | 37 + 8 files changed, 3696 insertions(+), 3 deletions(-) create mode 100644 storm-core/src/jvm/backtype/storm/generated/LogConfig.java create mode 100644 storm-core/src/jvm/backtype/storm/generated/LogLevel.java create mode 100644 storm-core/src/jvm/backtype/storm/generated/LogLevelAction.java diff --git a/storm-core/src/jvm/backtype/storm/generated/LogConfig.java b/storm-core/src/jvm/backtype/storm/generated/LogConfig.java new file mode 100644 index 00000000000..318ed86433f --- /dev/null +++ b/storm-core/src/jvm/backtype/storm/generated/LogConfig.java @@ -0,0 +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") +public class LogConfig implements org.apache.thrift.TBase, java.io.Serializable, Cloneable, Comparable { + 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, SchemeFactory> schemes = new HashMap, SchemeFactory>(); + static { + schemes.put(StandardScheme.class, new LogConfigStandardSchemeFactory()); + schemes.put(TupleScheme.class, new LogConfigTupleSchemeFactory()); + } + + private Map 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 byName = new HashMap(); + + 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 other. + */ + public LogConfig(LogConfig other) { + if (other.is_set_named_logger_level()) { + Map __this__named_logger_level = new HashMap(other.named_logger_level.size()); + for (Map.Entry 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(); + } + this.named_logger_level.put(key, val); + } + + public Map get_named_logger_level() { + return this.named_logger_level; + } + + public void set_named_logger_level(Map 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)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 list = new ArrayList(); + + 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 { + + 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(2*_map510.size); + String _key511; + LogLevel _val512; + for (int _i513 = 0; _i513 < _map510.size; ++_i513) + { + _key511 = iprot.readString(); + _val512 = new LogLevel(); + _val512.read(iprot); + struct.named_logger_level.put(_key511, _val512); + } + 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 _iter514 : struct.named_logger_level.entrySet()) + { + oprot.writeString(_iter514.getKey()); + _iter514.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 { + + @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 _iter515 : struct.named_logger_level.entrySet()) + { + oprot.writeString(_iter515.getKey()); + _iter515.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(2*_map516.size); + String _key517; + LogLevel _val518; + for (int _i519 = 0; _i519 < _map516.size; ++_i519) + { + _key517 = iprot.readString(); + _val518 = new LogLevel(); + _val518.read(iprot); + struct.named_logger_level.put(_key517, _val518); + } + } + struct.set_named_logger_level_isSet(true); + } + } + } + +} + diff --git a/storm-core/src/jvm/backtype/storm/generated/LogLevel.java b/storm-core/src/jvm/backtype/storm/generated/LogLevel.java new file mode 100644 index 00000000000..dba55d0f839 --- /dev/null +++ b/storm-core/src/jvm/backtype/storm/generated/LogLevel.java @@ -0,0 +1,836 @@ +/** + * 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") +public class LogLevel implements org.apache.thrift.TBase, java.io.Serializable, Cloneable, Comparable { + private static final org.apache.thrift.protocol.TStruct STRUCT_DESC = new org.apache.thrift.protocol.TStruct("LogLevel"); + + private static final org.apache.thrift.protocol.TField ACTION_FIELD_DESC = new org.apache.thrift.protocol.TField("action", org.apache.thrift.protocol.TType.I32, (short)1); + private static final org.apache.thrift.protocol.TField TARGET_LOG_LEVEL_FIELD_DESC = new org.apache.thrift.protocol.TField("target_log_level", org.apache.thrift.protocol.TType.STRING, (short)2); + private static final org.apache.thrift.protocol.TField RESET_LOG_LEVEL_TIMEOUT_SECS_FIELD_DESC = new org.apache.thrift.protocol.TField("reset_log_level_timeout_secs", org.apache.thrift.protocol.TType.I32, (short)3); + private static final org.apache.thrift.protocol.TField RESET_LOG_LEVEL_TIMEOUT_EPOCH_FIELD_DESC = new org.apache.thrift.protocol.TField("reset_log_level_timeout_epoch", org.apache.thrift.protocol.TType.I64, (short)4); + private static final org.apache.thrift.protocol.TField RESET_LOG_LEVEL_FIELD_DESC = new org.apache.thrift.protocol.TField("reset_log_level", org.apache.thrift.protocol.TType.STRING, (short)5); + + private static final Map, SchemeFactory> schemes = new HashMap, SchemeFactory>(); + static { + schemes.put(StandardScheme.class, new LogLevelStandardSchemeFactory()); + schemes.put(TupleScheme.class, new LogLevelTupleSchemeFactory()); + } + + private LogLevelAction action; // required + private String target_log_level; // optional + private int reset_log_level_timeout_secs; // optional + private long reset_log_level_timeout_epoch; // optional + private String reset_log_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 { + /** + * + * @see LogLevelAction + */ + ACTION((short)1, "action"), + TARGET_LOG_LEVEL((short)2, "target_log_level"), + RESET_LOG_LEVEL_TIMEOUT_SECS((short)3, "reset_log_level_timeout_secs"), + RESET_LOG_LEVEL_TIMEOUT_EPOCH((short)4, "reset_log_level_timeout_epoch"), + RESET_LOG_LEVEL((short)5, "reset_log_level"); + + private static final Map byName = new HashMap(); + + 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 1: // ACTION + return ACTION; + case 2: // TARGET_LOG_LEVEL + return TARGET_LOG_LEVEL; + case 3: // RESET_LOG_LEVEL_TIMEOUT_SECS + return RESET_LOG_LEVEL_TIMEOUT_SECS; + case 4: // RESET_LOG_LEVEL_TIMEOUT_EPOCH + return RESET_LOG_LEVEL_TIMEOUT_EPOCH; + case 5: // RESET_LOG_LEVEL + return RESET_LOG_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 int __RESET_LOG_LEVEL_TIMEOUT_SECS_ISSET_ID = 0; + private static final int __RESET_LOG_LEVEL_TIMEOUT_EPOCH_ISSET_ID = 1; + private byte __isset_bitfield = 0; + private static final _Fields optionals[] = {_Fields.TARGET_LOG_LEVEL,_Fields.RESET_LOG_LEVEL_TIMEOUT_SECS,_Fields.RESET_LOG_LEVEL_TIMEOUT_EPOCH,_Fields.RESET_LOG_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.ACTION, new org.apache.thrift.meta_data.FieldMetaData("action", org.apache.thrift.TFieldRequirementType.REQUIRED, + new org.apache.thrift.meta_data.EnumMetaData(org.apache.thrift.protocol.TType.ENUM, LogLevelAction.class))); + tmpMap.put(_Fields.TARGET_LOG_LEVEL, new org.apache.thrift.meta_data.FieldMetaData("target_log_level", org.apache.thrift.TFieldRequirementType.OPTIONAL, + new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRING))); + tmpMap.put(_Fields.RESET_LOG_LEVEL_TIMEOUT_SECS, new org.apache.thrift.meta_data.FieldMetaData("reset_log_level_timeout_secs", org.apache.thrift.TFieldRequirementType.OPTIONAL, + new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.I32))); + tmpMap.put(_Fields.RESET_LOG_LEVEL_TIMEOUT_EPOCH, new org.apache.thrift.meta_data.FieldMetaData("reset_log_level_timeout_epoch", org.apache.thrift.TFieldRequirementType.OPTIONAL, + new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.I64))); + tmpMap.put(_Fields.RESET_LOG_LEVEL, new org.apache.thrift.meta_data.FieldMetaData("reset_log_level", org.apache.thrift.TFieldRequirementType.OPTIONAL, + new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRING))); + metaDataMap = Collections.unmodifiableMap(tmpMap); + org.apache.thrift.meta_data.FieldMetaData.addStructMetaDataMap(LogLevel.class, metaDataMap); + } + + public LogLevel() { + } + + public LogLevel( + LogLevelAction action) + { + this(); + this.action = action; + } + + /** + * Performs a deep copy on other. + */ + public LogLevel(LogLevel other) { + __isset_bitfield = other.__isset_bitfield; + if (other.is_set_action()) { + this.action = other.action; + } + if (other.is_set_target_log_level()) { + this.target_log_level = other.target_log_level; + } + this.reset_log_level_timeout_secs = other.reset_log_level_timeout_secs; + this.reset_log_level_timeout_epoch = other.reset_log_level_timeout_epoch; + if (other.is_set_reset_log_level()) { + this.reset_log_level = other.reset_log_level; + } + } + + public LogLevel deepCopy() { + return new LogLevel(this); + } + + @Override + public void clear() { + this.action = null; + this.target_log_level = null; + set_reset_log_level_timeout_secs_isSet(false); + this.reset_log_level_timeout_secs = 0; + set_reset_log_level_timeout_epoch_isSet(false); + this.reset_log_level_timeout_epoch = 0; + this.reset_log_level = null; + } + + /** + * + * @see LogLevelAction + */ + public LogLevelAction get_action() { + return this.action; + } + + /** + * + * @see LogLevelAction + */ + public void set_action(LogLevelAction action) { + this.action = action; + } + + public void unset_action() { + this.action = null; + } + + /** Returns true if field action is set (has been assigned a value) and false otherwise */ + public boolean is_set_action() { + return this.action != null; + } + + public void set_action_isSet(boolean value) { + if (!value) { + this.action = null; + } + } + + public String get_target_log_level() { + return this.target_log_level; + } + + public void set_target_log_level(String target_log_level) { + this.target_log_level = target_log_level; + } + + public void unset_target_log_level() { + this.target_log_level = null; + } + + /** Returns true if field target_log_level is set (has been assigned a value) and false otherwise */ + public boolean is_set_target_log_level() { + return this.target_log_level != null; + } + + public void set_target_log_level_isSet(boolean value) { + if (!value) { + this.target_log_level = null; + } + } + + public int get_reset_log_level_timeout_secs() { + return this.reset_log_level_timeout_secs; + } + + public void set_reset_log_level_timeout_secs(int reset_log_level_timeout_secs) { + this.reset_log_level_timeout_secs = reset_log_level_timeout_secs; + set_reset_log_level_timeout_secs_isSet(true); + } + + public void unset_reset_log_level_timeout_secs() { + __isset_bitfield = EncodingUtils.clearBit(__isset_bitfield, __RESET_LOG_LEVEL_TIMEOUT_SECS_ISSET_ID); + } + + /** Returns true if field reset_log_level_timeout_secs is set (has been assigned a value) and false otherwise */ + public boolean is_set_reset_log_level_timeout_secs() { + return EncodingUtils.testBit(__isset_bitfield, __RESET_LOG_LEVEL_TIMEOUT_SECS_ISSET_ID); + } + + public void set_reset_log_level_timeout_secs_isSet(boolean value) { + __isset_bitfield = EncodingUtils.setBit(__isset_bitfield, __RESET_LOG_LEVEL_TIMEOUT_SECS_ISSET_ID, value); + } + + public long get_reset_log_level_timeout_epoch() { + return this.reset_log_level_timeout_epoch; + } + + public void set_reset_log_level_timeout_epoch(long reset_log_level_timeout_epoch) { + this.reset_log_level_timeout_epoch = reset_log_level_timeout_epoch; + set_reset_log_level_timeout_epoch_isSet(true); + } + + public void unset_reset_log_level_timeout_epoch() { + __isset_bitfield = EncodingUtils.clearBit(__isset_bitfield, __RESET_LOG_LEVEL_TIMEOUT_EPOCH_ISSET_ID); + } + + /** Returns true if field reset_log_level_timeout_epoch is set (has been assigned a value) and false otherwise */ + public boolean is_set_reset_log_level_timeout_epoch() { + return EncodingUtils.testBit(__isset_bitfield, __RESET_LOG_LEVEL_TIMEOUT_EPOCH_ISSET_ID); + } + + public void set_reset_log_level_timeout_epoch_isSet(boolean value) { + __isset_bitfield = EncodingUtils.setBit(__isset_bitfield, __RESET_LOG_LEVEL_TIMEOUT_EPOCH_ISSET_ID, value); + } + + public String get_reset_log_level() { + return this.reset_log_level; + } + + public void set_reset_log_level(String reset_log_level) { + this.reset_log_level = reset_log_level; + } + + public void unset_reset_log_level() { + this.reset_log_level = null; + } + + /** Returns true if field reset_log_level is set (has been assigned a value) and false otherwise */ + public boolean is_set_reset_log_level() { + return this.reset_log_level != null; + } + + public void set_reset_log_level_isSet(boolean value) { + if (!value) { + this.reset_log_level = null; + } + } + + public void setFieldValue(_Fields field, Object value) { + switch (field) { + case ACTION: + if (value == null) { + unset_action(); + } else { + set_action((LogLevelAction)value); + } + break; + + case TARGET_LOG_LEVEL: + if (value == null) { + unset_target_log_level(); + } else { + set_target_log_level((String)value); + } + break; + + case RESET_LOG_LEVEL_TIMEOUT_SECS: + if (value == null) { + unset_reset_log_level_timeout_secs(); + } else { + set_reset_log_level_timeout_secs((Integer)value); + } + break; + + case RESET_LOG_LEVEL_TIMEOUT_EPOCH: + if (value == null) { + unset_reset_log_level_timeout_epoch(); + } else { + set_reset_log_level_timeout_epoch((Long)value); + } + break; + + case RESET_LOG_LEVEL: + if (value == null) { + unset_reset_log_level(); + } else { + set_reset_log_level((String)value); + } + break; + + } + } + + public Object getFieldValue(_Fields field) { + switch (field) { + case ACTION: + return get_action(); + + case TARGET_LOG_LEVEL: + return get_target_log_level(); + + case RESET_LOG_LEVEL_TIMEOUT_SECS: + return Integer.valueOf(get_reset_log_level_timeout_secs()); + + case RESET_LOG_LEVEL_TIMEOUT_EPOCH: + return Long.valueOf(get_reset_log_level_timeout_epoch()); + + case RESET_LOG_LEVEL: + return get_reset_log_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 ACTION: + return is_set_action(); + case TARGET_LOG_LEVEL: + return is_set_target_log_level(); + case RESET_LOG_LEVEL_TIMEOUT_SECS: + return is_set_reset_log_level_timeout_secs(); + case RESET_LOG_LEVEL_TIMEOUT_EPOCH: + return is_set_reset_log_level_timeout_epoch(); + case RESET_LOG_LEVEL: + return is_set_reset_log_level(); + } + throw new IllegalStateException(); + } + + @Override + public boolean equals(Object that) { + if (that == null) + return false; + if (that instanceof LogLevel) + return this.equals((LogLevel)that); + return false; + } + + public boolean equals(LogLevel that) { + if (that == null) + return false; + + boolean this_present_action = true && this.is_set_action(); + boolean that_present_action = true && that.is_set_action(); + if (this_present_action || that_present_action) { + if (!(this_present_action && that_present_action)) + return false; + if (!this.action.equals(that.action)) + return false; + } + + boolean this_present_target_log_level = true && this.is_set_target_log_level(); + boolean that_present_target_log_level = true && that.is_set_target_log_level(); + if (this_present_target_log_level || that_present_target_log_level) { + if (!(this_present_target_log_level && that_present_target_log_level)) + return false; + if (!this.target_log_level.equals(that.target_log_level)) + return false; + } + + boolean this_present_reset_log_level_timeout_secs = true && this.is_set_reset_log_level_timeout_secs(); + boolean that_present_reset_log_level_timeout_secs = true && that.is_set_reset_log_level_timeout_secs(); + if (this_present_reset_log_level_timeout_secs || that_present_reset_log_level_timeout_secs) { + if (!(this_present_reset_log_level_timeout_secs && that_present_reset_log_level_timeout_secs)) + return false; + if (this.reset_log_level_timeout_secs != that.reset_log_level_timeout_secs) + return false; + } + + boolean this_present_reset_log_level_timeout_epoch = true && this.is_set_reset_log_level_timeout_epoch(); + boolean that_present_reset_log_level_timeout_epoch = true && that.is_set_reset_log_level_timeout_epoch(); + if (this_present_reset_log_level_timeout_epoch || that_present_reset_log_level_timeout_epoch) { + if (!(this_present_reset_log_level_timeout_epoch && that_present_reset_log_level_timeout_epoch)) + return false; + if (this.reset_log_level_timeout_epoch != that.reset_log_level_timeout_epoch) + return false; + } + + boolean this_present_reset_log_level = true && this.is_set_reset_log_level(); + boolean that_present_reset_log_level = true && that.is_set_reset_log_level(); + if (this_present_reset_log_level || that_present_reset_log_level) { + if (!(this_present_reset_log_level && that_present_reset_log_level)) + return false; + if (!this.reset_log_level.equals(that.reset_log_level)) + return false; + } + + return true; + } + + @Override + public int hashCode() { + List list = new ArrayList(); + + boolean present_action = true && (is_set_action()); + list.add(present_action); + if (present_action) + list.add(action.getValue()); + + boolean present_target_log_level = true && (is_set_target_log_level()); + list.add(present_target_log_level); + if (present_target_log_level) + list.add(target_log_level); + + boolean present_reset_log_level_timeout_secs = true && (is_set_reset_log_level_timeout_secs()); + list.add(present_reset_log_level_timeout_secs); + if (present_reset_log_level_timeout_secs) + list.add(reset_log_level_timeout_secs); + + boolean present_reset_log_level_timeout_epoch = true && (is_set_reset_log_level_timeout_epoch()); + list.add(present_reset_log_level_timeout_epoch); + if (present_reset_log_level_timeout_epoch) + list.add(reset_log_level_timeout_epoch); + + boolean present_reset_log_level = true && (is_set_reset_log_level()); + list.add(present_reset_log_level); + if (present_reset_log_level) + list.add(reset_log_level); + + return list.hashCode(); + } + + @Override + public int compareTo(LogLevel other) { + if (!getClass().equals(other.getClass())) { + return getClass().getName().compareTo(other.getClass().getName()); + } + + int lastComparison = 0; + + lastComparison = Boolean.valueOf(is_set_action()).compareTo(other.is_set_action()); + if (lastComparison != 0) { + return lastComparison; + } + if (is_set_action()) { + lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.action, other.action); + if (lastComparison != 0) { + return lastComparison; + } + } + lastComparison = Boolean.valueOf(is_set_target_log_level()).compareTo(other.is_set_target_log_level()); + if (lastComparison != 0) { + return lastComparison; + } + if (is_set_target_log_level()) { + lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.target_log_level, other.target_log_level); + if (lastComparison != 0) { + return lastComparison; + } + } + lastComparison = Boolean.valueOf(is_set_reset_log_level_timeout_secs()).compareTo(other.is_set_reset_log_level_timeout_secs()); + if (lastComparison != 0) { + return lastComparison; + } + if (is_set_reset_log_level_timeout_secs()) { + lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.reset_log_level_timeout_secs, other.reset_log_level_timeout_secs); + if (lastComparison != 0) { + return lastComparison; + } + } + lastComparison = Boolean.valueOf(is_set_reset_log_level_timeout_epoch()).compareTo(other.is_set_reset_log_level_timeout_epoch()); + if (lastComparison != 0) { + return lastComparison; + } + if (is_set_reset_log_level_timeout_epoch()) { + lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.reset_log_level_timeout_epoch, other.reset_log_level_timeout_epoch); + if (lastComparison != 0) { + return lastComparison; + } + } + lastComparison = Boolean.valueOf(is_set_reset_log_level()).compareTo(other.is_set_reset_log_level()); + if (lastComparison != 0) { + return lastComparison; + } + if (is_set_reset_log_level()) { + lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.reset_log_level, other.reset_log_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("LogLevel("); + boolean first = true; + + sb.append("action:"); + if (this.action == null) { + sb.append("null"); + } else { + sb.append(this.action); + } + first = false; + if (is_set_target_log_level()) { + if (!first) sb.append(", "); + sb.append("target_log_level:"); + if (this.target_log_level == null) { + sb.append("null"); + } else { + sb.append(this.target_log_level); + } + first = false; + } + if (is_set_reset_log_level_timeout_secs()) { + if (!first) sb.append(", "); + sb.append("reset_log_level_timeout_secs:"); + sb.append(this.reset_log_level_timeout_secs); + first = false; + } + if (is_set_reset_log_level_timeout_epoch()) { + if (!first) sb.append(", "); + sb.append("reset_log_level_timeout_epoch:"); + sb.append(this.reset_log_level_timeout_epoch); + first = false; + } + if (is_set_reset_log_level()) { + if (!first) sb.append(", "); + sb.append("reset_log_level:"); + if (this.reset_log_level == null) { + sb.append("null"); + } else { + sb.append(this.reset_log_level); + } + first = false; + } + sb.append(")"); + return sb.toString(); + } + + public void validate() throws org.apache.thrift.TException { + // check for required fields + if (!is_set_action()) { + throw new org.apache.thrift.protocol.TProtocolException("Required field 'action' is unset! Struct:" + toString()); + } + + // 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 { + // it doesn't seem like you should have to do this, but java serialization is wacky, and doesn't call the default constructor. + __isset_bitfield = 0; + 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 LogLevelStandardSchemeFactory implements SchemeFactory { + public LogLevelStandardScheme getScheme() { + return new LogLevelStandardScheme(); + } + } + + private static class LogLevelStandardScheme extends StandardScheme { + + public void read(org.apache.thrift.protocol.TProtocol iprot, LogLevel 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 1: // ACTION + if (schemeField.type == org.apache.thrift.protocol.TType.I32) { + struct.action = backtype.storm.generated.LogLevelAction.findByValue(iprot.readI32()); + struct.set_action_isSet(true); + } else { + org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type); + } + break; + case 2: // TARGET_LOG_LEVEL + if (schemeField.type == org.apache.thrift.protocol.TType.STRING) { + struct.target_log_level = iprot.readString(); + struct.set_target_log_level_isSet(true); + } else { + org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type); + } + break; + case 3: // RESET_LOG_LEVEL_TIMEOUT_SECS + if (schemeField.type == org.apache.thrift.protocol.TType.I32) { + struct.reset_log_level_timeout_secs = iprot.readI32(); + struct.set_reset_log_level_timeout_secs_isSet(true); + } else { + org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type); + } + break; + case 4: // RESET_LOG_LEVEL_TIMEOUT_EPOCH + if (schemeField.type == org.apache.thrift.protocol.TType.I64) { + struct.reset_log_level_timeout_epoch = iprot.readI64(); + struct.set_reset_log_level_timeout_epoch_isSet(true); + } else { + org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type); + } + break; + case 5: // RESET_LOG_LEVEL + if (schemeField.type == org.apache.thrift.protocol.TType.STRING) { + struct.reset_log_level = iprot.readString(); + struct.set_reset_log_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, LogLevel struct) throws org.apache.thrift.TException { + struct.validate(); + + oprot.writeStructBegin(STRUCT_DESC); + if (struct.action != null) { + oprot.writeFieldBegin(ACTION_FIELD_DESC); + oprot.writeI32(struct.action.getValue()); + oprot.writeFieldEnd(); + } + if (struct.target_log_level != null) { + if (struct.is_set_target_log_level()) { + oprot.writeFieldBegin(TARGET_LOG_LEVEL_FIELD_DESC); + oprot.writeString(struct.target_log_level); + oprot.writeFieldEnd(); + } + } + if (struct.is_set_reset_log_level_timeout_secs()) { + oprot.writeFieldBegin(RESET_LOG_LEVEL_TIMEOUT_SECS_FIELD_DESC); + oprot.writeI32(struct.reset_log_level_timeout_secs); + oprot.writeFieldEnd(); + } + if (struct.is_set_reset_log_level_timeout_epoch()) { + oprot.writeFieldBegin(RESET_LOG_LEVEL_TIMEOUT_EPOCH_FIELD_DESC); + oprot.writeI64(struct.reset_log_level_timeout_epoch); + oprot.writeFieldEnd(); + } + if (struct.reset_log_level != null) { + if (struct.is_set_reset_log_level()) { + oprot.writeFieldBegin(RESET_LOG_LEVEL_FIELD_DESC); + oprot.writeString(struct.reset_log_level); + oprot.writeFieldEnd(); + } + } + oprot.writeFieldStop(); + oprot.writeStructEnd(); + } + + } + + private static class LogLevelTupleSchemeFactory implements SchemeFactory { + public LogLevelTupleScheme getScheme() { + return new LogLevelTupleScheme(); + } + } + + private static class LogLevelTupleScheme extends TupleScheme { + + @Override + public void write(org.apache.thrift.protocol.TProtocol prot, LogLevel struct) throws org.apache.thrift.TException { + TTupleProtocol oprot = (TTupleProtocol) prot; + oprot.writeI32(struct.action.getValue()); + BitSet optionals = new BitSet(); + if (struct.is_set_target_log_level()) { + optionals.set(0); + } + if (struct.is_set_reset_log_level_timeout_secs()) { + optionals.set(1); + } + if (struct.is_set_reset_log_level_timeout_epoch()) { + optionals.set(2); + } + if (struct.is_set_reset_log_level()) { + optionals.set(3); + } + oprot.writeBitSet(optionals, 4); + if (struct.is_set_target_log_level()) { + oprot.writeString(struct.target_log_level); + } + if (struct.is_set_reset_log_level_timeout_secs()) { + oprot.writeI32(struct.reset_log_level_timeout_secs); + } + if (struct.is_set_reset_log_level_timeout_epoch()) { + oprot.writeI64(struct.reset_log_level_timeout_epoch); + } + if (struct.is_set_reset_log_level()) { + oprot.writeString(struct.reset_log_level); + } + } + + @Override + public void read(org.apache.thrift.protocol.TProtocol prot, LogLevel struct) throws org.apache.thrift.TException { + TTupleProtocol iprot = (TTupleProtocol) prot; + struct.action = backtype.storm.generated.LogLevelAction.findByValue(iprot.readI32()); + struct.set_action_isSet(true); + BitSet incoming = iprot.readBitSet(4); + if (incoming.get(0)) { + struct.target_log_level = iprot.readString(); + struct.set_target_log_level_isSet(true); + } + if (incoming.get(1)) { + struct.reset_log_level_timeout_secs = iprot.readI32(); + struct.set_reset_log_level_timeout_secs_isSet(true); + } + if (incoming.get(2)) { + struct.reset_log_level_timeout_epoch = iprot.readI64(); + struct.set_reset_log_level_timeout_epoch_isSet(true); + } + if (incoming.get(3)) { + struct.reset_log_level = iprot.readString(); + struct.set_reset_log_level_isSet(true); + } + } + } + +} + diff --git a/storm-core/src/jvm/backtype/storm/generated/LogLevelAction.java b/storm-core/src/jvm/backtype/storm/generated/LogLevelAction.java new file mode 100644 index 00000000000..c649bcfa706 --- /dev/null +++ b/storm-core/src/jvm/backtype/storm/generated/LogLevelAction.java @@ -0,0 +1,65 @@ +/** + * 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 java.util.Map; +import java.util.HashMap; +import org.apache.thrift.TEnum; + +public enum LogLevelAction implements org.apache.thrift.TEnum { + UNCHANGED(1), + UPDATE(2), + REMOVE(3); + + private final int value; + + private LogLevelAction(int value) { + this.value = value; + } + + /** + * Get the integer value of this enum value, as defined in the Thrift IDL. + */ + public int getValue() { + return value; + } + + /** + * Find a the enum type by its integer value, as defined in the Thrift IDL. + * @return null if the value is not found. + */ + public static LogLevelAction findByValue(int value) { + switch (value) { + case 1: + return UNCHANGED; + case 2: + return UPDATE; + case 3: + return REMOVE; + default: + return null; + } + } +} diff --git a/storm-core/src/jvm/backtype/storm/generated/Nimbus.java b/storm-core/src/jvm/backtype/storm/generated/Nimbus.java index 3a5d5dfe7d1..1d0114e4edb 100644 --- a/storm-core/src/jvm/backtype/storm/generated/Nimbus.java +++ b/storm-core/src/jvm/backtype/storm/generated/Nimbus.java @@ -51,7 +51,7 @@ import org.slf4j.LoggerFactory; @SuppressWarnings({"cast", "rawtypes", "serial", "unchecked"}) -@Generated(value = "Autogenerated by Thrift Compiler (0.9.2)", date = "2015-8-24") +@Generated(value = "Autogenerated by Thrift Compiler (0.9.2)", date = "2015-9-24") public class Nimbus { public interface Iface { @@ -70,6 +70,10 @@ public interface Iface { public void rebalance(String name, RebalanceOptions options) throws NotAliveException, InvalidTopologyException, AuthorizationException, org.apache.thrift.TException; + public void setLogConfig(String name, LogConfig config) throws org.apache.thrift.TException; + + public LogConfig getLogConfig(String name) throws org.apache.thrift.TException; + /** * Enable/disable logging the tuples generated in topology via an internal EventLogger bolt. The component name is optional * and if null or empty, the debug flag will apply to the entire topology. @@ -138,6 +142,10 @@ public interface AsyncIface { public void rebalance(String name, RebalanceOptions options, org.apache.thrift.async.AsyncMethodCallback resultHandler) throws org.apache.thrift.TException; + public void setLogConfig(String name, LogConfig config, org.apache.thrift.async.AsyncMethodCallback resultHandler) throws org.apache.thrift.TException; + + public void getLogConfig(String name, org.apache.thrift.async.AsyncMethodCallback resultHandler) throws org.apache.thrift.TException; + public void debug(String name, String component, boolean enable, double samplingPercentage, org.apache.thrift.async.AsyncMethodCallback resultHandler) throws org.apache.thrift.TException; public void uploadNewCredentials(String name, Credentials creds, org.apache.thrift.async.AsyncMethodCallback resultHandler) throws org.apache.thrift.TException; @@ -388,6 +396,50 @@ public void recv_rebalance() throws NotAliveException, InvalidTopologyException, return; } + public void setLogConfig(String name, LogConfig config) throws org.apache.thrift.TException + { + send_setLogConfig(name, config); + recv_setLogConfig(); + } + + public void send_setLogConfig(String name, LogConfig config) throws org.apache.thrift.TException + { + setLogConfig_args args = new setLogConfig_args(); + args.set_name(name); + args.set_config(config); + sendBase("setLogConfig", args); + } + + public void recv_setLogConfig() throws org.apache.thrift.TException + { + setLogConfig_result result = new setLogConfig_result(); + receiveBase(result, "setLogConfig"); + return; + } + + public LogConfig getLogConfig(String name) throws org.apache.thrift.TException + { + send_getLogConfig(name); + return recv_getLogConfig(); + } + + public void send_getLogConfig(String name) throws org.apache.thrift.TException + { + getLogConfig_args args = new getLogConfig_args(); + args.set_name(name); + sendBase("getLogConfig", args); + } + + public LogConfig recv_getLogConfig() throws org.apache.thrift.TException + { + getLogConfig_result result = new getLogConfig_result(); + receiveBase(result, "getLogConfig"); + if (result.is_set_success()) { + return result.success; + } + throw new org.apache.thrift.TApplicationException(org.apache.thrift.TApplicationException.MISSING_RESULT, "getLogConfig failed: unknown result"); + } + public void debug(String name, String component, boolean enable, double samplingPercentage) throws NotAliveException, AuthorizationException, org.apache.thrift.TException { send_debug(name, component, enable, samplingPercentage); @@ -1036,6 +1088,73 @@ public void getResult() throws NotAliveException, InvalidTopologyException, Auth } } + public void setLogConfig(String name, LogConfig config, org.apache.thrift.async.AsyncMethodCallback resultHandler) throws org.apache.thrift.TException { + checkReady(); + setLogConfig_call method_call = new setLogConfig_call(name, config, resultHandler, this, ___protocolFactory, ___transport); + this.___currentMethod = method_call; + ___manager.call(method_call); + } + + public static class setLogConfig_call extends org.apache.thrift.async.TAsyncMethodCall { + private String name; + private LogConfig config; + public setLogConfig_call(String name, LogConfig config, org.apache.thrift.async.AsyncMethodCallback resultHandler, org.apache.thrift.async.TAsyncClient client, org.apache.thrift.protocol.TProtocolFactory protocolFactory, org.apache.thrift.transport.TNonblockingTransport transport) throws org.apache.thrift.TException { + super(client, protocolFactory, transport, resultHandler, false); + this.name = name; + this.config = config; + } + + public void write_args(org.apache.thrift.protocol.TProtocol prot) throws org.apache.thrift.TException { + prot.writeMessageBegin(new org.apache.thrift.protocol.TMessage("setLogConfig", org.apache.thrift.protocol.TMessageType.CALL, 0)); + setLogConfig_args args = new setLogConfig_args(); + args.set_name(name); + args.set_config(config); + args.write(prot); + prot.writeMessageEnd(); + } + + public void getResult() throws org.apache.thrift.TException { + if (getState() != org.apache.thrift.async.TAsyncMethodCall.State.RESPONSE_READ) { + throw new IllegalStateException("Method call not finished!"); + } + org.apache.thrift.transport.TMemoryInputTransport memoryTransport = new org.apache.thrift.transport.TMemoryInputTransport(getFrameBuffer().array()); + org.apache.thrift.protocol.TProtocol prot = client.getProtocolFactory().getProtocol(memoryTransport); + (new Client(prot)).recv_setLogConfig(); + } + } + + public void getLogConfig(String name, org.apache.thrift.async.AsyncMethodCallback resultHandler) throws org.apache.thrift.TException { + checkReady(); + getLogConfig_call method_call = new getLogConfig_call(name, resultHandler, this, ___protocolFactory, ___transport); + this.___currentMethod = method_call; + ___manager.call(method_call); + } + + public static class getLogConfig_call extends org.apache.thrift.async.TAsyncMethodCall { + private String name; + public getLogConfig_call(String name, org.apache.thrift.async.AsyncMethodCallback resultHandler, org.apache.thrift.async.TAsyncClient client, org.apache.thrift.protocol.TProtocolFactory protocolFactory, org.apache.thrift.transport.TNonblockingTransport transport) throws org.apache.thrift.TException { + super(client, protocolFactory, transport, resultHandler, false); + this.name = name; + } + + public void write_args(org.apache.thrift.protocol.TProtocol prot) throws org.apache.thrift.TException { + prot.writeMessageBegin(new org.apache.thrift.protocol.TMessage("getLogConfig", org.apache.thrift.protocol.TMessageType.CALL, 0)); + getLogConfig_args args = new getLogConfig_args(); + args.set_name(name); + args.write(prot); + prot.writeMessageEnd(); + } + + public LogConfig getResult() throws org.apache.thrift.TException { + if (getState() != org.apache.thrift.async.TAsyncMethodCall.State.RESPONSE_READ) { + throw new IllegalStateException("Method call not finished!"); + } + org.apache.thrift.transport.TMemoryInputTransport memoryTransport = new org.apache.thrift.transport.TMemoryInputTransport(getFrameBuffer().array()); + org.apache.thrift.protocol.TProtocol prot = client.getProtocolFactory().getProtocol(memoryTransport); + return (new Client(prot)).recv_getLogConfig(); + } + } + public void debug(String name, String component, boolean enable, double samplingPercentage, org.apache.thrift.async.AsyncMethodCallback resultHandler) throws org.apache.thrift.TException { checkReady(); debug_call method_call = new debug_call(name, component, enable, samplingPercentage, resultHandler, this, ___protocolFactory, ___transport); @@ -1513,6 +1632,8 @@ protected Processor(I iface, Map extends org.apache.thrift.ProcessFunction { + public setLogConfig() { + super("setLogConfig"); + } + + public setLogConfig_args getEmptyArgsInstance() { + return new setLogConfig_args(); + } + + protected boolean isOneway() { + return false; + } + + public setLogConfig_result getResult(I iface, setLogConfig_args args) throws org.apache.thrift.TException { + setLogConfig_result result = new setLogConfig_result(); + iface.setLogConfig(args.name, args.config); + return result; + } + } + + public static class getLogConfig extends org.apache.thrift.ProcessFunction { + public getLogConfig() { + super("getLogConfig"); + } + + public getLogConfig_args getEmptyArgsInstance() { + return new getLogConfig_args(); + } + + protected boolean isOneway() { + return false; + } + + public getLogConfig_result getResult(I iface, getLogConfig_args args) throws org.apache.thrift.TException { + getLogConfig_result result = new getLogConfig_result(); + result.success = iface.getLogConfig(args.name); + return result; + } + } + public static class debug extends org.apache.thrift.ProcessFunction { public debug() { super("debug"); @@ -2090,6 +2251,8 @@ protected AsyncProcessor(I iface, Map extends org.apache.thrift.AsyncProcessFunction { + public setLogConfig() { + super("setLogConfig"); + } + + public setLogConfig_args getEmptyArgsInstance() { + return new setLogConfig_args(); + } + + public AsyncMethodCallback getResultHandler(final AsyncFrameBuffer fb, final int seqid) { + final org.apache.thrift.AsyncProcessFunction fcall = this; + return new AsyncMethodCallback() { + public void onComplete(Void o) { + setLogConfig_result result = new setLogConfig_result(); + try { + fcall.sendResponse(fb,result, org.apache.thrift.protocol.TMessageType.REPLY,seqid); + return; + } catch (Exception e) { + LOGGER.error("Exception writing to internal frame buffer", e); + } + fb.close(); + } + public void onError(Exception e) { + byte msgType = org.apache.thrift.protocol.TMessageType.REPLY; + org.apache.thrift.TBase msg; + setLogConfig_result result = new setLogConfig_result(); + { + msgType = org.apache.thrift.protocol.TMessageType.EXCEPTION; + msg = (org.apache.thrift.TBase)new org.apache.thrift.TApplicationException(org.apache.thrift.TApplicationException.INTERNAL_ERROR, e.getMessage()); + } + try { + fcall.sendResponse(fb,msg,msgType,seqid); + return; + } catch (Exception ex) { + LOGGER.error("Exception writing to internal frame buffer", ex); + } + fb.close(); + } + }; + } + + protected boolean isOneway() { + return false; + } + + public void start(I iface, setLogConfig_args args, org.apache.thrift.async.AsyncMethodCallback resultHandler) throws TException { + iface.setLogConfig(args.name, args.config,resultHandler); + } + } + + public static class getLogConfig extends org.apache.thrift.AsyncProcessFunction { + public getLogConfig() { + super("getLogConfig"); + } + + public getLogConfig_args getEmptyArgsInstance() { + return new getLogConfig_args(); + } + + public AsyncMethodCallback getResultHandler(final AsyncFrameBuffer fb, final int seqid) { + final org.apache.thrift.AsyncProcessFunction fcall = this; + return new AsyncMethodCallback() { + public void onComplete(LogConfig o) { + getLogConfig_result result = new getLogConfig_result(); + result.success = o; + try { + fcall.sendResponse(fb,result, org.apache.thrift.protocol.TMessageType.REPLY,seqid); + return; + } catch (Exception e) { + LOGGER.error("Exception writing to internal frame buffer", e); + } + fb.close(); + } + public void onError(Exception e) { + byte msgType = org.apache.thrift.protocol.TMessageType.REPLY; + org.apache.thrift.TBase msg; + getLogConfig_result result = new getLogConfig_result(); + { + msgType = org.apache.thrift.protocol.TMessageType.EXCEPTION; + msg = (org.apache.thrift.TBase)new org.apache.thrift.TApplicationException(org.apache.thrift.TApplicationException.INTERNAL_ERROR, e.getMessage()); + } + try { + fcall.sendResponse(fb,msg,msgType,seqid); + return; + } catch (Exception ex) { + LOGGER.error("Exception writing to internal frame buffer", ex); + } + fb.close(); + } + }; + } + + protected boolean isOneway() { + return false; + } + + public void start(I iface, getLogConfig_args args, org.apache.thrift.async.AsyncMethodCallback resultHandler) throws TException { + iface.getLogConfig(args.name,resultHandler); + } + } + public static class debug extends org.apache.thrift.AsyncProcessFunction { public debug() { super("debug"); @@ -10432,6 +10696,1440 @@ public void read(org.apache.thrift.protocol.TProtocol prot, rebalance_result str } + public static class setLogConfig_args implements org.apache.thrift.TBase, java.io.Serializable, Cloneable, Comparable { + private static final org.apache.thrift.protocol.TStruct STRUCT_DESC = new org.apache.thrift.protocol.TStruct("setLogConfig_args"); + + private static final org.apache.thrift.protocol.TField NAME_FIELD_DESC = new org.apache.thrift.protocol.TField("name", org.apache.thrift.protocol.TType.STRING, (short)1); + private static final org.apache.thrift.protocol.TField CONFIG_FIELD_DESC = new org.apache.thrift.protocol.TField("config", org.apache.thrift.protocol.TType.STRUCT, (short)2); + + private static final Map, SchemeFactory> schemes = new HashMap, SchemeFactory>(); + static { + schemes.put(StandardScheme.class, new setLogConfig_argsStandardSchemeFactory()); + schemes.put(TupleScheme.class, new setLogConfig_argsTupleSchemeFactory()); + } + + private String name; // required + private LogConfig config; // required + + /** The set of fields this struct contains, along with convenience methods for finding and manipulating them. */ + public enum _Fields implements org.apache.thrift.TFieldIdEnum { + NAME((short)1, "name"), + CONFIG((short)2, "config"); + + private static final Map byName = new HashMap(); + + 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 1: // NAME + return NAME; + case 2: // CONFIG + return CONFIG; + 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 + 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.NAME, new org.apache.thrift.meta_data.FieldMetaData("name", org.apache.thrift.TFieldRequirementType.DEFAULT, + new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRING))); + tmpMap.put(_Fields.CONFIG, new org.apache.thrift.meta_data.FieldMetaData("config", org.apache.thrift.TFieldRequirementType.DEFAULT, + new org.apache.thrift.meta_data.StructMetaData(org.apache.thrift.protocol.TType.STRUCT, LogConfig.class))); + metaDataMap = Collections.unmodifiableMap(tmpMap); + org.apache.thrift.meta_data.FieldMetaData.addStructMetaDataMap(setLogConfig_args.class, metaDataMap); + } + + public setLogConfig_args() { + } + + public setLogConfig_args( + String name, + LogConfig config) + { + this(); + this.name = name; + this.config = config; + } + + /** + * Performs a deep copy on other. + */ + public setLogConfig_args(setLogConfig_args other) { + if (other.is_set_name()) { + this.name = other.name; + } + if (other.is_set_config()) { + this.config = new LogConfig(other.config); + } + } + + public setLogConfig_args deepCopy() { + return new setLogConfig_args(this); + } + + @Override + public void clear() { + this.name = null; + this.config = null; + } + + public String get_name() { + return this.name; + } + + public void set_name(String name) { + this.name = name; + } + + public void unset_name() { + this.name = null; + } + + /** Returns true if field name is set (has been assigned a value) and false otherwise */ + public boolean is_set_name() { + return this.name != null; + } + + public void set_name_isSet(boolean value) { + if (!value) { + this.name = null; + } + } + + public LogConfig get_config() { + return this.config; + } + + public void set_config(LogConfig config) { + this.config = config; + } + + public void unset_config() { + this.config = null; + } + + /** Returns true if field config is set (has been assigned a value) and false otherwise */ + public boolean is_set_config() { + return this.config != null; + } + + public void set_config_isSet(boolean value) { + if (!value) { + this.config = null; + } + } + + public void setFieldValue(_Fields field, Object value) { + switch (field) { + case NAME: + if (value == null) { + unset_name(); + } else { + set_name((String)value); + } + break; + + case CONFIG: + if (value == null) { + unset_config(); + } else { + set_config((LogConfig)value); + } + break; + + } + } + + public Object getFieldValue(_Fields field) { + switch (field) { + case NAME: + return get_name(); + + case CONFIG: + return get_config(); + + } + 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 NAME: + return is_set_name(); + case CONFIG: + return is_set_config(); + } + throw new IllegalStateException(); + } + + @Override + public boolean equals(Object that) { + if (that == null) + return false; + if (that instanceof setLogConfig_args) + return this.equals((setLogConfig_args)that); + return false; + } + + public boolean equals(setLogConfig_args that) { + if (that == null) + return false; + + boolean this_present_name = true && this.is_set_name(); + boolean that_present_name = true && that.is_set_name(); + if (this_present_name || that_present_name) { + if (!(this_present_name && that_present_name)) + return false; + if (!this.name.equals(that.name)) + return false; + } + + boolean this_present_config = true && this.is_set_config(); + boolean that_present_config = true && that.is_set_config(); + if (this_present_config || that_present_config) { + if (!(this_present_config && that_present_config)) + return false; + if (!this.config.equals(that.config)) + return false; + } + + return true; + } + + @Override + public int hashCode() { + List list = new ArrayList(); + + boolean present_name = true && (is_set_name()); + list.add(present_name); + if (present_name) + list.add(name); + + boolean present_config = true && (is_set_config()); + list.add(present_config); + if (present_config) + list.add(config); + + return list.hashCode(); + } + + @Override + public int compareTo(setLogConfig_args other) { + if (!getClass().equals(other.getClass())) { + return getClass().getName().compareTo(other.getClass().getName()); + } + + int lastComparison = 0; + + lastComparison = Boolean.valueOf(is_set_name()).compareTo(other.is_set_name()); + if (lastComparison != 0) { + return lastComparison; + } + if (is_set_name()) { + lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.name, other.name); + if (lastComparison != 0) { + return lastComparison; + } + } + lastComparison = Boolean.valueOf(is_set_config()).compareTo(other.is_set_config()); + if (lastComparison != 0) { + return lastComparison; + } + if (is_set_config()) { + lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.config, other.config); + 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("setLogConfig_args("); + boolean first = true; + + sb.append("name:"); + if (this.name == null) { + sb.append("null"); + } else { + sb.append(this.name); + } + first = false; + if (!first) sb.append(", "); + sb.append("config:"); + if (this.config == null) { + sb.append("null"); + } else { + sb.append(this.config); + } + first = false; + sb.append(")"); + return sb.toString(); + } + + public void validate() throws org.apache.thrift.TException { + // check for required fields + // check for sub-struct validity + if (config != null) { + config.validate(); + } + } + + 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 setLogConfig_argsStandardSchemeFactory implements SchemeFactory { + public setLogConfig_argsStandardScheme getScheme() { + return new setLogConfig_argsStandardScheme(); + } + } + + private static class setLogConfig_argsStandardScheme extends StandardScheme { + + public void read(org.apache.thrift.protocol.TProtocol iprot, setLogConfig_args 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 1: // NAME + if (schemeField.type == org.apache.thrift.protocol.TType.STRING) { + struct.name = iprot.readString(); + struct.set_name_isSet(true); + } else { + org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type); + } + break; + case 2: // CONFIG + if (schemeField.type == org.apache.thrift.protocol.TType.STRUCT) { + struct.config = new LogConfig(); + struct.config.read(iprot); + struct.set_config_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, setLogConfig_args struct) throws org.apache.thrift.TException { + struct.validate(); + + oprot.writeStructBegin(STRUCT_DESC); + if (struct.name != null) { + oprot.writeFieldBegin(NAME_FIELD_DESC); + oprot.writeString(struct.name); + oprot.writeFieldEnd(); + } + if (struct.config != null) { + oprot.writeFieldBegin(CONFIG_FIELD_DESC); + struct.config.write(oprot); + oprot.writeFieldEnd(); + } + oprot.writeFieldStop(); + oprot.writeStructEnd(); + } + + } + + private static class setLogConfig_argsTupleSchemeFactory implements SchemeFactory { + public setLogConfig_argsTupleScheme getScheme() { + return new setLogConfig_argsTupleScheme(); + } + } + + private static class setLogConfig_argsTupleScheme extends TupleScheme { + + @Override + public void write(org.apache.thrift.protocol.TProtocol prot, setLogConfig_args struct) throws org.apache.thrift.TException { + TTupleProtocol oprot = (TTupleProtocol) prot; + BitSet optionals = new BitSet(); + if (struct.is_set_name()) { + optionals.set(0); + } + if (struct.is_set_config()) { + optionals.set(1); + } + oprot.writeBitSet(optionals, 2); + if (struct.is_set_name()) { + oprot.writeString(struct.name); + } + if (struct.is_set_config()) { + struct.config.write(oprot); + } + } + + @Override + public void read(org.apache.thrift.protocol.TProtocol prot, setLogConfig_args struct) throws org.apache.thrift.TException { + TTupleProtocol iprot = (TTupleProtocol) prot; + BitSet incoming = iprot.readBitSet(2); + if (incoming.get(0)) { + struct.name = iprot.readString(); + struct.set_name_isSet(true); + } + if (incoming.get(1)) { + struct.config = new LogConfig(); + struct.config.read(iprot); + struct.set_config_isSet(true); + } + } + } + + } + + public static class setLogConfig_result implements org.apache.thrift.TBase, java.io.Serializable, Cloneable, Comparable { + private static final org.apache.thrift.protocol.TStruct STRUCT_DESC = new org.apache.thrift.protocol.TStruct("setLogConfig_result"); + + + private static final Map, SchemeFactory> schemes = new HashMap, SchemeFactory>(); + static { + schemes.put(StandardScheme.class, new setLogConfig_resultStandardSchemeFactory()); + schemes.put(TupleScheme.class, new setLogConfig_resultTupleSchemeFactory()); + } + + + /** The set of fields this struct contains, along with convenience methods for finding and manipulating them. */ + public enum _Fields implements org.apache.thrift.TFieldIdEnum { +; + + private static final Map byName = new HashMap(); + + 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) { + 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; + } + } + 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); + metaDataMap = Collections.unmodifiableMap(tmpMap); + org.apache.thrift.meta_data.FieldMetaData.addStructMetaDataMap(setLogConfig_result.class, metaDataMap); + } + + public setLogConfig_result() { + } + + /** + * Performs a deep copy on other. + */ + public setLogConfig_result(setLogConfig_result other) { + } + + public setLogConfig_result deepCopy() { + return new setLogConfig_result(this); + } + + @Override + public void clear() { + } + + public void setFieldValue(_Fields field, Object value) { + switch (field) { + } + } + + public Object getFieldValue(_Fields field) { + switch (field) { + } + 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) { + } + throw new IllegalStateException(); + } + + @Override + public boolean equals(Object that) { + if (that == null) + return false; + if (that instanceof setLogConfig_result) + return this.equals((setLogConfig_result)that); + return false; + } + + public boolean equals(setLogConfig_result that) { + if (that == null) + return false; + + return true; + } + + @Override + public int hashCode() { + List list = new ArrayList(); + + return list.hashCode(); + } + + @Override + public int compareTo(setLogConfig_result other) { + if (!getClass().equals(other.getClass())) { + return getClass().getName().compareTo(other.getClass().getName()); + } + + int lastComparison = 0; + + 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("setLogConfig_result("); + boolean first = true; + + 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 setLogConfig_resultStandardSchemeFactory implements SchemeFactory { + public setLogConfig_resultStandardScheme getScheme() { + return new setLogConfig_resultStandardScheme(); + } + } + + private static class setLogConfig_resultStandardScheme extends StandardScheme { + + public void read(org.apache.thrift.protocol.TProtocol iprot, setLogConfig_result 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) { + 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, setLogConfig_result struct) throws org.apache.thrift.TException { + struct.validate(); + + oprot.writeStructBegin(STRUCT_DESC); + oprot.writeFieldStop(); + oprot.writeStructEnd(); + } + + } + + private static class setLogConfig_resultTupleSchemeFactory implements SchemeFactory { + public setLogConfig_resultTupleScheme getScheme() { + return new setLogConfig_resultTupleScheme(); + } + } + + private static class setLogConfig_resultTupleScheme extends TupleScheme { + + @Override + public void write(org.apache.thrift.protocol.TProtocol prot, setLogConfig_result struct) throws org.apache.thrift.TException { + TTupleProtocol oprot = (TTupleProtocol) prot; + } + + @Override + public void read(org.apache.thrift.protocol.TProtocol prot, setLogConfig_result struct) throws org.apache.thrift.TException { + TTupleProtocol iprot = (TTupleProtocol) prot; + } + } + + } + + public static class getLogConfig_args implements org.apache.thrift.TBase, java.io.Serializable, Cloneable, Comparable { + private static final org.apache.thrift.protocol.TStruct STRUCT_DESC = new org.apache.thrift.protocol.TStruct("getLogConfig_args"); + + private static final org.apache.thrift.protocol.TField NAME_FIELD_DESC = new org.apache.thrift.protocol.TField("name", org.apache.thrift.protocol.TType.STRING, (short)1); + + private static final Map, SchemeFactory> schemes = new HashMap, SchemeFactory>(); + static { + schemes.put(StandardScheme.class, new getLogConfig_argsStandardSchemeFactory()); + schemes.put(TupleScheme.class, new getLogConfig_argsTupleSchemeFactory()); + } + + private String name; // required + + /** The set of fields this struct contains, along with convenience methods for finding and manipulating them. */ + public enum _Fields implements org.apache.thrift.TFieldIdEnum { + NAME((short)1, "name"); + + private static final Map byName = new HashMap(); + + 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 1: // NAME + return NAME; + 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 + 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.NAME, new org.apache.thrift.meta_data.FieldMetaData("name", org.apache.thrift.TFieldRequirementType.DEFAULT, + new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRING))); + metaDataMap = Collections.unmodifiableMap(tmpMap); + org.apache.thrift.meta_data.FieldMetaData.addStructMetaDataMap(getLogConfig_args.class, metaDataMap); + } + + public getLogConfig_args() { + } + + public getLogConfig_args( + String name) + { + this(); + this.name = name; + } + + /** + * Performs a deep copy on other. + */ + public getLogConfig_args(getLogConfig_args other) { + if (other.is_set_name()) { + this.name = other.name; + } + } + + public getLogConfig_args deepCopy() { + return new getLogConfig_args(this); + } + + @Override + public void clear() { + this.name = null; + } + + public String get_name() { + return this.name; + } + + public void set_name(String name) { + this.name = name; + } + + public void unset_name() { + this.name = null; + } + + /** Returns true if field name is set (has been assigned a value) and false otherwise */ + public boolean is_set_name() { + return this.name != null; + } + + public void set_name_isSet(boolean value) { + if (!value) { + this.name = null; + } + } + + public void setFieldValue(_Fields field, Object value) { + switch (field) { + case NAME: + if (value == null) { + unset_name(); + } else { + set_name((String)value); + } + break; + + } + } + + public Object getFieldValue(_Fields field) { + switch (field) { + case NAME: + return get_name(); + + } + 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 NAME: + return is_set_name(); + } + throw new IllegalStateException(); + } + + @Override + public boolean equals(Object that) { + if (that == null) + return false; + if (that instanceof getLogConfig_args) + return this.equals((getLogConfig_args)that); + return false; + } + + public boolean equals(getLogConfig_args that) { + if (that == null) + return false; + + boolean this_present_name = true && this.is_set_name(); + boolean that_present_name = true && that.is_set_name(); + if (this_present_name || that_present_name) { + if (!(this_present_name && that_present_name)) + return false; + if (!this.name.equals(that.name)) + return false; + } + + return true; + } + + @Override + public int hashCode() { + List list = new ArrayList(); + + boolean present_name = true && (is_set_name()); + list.add(present_name); + if (present_name) + list.add(name); + + return list.hashCode(); + } + + @Override + public int compareTo(getLogConfig_args other) { + if (!getClass().equals(other.getClass())) { + return getClass().getName().compareTo(other.getClass().getName()); + } + + int lastComparison = 0; + + lastComparison = Boolean.valueOf(is_set_name()).compareTo(other.is_set_name()); + if (lastComparison != 0) { + return lastComparison; + } + if (is_set_name()) { + lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.name, other.name); + 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("getLogConfig_args("); + boolean first = true; + + sb.append("name:"); + if (this.name == null) { + sb.append("null"); + } else { + sb.append(this.name); + } + 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 getLogConfig_argsStandardSchemeFactory implements SchemeFactory { + public getLogConfig_argsStandardScheme getScheme() { + return new getLogConfig_argsStandardScheme(); + } + } + + private static class getLogConfig_argsStandardScheme extends StandardScheme { + + public void read(org.apache.thrift.protocol.TProtocol iprot, getLogConfig_args 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 1: // NAME + if (schemeField.type == org.apache.thrift.protocol.TType.STRING) { + struct.name = iprot.readString(); + struct.set_name_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, getLogConfig_args struct) throws org.apache.thrift.TException { + struct.validate(); + + oprot.writeStructBegin(STRUCT_DESC); + if (struct.name != null) { + oprot.writeFieldBegin(NAME_FIELD_DESC); + oprot.writeString(struct.name); + oprot.writeFieldEnd(); + } + oprot.writeFieldStop(); + oprot.writeStructEnd(); + } + + } + + private static class getLogConfig_argsTupleSchemeFactory implements SchemeFactory { + public getLogConfig_argsTupleScheme getScheme() { + return new getLogConfig_argsTupleScheme(); + } + } + + private static class getLogConfig_argsTupleScheme extends TupleScheme { + + @Override + public void write(org.apache.thrift.protocol.TProtocol prot, getLogConfig_args struct) throws org.apache.thrift.TException { + TTupleProtocol oprot = (TTupleProtocol) prot; + BitSet optionals = new BitSet(); + if (struct.is_set_name()) { + optionals.set(0); + } + oprot.writeBitSet(optionals, 1); + if (struct.is_set_name()) { + oprot.writeString(struct.name); + } + } + + @Override + public void read(org.apache.thrift.protocol.TProtocol prot, getLogConfig_args struct) throws org.apache.thrift.TException { + TTupleProtocol iprot = (TTupleProtocol) prot; + BitSet incoming = iprot.readBitSet(1); + if (incoming.get(0)) { + struct.name = iprot.readString(); + struct.set_name_isSet(true); + } + } + } + + } + + public static class getLogConfig_result implements org.apache.thrift.TBase, java.io.Serializable, Cloneable, Comparable { + private static final org.apache.thrift.protocol.TStruct STRUCT_DESC = new org.apache.thrift.protocol.TStruct("getLogConfig_result"); + + private static final org.apache.thrift.protocol.TField SUCCESS_FIELD_DESC = new org.apache.thrift.protocol.TField("success", org.apache.thrift.protocol.TType.STRUCT, (short)0); + + private static final Map, SchemeFactory> schemes = new HashMap, SchemeFactory>(); + static { + schemes.put(StandardScheme.class, new getLogConfig_resultStandardSchemeFactory()); + schemes.put(TupleScheme.class, new getLogConfig_resultTupleSchemeFactory()); + } + + private LogConfig success; // required + + /** The set of fields this struct contains, along with convenience methods for finding and manipulating them. */ + public enum _Fields implements org.apache.thrift.TFieldIdEnum { + SUCCESS((short)0, "success"); + + private static final Map byName = new HashMap(); + + 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 0: // SUCCESS + return SUCCESS; + 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 + 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.SUCCESS, new org.apache.thrift.meta_data.FieldMetaData("success", org.apache.thrift.TFieldRequirementType.DEFAULT, + new org.apache.thrift.meta_data.StructMetaData(org.apache.thrift.protocol.TType.STRUCT, LogConfig.class))); + metaDataMap = Collections.unmodifiableMap(tmpMap); + org.apache.thrift.meta_data.FieldMetaData.addStructMetaDataMap(getLogConfig_result.class, metaDataMap); + } + + public getLogConfig_result() { + } + + public getLogConfig_result( + LogConfig success) + { + this(); + this.success = success; + } + + /** + * Performs a deep copy on other. + */ + public getLogConfig_result(getLogConfig_result other) { + if (other.is_set_success()) { + this.success = new LogConfig(other.success); + } + } + + public getLogConfig_result deepCopy() { + return new getLogConfig_result(this); + } + + @Override + public void clear() { + this.success = null; + } + + public LogConfig get_success() { + return this.success; + } + + public void set_success(LogConfig success) { + this.success = success; + } + + public void unset_success() { + this.success = null; + } + + /** Returns true if field success is set (has been assigned a value) and false otherwise */ + public boolean is_set_success() { + return this.success != null; + } + + public void set_success_isSet(boolean value) { + if (!value) { + this.success = null; + } + } + + public void setFieldValue(_Fields field, Object value) { + switch (field) { + case SUCCESS: + if (value == null) { + unset_success(); + } else { + set_success((LogConfig)value); + } + break; + + } + } + + public Object getFieldValue(_Fields field) { + switch (field) { + case SUCCESS: + return get_success(); + + } + 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 SUCCESS: + return is_set_success(); + } + throw new IllegalStateException(); + } + + @Override + public boolean equals(Object that) { + if (that == null) + return false; + if (that instanceof getLogConfig_result) + return this.equals((getLogConfig_result)that); + return false; + } + + public boolean equals(getLogConfig_result that) { + if (that == null) + return false; + + boolean this_present_success = true && this.is_set_success(); + boolean that_present_success = true && that.is_set_success(); + if (this_present_success || that_present_success) { + if (!(this_present_success && that_present_success)) + return false; + if (!this.success.equals(that.success)) + return false; + } + + return true; + } + + @Override + public int hashCode() { + List list = new ArrayList(); + + boolean present_success = true && (is_set_success()); + list.add(present_success); + if (present_success) + list.add(success); + + return list.hashCode(); + } + + @Override + public int compareTo(getLogConfig_result other) { + if (!getClass().equals(other.getClass())) { + return getClass().getName().compareTo(other.getClass().getName()); + } + + int lastComparison = 0; + + lastComparison = Boolean.valueOf(is_set_success()).compareTo(other.is_set_success()); + if (lastComparison != 0) { + return lastComparison; + } + if (is_set_success()) { + lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.success, other.success); + 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("getLogConfig_result("); + boolean first = true; + + sb.append("success:"); + if (this.success == null) { + sb.append("null"); + } else { + sb.append(this.success); + } + first = false; + sb.append(")"); + return sb.toString(); + } + + public void validate() throws org.apache.thrift.TException { + // check for required fields + // check for sub-struct validity + if (success != null) { + success.validate(); + } + } + + 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 getLogConfig_resultStandardSchemeFactory implements SchemeFactory { + public getLogConfig_resultStandardScheme getScheme() { + return new getLogConfig_resultStandardScheme(); + } + } + + private static class getLogConfig_resultStandardScheme extends StandardScheme { + + public void read(org.apache.thrift.protocol.TProtocol iprot, getLogConfig_result 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 0: // SUCCESS + if (schemeField.type == org.apache.thrift.protocol.TType.STRUCT) { + struct.success = new LogConfig(); + struct.success.read(iprot); + struct.set_success_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, getLogConfig_result struct) throws org.apache.thrift.TException { + struct.validate(); + + oprot.writeStructBegin(STRUCT_DESC); + if (struct.success != null) { + oprot.writeFieldBegin(SUCCESS_FIELD_DESC); + struct.success.write(oprot); + oprot.writeFieldEnd(); + } + oprot.writeFieldStop(); + oprot.writeStructEnd(); + } + + } + + private static class getLogConfig_resultTupleSchemeFactory implements SchemeFactory { + public getLogConfig_resultTupleScheme getScheme() { + return new getLogConfig_resultTupleScheme(); + } + } + + private static class getLogConfig_resultTupleScheme extends TupleScheme { + + @Override + public void write(org.apache.thrift.protocol.TProtocol prot, getLogConfig_result struct) throws org.apache.thrift.TException { + TTupleProtocol oprot = (TTupleProtocol) prot; + BitSet optionals = new BitSet(); + if (struct.is_set_success()) { + optionals.set(0); + } + oprot.writeBitSet(optionals, 1); + if (struct.is_set_success()) { + struct.success.write(oprot); + } + } + + @Override + public void read(org.apache.thrift.protocol.TProtocol prot, getLogConfig_result struct) throws org.apache.thrift.TException { + TTupleProtocol iprot = (TTupleProtocol) prot; + BitSet incoming = iprot.readBitSet(1); + if (incoming.get(0)) { + struct.success = new LogConfig(); + struct.success.read(iprot); + struct.set_success_isSet(true); + } + } + } + + } + public static class debug_args implements org.apache.thrift.TBase, java.io.Serializable, Cloneable, Comparable { private static final org.apache.thrift.protocol.TStruct STRUCT_DESC = new org.apache.thrift.protocol.TStruct("debug_args"); diff --git a/storm-core/src/py/storm/Nimbus-remote b/storm-core/src/py/storm/Nimbus-remote index fff63f922a2..c5b4b0c5d54 100644 --- a/storm-core/src/py/storm/Nimbus-remote +++ b/storm-core/src/py/storm/Nimbus-remote @@ -49,6 +49,8 @@ if len(sys.argv) <= 1 or sys.argv[1] == '--help': print(' void activate(string name)') print(' void deactivate(string name)') print(' void rebalance(string name, RebalanceOptions options)') + print(' void setLogConfig(string name, LogConfig config)') + print(' LogConfig getLogConfig(string name)') print(' void debug(string name, string component, bool enable, double samplingPercentage)') print(' void uploadNewCredentials(string name, Credentials creds)') print(' string beginFileUpload()') @@ -161,6 +163,18 @@ elif cmd == 'rebalance': sys.exit(1) pp.pprint(client.rebalance(args[0],eval(args[1]),)) +elif cmd == 'setLogConfig': + if len(args) != 2: + print('setLogConfig requires 2 args') + sys.exit(1) + pp.pprint(client.setLogConfig(args[0],eval(args[1]),)) + +elif cmd == 'getLogConfig': + if len(args) != 1: + print('getLogConfig requires 1 args') + sys.exit(1) + pp.pprint(client.getLogConfig(args[0],)) + elif cmd == 'debug': if len(args) != 4: print('debug requires 4 args') diff --git a/storm-core/src/py/storm/Nimbus.py b/storm-core/src/py/storm/Nimbus.py index 0caeed0dedb..cf7adbf47c5 100644 --- a/storm-core/src/py/storm/Nimbus.py +++ b/storm-core/src/py/storm/Nimbus.py @@ -94,6 +94,21 @@ def rebalance(self, name, options): """ pass + def setLogConfig(self, name, config): + """ + Parameters: + - name + - config + """ + pass + + def getLogConfig(self, name): + """ + Parameters: + - name + """ + pass + def debug(self, name, component, enable, samplingPercentage): """ Enable/disable logging the tuples generated in topology via an internal EventLogger bolt. The component name is optional @@ -102,7 +117,6 @@ def debug(self, name, component, enable, samplingPercentage): The 'samplingPercentage' will limit loggging to a percentage of generated tuples. - Parameters: - name - component @@ -460,12 +474,74 @@ def recv_rebalance(self): raise result.aze return + def setLogConfig(self, name, config): + """ + Parameters: + - name + - config + """ + self.send_setLogConfig(name, config) + self.recv_setLogConfig() + + def send_setLogConfig(self, name, config): + self._oprot.writeMessageBegin('setLogConfig', TMessageType.CALL, self._seqid) + args = setLogConfig_args() + args.name = name + args.config = config + args.write(self._oprot) + self._oprot.writeMessageEnd() + self._oprot.trans.flush() + + def recv_setLogConfig(self): + iprot = self._iprot + (fname, mtype, rseqid) = iprot.readMessageBegin() + if mtype == TMessageType.EXCEPTION: + x = TApplicationException() + x.read(iprot) + iprot.readMessageEnd() + raise x + result = setLogConfig_result() + result.read(iprot) + iprot.readMessageEnd() + return + + def getLogConfig(self, name): + """ + Parameters: + - name + """ + self.send_getLogConfig(name) + return self.recv_getLogConfig() + + def send_getLogConfig(self, name): + self._oprot.writeMessageBegin('getLogConfig', TMessageType.CALL, self._seqid) + args = getLogConfig_args() + args.name = name + args.write(self._oprot) + self._oprot.writeMessageEnd() + self._oprot.trans.flush() + + def recv_getLogConfig(self): + iprot = self._iprot + (fname, mtype, rseqid) = iprot.readMessageBegin() + if mtype == TMessageType.EXCEPTION: + x = TApplicationException() + x.read(iprot) + iprot.readMessageEnd() + raise x + result = getLogConfig_result() + result.read(iprot) + iprot.readMessageEnd() + if result.success is not None: + return result.success + raise TApplicationException(TApplicationException.MISSING_RESULT, "getLogConfig failed: unknown result"); + def debug(self, name, component, enable, samplingPercentage): """ Enable/disable logging the tuples generated in topology via an internal EventLogger bolt. The component name is optional and if null or empty, the debug flag will apply to the entire topology. - If 'samplingPercentage' is specified, it will limit loggging to a percentage of generated tuples. The default is to log all (100 pct). + The 'samplingPercentage' will limit loggging to a percentage of generated tuples. Parameters: @@ -949,6 +1025,8 @@ def __init__(self, handler): self._processMap["activate"] = Processor.process_activate self._processMap["deactivate"] = Processor.process_deactivate self._processMap["rebalance"] = Processor.process_rebalance + self._processMap["setLogConfig"] = Processor.process_setLogConfig + self._processMap["getLogConfig"] = Processor.process_getLogConfig self._processMap["debug"] = Processor.process_debug self._processMap["uploadNewCredentials"] = Processor.process_uploadNewCredentials self._processMap["beginFileUpload"] = Processor.process_beginFileUpload @@ -1097,6 +1175,28 @@ def process_rebalance(self, seqid, iprot, oprot): oprot.writeMessageEnd() oprot.trans.flush() + def process_setLogConfig(self, seqid, iprot, oprot): + args = setLogConfig_args() + args.read(iprot) + iprot.readMessageEnd() + result = setLogConfig_result() + self._handler.setLogConfig(args.name, args.config) + oprot.writeMessageBegin("setLogConfig", TMessageType.REPLY, seqid) + result.write(oprot) + oprot.writeMessageEnd() + oprot.trans.flush() + + def process_getLogConfig(self, seqid, iprot, oprot): + args = getLogConfig_args() + args.read(iprot) + iprot.readMessageEnd() + result = getLogConfig_result() + result.success = self._handler.getLogConfig(args.name) + oprot.writeMessageBegin("getLogConfig", TMessageType.REPLY, seqid) + result.write(oprot) + oprot.writeMessageEnd() + oprot.trans.flush() + def process_debug(self, seqid, iprot, oprot): args = debug_args() args.read(iprot) @@ -2491,6 +2591,261 @@ def __eq__(self, other): def __ne__(self, other): return not (self == other) +class setLogConfig_args: + """ + Attributes: + - name + - config + """ + + thrift_spec = ( + None, # 0 + (1, TType.STRING, 'name', None, None, ), # 1 + (2, TType.STRUCT, 'config', (LogConfig, LogConfig.thrift_spec), None, ), # 2 + ) + + def __init__(self, name=None, config=None,): + self.name = name + self.config = config + + 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.STRING: + self.name = iprot.readString().decode('utf-8') + else: + iprot.skip(ftype) + elif fid == 2: + if ftype == TType.STRUCT: + self.config = LogConfig() + self.config.read(iprot) + 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('setLogConfig_args') + if self.name is not None: + oprot.writeFieldBegin('name', TType.STRING, 1) + oprot.writeString(self.name.encode('utf-8')) + oprot.writeFieldEnd() + if self.config is not None: + oprot.writeFieldBegin('config', TType.STRUCT, 2) + self.config.write(oprot) + oprot.writeFieldEnd() + oprot.writeFieldStop() + oprot.writeStructEnd() + + def validate(self): + return + + + def __hash__(self): + value = 17 + value = (value * 31) ^ hash(self.name) + value = (value * 31) ^ hash(self.config) + 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 setLogConfig_result: + + thrift_spec = ( + ) + + 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 + 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('setLogConfig_result') + oprot.writeFieldStop() + oprot.writeStructEnd() + + def validate(self): + return + + + def __hash__(self): + value = 17 + 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 getLogConfig_args: + """ + Attributes: + - name + """ + + thrift_spec = ( + None, # 0 + (1, TType.STRING, 'name', None, None, ), # 1 + ) + + def __init__(self, name=None,): + self.name = name + + 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.STRING: + self.name = 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('getLogConfig_args') + if self.name is not None: + oprot.writeFieldBegin('name', TType.STRING, 1) + oprot.writeString(self.name.encode('utf-8')) + oprot.writeFieldEnd() + oprot.writeFieldStop() + oprot.writeStructEnd() + + def validate(self): + return + + + def __hash__(self): + value = 17 + value = (value * 31) ^ hash(self.name) + 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 getLogConfig_result: + """ + Attributes: + - success + """ + + thrift_spec = ( + (0, TType.STRUCT, 'success', (LogConfig, LogConfig.thrift_spec), None, ), # 0 + ) + + def __init__(self, success=None,): + self.success = success + + 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 == 0: + if ftype == TType.STRUCT: + self.success = LogConfig() + self.success.read(iprot) + 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('getLogConfig_result') + if self.success is not None: + oprot.writeFieldBegin('success', TType.STRUCT, 0) + self.success.write(oprot) + oprot.writeFieldEnd() + oprot.writeFieldStop() + oprot.writeStructEnd() + + def validate(self): + return + + + def __hash__(self): + value = 17 + value = (value * 31) ^ hash(self.success) + 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 debug_args: """ Attributes: diff --git a/storm-core/src/py/storm/ttypes.py b/storm-core/src/py/storm/ttypes.py index 4f484490075..18818583d08 100644 --- a/storm-core/src/py/storm/ttypes.py +++ b/storm-core/src/py/storm/ttypes.py @@ -85,6 +85,23 @@ class NumErrorsChoice: "ONE": 2, } +class LogLevelAction: + UNCHANGED = 1 + UPDATE = 2 + REMOVE = 3 + + _VALUES_TO_NAMES = { + 1: "UNCHANGED", + 2: "UPDATE", + 3: "REMOVE", + } + + _NAMES_TO_VALUES = { + "UNCHANGED": 1, + "UPDATE": 2, + "REMOVE": 3, + } + class JavaObjectArg: """ @@ -6348,6 +6365,202 @@ def __eq__(self, other): 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 + 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) + 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: diff --git a/storm-core/src/storm.thrift b/storm-core/src/storm.thrift index f6876816aed..eba9fcda505 100644 --- a/storm-core/src/storm.thrift +++ b/storm-core/src/storm.thrift @@ -358,6 +358,38 @@ struct GetInfoOptions { 1: optional NumErrorsChoice num_err_choice; } +enum LogLevelAction { + UNCHANGED = 1, + UPDATE = 2, + REMOVE = 3 +} + +struct LogLevel { + 1: required LogLevelAction action; + + // during this thrift call, we'll move logger to target_log_level + 2: optional string target_log_level; + + // number of seconds that target_log_level should be kept + // after this timeout, the loggers will be reset to reset_log_level + // if timeout is 0, we will not reset + 3: optional i32 reset_log_level_timeout_secs; + + // number of seconds since unix epoch corresponding to + // current time (when message gets to nimbus) + reset_log_level_timeout_se + // NOTE: this field gets set in Nimbus + 4: optional i64 reset_log_level_timeout_epoch; + + // if reset timeout was set, then we would reset + // to this level after timeout (or INFO by default) + 5: optional string reset_log_level; +} + +struct LogConfig { + // logger name -> log level map + 2: optional map named_logger_level; +} + service Nimbus { void submitTopology(1: string name, 2: string uploadedJarLocation, 3: string jsonConf, 4: StormTopology topology) throws (1: AlreadyAliveException e, 2: InvalidTopologyException ite, 3: AuthorizationException aze); void submitTopologyWithOpts(1: string name, 2: string uploadedJarLocation, 3: string jsonConf, 4: StormTopology topology, 5: SubmitOptions options) throws (1: AlreadyAliveException e, 2: InvalidTopologyException ite, 3: AuthorizationException aze); @@ -366,6 +398,11 @@ service Nimbus { void activate(1: string name) throws (1: NotAliveException e, 2: AuthorizationException aze); void deactivate(1: string name) throws (1: NotAliveException e, 2: AuthorizationException aze); void rebalance(1: string name, 2: RebalanceOptions options) throws (1: NotAliveException e, 2: InvalidTopologyException ite, 3: AuthorizationException aze); + + // dynamic log levels + void setLogConfig(1: string name, 2: LogConfig config); + LogConfig getLogConfig(1: string name); + /** * Enable/disable logging the tuples generated in topology via an internal EventLogger bolt. The component name is optional * and if null or empty, the debug flag will apply to the entire topology. From 250ab1132e5cb26ac9cf1af5c47cbaf98390923a Mon Sep 17 00:00:00 2001 From: Kishor Patil Date: Fri, 25 Sep 2015 20:00:45 +0000 Subject: [PATCH 2/5] Adding Dynamic Logger to UI, cli and supervisors --- bin/storm.py | 35 +++- conf/defaults.yaml | 3 + .../storm/starter/MultipleLoggerTopology.java | 105 ++++++++++ storm-core/src/clj/backtype/storm/cluster.clj | 35 +++- .../backtype/storm/command/set_log_level.clj | 75 ++++++++ .../src/clj/backtype/storm/daemon/nimbus.clj | 47 ++++- .../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 + .../auth/authorizer/SimpleACLAuthorizer.java | 2 +- storm-core/src/ui/public/css/style.css | 8 + storm-core/src/ui/public/js/script.js | 20 ++ .../templates/topology-page-template.html | 70 ++++++- storm-core/src/ui/public/topology.html | 149 ++++++++++++++- .../test/clj/backtype/storm/nimbus_test.clj | 56 +++++- .../clj/backtype/storm/supervisor_test.clj | 4 + .../test/clj/backtype/storm/worker_test.clj | 179 +++++++++++++++++- 18 files changed, 941 insertions(+), 18 deletions(-) create mode 100644 examples/storm-starter/src/jvm/storm/starter/MultipleLoggerTopology.java create mode 100644 storm-core/src/clj/backtype/storm/command/set_log_level.clj diff --git a/bin/storm.py b/bin/storm.py index 024912f4ac9..7b1dc835ef7 100755 --- a/bin/storm.py +++ b/bin/storm.py @@ -277,6 +277,39 @@ def activate(*args): jvmtype="-client", extrajars=[USER_CONF_DIR, STORM_BIN_DIR]) +def set_log_level(*args): + """ + Dynamically change topology log levels + + Syntax: [storm set_log_level -l [logger name]=[log level][:optional timeout] -r [logger name] + where log level is one of: + ALL, TRACE, DEBUG, INFO, WARN, ERROR, FATAL, OFF + and timeout is integer seconds. + + e.g. + ./bin/storm set_log_level -l ROOT=DEBUG:30 + + Set the root logger's level to DEBUG for 30 seconds + + ./bin/storm set_log_level -l com.myapp=WARN + + Set the com.myapp logger's level to WARN for 30 seconds + + ./bin/storm set_log_level -l com.myapp=WARN -l com.myOtherLogger=ERROR:123 + + Set the com.myapp logger's level to WARN indifinitely, and com.myOtherLogger + to ERROR for 123 seconds + + ./bin/storm set_log_level -r com.myOtherLogger + + Clears settings, resetting back to the original level + """ + exec_storm_class( + "backtype.storm.command.set_log_level", + args=args, + jvmtype="-client", + extrajars=[USER_CONF_DIR, STORM_BIN_DIR]) + def listtopos(*args): """Syntax: [storm list] @@ -561,7 +594,7 @@ def unknown_command(*args): "remoteconfvalue": print_remoteconfvalue, "repl": repl, "classpath": print_classpath, "activate": activate, "deactivate": deactivate, "rebalance": rebalance, "help": print_usage, "list": listtopos, "dev-zookeeper": dev_zookeeper, "version": version, "monitor": monitor, - "upload-credentials": upload_credentials, "get-errors": get_errors } + "upload-credentials": upload_credentials, "get-errors": get_errors, "set_log_level": set_log_level } def parse_config(config_list): global CONFIG_OPTS diff --git a/conf/defaults.yaml b/conf/defaults.yaml index 43ef8f413ef..4a8e354b1ea 100644 --- a/conf/defaults.yaml +++ b/conf/defaults.yaml @@ -138,6 +138,9 @@ worker.childopts: "-Xmx768m" worker.gc.childopts: "" worker.heartbeat.frequency.secs: 1 +# check whether dynamic log levels can be reset from DEBUG to INFO in workers +worker.log.level.reset.poll.secs: 30 + # control how many worker receiver threads we need per worker topology.worker.receiver.thread.count: 1 diff --git a/examples/storm-starter/src/jvm/storm/starter/MultipleLoggerTopology.java b/examples/storm-starter/src/jvm/storm/starter/MultipleLoggerTopology.java new file mode 100644 index 00000000000..4285ff9f4a5 --- /dev/null +++ b/examples/storm-starter/src/jvm/storm/starter/MultipleLoggerTopology.java @@ -0,0 +1,105 @@ +/** + * 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. + */ +package storm.starter; + +import backtype.storm.Config; +import backtype.storm.LocalCluster; +import backtype.storm.StormSubmitter; +import backtype.storm.task.OutputCollector; +import backtype.storm.task.TopologyContext; +import backtype.storm.testing.TestWordSpout; +import backtype.storm.topology.OutputFieldsDeclarer; +import backtype.storm.topology.TopologyBuilder; +import backtype.storm.topology.base.BaseRichBolt; +import backtype.storm.tuple.Fields; +import backtype.storm.tuple.Tuple; +import backtype.storm.tuple.Values; +import backtype.storm.utils.Utils; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.List; +import java.util.Map; + +/** + * This is a basic example of a Storm topology. + */ +public class MultipleLoggerTopology { + public static class ExclamationLoggingBolt extends BaseRichBolt { + OutputCollector _collector; + Logger _rootLogger = LoggerFactory.getLogger (Logger.ROOT_LOGGER_NAME); + // ensure the loggers are configured in the worker.xml before + // trying to use them here + Logger _logger = LoggerFactory.getLogger ("com.myapp"); + Logger _subLogger = LoggerFactory.getLogger ("com.myapp.sub"); + + @Override + public void prepare(Map conf, TopologyContext context, OutputCollector collector) { + _collector = collector; + } + + @Override + public void execute(Tuple tuple) { + _rootLogger.debug ("root: This is a DEBUG message"); + _rootLogger.info ("root: This is an INFO message"); + _rootLogger.warn ("root: This is a WARN message"); + _rootLogger.error ("root: This is an ERROR message"); + + _logger.debug ("myapp: This is a DEBUG message"); + _logger.info ("myapp: This is an INFO message"); + _logger.warn ("myapp: This is a WARN message"); + _logger.error ("myapp: This is an ERROR message"); + + _subLogger.debug ("myapp.sub: This is a DEBUG message"); + _subLogger.info ("myapp.sub: This is an INFO message"); + _subLogger.warn ("myapp.sub: This is a WARN message"); + _subLogger.error ("myapp.sub: This is an ERROR message"); + + _collector.emit(tuple, new Values(tuple.getString(0) + "!!!")); + _collector.ack(tuple); + } + + @Override + public void declareOutputFields(OutputFieldsDeclarer declarer) { + declarer.declare(new Fields("word")); + } + } + + public static void main(String[] args) throws Exception { + TopologyBuilder builder = new TopologyBuilder(); + + builder.setSpout("word", new TestWordSpout(), 10); + builder.setBolt("exclaim1", new ExclamationLoggingBolt(), 3).shuffleGrouping("word"); + builder.setBolt("exclaim2", new ExclamationLoggingBolt(), 2).shuffleGrouping("exclaim1"); + + Config conf = new Config(); + conf.setDebug(true); + + if (args != null && args.length > 0) { + conf.setNumWorkers(2); + StormSubmitter.submitTopologyWithProgressBar(args[0], conf, builder.createTopology()); + } else { + LocalCluster cluster = new LocalCluster(); + cluster.submitTopology("test", conf, builder.createTopology()); + Utils.sleep(10000); + cluster.killTopology("test"); + cluster.shutdown(); + } + } +} diff --git a/storm-core/src/clj/backtype/storm/cluster.clj b/storm-core/src/clj/backtype/storm/cluster.clj index 99fb49e436a..77c576fcdb0 100644 --- a/storm-core/src/clj/backtype/storm/cluster.clj +++ b/storm-core/src/clj/backtype/storm/cluster.clj @@ -16,7 +16,8 @@ (ns backtype.storm.cluster (:import [org.apache.zookeeper.data Stat ACL Id] - [backtype.storm.generated SupervisorInfo Assignment StormBase ClusterWorkerHeartbeat ErrorInfo Credentials NimbusSummary] + [backtype.storm.generated SupervisorInfo Assignment StormBase ClusterWorkerHeartbeat ErrorInfo Credentials NimbusSummary + LogConfig] [java.io Serializable]) (:import [org.apache.zookeeper KeeperException KeeperException$NoNodeException ZooDefs ZooDefs$Ids ZooDefs$Perms]) (:import [org.apache.curator.framework.state ConnectionStateListener ConnectionState]) @@ -176,8 +177,11 @@ (setup-heartbeats! [this storm-id]) (teardown-heartbeats! [this storm-id]) (teardown-topology-errors! [this storm-id]) + (teardown-topology-log-config! [this storm-id]) (heartbeat-storms [this]) (error-topologies [this]) + (set-topology-log-config! [this storm-id log-config]) + (topology-log-config [this storm-id cb]) (worker-heartbeat! [this storm-id node port info]) (remove-worker-heartbeat! [this storm-id node port]) (supervisor-heartbeat! [this supervisor-id info]) @@ -209,7 +213,7 @@ (def CODE-DISTRIBUTOR-ROOT "code-distributor") (def NIMBUSES-ROOT "nimbuses") (def CREDENTIALS-ROOT "credentials") - +(def LOGCONFIG-ROOT "logconfigs") (def ASSIGNMENTS-SUBTREE (str "/" ASSIGNMENTS-ROOT)) (def STORMS-SUBTREE (str "/" STORMS-ROOT)) @@ -220,6 +224,7 @@ (def CODE-DISTRIBUTOR-SUBTREE (str "/" CODE-DISTRIBUTOR-ROOT)) (def NIMBUSES-SUBTREE (str "/" NIMBUSES-ROOT)) (def CREDENTIALS-SUBTREE (str "/" CREDENTIALS-ROOT)) +(def LOGCONFIG-SUBTREE (str "/" LOGCONFIG-ROOT)) (defn supervisor-path [id] @@ -279,6 +284,10 @@ [storm-id] (str CREDENTIALS-SUBTREE "/" storm-id)) +(defn log-config-path + [storm-id] + (str LOGCONFIG-SUBTREE "/" storm-id)) + (defn- issue-callback! [cb-atom] (let [cb @cb-atom] @@ -332,6 +341,7 @@ storm-base-callback (atom {}) code-distributor-callback (atom nil) credentials-callback (atom {}) + log-config-callback (atom {}) state-id (register cluster-state (fn [type path] @@ -347,10 +357,12 @@ CODE-DISTRIBUTOR-ROOT (issue-callback! code-distributor-callback) STORMS-ROOT (issue-map-callback! storm-base-callback (first args)) CREDENTIALS-ROOT (issue-map-callback! credentials-callback (first args)) + LOGCONFIG-ROOT (issue-map-callback! log-config-callback (first args)) BACKPRESSURE-ROOT (issue-map-callback! backpressure-callback (first args)) ;; this should never happen (exit-process! 30 "Unknown callback for subtree " subtree args)))))] - (doseq [p [ASSIGNMENTS-SUBTREE STORMS-SUBTREE SUPERVISORS-SUBTREE WORKERBEATS-SUBTREE ERRORS-SUBTREE CODE-DISTRIBUTOR-SUBTREE NIMBUSES-SUBTREE]] + (doseq [p [ASSIGNMENTS-SUBTREE STORMS-SUBTREE SUPERVISORS-SUBTREE WORKERBEATS-SUBTREE ERRORS-SUBTREE CODE-DISTRIBUTOR-SUBTREE NIMBUSES-SUBTREE + LOGCONFIG-SUBTREE]] (mkdirs cluster-state p acls)) (reify StormClusterState @@ -461,6 +473,16 @@ [this supervisor-id] (clojurify-supervisor-info (maybe-deserialize (get-data cluster-state (supervisor-path supervisor-id) false) SupervisorInfo))) + (topology-log-config + [this storm-id cb] + (when cb + (swap! log-config-callback assoc storm-id cb)) + (maybe-deserialize (.get_data cluster-state (log-config-path storm-id) (not-nil? cb)) LogConfig)) + + (set-topology-log-config! + [this storm-id log-config] + (.set_data cluster-state (log-config-path storm-id) (Utils/serialize log-config) acls)) + (worker-heartbeat! [this storm-id node port info] (let [thrift-worker-hb (thriftify-zk-worker-hb info)] @@ -518,6 +540,13 @@ (catch KeeperException e (log-warn-error e "Could not teardown errors for " storm-id)))) + (teardown-topology-log-config! + [this storm-id] + (try-cause + (.delete_node cluster-state (log-config-path storm-id)) + (catch KeeperException e + (log-warn-error e "Could not teardown log configs for " storm-id)))) + (supervisor-heartbeat! [this supervisor-id info] (let [thrift-supervisor-info (thriftify-supervisor-info info)] diff --git a/storm-core/src/clj/backtype/storm/command/set_log_level.clj b/storm-core/src/clj/backtype/storm/command/set_log_level.clj new file mode 100644 index 00000000000..3b50c3a0a03 --- /dev/null +++ b/storm-core/src/clj/backtype/storm/command/set_log_level.clj @@ -0,0 +1,75 @@ +;; 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. +(ns backtype.storm.command.set-log-level + (:use [clojure.tools.cli :only [cli]]) + (:use [backtype.storm thrift log]) + (:import [org.apache.logging.log4j Level]) + (:import [backtype.storm.generated LogConfig LogLevel LogLevelAction]) + (:gen-class)) + +(defn- get-storm-id + "Get topology id for a running topology from the topology name." + [nimbus name] + (let [info (.getClusterInfo nimbus) + topologies (.get_topologies info) + topology (first (filter (fn [topo] (= name (.get_name topo))) topologies))] + (if topology + (.get_id topology) + (throw (.IllegalArgumentException (str name " is not a running topology")))))) + +(defn- parse-named-log-levels [action] + "Parses [logger name]=[level string]:[optional timeout],[logger name2]... + + e.g. ROOT=DEBUG:30 + root logger, debug for 30 seconds + + org.apache.foo=WARN + org.apache.foo set to WARN indefinitely" + (fn [^String s] + (let [log-args (re-find #"(.*)=([A-Z]+):?(\d*)" s) + name (if (= action LogLevelAction/REMOVE) s (nth log-args 1)) + level (Level/toLevel (nth log-args 2)) + timeout-str (nth log-args 3) + log-level (LogLevel.)] + (if (= action LogLevelAction/REMOVE) + (.set_action log-level action) + (do + (.set_action log-level action) + (.set_target_log_level log-level (.toString level)) + (.set_reset_log_level_timeout_secs log-level + (Integer. (if (= timeout-str "") "0" timeout-str))))) + {name log-level}))) + +(defn- merge-together [previous key val] + (assoc previous key + (if-let [oldval (get previous key)] + (merge oldval val) + val))) + +(defn -main [& args] + (let [[{log-setting :log-setting remove-log-setting :remove-log-setting} [name] _] + (cli args ["-l" "--log-setting" + :parse-fn (parse-named-log-levels LogLevelAction/UPDATE) + :assoc-fn merge-together] + ["-r" "--remove-log-setting" + :parse-fn (parse-named-log-levels LogLevelAction/REMOVE) + :assoc-fn merge-together])] + (with-configured-nimbus-connection nimbus + (let [log-config (LogConfig.)] + (doseq [[log-name log-val] (merge log-setting remove-log-setting)] + (.put_to_named_logger_level log-config log-name log-val)) + (log-message "Sent log config " log-config " for topology " name) + (.setLogConfig nimbus (get-storm-id nimbus name) log-config))))) diff --git a/storm-core/src/clj/backtype/storm/daemon/nimbus.clj b/storm-core/src/clj/backtype/storm/daemon/nimbus.clj index 7ea515b595b..c797c4bd49a 100644 --- a/storm-core/src/clj/backtype/storm/daemon/nimbus.clj +++ b/storm-core/src/clj/backtype/storm/daemon/nimbus.clj @@ -35,7 +35,8 @@ (:import [backtype.storm.generated NotAliveException AlreadyAliveException StormTopology ErrorInfo ExecutorInfo InvalidTopologyException Nimbus$Iface Nimbus$Processor SubmitOptions TopologyInitialStatus KillOptions RebalanceOptions ClusterSummary SupervisorSummary TopologySummary TopologyInfo - ExecutorSummary AuthorizationException GetInfoOptions NumErrorsChoice]) + ExecutorSummary AuthorizationException GetInfoOptions NumErrorsChoice + 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]]) @@ -44,6 +45,8 @@ (:use [backtype.storm.daemon common]) (:import [org.apache.zookeeper data.ACL ZooDefs$Ids ZooDefs$Perms]) (:import [backtype.storm.utils VersionInfo]) + (:require [clj-time.core :as time]) + (:require [clj-time.coerce :as coerce]) (:gen-class :methods [^{:static true} [launch [backtype.storm.scheduler.INimbus] void]])) @@ -102,6 +105,7 @@ NIMBUS-ZK-ACLS)) :submit-lock (Object.) :cred-update-lock (Object.) + :log-update-lock (Object.) :heartbeats-cache (atom {}) :downloaders (file-cache-map conf) :uploaders (file-cache-map conf) @@ -927,6 +931,7 @@ (if (:code-distributor nimbus) (.cleanup (:code-distributor nimbus) id)) (.teardown-heartbeats! storm-cluster-state id) (.teardown-topology-errors! storm-cluster-state id) + (.teardown-topology-log-config! storm-cluster-state id) (rmr (master-stormdist-root conf id)) (swap! (:heartbeats-cache nimbus) dissoc id)) ))) @@ -1067,6 +1072,13 @@ (InvalidTopologyException. (str "Failed to submit topology. Topology requests more than " workers-allowed " workers.")))))) +(defn- set-logger-timeouts [log-config] + (let [timeout-secs (.get_reset_log_level_timeout_secs log-config) + timeout (time/plus (time/now) (time/secs timeout-secs))] + (if (time/after? timeout (time/now)) + (.set_reset_log_level_timeout_epoch log-config (coerce/to-long timeout)) + (.unset_reset_log_level_timeout_epoch log-config)))) + (defserverfn service-handler [conf inimbus] (.prepare inimbus conf (master-inimbus-dir conf)) (log-message "Starting Nimbus with conf " conf) @@ -1265,6 +1277,31 @@ (locking (:submit-lock nimbus) (.update-storm! storm-cluster-state storm-id storm-base-updates)))) + (^void setLogConfig [this ^String id ^LogConfig log-config-msg] + (let [topology-conf (try-read-storm-conf conf id) + storm-name (topology-conf TOPOLOGY-NAME) + _ (check-authorization! nimbus storm-name topology-conf "setLogConfig") + storm-cluster-state (:storm-cluster-state nimbus) + merged-log-config (or (.topology-log-config storm-cluster-state id nil) (LogConfig.)) + named-loggers (.get_named_logger_level merged-log-config)] + (doseq [[_ level] named-loggers] + (.set_action level LogLevelAction/UNCHANGED)) + (doseq [[logger-name log-config] (.get_named_logger_level log-config-msg)] + (let [action (.get_action log-config)] + (if (clojure.string/blank? logger-name) + (throw (RuntimeException. "Named loggers need a valid name. Use ROOT for the root logger"))) + (condp = action + LogLevelAction/UPDATE + (do (set-logger-timeouts log-config) + (.put_to_named_logger_level merged-log-config logger-name log-config)) + LogLevelAction/REMOVE + (let [named-loggers (.get_named_logger_level merged-log-config)] + (if (and (not (nil? named-loggers)) + (.containsKey named-loggers logger-name)) + (.remove named-loggers logger-name)))))) + (log-message "Setting log config for " storm-name ":" merged-log-config) + (.set-topology-log-config! storm-cluster-state id merged-log-config))) + (uploadNewCredentials [this storm-name credentials] (let [storm-cluster-state (:storm-cluster-state nimbus) storm-id (get-storm-id storm-cluster-state storm-name) @@ -1333,6 +1370,14 @@ (check-authorization! nimbus nil nil "getNimbusConf") (to-json (:conf nimbus))) + (^LogConfig getLogConfig [this ^String id] + (let [topology-conf (try-read-storm-conf conf id) + storm-name (topology-conf TOPOLOGY-NAME) + _ (check-authorization! nimbus storm-name topology-conf "getLogConfig") + storm-cluster-state (:storm-cluster-state nimbus) + log-config (.topology-log-config storm-cluster-state id nil)] + (if log-config log-config (LogConfig.)))) + (^String getTopologyConf [this ^String id] (let [topology-conf (try-read-storm-conf conf id) storm-name (topology-conf TOPOLOGY-NAME)] diff --git a/storm-core/src/clj/backtype/storm/daemon/supervisor.clj b/storm-core/src/clj/backtype/storm/daemon/supervisor.clj index 2a7613d2ef2..f7c4c0bc292 100644 --- a/storm-core/src/clj/backtype/storm/daemon/supervisor.clj +++ b/storm-core/src/clj/backtype/storm/daemon/supervisor.clj @@ -698,6 +698,7 @@ (str "-Dworker.port=" port) (str "-Dstorm.log.dir=" storm-log-dir) (str "-Dlog4j.configurationFile=" storm-log4j2-conf-dir file-path-separator "worker.xml") + (str "-DLog4jContextSelector=org.apache.logging.log4j.core.selector.BasicContextSelector") "backtype.storm.LogWriter"] [(java-cmd) "-server"] worker-childopts @@ -711,6 +712,7 @@ (str "-Dstorm.log.dir=" storm-log-dir) (str "-Dlogging.sensitivity=" logging-sensitivity) (str "-Dlog4j.configurationFile=" storm-log4j2-conf-dir file-path-separator "worker.xml") + (str "-DLog4jContextSelector=org.apache.logging.log4j.core.selector.BasicContextSelector") (str "-Dstorm.id=" storm-id) (str "-Dworker.id=" worker-id) (str "-Dworker.port=" port) diff --git a/storm-core/src/clj/backtype/storm/daemon/worker.clj b/storm-core/src/clj/backtype/storm/daemon/worker.clj index 781a9599c01..40b43ef2654 100644 --- a/storm-core/src/clj/backtype/storm/daemon/worker.clj +++ b/storm-core/src/clj/backtype/storm/daemon/worker.clj @@ -16,6 +16,8 @@ (ns backtype.storm.daemon.worker (:use [backtype.storm.daemon common]) (:use [backtype.storm config log util timer local-state]) + (:require [clj-time.core :as time]) + (:require [clj-time.coerce :as coerce]) (:require [backtype.storm.daemon [executor :as executor]]) (:require [backtype.storm [disruptor :as disruptor] [cluster :as cluster]]) (:require [clojure.set :as set]) @@ -34,6 +36,10 @@ (:import [backtype.storm.security.auth AuthUtils]) (:import [javax.security.auth Subject]) (:import [java.security PrivilegedExceptionAction]) + (:import [org.apache.logging.log4j LogManager]) + (:import [org.apache.logging.log4j Level]) + (:import [org.apache.logging.log4j.core.config LoggerConfig]) + (:import [backtype.storm.generated LogConfig LogLevelAction]) (:gen-class)) (defmulti mk-suicide-fn cluster-mode) @@ -265,6 +271,7 @@ :heartbeat-timer (mk-halting-timer "heartbeat-timer") :refresh-connections-timer (mk-halting-timer "refresh-connections-timer") :refresh-credentials-timer (mk-halting-timer "refresh-credentials-timer") + :reset-log-levels-timer (mk-halting-timer "reset-log-levels-timer") :refresh-active-timer (mk-halting-timer "refresh-active-timer") :executor-heartbeat-timer (mk-halting-timer "executor-heartbeat-timer") :user-timer (mk-halting-timer "user-timer") @@ -439,6 +446,85 @@ (assoc conf "java.security.auth.login.config" login_conf_file) conf)) +(defn- get-logger-levels [] + (into {} + (let [logger-config (.getConfiguration (LogManager/getContext false))] + (for [[logger-name logger] (.getLoggers logger-config)] + {logger-name (.getLevel logger)})))) + +(defn set-logger-level [logger-context logger-name new-level] + (let [config (.getConfiguration logger-context) + logger-config (.getLoggerConfig config logger-name)] + (if (not (= (.getName logger-config) logger-name)) + ;; create a new config. Make it additive (true) s.t. inherit + ;; parents appenders + (let [new-logger-config (LoggerConfig. logger-name new-level true)] + (log-message "Adding config for: " new-logger-config " with level: " new-level) + (.addLogger config logger-name new-logger-config)) + (do + (log-message "Setting " logger-config " log level to: " new-level) + (.setLevel logger-config new-level))))) + +;; function called on timer to reset log levels last set to DEBUG +;; also called from process-log-config-change +(defn reset-log-levels [latest-log-config-atom] + (let [latest-log-config @latest-log-config-atom + logger-context (LogManager/getContext false)] + (doseq [[logger-name logger-setting] (sort latest-log-config)] + (let [timeout (:timeout logger-setting) + target-log-level (:target-log-level logger-setting) + reset-log-level (:reset-log-level logger-setting)] + (when (> (coerce/to-long (time/now)) timeout) + (log-message logger-name ": Resetting level to " reset-log-level) + (set-logger-level logger-context logger-name reset-log-level) + (swap! latest-log-config-atom + (fn [prev] + (dissoc prev logger-name)))))) + (.updateLoggers logger-context))) + +;; when a new log level is received from zookeeper, this function is called +(defn process-log-config-change [latest-log-config original-log-levels log-config] + (when log-config + (log-debug "Processing received log config: " log-config) + ;; merge log configs together + (let [loggers (.get_named_logger_level log-config) + logger-context (LogManager/getContext false)] + (def new-log-configs + (into {} + ;; merge named log levels + (for [[msg-logger-name logger-level] loggers] + (let [logger-name (if (= msg-logger-name "ROOT") + LogManager/ROOT_LOGGER_NAME + msg-logger-name)] + ;; the new-timeouts map now contains logger => timeout + (when (.is_set_reset_log_level_timeout_epoch logger-level) + {logger-name {:action (.get_action logger-level) + :target-log-level (Level/toLevel (.get_target_log_level logger-level)) + :reset-log-level (or (.get @original-log-levels logger-name) (Level/INFO)) + :timeout (.get_reset_log_level_timeout_epoch logger-level)}}))))) + + ;; look for deleted log timeouts + (doseq [[logger-name logger-val] (sort @latest-log-config)] + (when (not (contains? new-log-configs logger-name)) + ;; if we had a timeout, but the timeout is no longer active + (set-logger-level + logger-context logger-name (:reset-log-level logger-val)))) + + ;; apply new log settings we just received + ;; the merged configs are only for the reset logic + (doseq [[msg-logger-name logger-level] (sort (into {} (.get_named_logger_level log-config)))] + (let [logger-name (if (= msg-logger-name "ROOT") + LogManager/ROOT_LOGGER_NAME + msg-logger-name) + level (Level/toLevel (.get_target_log_level logger-level)) + action (.get_action logger-level)] + (if (= action LogLevelAction/UPDATE) + (set-logger-level logger-context logger-name level)))) + + (.updateLoggers logger-context) + (reset! latest-log-config new-log-configs) + (log-debug "New merged log config is " @latest-log-config)))) + ;; TODO: should worker even take the storm-id as input? this should be ;; deducable from cluster state (by searching through assignments) ;; what about if there's inconsistency in assignments? -> but nimbus @@ -452,6 +538,13 @@ ;; process. supervisor will register it in this case (when (= :distributed (cluster-mode conf)) (touch (worker-pid-path conf worker-id (process-pid)))) + + (declare establish-log-setting-callback) + + ;; start out with empty list of timeouts + (def latest-log-config (atom {})) + (def original-log-levels (atom {})) + (let [storm-conf (read-supervisor-storm-conf conf storm-id) storm-conf (override-login-config-with-system-property storm-conf) acls (Utils/getWorkerACL storm-conf) @@ -577,7 +670,18 @@ (let [throttle-on (.topology-backpressure (:storm-cluster-state worker) storm-id cb)] (reset! (:throttle-on worker) throttle-on))) new-throttle-on (.topology-backpressure (:storm-cluster-state worker) storm-id callback)] - (reset! (:throttle-on worker) new-throttle-on)))] + (reset! (:throttle-on worker) new-throttle-on))) + check-log-config-changed (fn [] + (let [log-config (.topology-log-config (:storm-cluster-state worker) storm-id nil)] + (process-log-config-change latest-log-config original-log-levels log-config) + (establish-log-setting-callback)))] + (reset! original-log-levels (get-logger-levels)) + (log-message "Started with log levels: " @original-log-levels) + + (defn establish-log-setting-callback [] + (.topology-log-config (:storm-cluster-state worker) storm-id (fn [args] (check-log-config-changed)))) + + (establish-log-setting-callback) (.credentials (:storm-cluster-state worker) storm-id (fn [args] (check-credentials-changed))) (schedule-recurring (:refresh-credentials-timer worker) 0 (conf TASK-CREDENTIALS-POLL-SECS) (fn [& args] @@ -585,6 +689,7 @@ (if ((:storm-conf worker) TOPOLOGY-BACKPRESSURE-ENABLE) (check-throttle-changed)))) (schedule-recurring (:refresh-connections-timer worker) 0 (conf TASK-REFRESH-POLL-SECS) refresh-connections) + (schedule-recurring (:reset-log-levels-timer worker) 0 (conf WORKER-LOG-LEVEL-RESET-POLL-SECS) (fn [] (reset-log-levels latest-log-config))) (schedule-recurring (:refresh-active-timer worker) 0 (conf TASK-REFRESH-POLL-SECS) (partial refresh-storm-active worker)) (log-message "Worker has topology config " (redact-value (:storm-conf worker) STORM-ZOOKEEPER-TOPOLOGY-AUTH-PAYLOAD)) diff --git a/storm-core/src/clj/backtype/storm/ui/core.clj b/storm-core/src/clj/backtype/storm/ui/core.clj index 414bfb1e6bd..8d68f41383d 100644 --- a/storm-core/src/clj/backtype/storm/ui/core.clj +++ b/storm-core/src/clj/backtype/storm/ui/core.clj @@ -32,7 +32,8 @@ ExecutorStats ExecutorSummary ExecutorInfo TopologyInfo SpoutStats BoltStats ErrorInfo ClusterSummary SupervisorSummary TopologySummary Nimbus$Client StormTopology GlobalStreamId RebalanceOptions - KillOptions GetInfoOptions NumErrorsChoice DebugOptions]) + KillOptions GetInfoOptions NumErrorsChoice DebugOptions + LogConfig LogLevel LogLevelAction]) (:import [backtype.storm.security.auth AuthUtils ReqContext]) (:import [backtype.storm.generated AuthorizationException]) (:import [backtype.storm.security.auth AuthUtils]) @@ -43,6 +44,7 @@ [ring.util.response :as resp] [backtype.storm [thrift :as thrift]]) (:import [org.apache.commons.lang StringEscapeUtils]) + (:import [org.apache.logging.log4j Level]) (:gen-class)) (def ^:dynamic *STORM-CONF* (read-storm-config)) @@ -991,6 +993,26 @@ "eventLogLink" (event-log-link topology-id summ topology component secure?)} spec errors)))) +(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)))) @@ -1059,6 +1081,9 @@ (json-response (component-page id component (:window m) (check-include-sys? (:sys m)) user (= scheme :https)) (:callback m)))) + (GET "/api/v1/topology/:id/logconfig" [:as {:keys [cookies servlet-request]} id & m] + (assert-authorized-user servlet-request "getTopology" (topology-config id)) + (json-response (log-config id) (:callback m))) (POST "/api/v1/topology/:id/activate" [:as {:keys [cookies servlet-request]} id & m] (thrift/with-configured-nimbus-connection nimbus (assert-authorized-user servlet-request "activate" (topology-config id)) @@ -1137,6 +1162,34 @@ (.killTopologyWithOpts nimbus name options) (log-message "Killing topology '" name "' with wait time: " wait-time " secs"))) (json-response (topology-op-response id "kill") (m "callback"))) + + (POST "/api/v1/topology/:id/logconfig" [:as {:keys [cookies servlet-request]} id namedLoggerLevels & m] + (assert-authorized-user servlet-request "setLogConfig" (topology-config id)) + (thrift/with-configured-nimbus-connection + nimbus + (let [new-log-config (LogConfig.)] + (doseq [[key level] namedLoggerLevels] + (let [logger-name (str key) + target-level (.get level "target_level") + timeout (or (.get level "timeout") 0) + named-logger-level (LogLevel.)] + ;; if target-level is nil, do not set it, user wants to clear + (log-message "The target level for " logger-name " is " target-level) + (if (nil? target-level) + (do + (.set_action named-logger-level LogLevelAction/REMOVE) + (.unset_target_log_level named-logger-level)) + (do + (.set_action named-logger-level LogLevelAction/UPDATE) + ;; the toLevel here ensures the string we get is valid + (.set_target_log_level named-logger-level (.name (Level/toLevel target-level))) + (.set_reset_log_level_timeout_secs named-logger-level timeout))) + (log-message "Adding this " logger-name " " named-logger-level " to " new-log-config) + (.put_to_named_logger_level new-log-config logger-name named-logger-level))) + (log-message "Setting topology " id " log config " new-log-config) + (.setLogConfig nimbus id new-log-config) + (json-response (log-config id) (m "callback"))))) + (GET "/" [:as {cookies :cookies}] (resp/redirect "/index.html")) (route/resources "/") diff --git a/storm-core/src/jvm/backtype/storm/Config.java b/storm-core/src/jvm/backtype/storm/Config.java index 0eff51b1eae..7d6000841d5 100644 --- a/storm-core/src/jvm/backtype/storm/Config.java +++ b/storm-core/src/jvm/backtype/storm/Config.java @@ -1038,6 +1038,13 @@ public class Config extends HashMap { public static final String TASK_REFRESH_POLL_SECS = "task.refresh.poll.secs"; public static final Object TASK_REFRESH_POLL_SECS_SCHEMA = ConfigValidation.IntegerValidator; + /** + * How often a worker should check dynamic log level timeouts for expiration. + * For expired logger settings, the clean up polling task will reset the log levels + * to the original levels (detected at startup), and will clean up the timeout map + */ + public static final String WORKER_LOG_LEVEL_RESET_POLL_SECS = "worker.log.level.reset.poll.secs"; + public static final Object WORKER_LOG_LEVEL_RESET_POLL_SECS_SCHEMA = ConfigValidation.PositiveIntegerValidator; /** * How often a task should sync credentials, worst case. diff --git a/storm-core/src/jvm/backtype/storm/security/auth/authorizer/SimpleACLAuthorizer.java b/storm-core/src/jvm/backtype/storm/security/auth/authorizer/SimpleACLAuthorizer.java index e50a587d31c..e332a133d9f 100644 --- 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,7 +44,7 @@ public class SimpleACLAuthorizer implements IAuthorizer { protected Set _userCommands = new HashSet(Arrays.asList("submitTopology", "fileUpload", "getNimbusConf", "getClusterInfo")); protected Set _supervisorCommands = new HashSet(Arrays.asList("fileDownload")); - protected Set _topoCommands = new HashSet(Arrays.asList("killTopology","rebalance","activate","deactivate","getTopologyConf","getTopology","getUserTopology","getTopologyInfo","uploadNewCredentials")); + protected Set _topoCommands = new HashSet(Arrays.asList("killTopology","rebalance","activate","deactivate","getTopologyConf","getTopology","getUserTopology","getTopologyInfo","uploadNewCredentials","setLogConfig","getLogConfig")); protected Set _admins; protected Set _supervisors; diff --git a/storm-core/src/ui/public/css/style.css b/storm-core/src/ui/public/css/style.css index e058850a8e6..b4384574fb8 100644 --- a/storm-core/src/ui/public/css/style.css +++ b/storm-core/src/ui/public/css/style.css @@ -24,6 +24,14 @@ padding: 0.5em; } +#change-log-level select{ + width:10em; +} + +#change-log-level input.timeout_input{ + width:5em; +} + body, .dataTables_wrapper label, div.dataTables_info[role="status"], diff --git a/storm-core/src/ui/public/js/script.js b/storm-core/src/ui/public/js/script.js index fe8643d5b91..a880205a710 100644 --- a/storm-core/src/ui/public/js/script.js +++ b/storm-core/src/ui/public/js/script.js @@ -81,6 +81,26 @@ function ensureInt(n) { return isInt; } +function sendRequest(id, action, extra, body, cb){ + var opts = { + type:'POST', + url:'/api/v1/topology/' + id + '/' + action + }; + + if (body) { + opts.data = JSON.stringify(body); + opts.contentType = 'application/json; charset=utf-8'; + } + + opts.url += extra ? "/" + extra : ""; + + $.ajax(opts).always(function(data){ + cb (data); + }).fail (function(){ + alert("Error while communicating with Nimbus."); + }); +} + function confirmComponentAction(topologyId, componentId, componentName, action, param, defaultParamValue, paramText, actionText) { var opts = { type:'POST', diff --git a/storm-core/src/ui/public/templates/topology-page-template.html b/storm-core/src/ui/public/templates/topology-page-template.html index 3292ee00db2..f0cc82299cb 100644 --- a/storm-core/src/ui/public/templates/topology-page-template.html +++ b/storm-core/src/ui/public/templates/topology-page-template.html @@ -362,5 +362,73 @@

Topology actions

+

- \ No newline at end of file + + + + + + + diff --git a/storm-core/src/ui/public/topology.html b/storm-core/src/ui/public/topology.html index 2b1214cc01f..e873bb63519 100644 --- a/storm-core/src/ui/public/topology.html +++ b/storm-core/src/ui/public/topology.html @@ -82,6 +82,146 @@

Topology summary

- \ No newline at end of file + diff --git a/storm-core/test/clj/backtype/storm/nimbus_test.clj b/storm-core/test/clj/backtype/storm/nimbus_test.clj index 0645f392334..387a6914e83 100644 --- a/storm-core/test/clj/backtype/storm/nimbus_test.clj +++ b/storm-core/test/clj/backtype/storm/nimbus_test.clj @@ -24,7 +24,8 @@ (:import [backtype.storm.nimbus ILeaderElector NimbusInfo]) (:import [backtype.storm.generated Credentials NotAliveException SubmitOptions TopologyInitialStatus TopologyStatus AlreadyAliveException KillOptions RebalanceOptions - InvalidTopologyException AuthorizationException]) + InvalidTopologyException AuthorizationException + LogConfig LogLevel LogLevelAction]) (:import [java.util HashMap]) (:import [java.io File]) (:import [backtype.storm.utils Time]) @@ -1329,3 +1330,56 @@ {})] (submit-local-topology nimbus "t1" {TOPOLOGY-WORKERS 1} topology) (.debug nimbus "t1" "" true 100)))) + +;; if the user sends an empty log config, nimbus will say that all +;; log configs it contains are LogLevelAction/UNCHANGED +(deftest empty-save-config-results-in-all-unchanged-actions + (with-local-cluster [cluster] + (let [nimbus (:nimbus cluster) + previous-config (LogConfig.) + level (LogLevel.) + mock-config (LogConfig.)] + ;; send something with content to nimbus beforehand + (.set_target_log_level level "ERROR") + (.set_action level LogLevelAction/UPDATE) + (.put_to_named_logger_level previous-config "test" level) + (stubbing [nimbus/check-storm-active! nil + nimbus/try-read-storm-conf {}] + (.setLogConfig nimbus "foo" previous-config) + (.setLogConfig nimbus "foo" mock-config) + (let [saved-config (.getLogConfig nimbus "foo") + levels (.get_named_logger_level saved-config)] + (is (= (.get_action (.get levels "test")) LogLevelAction/UNCHANGED))))))) + +(deftest log-level-update-merges-and-flags-existent-log-level + (with-local-cluster [cluster] + (stubbing [nimbus/check-storm-active! nil + nimbus/try-read-storm-conf {}] + (let [nimbus (:nimbus cluster) + previous-config (LogConfig.) + level (LogLevel.) + other-level (LogLevel.) + mock-config (LogConfig.)] + ;; send something with content to nimbus beforehand + (.set_target_log_level level "ERROR") + (.set_action level LogLevelAction/UPDATE) + (.put_to_named_logger_level previous-config "test" level) + + (.set_target_log_level other-level "DEBUG") + (.set_action other-level LogLevelAction/UPDATE) + (.put_to_named_logger_level previous-config "other-test" other-level) + (.setLogConfig nimbus "foo" previous-config) + + ;; only change "test" + (.set_target_log_level level "INFO") + (.set_action level LogLevelAction/UPDATE) + (.put_to_named_logger_level mock-config "test" level) + (.setLogConfig nimbus "foo" mock-config) + + (let [saved-config (.getLogConfig nimbus "foo") + levels (.get_named_logger_level saved-config)] + (is (= (.get_action (.get levels "test")) LogLevelAction/UPDATE)) + (is (= (.get_target_log_level (.get levels "test")) "INFO")) + + (is (= (.get_action (.get levels "other-test")) LogLevelAction/UNCHANGED)) + (is (= (.get_target_log_level (.get levels "other-test")) "DEBUG"))))))) diff --git a/storm-core/test/clj/backtype/storm/supervisor_test.clj b/storm-core/test/clj/backtype/storm/supervisor_test.clj index b17ea5ee302..64dd1cb9ca9 100644 --- a/storm-core/test/clj/backtype/storm/supervisor_test.clj +++ b/storm-core/test/clj/backtype/storm/supervisor_test.clj @@ -263,6 +263,7 @@ (str "-Dworker.port=" mock-port) "-Dstorm.log.dir=/logs" "-Dlog4j.configurationFile=/log4j2/worker.xml" + "-DLog4jContextSelector=org.apache.logging.log4j.core.selector.BasicContextSelector" "backtype.storm.LogWriter"] [(supervisor/java-cmd) "-server"] opts @@ -275,6 +276,7 @@ (str "-Dstorm.log.dir=" file-path-separator "logs") (str "-Dlogging.sensitivity=" mock-sensitivity) (str "-Dlog4j.configurationFile=" file-path-separator "log4j2" file-path-separator "worker.xml") + "-DLog4jContextSelector=org.apache.logging.log4j.core.selector.BasicContextSelector" (str "-Dstorm.id=" mock-storm-id) (str "-Dworker.id=" mock-worker-id) (str "-Dworker.port=" mock-port) @@ -395,6 +397,7 @@ " '-Dworker.port=" mock-port "'" " '-Dstorm.log.dir=/logs'" " '-Dlog4j.configurationFile=/log4j2/worker.xml'" + " '-DLog4jContextSelector=org.apache.logging.log4j.core.selector.BasicContextSelector'" " 'backtype.storm.LogWriter'" " 'java' '-server'" " " (shell-cmd opts) @@ -407,6 +410,7 @@ " '-Dstorm.log.dir=/logs'" " '-Dlogging.sensitivity=" mock-sensitivity "'" " '-Dlog4j.configurationFile=/log4j2/worker.xml'" + " '-DLog4jContextSelector=org.apache.logging.log4j.core.selector.BasicContextSelector'" " '-Dstorm.id=" mock-storm-id "'" " '-Dworker.id=" mock-worker-id "'" " '-Dworker.port=" mock-port "'" diff --git a/storm-core/test/clj/backtype/storm/worker_test.clj b/storm-core/test/clj/backtype/storm/worker_test.clj index 2e0533d70cc..b8e5f0fa600 100644 --- a/storm-core/test/clj/backtype/storm/worker_test.clj +++ b/storm-core/test/clj/backtype/storm/worker_test.clj @@ -15,15 +15,184 @@ ;; limitations under the License. (ns backtype.storm.worker-test (:use [clojure test]) + (:require [backtype.storm.daemon [worker :as worker]]) + (:require [backtype.storm [util :as util]]) + (:require [conjure.core]) + (:require [clj-time.core :as time]) + (:require [clj-time.coerce :as coerce]) + (:import [backtype.storm.generated LogConfig LogLevel LogLevelAction]) + (:import [org.apache.logging.log4j Level LogManager]) + (:import [org.slf4j Logger]) + (:use [conjure core]) + (:use [backtype.storm testing log]) + (:use [backtype.storm.daemon common]) + (:use [clojure.string :only [join]]) (:import [backtype.storm.messaging TaskMessage IContext IConnection ConnectionWithStatus ConnectionWithStatus$Status]) (:import [org.mockito Mockito]) - (:use [backtype.storm testing]) - (:use [backtype.storm.daemon common]) - - (:require [backtype.storm.daemon [worker :as worker]]) ) +(deftest test-log-reset-should-not-trigger-for-future-time + (with-local-cluster [cluster] + (let [worker (:worker cluster) + present (time/now) + the-future (coerce/to-long (time/plus present (time/secs 1))) + mock-config {"foo" {:timeout the-future}} + mock-config-atom (atom mock-config)] + (stubbing [time/now present] + (worker/reset-log-levels mock-config-atom) + ;; if the worker doesn't reset log levels, the atom should not be nil + (is (not(= @mock-config-atom nil))))))) + +(deftest test-log-reset-triggers-for-past-time + (with-local-cluster [cluster] + (let [worker (:worker cluster) + present (time/now) + past (time/plus present (time/secs -1)) + mock-config {"foo" { :timeout (coerce/to-long past) + :target-log-level Level/INFO + :reset-log-level Level/WARN}} + mock-config-atom (atom mock-config)] + (stubbing [time/now present] + (worker/reset-log-levels mock-config-atom) + ;; the logger config is removed from atom + (is (= @mock-config-atom {})))))) + +(deftest test-log-reset-resets-does-nothing-for-empty-log-config + (with-local-cluster [cluster] + (let [worker (:worker cluster) + present (time/now) + past (coerce/to-long (time/plus present (time/secs -1))) + mock-config {} + mock-config-atom (atom mock-config)] + (stubbing [worker/set-logger-level nil + time/now present] + (worker/reset-log-levels mock-config-atom) + ;; if the worker resets log level, the atom is nil'ed out + (is (= @mock-config-atom {})) + ;; test that the set-logger-level function was not called + (verify-call-times-for worker/set-logger-level 0))))) + +(deftest test-log-reset-resets-root-logger-if-set + (with-local-cluster [cluster] + (let [worker (:worker cluster) + present (time/now) + past (coerce/to-long (time/plus present (time/secs -1))) + mock-config {LogManager/ROOT_LOGGER_NAME {:timeout past + :target-log-level Level/DEBUG + :reset-log-level Level/WARN}} + mock-config-atom (atom mock-config)] + (stubbing [worker/set-logger-level nil + time/now present] + (worker/reset-log-levels mock-config-atom) + ;; if the worker resets log level, the atom is reset to {} + (is (= @mock-config-atom {})) + ;; ensure we reset back to WARN level + (verify-call-times-for worker/set-logger-level 1) + (verify-first-call-args-for-indices worker/set-logger-level [1 2] LogManager/ROOT_LOGGER_NAME Level/WARN))))) + +;;This should be removed when it goes into conjure +(defmacro verify-nth-call-args-for-indices + "Asserts that the function was called at least once, and the nth call was + passed the args specified, into the indices of the arglist specified. In + other words, it checks only the particular args you care about." + [n fn-name indices & args] + `(do + (assert-in-fake-context "verify-first-call-args-for-indices") + (assert-conjurified-fn "verify-first-call-args-for-indices" ~fn-name) + (is (< ~n (count (get @call-times ~fn-name))) + (str "(verify-nth-call-args-for-indices " ~n " " ~fn-name " " ~indices " " ~(join " " args) ")")) + (let [nth-call-args# (nth (get @call-times ~fn-name) ~n) + indices-in-range?# (< (apply max ~indices) (count nth-call-args#))] + (if indices-in-range?# + (is (= ~(vec args) (map #(nth nth-call-args# %) ~indices)) + (str "(verify-first-call-args-for-indices " ~n " " ~fn-name " " ~indices " " ~(join " " args) ")")) + (is (= :fail (format "indices %s are out of range for the args, %s" ~indices ~(vec args))) + (str "(verify-first-call-args-for-indices " ~n " " ~fn-name " " ~indices " " ~(join " " args) ")")))))) + +(deftest test-log-resets-named-loggers-with-past-timeout + (with-local-cluster [cluster] + (let [worker (:worker cluster) + present (time/now) + past (coerce/to-long (time/plus present (time/secs -1))) + mock-config {"my_debug_logger" {:timeout past + :target-log-level Level/DEBUG + :reset-log-level Level/INFO} + "my_info_logger" {:timeout past + :target-log-level Level/INFO + :reset-log-level Level/WARN} + "my_error_logger" {:timeout past + :target-log-level Level/ERROR + :reset-log-level Level/INFO}} + result (atom {}) + mock-config-atom (atom mock-config)] + (stubbing [worker/set-logger-level nil + time/now present] + (worker/reset-log-levels mock-config-atom) + ;; if the worker resets log level, the atom is reset to {} + (is (= @mock-config-atom {})) + (verify-call-times-for worker/set-logger-level 3) + (verify-nth-call-args-for-indices 0 worker/set-logger-level [1 2] "my_debug_logger" Level/INFO) + (verify-nth-call-args-for-indices 1 worker/set-logger-level [1 2] "my_error_logger" Level/INFO) + (verify-nth-call-args-for-indices 2 worker/set-logger-level [1 2] "my_info_logger" Level/WARN))))) + +(deftest test-process-root-log-level-to-debug-sets-logger-and-timeout-2 + (with-local-cluster [cluster] + (let [worker (:worker cluster) + mock-config (LogConfig.) + root-level (LogLevel.) + mock-config-atom (atom nil) + orig-levels (atom {}) + present (time/now) + in-thirty-seconds (coerce/to-long (time/plus present (time/secs 30)))] + ;; configure the root logger to be debug + (.set_reset_log_level_timeout_epoch root-level in-thirty-seconds) + (.set_target_log_level root-level "DEBUG") + (.set_action root-level LogLevelAction/UPDATE) + (.put_to_named_logger_level mock-config "ROOT" root-level) + (stubbing [worker/set-logger-level nil + time/now present] + (worker/process-log-config-change mock-config-atom orig-levels mock-config) + ;; test that the set-logger-level function was not called + (log-message "Tests " @mock-config-atom) + (verify-call-times-for worker/set-logger-level 1) + (verify-nth-call-args-for-indices 0 worker/set-logger-level [1 2] "" Level/DEBUG) + (let [root-result (get @mock-config-atom LogManager/ROOT_LOGGER_NAME)] + (is (= (:action root-result) LogLevelAction/UPDATE)) + (is (= (:target-log-level root-result) Level/DEBUG)) + ;; defaults to INFO level when the logger isn't found previously + (is (= (:reset-log-level root-result) Level/INFO)) + (is (= (:timeout root-result) in-thirty-seconds))))))) + +(deftest test-process-root-log-level-to-debug-sets-logger-and-timeout + (with-local-cluster [cluster] + (let [worker (:worker cluster) + mock-config (LogConfig.) + root-level (LogLevel.) + orig-levels (atom {}) + present (time/now) + in-thirty-seconds (coerce/to-long (time/plus present (time/secs 30))) + mock-config-atom (atom {})] + ;; configure the root logger to be debug + (doseq [named {"ROOT" "DEBUG" + "my_debug_logger" "DEBUG" + "my_info_logger" "INFO" + "my_error_logger" "ERROR"}] + (let [level (LogLevel.)] + (.set_action level LogLevelAction/UPDATE) + (.set_reset_log_level_timeout_epoch level in-thirty-seconds) + (.set_target_log_level level (val named)) + (.put_to_named_logger_level mock-config (key named) level))) + (log-message "Tests " mock-config) + (stubbing [worker/set-logger-level nil + time/now present] + (worker/process-log-config-change mock-config-atom orig-levels mock-config) + (verify-call-times-for worker/set-logger-level 4) + (verify-nth-call-args-for-indices 0 worker/set-logger-level [1 2] "" Level/DEBUG) + (verify-nth-call-args-for-indices 1 worker/set-logger-level [1 2] "my_debug_logger" Level/DEBUG) + (verify-nth-call-args-for-indices 2 worker/set-logger-level [1 2] "my_error_logger" Level/ERROR) + (verify-nth-call-args-for-indices 3 worker/set-logger-level [1 2] "my_info_logger" Level/INFO))))) + (deftest test-worker-is-connection-ready (let [connection (Mockito/mock ConnectionWithStatus)] (. (Mockito/when (.status connection)) thenReturn ConnectionWithStatus$Status/Ready) @@ -34,4 +203,4 @@ (. (Mockito/when (.status connection)) thenReturn ConnectionWithStatus$Status/Closed) (is (= false (worker/is-connection-ready connection))) - )) \ No newline at end of file + )) From 087f08ea314df2055bce61abbb54cc7443da41a9 Mon Sep 17 00:00:00 2001 From: Alessandro Bellina Date: Fri, 10 Apr 2015 12:07:22 -0500 Subject: [PATCH 3/5] Documentation brief for dynamic log level settings feature --- 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 3 files changed, 41 insertions(+) create mode 100644 docs/DYNAMIC_LOG_LEVEL_SETTINGS.md create mode 100644 docs/images/dynamic_log_level_settings_1.png create mode 100644 docs/images/dynamic_log_level_settings_2.png diff --git a/docs/DYNAMIC_LOG_LEVEL_SETTINGS.md b/docs/DYNAMIC_LOG_LEVEL_SETTINGS.md new file mode 100644 index 00000000000..f38b708e029 --- /dev/null +++ b/docs/DYNAMIC_LOG_LEVEL_SETTINGS.md @@ -0,0 +1,41 @@ +Dynamic Log Level Settings +========================== + +We have added the ability to set log level settings for a running topology using the Storm UI and the Storm CLI. + +The log level settings apply the same way as you'd expect from log4j, as all we are doing is telling log4j to set the level of the logger you provide. If you set the log level of a parent logger, the children loggers start using that level (unless the children have a more restrictive level already). A timeout can optionally be provided (except for DEBUG mode, where it’s required in the UI), if workers should reset log levels automatically. + +This revert action is triggered using a polling mechanism (every 30 seconds, but this is configurable), so you should expect your timeouts to be the value you provided plus anywhere between 0 and the setting's value. + +Using the Storm UI +------------- + +In order to set a level, click on a running topology, and then click on “Change Log Level” in the Topology Actions section. + +![Change Log Level dialog](images/dynamic_log_level_settings_1.png "Change Log Level dialog") + +Next, provide the logger name, select the level you expect (e.g. WARN), and a timeout in seconds (or 0 if not needed). Then click on “Add”. + +![After adding a log level setting](images/dynamic_log_level_settings_2.png "After adding a log level setting") + +To clear the log level click on the “Clear” button. This reverts the log level back to what it was before you added the setting. The log level line will disappear from the UI. + +While there is a delay resetting log levels back, setting the log level in the first place is immediate (or as quickly as the message can travel from the UI/CLI to the workers by way of nimbus and zookeeper). + +Using the CLI +------------- + +Using the CLI, issue the command: + +`./bin/storm set_log_level [topology name] -l [logger name]=[LEVEL]:[TIMEOUT]` + +For example: + +`./bin/storm set_log_level my_topology -l ROOT=DEBUG:30` + +Sets the ROOT logger to DEBUG for 30 seconds. + +`./bin/storm set_log_level my_topology -r ROOT` + +Clears the ROOT logger dynamic log level, resetting it to its original value. + diff --git a/docs/images/dynamic_log_level_settings_1.png b/docs/images/dynamic_log_level_settings_1.png new file mode 100644 index 0000000000000000000000000000000000000000..71d42e747804fa1638011d2b6100a7178a001788 GIT binary patch literal 93689 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�?S2?=~*K%4_J2<^$(Fe1A#ox-J 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 literal 0 HcmV?d00001 From 51c32531ae72adc56d071745677e375326b50fe8 Mon Sep 17 00:00:00 2001 From: Kishor Patil Date: Tue, 29 Sep 2015 09:31:25 -0500 Subject: [PATCH 4/5] Minor fix to lower scope on nimbus client call --- .../backtype/storm/command/set_log_level.clj | 24 +++++++++---------- 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/storm-core/src/clj/backtype/storm/command/set_log_level.clj b/storm-core/src/clj/backtype/storm/command/set_log_level.clj index 3b50c3a0a03..88b297d12f2 100644 --- a/storm-core/src/clj/backtype/storm/command/set_log_level.clj +++ b/storm-core/src/clj/backtype/storm/command/set_log_level.clj @@ -59,17 +59,17 @@ (merge oldval val) val))) -(defn -main [& args] +(defn -main [& args] (let [[{log-setting :log-setting remove-log-setting :remove-log-setting} [name] _] - (cli args ["-l" "--log-setting" - :parse-fn (parse-named-log-levels LogLevelAction/UPDATE) - :assoc-fn merge-together] - ["-r" "--remove-log-setting" - :parse-fn (parse-named-log-levels LogLevelAction/REMOVE) - :assoc-fn merge-together])] + (cli args ["-l" "--log-setting" + :parse-fn (parse-named-log-levels LogLevelAction/UPDATE) + :assoc-fn merge-together] + ["-r" "--remove-log-setting" + :parse-fn (parse-named-log-levels LogLevelAction/REMOVE) + :assoc-fn merge-together]) + log-config (LogConfig.)] + (doseq [[log-name log-val] (merge log-setting remove-log-setting)] + (.put_to_named_logger_level log-config log-name log-val)) + (log-message "Sent log config " log-config " for topology " name) (with-configured-nimbus-connection nimbus - (let [log-config (LogConfig.)] - (doseq [[log-name log-val] (merge log-setting remove-log-setting)] - (.put_to_named_logger_level log-config log-name log-val)) - (log-message "Sent log config " log-config " for topology " name) - (.setLogConfig nimbus (get-storm-id nimbus name) log-config))))) + (.setLogConfig nimbus (get-storm-id nimbus name) log-config)))) From 754017f1c16bc74797a39c2cbb64e8c5e50f3010 Mon Sep 17 00:00:00 2001 From: Kishor Patil Date: Wed, 30 Sep 2015 07:50:44 -0500 Subject: [PATCH 5/5] Clearing logconfig zk node for topology as part of remove-storm --- storm-core/src/clj/backtype/storm/cluster.clj | 9 +-------- storm-core/src/clj/backtype/storm/daemon/nimbus.clj | 1 - 2 files changed, 1 insertion(+), 9 deletions(-) diff --git a/storm-core/src/clj/backtype/storm/cluster.clj b/storm-core/src/clj/backtype/storm/cluster.clj index 77c576fcdb0..e471e53a8d0 100644 --- a/storm-core/src/clj/backtype/storm/cluster.clj +++ b/storm-core/src/clj/backtype/storm/cluster.clj @@ -177,7 +177,6 @@ (setup-heartbeats! [this storm-id]) (teardown-heartbeats! [this storm-id]) (teardown-topology-errors! [this storm-id]) - (teardown-topology-log-config! [this storm-id]) (heartbeat-storms [this]) (error-topologies [this]) (set-topology-log-config! [this storm-id log-config]) @@ -540,13 +539,6 @@ (catch KeeperException e (log-warn-error e "Could not teardown errors for " storm-id)))) - (teardown-topology-log-config! - [this storm-id] - (try-cause - (.delete_node cluster-state (log-config-path storm-id)) - (catch KeeperException e - (log-warn-error e "Could not teardown log configs for " storm-id)))) - (supervisor-heartbeat! [this supervisor-id info] (let [thrift-supervisor-info (thriftify-supervisor-info info)] @@ -599,6 +591,7 @@ (delete-node cluster-state (assignment-path storm-id)) (delete-node cluster-state (code-distributor-path storm-id)) (delete-node cluster-state (credentials-path storm-id)) + (delete-node cluster-state (log-config-path storm-id)) (remove-storm-base! this storm-id)) (set-credentials! diff --git a/storm-core/src/clj/backtype/storm/daemon/nimbus.clj b/storm-core/src/clj/backtype/storm/daemon/nimbus.clj index c797c4bd49a..19870f1e8e2 100644 --- a/storm-core/src/clj/backtype/storm/daemon/nimbus.clj +++ b/storm-core/src/clj/backtype/storm/daemon/nimbus.clj @@ -931,7 +931,6 @@ (if (:code-distributor nimbus) (.cleanup (:code-distributor nimbus) id)) (.teardown-heartbeats! storm-cluster-state id) (.teardown-topology-errors! storm-cluster-state id) - (.teardown-topology-log-config! storm-cluster-state id) (rmr (master-stormdist-root conf id)) (swap! (:heartbeats-cache nimbus) dissoc id)) )))