All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.swirlds.logging.api.internal.format.StackTracePrinter Maven / Gradle / Ivy

Go to download

Swirlds is a software platform designed to build fully-distributed applications that harness the power of the cloud without servers. Now you can develop applications with fairness in decision making, speed, trust and reliability, at a fraction of the cost of traditional server-based platforms.

There is a newer version: 0.56.5
Show newest version
/*
 * Copyright (C) 2023-2024 Hedera Hashgraph, LLC
 *
 * 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.swirlds.logging.api.internal.format;

import edu.umd.cs.findbugs.annotations.NonNull;
import edu.umd.cs.findbugs.annotations.Nullable;
import java.io.IOException;
import java.util.Collections;
import java.util.IdentityHashMap;
import java.util.Set;

/**
 * This class is responsible for printing stack traces of exceptions to a specified Appendable object. It includes
 * functionality to avoid printing circular references and to handle cases where certain parts of the trace have already
 * been printed. It also includes emergency logging for null references.
 */
public class StackTracePrinter {

    private static final int MAX_STACK_TRACE_DEPTH = -1;
    public static final String LINE_SEPARATOR = System.lineSeparator();

    /**
     * Prints the stack trace of a throwable to a provided Appendable writer. Avoids printing circular references and
     * handles already printed traces.
     *
     * @param writer         The Appendable object to write the stack trace to.
     * @param throwable      The Throwable object whose stack trace is to be printed.
     */
    public static void print(final @NonNull StringBuilder writer, final @Nullable Throwable throwable)
            throws IOException {
        final Set alreadyPrinted = Collections.newSetFromMap(new IdentityHashMap<>());
        alreadyPrinted.add(throwable);
        Throwable currentThrowable = throwable;
        StackTraceElement[] enclosingTrace = new StackTraceElement[0];
        while (currentThrowable != null) {
            writer.append(currentThrowable.getClass().getName());
            writer.append(": ");
            writer.append(currentThrowable.getMessage());
            writer.append(LINE_SEPARATOR);

            final StackTraceElement[] stackTrace = currentThrowable.getStackTrace();
            int m = stackTrace.length - 1;
            int n = enclosingTrace.length - 1;
            while (m >= 0 && n >= 0 && stackTrace[m].equals(enclosingTrace[n])) {
                m--;
                n--;
            }
            if (MAX_STACK_TRACE_DEPTH >= 0) {
                m = Math.min(m, MAX_STACK_TRACE_DEPTH);
            }
            final int skippedFrames = stackTrace.length - 1 - m;
            for (int i = 0; i <= m; i++) {
                final StackTraceElement stackTraceElement = stackTrace[i];
                final String moduleName = stackTraceElement.getModuleName();
                final String fileName = stackTraceElement.getFileName();
                writer.append("\tat ");
                if (moduleName != null) {
                    writer.append(moduleName);
                    writer.append("/");
                }
                writer.append(stackTraceElement.getClassName());
                writer.append(".");
                writer.append(stackTraceElement.getMethodName());
                if (fileName != null) {
                    writer.append("(");
                    writer.append(fileName);
                    writer.append(":");
                    writer.append(stackTraceElement.getLineNumber());
                    writer.append(")");
                } else {
                    writer.append("(Unknown Source)");
                }

                writer.append(LINE_SEPARATOR);
            }
            if (skippedFrames != 0) {
                writer.append("\t... ");
                writer.append(skippedFrames);
                writer.append(" more");
                writer.append(LINE_SEPARATOR);
            }

            final Throwable cause = currentThrowable.getCause();
            enclosingTrace = stackTrace;
            if (cause != null) {
                writer.append("Caused by: "); // Separator for cause
                if (!alreadyPrinted.add(cause)) {
                    writer.append("[CIRCULAR REFERENCE: ").append(cause).append("]");
                    currentThrowable = null;
                } else {
                    currentThrowable = cause;
                }
            } else {
                currentThrowable = null;
            }
        }
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy