// Path: kawala-common/src/main/java/com/kaching/platform/common/Strings.java
// public static String format(String template, Object... args) {
//   template = String.valueOf(template); // null -> "null"
// 
//   // start substituting the arguments into the '%s' placeholders
//   StringBuilder builder = new StringBuilder(
//       template.length() + 16 * args.length);
//   int templateStart = 0;
//   int i = 0;
//   while (i < args.length) {
//     int placeholderStart = template.indexOf("%s", templateStart);
//     if (placeholderStart == -1) {
//       break;
//     }
//     builder.append(template.substring(templateStart, placeholderStart));
//     builder.append(args[i++]);
//     templateStart = placeholderStart + 2;
//   }
//   builder.append(template.substring(templateStart));
// 
//   // if we run out of placeholders, append the extra args in square braces
//   if (i < args.length) {
//     builder.append(" [");
//     builder.append(args[i++]);
//     while (i < args.length) {
//       builder.append(", ");
//       builder.append(args[i++]);
//     }
//     builder.append("]");
//   }
// 
//   return builder.toString();
// }
// 
// Path: kawala-common/src/main/java/com/kaching/platform/common/Pair.java
// public class Pair<S, T> {
// 
//   public final S left;
//   public final T right;
// 
//   public static <S, T> Pair<S, T> of(S left, T right) {
//     return new Pair<S, T>(left, right);
//   }
// 
//   public Pair(S left, T right) {
//     this.left = left;
//     this.right = right;
//   }
// 
//   @Override
//   public int hashCode() {
//     return Objects.hashCode(left, right);
//   }
// 
//   @Override
//   public boolean equals(Object obj) {
//     if (this == obj) {
//       return true;
//     }
//     if (obj == null) {
//       return false;
//     }
//     if (getClass() != obj.getClass()) {
//       return false;
//     }
// 
//     Pair<?, ?> other = (Pair<?, ?>) obj;
//     return Objects.equal(left, other.left) &&
//            Objects.equal(right, other.right);
//   }
// 
//   @Override
//   public String toString() {
//     return "(" + left + "," + right + ")";
//   }
// 
// }


import static com.kaching.platform.common.Strings.format;
import org.apache.commons.logging.LogFactory;
import org.apache.log4j.MDC;
import org.perf4j.commonslog.CommonsLogStopWatch;
import com.google.common.annotations.VisibleForTesting;
import com.kaching.platform.common.Pair;
/**
 * Copyright 2010 Wealthfront Inc. Licensed 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 com.kaching.platform.common.logging;




/**
 * A convenient interface on top of Log4J that makes using log4j along with
 * {@link String#format(String, Object...)} more concise. Its interface is
 * similar to log4j's {@link org.apache.commons.logging.Log} with the addition
 * of varargs arguments that are used to render the any format specifiers in the
 * log message.
 */
public class Log {
  public static Log getLog(Class<?> clazz) {
    return new Log(clazz);
  }

  public static Log getLog(String name) {
    return new Log(name);
  }

  public static void logContextPut(String key, Object value) {
    MDC.put(key, value);
  }

  public static void logContextRemove(String key) {
    MDC.remove(key);
  }

  public static void withLogContext(Runnable runnable,
// Path: kawala-common/src/main/java/com/kaching/platform/common/Strings.java
// public static String format(String template, Object... args) {
//   template = String.valueOf(template); // null -> "null"
// 
//   // start substituting the arguments into the '%s' placeholders
//   StringBuilder builder = new StringBuilder(
//       template.length() + 16 * args.length);
//   int templateStart = 0;
//   int i = 0;
//   while (i < args.length) {
//     int placeholderStart = template.indexOf("%s", templateStart);
//     if (placeholderStart == -1) {
//       break;
//     }
//     builder.append(template.substring(templateStart, placeholderStart));
//     builder.append(args[i++]);
//     templateStart = placeholderStart + 2;
//   }
//   builder.append(template.substring(templateStart));
// 
//   // if we run out of placeholders, append the extra args in square braces
//   if (i < args.length) {
//     builder.append(" [");
//     builder.append(args[i++]);
//     while (i < args.length) {
//       builder.append(", ");
//       builder.append(args[i++]);
//     }
//     builder.append("]");
//   }
// 
//   return builder.toString();
// }
// 
// Path: kawala-common/src/main/java/com/kaching/platform/common/Pair.java
// public class Pair<S, T> {
// 
//   public final S left;
//   public final T right;
// 
//   public static <S, T> Pair<S, T> of(S left, T right) {
//     return new Pair<S, T>(left, right);
//   }
// 
//   public Pair(S left, T right) {
//     this.left = left;
//     this.right = right;
//   }
// 
//   @Override
//   public int hashCode() {
//     return Objects.hashCode(left, right);
//   }
// 
//   @Override
//   public boolean equals(Object obj) {
//     if (this == obj) {
//       return true;
//     }
//     if (obj == null) {
//       return false;
//     }
//     if (getClass() != obj.getClass()) {
//       return false;
//     }
// 
//     Pair<?, ?> other = (Pair<?, ?>) obj;
//     return Objects.equal(left, other.left) &&
//            Objects.equal(right, other.right);
//   }
// 
//   @Override
//   public String toString() {
//     return "(" + left + "," + right + ")";
//   }
// 
// }


// Path: kawala-common/src/main/java/com/kaching/platform/common/logging/Log.java
import static com.kaching.platform.common.Strings.format;
import org.apache.commons.logging.LogFactory;
import org.apache.log4j.MDC;
import org.perf4j.commonslog.CommonsLogStopWatch;
import com.google.common.annotations.VisibleForTesting;
import com.kaching.platform.common.Pair;

/**
 * Copyright 2010 Wealthfront Inc. Licensed 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 com.kaching.platform.common.logging;




/**
 * A convenient interface on top of Log4J that makes using log4j along with
 * {@link String#format(String, Object...)} more concise. Its interface is
 * similar to log4j's {@link org.apache.commons.logging.Log} with the addition
 * of varargs arguments that are used to render the any format specifiers in the
 * log message.
 */
public class Log {
  public static Log getLog(Class<?> clazz) {
    return new Log(clazz);
  }

  public static Log getLog(String name) {
    return new Log(name);
  }

  public static void logContextPut(String key, Object value) {
    MDC.put(key, value);
  }

  public static void logContextRemove(String key) {
    MDC.remove(key);
  }

  public static void withLogContext(Runnable runnable,
      Pair<String, Object>... contexts) {