Skip to content

Commit

Permalink
Add a method for debugging to a file
Browse files Browse the repository at this point in the history
Added debug methods that can be useful for appending messages to a
specified file, optionally including timestamp and/or stack trace.
These methods are safe to call concurrently, even across multiple
processes.
  • Loading branch information
dirmgr committed Sep 23, 2021
1 parent 1b710d6 commit ccd189c
Show file tree
Hide file tree
Showing 4 changed files with 170 additions and 1 deletion.
2 changes: 2 additions & 0 deletions messages/unboundid-ldapsdk-util.properties
Original file line number Diff line number Diff line change
Expand Up @@ -1216,3 +1216,5 @@ ERR_BC_FIPS_HELPER_CANNOT_LOAD_JSSE_PROVIDER_CLASS=Unable to load the Bouncy \
ERR_BC_FIPS_PROVIDER_CANNOT_INSTANTIATE_JSSE_PROVIDER=An unexpected error \
occurred while attempting to create an instance of the Bouncy Castle JSSE \
provider class ''{0}'': {1}
ERR_DEBUG_CANNOT_WRITE_TO_FILE=An unexpected error occurred while attempting \
to write a debug message to file ''{0}'': {1}. The debug message was: {2}
113 changes: 113 additions & 0 deletions src/com/unboundid/util/Debug.java
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,12 @@



import java.io.File;
import java.io.Serializable;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.channels.FileLock;
import java.nio.file.StandardOpenOption;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.EnumSet;
Expand All @@ -61,6 +66,8 @@
import com.unboundid.ldif.LDIFRecord;
import com.unboundid.util.json.JSONBuffer;

import static com.unboundid.util.UtilityMessages.*;



/**
Expand Down Expand Up @@ -1702,4 +1709,110 @@ private static void log(@NotNull final Level level,
{
logger.log(level, buffer.toString(), thrown);
}



/**
* Appends the provided debug message to the specified file. This method
* should be safe to call concurrently, even across multiple processes.
*
* @param path The path to the file to which the message should be
* appended. It must not be {@code null}.
* @param message The debug message to be appended to the file. It must not
* be {@code null}.
*/
public static void debugToFile(@NotNull final String path,
@NotNull final String message)
{
debugToFile(new File(path), true, true, message);
}



/**
* Appends the provided debug message to the specified file. This method
* should be safe to call concurrently, even across multiple processes.
*
* @param file The file to which the message should be appended. It must
* not be {@code null}.
* @param message The debug message to be appended to the file. It must not
* be {@code null}.
*/
public static void debugToFile(@NotNull final File file,
@NotNull final String message)
{
debugToFile(file, true, true, message);
}



/**
* Appends the provided debug message to the specified file. This method
* should be safe to call concurrently, even across multiple processes.
*
* @param file The file to which the message should be
* appended. It must not be {@code null}.
* @param includeTimestamp Indicates whether to include a timestamp along
* with the debug message.
* @param includeStackTrace Indicates whether to include a stack trace along
* with the debug message.
* @param message The debug message to be appended to the file.
* It must not be {@code null}.
*/
public static synchronized void debugToFile(@NotNull final File file,
final boolean includeTimestamp,
final boolean includeStackTrace,
@NotNull final String message)
{
try
{
try (FileChannel fileChannel = FileChannel.open(
file.toPath(),
StaticUtils.setOf(
StandardOpenOption.WRITE,
StandardOpenOption.CREATE,
StandardOpenOption.APPEND,
StandardOpenOption.SYNC)))
{
try (FileLock fileLock = fileChannel.lock())
{
final ByteStringBuffer messageBuffer = new ByteStringBuffer();

if (fileChannel.size() > 0L)
{
messageBuffer.append(StaticUtils.EOL_BYTES);
}

if (includeTimestamp)
{
messageBuffer.append(
StaticUtils.encodeRFC3339Time(System.currentTimeMillis()));
messageBuffer.append(StaticUtils.EOL_BYTES);
}

messageBuffer.append(message);
messageBuffer.append(StaticUtils.EOL_BYTES);

if (includeStackTrace)
{
messageBuffer.append(StaticUtils.getStackTrace(
Thread.currentThread().getStackTrace()));
messageBuffer.append(StaticUtils.EOL_BYTES);
}

fileChannel.write(ByteBuffer.wrap(
messageBuffer.getBackingArray(), 0, messageBuffer.length()));
}
}
}
catch (final Exception e)
{
// An error occurred while attempting to write to the file. As a
// fallback, print a message about it to standard error.
Debug.debugException(e);
System.err.println(ERR_DEBUG_CANNOT_WRITE_TO_FILE.get(
file.getAbsolutePath(), StaticUtils.getExceptionMessage(e),
message));
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -298,7 +298,7 @@ public void testLoggerLogLevel(final File f)
throws Exception
{
final Map<String,Set<Integer>> allowedExceptions = StaticUtils.mapOf(
"Debug.java", StaticUtils.setOf(92),
"Debug.java", StaticUtils.setOf(99),
"StaticUtils.java", StaticUtils.setOf(563, 586));

final Map<Integer,String> unwrappedLines =
Expand Down
54 changes: 54 additions & 0 deletions tests/unit/src/com/unboundid/util/DebugTestCase.java
Original file line number Diff line number Diff line change
Expand Up @@ -38,10 +38,14 @@


import java.io.ByteArrayInputStream;
import java.io.File;
import java.util.ArrayList;
import java.util.EnumSet;
import java.util.HashSet;
import java.util.List;
import java.util.Properties;
import java.util.Set;
import java.util.UUID;
import java.util.logging.Level;
import java.util.logging.Logger;

Expand Down Expand Up @@ -4823,4 +4827,54 @@ private static Set<String> getNames(final String... baseNames)

return nameSet;
}



/**
* Tests the behavior of the methods that can be used to write debug
* messages to a specified file.
*
* @throws Exception If an unexpected problem occurs.
*/
@Test()
public void testDebugToFile()
throws Exception
{
final List<String> messages = new ArrayList<>();

final File debugFile = createTempFile();
assertTrue(debugFile.delete());

String uuid = UUID.randomUUID().toString();
messages.add(uuid);
Debug.debugToFile(debugFile.getAbsolutePath(), uuid);

uuid = UUID.randomUUID().toString();
messages.add(uuid);
Debug.debugToFile(debugFile, uuid);

uuid = UUID.randomUUID().toString();
messages.add(uuid);
Debug.debugToFile(debugFile, true, true, uuid);

uuid = UUID.randomUUID().toString();
messages.add(uuid);
Debug.debugToFile(debugFile, false, true, uuid);

uuid = UUID.randomUUID().toString();
messages.add(uuid);
Debug.debugToFile(debugFile, true, false, uuid);

uuid = UUID.randomUUID().toString();
messages.add(uuid);
Debug.debugToFile(debugFile, false, false, uuid);

final List<String> lines = StaticUtils.readFileLines(debugFile);
for (final String message : messages)
{
assertTrue(lines.contains(message));
}

assertTrue(lines.contains(""));
}
}

0 comments on commit ccd189c

Please sign in to comment.