private void tryLog(boolean isHealthy) {
        LogLevel logLevel = isHealthy
                ? LogLevel.DEBUG
                : LogLevel.WARN;
        if (LOGGER.isEnabled(logLevel)) {
            LOGGER.log(logLevel,
                    "Used system memory: {}/{}; "
                            + "Used available memory: {}/{}; "
                            + "Used direct memory: {}/{}/{}; "
                            + "Used heap memory: {}/{}; "
                            + "Used non-heap memory: {}",
                    asMbString(usedSystemMemory),
                    asMbString(totalPhysicalMemorySize),

                    asMbString(usedAvailableMemory),
                    asMbString(maxAvailableMemory),

                    asMbString(usedDirectMemory),
                    asMbString(maxAvailableDirectMemory),
                    asMbString(maxDirectMemory),

                    asMbString(usedHeapMemory),
                    asMbString(maxHeapMemory),

                    asMbString(usedNonHeapMemory));
        }
        long now = System.nanoTime();
        float usedMemoryPercentage = 100F * usedDirectMemory / maxDirectMemory;
        if (directMemoryWarningThresholdPercentage > 0
                && directMemoryWarningThresholdPercentage < usedMemoryPercentage
                && minMemoryWarningIntervalNanos < (now - lastDirectMemoryWarningTimestampNanos)) {
            lastDirectMemoryWarningTimestampNanos = now;
            LOGGER.warn("The used direct memory has exceeded the warning threshold: {}/{}/{}/{}",
                    asMbString(usedDirectMemory),
                    asMbString(maxDirectMemory),
                    usedMemoryPercentage,
                    directMemoryWarningThresholdPercentage);
        }
        usedMemoryPercentage = 100F * usedHeapMemory / maxHeapMemory;
        if (heapMemoryWarningThresholdPercentage > 0
                && heapMemoryWarningThresholdPercentage < usedMemoryPercentage
                && minMemoryWarningIntervalNanos < (now - lastHeapMemoryWarningTimestampNanos)) {
            lastHeapMemoryWarningTimestampNanos = now;
            LOGGER.warn("The used heap memory has exceeded the warning threshold: {}/{}/{}/{}",
                    asMbString(usedHeapMemory),
                    asMbString(maxHeapMemory),
                    usedMemoryPercentage,
                    heapMemoryWarningThresholdPercentage);
        }
        // TODO: add tests
        if (!isHealthy
                && heapMemoryGcThresholdPercentage > 0
                && heapMemoryGcThresholdPercentage < usedMemoryPercentage
                && minHeapMemoryGcIntervalNanos < (now - lastHeapMemoryGcTimestampNanos)) {
            lastHeapMemoryGcTimestampNanos = now;
            LOGGER.info(
                    "Trying to start GC because the available memory has exceeded and the used heap memory has exceeded the GC threshold: {}/{}/{}/{}",
                    asMbString(usedHeapMemory),
                    asMbString(maxHeapMemory),
                    usedMemoryPercentage,
                    heapMemoryGcThresholdPercentage);
            System.gc();
        }
    }
@author James Chen
@implNote JVM Total Memory: 1. Off-Heap: a. Mapped files, b. Direct buffers c. Java stacks d.
          Metaspace (Class metadata: Constant pool, Field & Method data), e. Native code (JVM
          internal use only): PC registers, Native method stacks, Code cache, Structures used &
          allocated by native libraries(e.g IO libraries), Shared libraries of the JVM, etc. f.
          etc 2. Heap (eden, survivor, old)
          <a href="https://www.oracle.com/technetwork/tutorials/tutorials-1876574.html"> Getting
          Started with the G1 Garbage Collector</a>
@see jdk.internal.access.JavaNioAccess#getDirectBufferPool
@see io.micrometer.core.instrument.binder.jvm.JvmMemoryMetrics
turms-server-common/src/main/java/im/turms/server/common/infra/healthcheck/MemoryHealthChecker.java