static void dissectFrame(
        final DriverEventCode eventCode,
        final MutableDirectBuffer buffer,
        final int offset,
        final StringBuilder builder)
    {
        int encodedLength = dissectLogHeader(CONTEXT, eventCode, buffer, offset, builder);

        builder.append(": address=");

        encodedLength += dissectSocketAddress(buffer, offset + encodedLength, builder);

        builder.append(" ");

        final int frameOffset = offset + encodedLength;
        final int frameType = frameType(buffer, frameOffset);
        switch (frameType)
        {
            case HeaderFlyweight.HDR_TYPE_PAD:
            case HeaderFlyweight.HDR_TYPE_DATA:
                DATA_HEADER.wrap(buffer, frameOffset, buffer.capacity() - frameOffset);
                dissectDataFrame(builder);
                break;

            case HeaderFlyweight.HDR_TYPE_SM:
                SM_HEADER.wrap(buffer, frameOffset, buffer.capacity() - frameOffset);
                dissectStatusFrame(builder);
                break;

            case HeaderFlyweight.HDR_TYPE_NAK:
                NAK_HEADER.wrap(buffer, frameOffset, buffer.capacity() - frameOffset);
                dissectNakFrame(builder);
                break;

            case HeaderFlyweight.HDR_TYPE_SETUP:
                SETUP_HEADER.wrap(buffer, frameOffset, buffer.capacity() - frameOffset);
                dissectSetupFrame(builder);
                break;

            case HeaderFlyweight.HDR_TYPE_RTTM:
                RTT_MEASUREMENT.wrap(buffer, frameOffset, buffer.capacity() - frameOffset);
                dissectRttFrame(builder);
                break;

            case HeaderFlyweight.HDR_TYPE_RES:
                dissectResFrame(buffer, frameOffset, builder);
                break;

            case HeaderFlyweight.HDR_TYPE_RSP_SETUP:
                RSP_SETUP.wrap(buffer, frameOffset, buffer.capacity() - frameOffset);
                dissectRspSetupFrame(builder);
                break;

            default:
                builder.append("type=UNKNOWN(").append(frameType).append(")");
                break;
        }
    }
@Test
    void dissectFrameTypeNak()
    {
        internalEncodeLogHeader(buffer, 0, 3, 3, () -> 3_000_000_000L);
        final int socketAddressOffset = encodeSocketAddress(
            buffer, LOG_HEADER_LENGTH, new InetSocketAddress("localhost", 8888));
        final NakFlyweight flyweight = new NakFlyweight();
        flyweight.wrap(buffer, LOG_HEADER_LENGTH + socketAddressOffset, 300);
        flyweight.headerType(HDR_TYPE_NAK);
        flyweight.flags((short)2);
        flyweight.frameLength(54);
        flyweight.sessionId(5);
        flyweight.streamId(8);
        flyweight.termId(20);
        flyweight.termOffset(0);
        flyweight.length(999999);

        dissectFrame(FRAME_OUT, buffer, 0, builder);

        assertEquals("[3.000000000] " + CONTEXT + ": " + FRAME_OUT.name() +
            " [3/3]: address=127.0.0.1:8888 type=NAK flags=00000010 frameLength=54 sessionId=5 streamId=8 " +
            "termId=20 termOffset=0 length=999999",
            builder.toString());
    }