]> source.dussan.org Git - sonarqube.git/commitdiff
fork Profiler into sonar-core to change return type of stop methods
authorSébastien Lesaint <sebastien.lesaint@sonarsource.com>
Mon, 27 Jul 2015 13:35:28 +0000 (15:35 +0200)
committerSébastien Lesaint <sebastien.lesaint@sonarsource.com>
Wed, 29 Jul 2015 13:35:12 +0000 (15:35 +0200)
sonar-core/src/main/java/org/sonar/core/util/logs/DefaultProfiler.java [new file with mode: 0644]
sonar-core/src/main/java/org/sonar/core/util/logs/NullProfiler.java [new file with mode: 0644]
sonar-core/src/main/java/org/sonar/core/util/logs/Profiler.java [new file with mode: 0644]
sonar-core/src/test/java/org/sonar/core/util/logs/DefaultProfilerTest.java [new file with mode: 0644]
sonar-core/src/test/java/org/sonar/core/util/logs/NullProfilerTest.java [new file with mode: 0644]
sonar-core/src/test/java/org/sonar/core/util/logs/ProfilerTest.java [new file with mode: 0644]

diff --git a/sonar-core/src/main/java/org/sonar/core/util/logs/DefaultProfiler.java b/sonar-core/src/main/java/org/sonar/core/util/logs/DefaultProfiler.java
new file mode 100644 (file)
index 0000000..83bbde6
--- /dev/null
@@ -0,0 +1,194 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+package org.sonar.core.util.logs;
+
+import java.util.LinkedHashMap;
+import java.util.Map;
+import java.util.Objects;
+import javax.annotation.Nullable;
+import org.apache.commons.lang.StringUtils;
+import org.sonar.api.utils.System2;
+import org.sonar.api.utils.log.Logger;
+import org.sonar.api.utils.log.LoggerLevel;
+
+class DefaultProfiler extends Profiler {
+
+  private static final String CONTEXT_SEPARATOR = " | ";
+
+  private final LinkedHashMap<String, Object> context = new LinkedHashMap<>();
+  private final Logger logger;
+
+  private long startTime = 0L;
+  private String startMessage = null;
+
+  public DefaultProfiler(Logger logger) {
+    this.logger = logger;
+  }
+
+  @Override
+  public boolean isDebugEnabled() {
+    return logger.isDebugEnabled();
+  }
+
+  @Override
+  public boolean isTraceEnabled() {
+    return logger.isTraceEnabled();
+  }
+
+  @Override
+  public Profiler start() {
+    this.startTime = System2.INSTANCE.now();
+    this.startMessage = null;
+    return this;
+  }
+
+  @Override
+  public Profiler startTrace(String message) {
+    this.startTime = System2.INSTANCE.now();
+    this.startMessage = message;
+    StringBuilder sb = new StringBuilder();
+    sb.append(message);
+    appendContext(sb);
+    logger.trace(sb.toString());
+    return this;
+  }
+
+  @Override
+  public Profiler startDebug(String message) {
+    this.startTime = System2.INSTANCE.now();
+    this.startMessage = message;
+    StringBuilder sb = new StringBuilder();
+    sb.append(message);
+    appendContext(sb);
+    logger.debug(sb.toString());
+    return this;
+  }
+
+  @Override
+  public Profiler startInfo(String message) {
+    this.startTime = System2.INSTANCE.now();
+    this.startMessage = message;
+    StringBuilder sb = new StringBuilder();
+    sb.append(message);
+    appendContext(sb);
+    logger.info(sb.toString());
+    return this;
+  }
+
+
+  @Override
+  public long stopTrace() {
+    return doStopWithoutMessage(LoggerLevel.TRACE);
+  }
+
+  @Override
+  public long stopDebug() {
+    return doStopWithoutMessage(LoggerLevel.DEBUG);
+  }
+
+  @Override
+  public long stopInfo() {
+    return doStopWithoutMessage(LoggerLevel.INFO);
+  }
+
+  private long doStopWithoutMessage(LoggerLevel level) {
+    if (startMessage == null) {
+      throw new IllegalStateException("Profiler#stopXXX() can't be called without any message defined in start methods");
+    }
+    return doStop(level, startMessage, " (done)");
+  }
+
+  @Override
+  public long stopTrace(String message) {
+    return doStop(LoggerLevel.TRACE, message, "");
+  }
+
+  @Override
+  public long stopDebug(String message) {
+    return doStop(LoggerLevel.DEBUG, message, "");
+  }
+
+  @Override
+  public long stopInfo(String message) {
+    return doStop(LoggerLevel.INFO, message, "");
+  }
+
+  private long doStop(LoggerLevel level, @Nullable String message, String messageSuffix) {
+    if (startTime == 0L) {
+      throw new IllegalStateException("Profiler must be started before being stopped");
+    }
+    long duration = System2.INSTANCE.now() - startTime;
+    StringBuilder sb = new StringBuilder();
+    if (!StringUtils.isEmpty(message)) {
+      sb.append(message);
+      sb.append(messageSuffix);
+      sb.append(CONTEXT_SEPARATOR);
+    }
+    sb.append("time=").append(duration).append("ms");
+    appendContext(sb);
+    log(level, sb.toString());
+    startTime = 0L;
+    startMessage = null;
+    context.clear();
+    return duration;
+  }
+
+  void log(LoggerLevel level, String msg) {
+    switch (level) {
+      case TRACE:
+        logger.trace(msg);
+        break;
+      case DEBUG:
+        logger.debug(msg);
+        break;
+      case INFO:
+        logger.info(msg);
+        break;
+      case WARN:
+        logger.warn(msg);
+        break;
+      case ERROR:
+        logger.error(msg);
+        break;
+      default:
+        throw new IllegalArgumentException("Unsupported LoggerLevel value: " + level);
+    }
+  }
+
+  private void appendContext(StringBuilder sb) {
+    for (Map.Entry<String, Object> entry : context.entrySet()) {
+      if (sb.length() > 0) {
+        sb.append(CONTEXT_SEPARATOR);
+      }
+      sb.append(entry.getKey()).append("=").append(Objects.toString(entry.getValue()));
+    }
+  }
+
+  @Override
+  public Profiler addContext(String key, @Nullable Object value) {
+    if (value == null) {
+      context.remove(key);
+    } else {
+      context.put(key, value);
+    }
+    return this;
+  }
+
+}
diff --git a/sonar-core/src/main/java/org/sonar/core/util/logs/NullProfiler.java b/sonar-core/src/main/java/org/sonar/core/util/logs/NullProfiler.java
new file mode 100644 (file)
index 0000000..665f71d
--- /dev/null
@@ -0,0 +1,96 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+package org.sonar.core.util.logs;
+
+import javax.annotation.Nullable;
+
+class NullProfiler extends Profiler {
+
+  static final NullProfiler NULL_INSTANCE = new NullProfiler();
+
+  private NullProfiler() {
+  }
+
+  @Override
+  public boolean isDebugEnabled() {
+    return false;
+  }
+
+  @Override
+  public boolean isTraceEnabled() {
+    return false;
+  }
+
+  @Override
+  public Profiler start() {
+    return this;
+  }
+
+  @Override
+  public Profiler startTrace(String message) {
+    return this;
+  }
+
+  @Override
+  public Profiler startDebug(String message) {
+    return this;
+  }
+
+  @Override
+  public Profiler startInfo(String message) {
+    return this;
+  }
+
+  @Override
+  public long stopTrace() {
+    return 0;
+  }
+
+  @Override
+  public long stopDebug() {
+    return 0;
+  }
+
+  @Override
+  public long stopInfo() {
+    return 0;
+  }
+
+  @Override
+  public long stopTrace(String message) {
+    return 0;
+  }
+
+  @Override
+  public long stopDebug(String message) {
+    return 0;
+  }
+
+  @Override
+  public long stopInfo(String message) {
+    return 0;
+  }
+
+  @Override
+  public Profiler addContext(String key, @Nullable Object value) {
+    // nothing to do
+    return this;
+  }
+}
diff --git a/sonar-core/src/main/java/org/sonar/core/util/logs/Profiler.java b/sonar-core/src/main/java/org/sonar/core/util/logs/Profiler.java
new file mode 100644 (file)
index 0000000..eaf7960
--- /dev/null
@@ -0,0 +1,81 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+package org.sonar.core.util.logs;
+
+import javax.annotation.Nullable;
+import org.sonar.api.utils.log.Logger;
+
+/**
+ *
+ * @since 5.1
+ */
+public abstract class Profiler {
+
+  public static Profiler create(Logger logger) {
+    return new DefaultProfiler(logger);
+  }
+
+  public static Profiler createIfTrace(Logger logger) {
+    if (logger.isTraceEnabled()) {
+      return create(logger);
+    }
+    return NullProfiler.NULL_INSTANCE;
+  }
+
+  public static Profiler createIfDebug(Logger logger) {
+    if (logger.isDebugEnabled()) {
+      return create(logger);
+    }
+    return NullProfiler.NULL_INSTANCE;
+  }
+
+  public abstract boolean isDebugEnabled();
+
+  public abstract boolean isTraceEnabled();
+
+  public abstract Profiler start();
+
+  public abstract Profiler startTrace(String message);
+
+  public abstract Profiler startDebug(String message);
+
+  public abstract Profiler startInfo(String message);
+
+  /**
+   * Works only if a message have been set in startXXX() methods.
+   */
+  public abstract long stopTrace();
+
+  public abstract long stopDebug();
+
+  public abstract long stopInfo();
+
+  public abstract long stopTrace(String message);
+
+  public abstract long stopDebug(String message);
+
+  public abstract long stopInfo(String message);
+
+  /**
+   * Context information is removed if value is <code>null</code>.
+   */
+  public abstract Profiler addContext(String key, @Nullable Object value);
+
+}
diff --git a/sonar-core/src/test/java/org/sonar/core/util/logs/DefaultProfilerTest.java b/sonar-core/src/test/java/org/sonar/core/util/logs/DefaultProfilerTest.java
new file mode 100644 (file)
index 0000000..7a71b45
--- /dev/null
@@ -0,0 +1,192 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+package org.sonar.core.util.logs;
+
+import org.junit.Rule;
+import org.junit.Test;
+import org.sonar.api.utils.log.LogTester;
+import org.sonar.api.utils.log.LoggerLevel;
+import org.sonar.api.utils.log.Loggers;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.junit.Assert.fail;
+
+public class DefaultProfilerTest {
+
+  @Rule
+  public LogTester tester = new LogTester();
+
+  Profiler underTest = Profiler.create(Loggers.get("DefaultProfilerTest"));
+
+  @Test
+  public void test_levels() throws Exception {
+    // trace by default
+    assertThat(underTest.isDebugEnabled()).isTrue();
+    assertThat(underTest.isTraceEnabled()).isTrue();
+
+    tester.setLevel(LoggerLevel.DEBUG);
+    assertThat(underTest.isDebugEnabled()).isTrue();
+    assertThat(underTest.isTraceEnabled()).isFalse();
+
+    tester.setLevel(LoggerLevel.INFO);
+    assertThat(underTest.isDebugEnabled()).isFalse();
+    assertThat(underTest.isTraceEnabled()).isFalse();
+  }
+
+  @Test
+  public void stop_reuses_start_message() throws InterruptedException {
+    tester.setLevel(LoggerLevel.TRACE);
+
+    // trace
+    underTest.startTrace("Register rules");
+    Thread.sleep(2);
+    assertThat(tester.logs()).containsOnly("Register rules");
+    long timing = underTest.stopTrace();
+    assertThat(timing).isGreaterThan(0);
+    assertThat(tester.logs()).hasSize(2);
+    assertThat(tester.logs().get(1)).startsWith("Register rules (done) | time=" + timing);
+    tester.clear();
+
+    // debug
+    underTest.startDebug("Register rules");
+    Thread.sleep(2);
+    assertThat(tester.logs()).containsOnly("Register rules");
+    timing = underTest.stopTrace();
+    assertThat(timing).isGreaterThan(0);
+    assertThat(tester.logs()).hasSize(2);
+    assertThat(tester.logs().get(1)).startsWith("Register rules (done) | time="  + timing);
+    tester.clear();
+
+    // info
+    underTest.startInfo("Register rules");
+    Thread.sleep(2);
+    assertThat(tester.logs()).containsOnly("Register rules");
+    timing = underTest.stopTrace();
+    assertThat(timing).isGreaterThan(0);
+    assertThat(tester.logs()).hasSize(2);
+    assertThat(tester.logs().get(1)).startsWith("Register rules (done) | time=" + timing);
+  }
+
+  @Test
+  public void different_start_and_stop_messages() {
+    tester.setLevel(LoggerLevel.TRACE);
+
+    // start TRACE and stop DEBUG
+    underTest.startTrace("Register rules");
+    underTest.stopDebug("Rules registered");
+    assertThat(tester.logs()).hasSize(2);
+    assertThat(tester.logs().get(0)).contains("Register rules");
+    assertThat(tester.logs().get(1)).startsWith("Rules registered | time=");
+    tester.clear();
+
+    // start DEBUG and stop INFO
+    underTest.startDebug("Register rules");
+    underTest.stopInfo("Rules registered");
+    assertThat(tester.logs()).hasSize(2);
+    assertThat(tester.logs().get(0)).contains("Register rules");
+    assertThat(tester.logs().get(1)).startsWith("Rules registered | time=");
+    tester.clear();
+
+    // start INFO and stop TRACE
+    underTest.startInfo("Register rules");
+    underTest.stopTrace("Rules registered");
+    assertThat(tester.logs()).hasSize(2);
+    assertThat(tester.logs().get(0)).contains("Register rules");
+    assertThat(tester.logs().get(1)).startsWith("Rules registered | time=");
+  }
+
+  @Test
+  public void log_on_at_stop() {
+    tester.setLevel(LoggerLevel.TRACE);
+
+    // trace
+    underTest.start();
+    underTest.stopTrace("Rules registered");
+    assertThat(tester.logs()).hasSize(1);
+    assertThat(tester.logs().get(0)).startsWith("Rules registered | time=");
+    tester.clear();
+
+    // debug
+    underTest.start();
+    underTest.stopDebug("Rules registered");
+    assertThat(tester.logs()).hasSize(1);
+    assertThat(tester.logs().get(0)).startsWith("Rules registered | time=");
+    tester.clear();
+
+    // info
+    underTest.start();
+    underTest.stopInfo("Rules registered");
+    assertThat(tester.logs()).hasSize(1);
+    assertThat(tester.logs().get(0)).startsWith("Rules registered | time=");
+  }
+
+  @Test
+  public void add_context() {
+    org.sonar.core.util.logs.Profiler profiler = Profiler.create(Loggers.get("DefaultProfilerTest"));
+    profiler.addContext("a_string", "bar");
+    profiler.addContext("null_value", null);
+    profiler.addContext("an_int", 42);
+    profiler.start();
+    // do not write context as there's no message
+    assertThat(tester.logs()).isEmpty();
+
+    profiler.addContext("after_start", true);
+    profiler.stopInfo("Rules registered");
+    assertThat(tester.logs()).hasSize(1);
+    assertThat(tester.logs().get(0))
+      .startsWith("Rules registered | time=")
+      .endsWith("ms | a_string=bar | an_int=42 | after_start=true");
+  }
+
+  @Test
+  public void empty_message() {
+    underTest.addContext("foo", "bar");
+    underTest.startInfo("");
+    assertThat(tester.logs()).containsOnly("foo=bar");
+
+    underTest.addContext("after_start", true);
+    underTest.stopInfo("");
+    assertThat(tester.logs()).hasSize(2);
+    assertThat(tester.logs().get(1))
+      .startsWith("time=")
+      .endsWith("ms | foo=bar | after_start=true");
+  }
+
+  @Test
+  public void fail_if_stop_without_message() {
+    underTest.start();
+    try {
+      underTest.stopInfo();
+      fail();
+    } catch (IllegalStateException e) {
+      assertThat(e).hasMessage("Profiler#stopXXX() can't be called without any message defined in start methods");
+    }
+  }
+
+  @Test
+  public void fail_if_stop_without_start() {
+    try {
+      underTest.stopDebug("foo");
+      fail();
+    } catch (IllegalStateException e) {
+      assertThat(e).hasMessage("Profiler must be started before being stopped");
+    }
+  }
+}
diff --git a/sonar-core/src/test/java/org/sonar/core/util/logs/NullProfilerTest.java b/sonar-core/src/test/java/org/sonar/core/util/logs/NullProfilerTest.java
new file mode 100644 (file)
index 0000000..6572d49
--- /dev/null
@@ -0,0 +1,53 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+package org.sonar.core.util.logs;
+
+import org.junit.Test;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+public class NullProfilerTest {
+
+  NullProfiler underTest = NullProfiler.NULL_INSTANCE;
+
+  @Test
+  public void do_not_fail() {
+    assertThat(underTest.start()).isSameAs(underTest);
+    assertThat(underTest.startTrace("")).isSameAs(underTest);
+    assertThat(underTest.startDebug("")).isSameAs(underTest);
+    assertThat(underTest.startInfo("")).isSameAs(underTest);
+
+    assertThat(underTest.isDebugEnabled()).isFalse();
+    assertThat(underTest.isTraceEnabled()).isFalse();
+    assertThat(underTest.addContext("foo", "bar")).isSameAs(underTest);
+  }
+
+  @Test
+  public void stop_methods_returns_0() {
+    underTest.start();
+    assertThat(underTest.stopInfo()).isEqualTo(0);
+    assertThat(underTest.stopInfo("msg")).isEqualTo(0);
+    assertThat(underTest.stopDebug()).isEqualTo(0);
+    assertThat(underTest.stopDebug("msg")).isEqualTo(0);
+    assertThat(underTest.stopTrace()).isEqualTo(0);
+    assertThat(underTest.stopTrace("msg")).isEqualTo(0);
+
+  }
+}
diff --git a/sonar-core/src/test/java/org/sonar/core/util/logs/ProfilerTest.java b/sonar-core/src/test/java/org/sonar/core/util/logs/ProfilerTest.java
new file mode 100644 (file)
index 0000000..b58a843
--- /dev/null
@@ -0,0 +1,61 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+package org.sonar.core.util.logs;
+
+import org.junit.Rule;
+import org.junit.Test;
+import org.sonar.api.utils.log.LogTester;
+import org.sonar.api.utils.log.LoggerLevel;
+import org.sonar.api.utils.log.Loggers;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+public class ProfilerTest {
+  @Rule
+  public LogTester tester = new LogTester();
+
+  @Test
+  public void create() {
+    Profiler profiler = Profiler.create(Loggers.get("foo"));
+    assertThat(profiler).isInstanceOf(DefaultProfiler.class);
+  }
+
+  @Test
+  public void create_null_profiler_if_trace_level_is_disabled() {
+    tester.setLevel(LoggerLevel.TRACE);
+    Profiler profiler = Profiler.createIfTrace(Loggers.get("foo"));
+    assertThat(profiler).isInstanceOf(DefaultProfiler.class);
+
+    tester.setLevel(LoggerLevel.DEBUG);
+    profiler = Profiler.createIfTrace(Loggers.get("foo"));
+    assertThat(profiler).isInstanceOf(NullProfiler.class);
+  }
+
+  @Test
+  public void create_null_profiler_if_debug_level_is_disabled() {
+    tester.setLevel(LoggerLevel.TRACE);
+    Profiler profiler = Profiler.createIfDebug(Loggers.get("foo"));
+    assertThat(profiler).isInstanceOf(DefaultProfiler.class);
+
+    tester.setLevel(LoggerLevel.INFO);
+    profiler = Profiler.createIfDebug(Loggers.get("foo"));
+    assertThat(profiler).isInstanceOf(NullProfiler.class);
+  }
+}