Skip to content

Collect network statistics and make it available for the user applications. #8310

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 6 commits into from
Nov 12, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
119 changes: 119 additions & 0 deletions doc/README.isql_enhancements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -324,3 +324,122 @@ RDB$RELATIONS | 59| | | |

-- turn per-table stats off, using shortened name
SQL> SET PER_TAB OFF;



12) SET WIRE_STATS option.

Author: Vladyslav Khorsun <hvlad at users sourceforge net>

When set to ON shows wire (network) statistics after query execution.
It is set to OFF by default. The name WIRE_STATS could be shortened up to WIRE.

The statistics counters shown in two groups: 'logical' and 'physical':
- logical counters show numbers of packets in terms of Firebird wire protocol
and number of bytes send before compression and received after decompression;
- physical counters show number of physical packets and bytes send and
received over the wire, number of bytes could be affected by wire compression,
if present. Also, number of network roundtrips is shown: it is number of
changes of IO direction from 'send' to 'receive'.

Note, wire statistics is gathered by Remote provider only, i.e. it is always
zero for embedded connections. Also, it is collected by client and IO direction
(send, receive) is shown from client point of view.

Examples:

1. INET protocol with wire compression.
Set WireCompression = true in firebird.conf

>isql inet://employee

SQL> SET;
Print statistics: OFF
Print per-table stats: OFF
Print wire stats: OFF
...

SQL> SET WIRE;
SQL>
SQL> SELECT COUNT(*) FROM RDB$RELATIONS;

COUNT
=====================
67

Wire logical statistics:
send packets = 6
recv packets = 5
send bytes = 184
recv bytes = 224
Wire physical statistics:
send packets = 3
recv packets = 2
send bytes = 123
recv bytes = 88
roundtrips = 2

Note difference due to wire compression in send/recv bytes for logical and
physical stats.


2. XNET protocol (wire compression is not used).

>isql xnet://employee

SQL> SET WIRE;
SQL>
SQL> SELECT COUNT(*) FROM RDB$RELATIONS;

COUNT
=====================
67

Wire logical statistics:
send packets = 5
recv packets = 6
send bytes = 176
recv bytes = 256
Wire physical statistics:
send packets = 5
recv packets = 5
send bytes = 176
recv bytes = 256
roundtrips = 5

Note, send/recv bytes for logical and physical stats are equal.


3. Embedded connection (wire statistics is absent).

SQL> SET WIRE;
SQL>
SQL> select count(*) from rdb$relations;

COUNT
=====================
67

Wire logical statistics:
send packets = 0
recv packets = 0
send bytes = 0
recv bytes = 0
Wire physical statistics:
send packets = 0
recv packets = 0
send bytes = 0
recv bytes = 0
roundtrips = 0



13) SHOW WIRE_STATISTICS command.

Author: Vladyslav Khorsun <hvlad at users sourceforge net>

New ISQL command that shows accumulated wire statistics. There is also
shortened alias WIRE_STATS.

The command show values of wire statistics counters, accumulated since the
connection start time. Format is the same as of SET STATS above.
11 changes: 11 additions & 0 deletions src/include/firebird/impl/inf_pub.h
Original file line number Diff line number Diff line change
Expand Up @@ -178,6 +178,17 @@ enum db_info_types

fb_info_parallel_workers = 149,

// Wire stats items, implemented by Remote provider only
fb_info_wire_out_packets = 150,
fb_info_wire_in_packets = 151,
fb_info_wire_out_bytes = 152,
fb_info_wire_in_bytes = 153,
fb_info_wire_snd_packets = 154,
fb_info_wire_rcv_packets = 155,
fb_info_wire_snd_bytes = 156,
fb_info_wire_rcv_bytes = 157,
fb_info_wire_roundtrips = 158,

isc_info_db_last_value /* Leave this LAST! */
};

Expand Down
9 changes: 9 additions & 0 deletions src/include/gen/Firebird.pas
Original file line number Diff line number Diff line change
Expand Up @@ -4496,6 +4496,15 @@ IProfilerStatsImpl = class(IProfilerStats)
fb_info_username = byte(147);
fb_info_sqlrole = byte(148);
fb_info_parallel_workers = byte(149);
fb_info_wire_out_packets = byte(150);
fb_info_wire_in_packets = byte(151);
fb_info_wire_out_bytes = byte(152);
fb_info_wire_in_bytes = byte(153);
fb_info_wire_snd_packets = byte(154);
fb_info_wire_rcv_packets = byte(155);
fb_info_wire_snd_bytes = byte(156);
fb_info_wire_rcv_bytes = byte(157);
fb_info_wire_roundtrips = byte(158);
fb_info_crypt_encrypted = $01;
fb_info_crypt_process = $02;
fb_feature_multi_statements = byte(1);
Expand Down
137 changes: 135 additions & 2 deletions src/isql/isql.epp
Original file line number Diff line number Diff line change
Expand Up @@ -587,6 +587,7 @@ public:
KeepTranParams = true;
TranParams->assign(DEFAULT_DML_TRANS_SQL);
PerTableStats = false;
WireStats = false;
}

ColList global_Cols;
Expand All @@ -611,6 +612,7 @@ public:
SCHAR ISQL_charset[MAXCHARSET_SIZE];
bool KeepTranParams;
bool PerTableStats;
bool WireStats;
};

static SetValues setValues;
Expand Down Expand Up @@ -5381,7 +5383,7 @@ static processing_state frontend_set(const char* cmd, const char* const* parms,
exec_path_display,
sql, warning, sqlCont, heading, bail,
bulk_insert, maxrows, stmtTimeout,
keepTranParams, perTableStats,
keepTranParams, perTableStats, wireStats,
wrong
};
SetOptions(const optionsMap* inmap, size_t insize, int wrongval)
Expand Down Expand Up @@ -5422,7 +5424,8 @@ static processing_state frontend_set(const char* cmd, const char* const* parms,
{SetOptions::stmtTimeout, "LOCAL_TIMEOUT", 0},
{SetOptions::sqlCont, "DECFLOAT", 0},
{SetOptions::keepTranParams, "KEEP_TRAN_PARAMS", 9},
{SetOptions::perTableStats, "PER_TABLE_STATS", 7}
{SetOptions::perTableStats, "PER_TABLE_STATS", 7},
{SetOptions::wireStats, "WIRE_STATS", 4}
};

// Display current set options
Expand Down Expand Up @@ -5662,6 +5665,10 @@ static processing_state frontend_set(const char* cmd, const char* const* parms,
ret = do_set_command(parms[2], &setValues.PerTableStats);
break;

case SetOptions::wireStats:
ret = do_set_command(parms[2], &setValues.WireStats);
break;

default:
//{
// TEXT msg_string[MSG_LENGTH];
Expand Down Expand Up @@ -6452,6 +6459,7 @@ static processing_state print_sets()

print_set("Print statistics:", setValues.Stats);
print_set("Print per-table stats:", setValues.PerTableStats);
print_set("Print wire stats:", setValues.WireStats);
print_set("Echo commands:", setValues.Echo);
print_set("List format:", setValues.List);
print_set("Show Row Count:", setValues.Docount);
Expand Down Expand Up @@ -9004,6 +9012,10 @@ static processing_state process_statement(const TEXT* str2)
if (setValues.PerTableStats)
perTableStats->getStats(DB, true);

IsqlWireStats wireStats(DB);
if (setValues.WireStats)
wireStats.get(true);

// Prepare the dynamic query stored in string.
// But put this on the DDL transaction to get maximum visibility of
// metadata.
Expand Down Expand Up @@ -9172,6 +9184,9 @@ static processing_state process_statement(const TEXT* str2)
if (setValues.PerTableStats)
perTableStats->getStats(DB, false);

if (setValues.WireStats)
wireStats.print(false);

return ret;
}

Expand All @@ -9191,6 +9206,9 @@ static processing_state process_statement(const TEXT* str2)
if (setValues.PerTableStats)
perTableStats->getStats(DB, false);

if (setValues.WireStats)
wireStats.print(false);

return ret;
}

Expand Down Expand Up @@ -9238,6 +9256,9 @@ static processing_state process_statement(const TEXT* str2)
if (setValues.PerTableStats)
perTableStats->getStats(DB, false);

if (setValues.WireStats)
wireStats.print(false);

return ret;
}

Expand Down Expand Up @@ -9433,6 +9454,9 @@ static processing_state process_statement(const TEXT* str2)
if (setValues.PerTableStats)
perTableStats->getStats(DB, false);

if (setValues.WireStats)
wireStats.print(false);

if (pad)
ISQL_FREE(pad);
if (line)
Expand Down Expand Up @@ -9930,3 +9954,112 @@ unsigned PerTableStats::loadRelNames(Firebird::IAttachment* att)

return maxLen;
}

/// class IsqlWireStats

bool IsqlWireStats::get(bool initial)
{
if (!m_att)
return false;

const UCHAR info[] = {
fb_info_wire_snd_packets, fb_info_wire_rcv_packets,
fb_info_wire_out_packets, fb_info_wire_in_packets,
fb_info_wire_snd_bytes, fb_info_wire_rcv_bytes,
fb_info_wire_out_bytes, fb_info_wire_in_bytes,
fb_info_wire_roundtrips,
isc_info_end
};

UCHAR buffer[128];

m_att->getInfo(fbStatus, sizeof(info), info, sizeof(buffer), buffer);

if (fbStatus->getState() & Firebird::IStatus::STATE_ERRORS)
return false;

Firebird::ClumpletReader p(Firebird::ClumpletReader::InfoResponse, buffer, sizeof(buffer));
for (; !p.isEof(); p.moveNext())
{
FB_UINT64* pField = nullptr;
switch (p.getClumpTag())
{
case fb_info_wire_snd_packets:
pField = &m_snd_packets;
break;
case fb_info_wire_rcv_packets:
pField = &m_rcv_packets;
break;
case fb_info_wire_out_packets:
pField = &m_out_packets;
break;
case fb_info_wire_in_packets:
pField = &m_in_packets;
break;
case fb_info_wire_snd_bytes:
pField = &m_snd_bytes;
break;
case fb_info_wire_rcv_bytes:
pField = &m_rcv_bytes;
break;
case fb_info_wire_out_bytes:
pField = &m_out_bytes;
break;
case fb_info_wire_in_bytes:
pField = &m_in_bytes;
break;
case fb_info_wire_roundtrips:
pField = &m_roundtrips;
break;
case isc_info_end:
break;
case isc_info_error:
// don't return false here, as we not put error into status
return true;
/* uncomment to show error (isc_infunk) instead
{
ISC_STATUS errs[3] = { isc_arg_gds, 0, isc_arg_end };
auto b = p.getBytes();
errs[1] = isc_portable_integer(b + 1, p.getClumpLength() - 1);
fbStatus->setErrors(errs);
return false;
}*/

default:
fb_assert(false);
break;
}

if (pField)
{
const FB_UINT64 val = p.getBigInt();
*pField = initial ? val : val - *pField;
}
}

return true;
}

bool IsqlWireStats::print(bool initial)
{
if (!get(initial))
{
ISQL_errmsg(fbStatus);
return false;
}

IUTILS_printf2(Diag, "Wire logical statistics:%s", NEWLINE);
IUTILS_printf2(Diag, " send packets = %8" SQUADFORMAT "%s", m_out_packets, NEWLINE);
IUTILS_printf2(Diag, " recv packets = %8" SQUADFORMAT "%s", m_in_packets, NEWLINE);
IUTILS_printf2(Diag, " send bytes = %8" SQUADFORMAT "%s", m_out_bytes, NEWLINE);
IUTILS_printf2(Diag, " recv bytes = %8" SQUADFORMAT "%s", m_in_bytes, NEWLINE);

IUTILS_printf2(Diag, "Wire physical statistics:%s", NEWLINE);
IUTILS_printf2(Diag, " send packets = %8" SQUADFORMAT "%s", m_snd_packets, NEWLINE);
IUTILS_printf2(Diag, " recv packets = %8" SQUADFORMAT "%s", m_rcv_packets, NEWLINE);
IUTILS_printf2(Diag, " send bytes = %8" SQUADFORMAT "%s", m_snd_bytes, NEWLINE);
IUTILS_printf2(Diag, " recv bytes = %8" SQUADFORMAT "%s", m_rcv_bytes, NEWLINE);
IUTILS_printf2(Diag, " roundtrips = %8" SQUADFORMAT "%s", m_roundtrips, NEWLINE);

return true;
}
Loading
Loading