Skip to content

Commit 4e90a60

Browse files
committed
feat: skip extra spaces for JSONs in query log
test added. doc actualized. ref: #3329
1 parent 8963d3c commit 4e90a60

File tree

4 files changed

+120
-15
lines changed

4 files changed

+120
-15
lines changed

manual/english/Logging/Query_logging.md

Lines changed: 3 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -48,26 +48,16 @@ The features of the Manticore SQL log format compared to the [plain format](../L
4848
* The query log can be replayed.
4949
* Additional performance counters (currently, per-agent distributed query times) are logged.
5050
* Each log entry is a valid Manticore SQL/JSON statement that reconstructs the full request, except if the logged request is too large and needs to be shortened for performance reasons.
51-
* JSON requests and additional messages, counters, etc., are logged as comments.
51+
* JSON requests are logged as comments, skipping extra whitespaces between elements.
52+
* Additional messages, counters, etc., are logged as comments.
5253

5354
<!-- intro -->
5455
`sphinxql` log entries example:
5556
<!-- request Example -->
5657
```sql
5758
/* Sun Apr 28 12:38:02.808 2024 conn 2 (127.0.0.1:53228) real 0.000 wall 0.000 found 0 */ SELECT * FROM test WHERE MATCH('test') OPTION ranker=proximity;
5859
/* Sun Apr 28 12:38:05.585 2024 conn 2 (127.0.0.1:53228) real 0.001 wall 0.001 found 0 */ SELECT * FROM test WHERE MATCH('test') GROUP BY channel_id OPTION ranker=proximity;
59-
/* Sun Apr 28 12:40:57.366 2024 conn 4 (127.0.0.1:53256) real 0.000 wall 0.000 found 0 */ /*{
60-
"table" : "test",
61-
"query":
62-
{
63-
"match":
64-
{
65-
"*" : "test"
66-
}
67-
},
68-
"_source": ["f"],
69-
"limit": 30
70-
} */
60+
/* Sun Apr 28 12:40:57.366 2024 conn 4 (127.0.0.1:53256) real 0.000 wall 0.000 found 0 */ /*{ "index" : "test", "query": { "match": { "*" : "test" } }, "_source": ["f"], "limit": 30 } */
7161
```
7262
<!-- end -->
7363

src/daemon/logger.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,7 @@ void FormatSphinxql ( const CSphQuery & q, const CSphQuery & tJoinOptions, int i
6666
void LogQuery ( const CSphQuery & q, const CSphQuery & tJoinOptions, const CSphQueryResultMeta & tMeta, const CSphVector<int64_t> & dAgentTimes );
6767
void LogSphinxqlClause ( Str_t sQuery, int iRealTime );
6868
void LogQueryToSphinxlLog (const CSphString& sQuery, const CSphString& sError );
69+
void VacuumSpacesFromJson ( const char* szJson, StringBuilder_c & tBuf ) noexcept;
6970

7071
class LogStmtGuard_c
7172
{

src/daemon/query_log.cpp

Lines changed: 64 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -453,13 +453,75 @@ static void FormatIndexHints ( const CSphQuery & tQuery, StringBuilder_c & tBuf
453453
tBuf << " */";
454454
}
455455

456+
void VacuumSpacesFromJson ( const char* szJson, StringBuilder_c & tBuf ) noexcept
457+
{
458+
if (!szJson)
459+
return;
460+
enum class eStates { initial, has_space, quoted, backslash };
461+
auto eState = eStates::initial;
462+
while (*szJson)
463+
{
464+
const char c = *szJson++;
465+
switch (eState)
466+
{
467+
case eStates::initial:
468+
switch (c)
469+
{
470+
case ' ':
471+
case '\t':
472+
case '\n':
473+
case '\r': eState = eStates::has_space;
474+
tBuf << " "; break;
475+
case '"': eState = eStates::quoted;
476+
tBuf << "\""; break;
477+
default:
478+
tBuf << c; break;
479+
}
480+
break;
481+
482+
case eStates::has_space:
483+
switch (c)
484+
{
485+
case ' ':
486+
case '\t':
487+
case '\n':
488+
case '\r': break;
489+
case '"': eState = eStates::quoted;
490+
tBuf << "\""; break;
491+
default: eState = eStates::initial;
492+
tBuf << c; break;
493+
}
494+
break;
495+
496+
case eStates::quoted:
497+
tBuf << c;
498+
switch (c)
499+
{
500+
case '"': eState = eStates::initial; break;
501+
case '\\': eState = eStates::backslash;
502+
default: break;
503+
}
504+
break;
505+
506+
case eStates::backslash:
507+
tBuf << c;
508+
eState = eStates::quoted;
509+
}
510+
}
511+
}
512+
456513

457514
static void LogQueryJson ( const CSphQuery & q, StringBuilder_c & tBuf )
458515
{
516+
tBuf << " /*";
459517
if ( q.m_sRawQuery.IsEmpty() )
460-
tBuf << " /*" << "{\"index\":\"" << q.m_sIndexes << "\"}*/ /*" << q.m_sQuery << " */";
518+
{
519+
tBuf << "{\"index\":\"" << q.m_sIndexes << "\"}*/ /*";
520+
VacuumSpacesFromJson ( q.m_sQuery.cstr(), tBuf );
521+
}
461522
else
462-
tBuf << " /*" << q.m_sRawQuery << " */";
523+
VacuumSpacesFromJson ( q.m_sRawQuery.cstr(), tBuf );
524+
tBuf << " */";
463525
}
464526

465527

src/gtests/gtests_stringbuilder.cpp

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
#include "std/string.h"
1717
#include "std/scoped_comma.h"
1818
#include "sphinxjson.h"
19+
#include "daemon/logger.h"
1920

2021

2122
//////////////////////////////////////////////////////////////////////////
@@ -664,3 +665,54 @@ TEST ( functions, JsonEscapedBuilder_sugar )
664665
tOut.AppendEscaped ( "\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f" );
665666
EXPECT_STREQ ( tOut.cstr(), "\"\\u0010\\u0011\\u0012\\u0013\\u0014\\u0015\\u0016\\u0017\\u0018\\u0019\\u001a\\u001b\\u001c\\u001d\\u001e\\u001f\"" );
666667
}
668+
669+
TEST ( functions, VacuumSpacesFromJson )
670+
{
671+
StringBuilder_c tOut;
672+
VacuumSpacesFromJson ( "bla", tOut );
673+
EXPECT_STREQ ( tOut.cstr(), "bla" );
674+
675+
tOut.Clear();
676+
VacuumSpacesFromJson ( "a b", tOut );
677+
EXPECT_STREQ ( tOut.cstr(), "a b" );
678+
679+
tOut.Clear();
680+
VacuumSpacesFromJson ( "a b\"a b", tOut );
681+
EXPECT_STREQ ( tOut.cstr(), "a b\"a b" );
682+
683+
tOut.Clear();
684+
VacuumSpacesFromJson ( "(a \t\r\n b)", tOut );
685+
EXPECT_STREQ ( tOut.cstr(), "(a b)" );
686+
687+
tOut.Clear();
688+
VacuumSpacesFromJson ( "\"(a \t\r\n b)\"", tOut );
689+
EXPECT_STREQ ( tOut.cstr(), "\"(a \t\r\n b)\"" );
690+
691+
tOut.Clear();
692+
VacuumSpacesFromJson ( R"(a \t\r\n b)", tOut );
693+
EXPECT_STREQ ( tOut.cstr(), R"(a \t\r\n b)" );
694+
695+
tOut.Clear();
696+
VacuumSpacesFromJson ( "a \r b\"a \n c\" \t d", tOut );
697+
EXPECT_STREQ ( tOut.cstr(), "a b\"a \n c\" d" );
698+
699+
tOut.Clear();
700+
VacuumSpacesFromJson ( "a \r b\"a \\\" c\" \t d", tOut );
701+
EXPECT_STREQ ( tOut.cstr(), "a b\"a \\\" c\" d" );
702+
703+
tOut.Clear();
704+
VacuumSpacesFromJson ( R"({
705+
"index" : "test",
706+
"query":
707+
{
708+
"match":
709+
{
710+
"*" : "test"
711+
}
712+
},
713+
"_source": ["f"],
714+
"limit": 30
715+
})", tOut );
716+
EXPECT_STREQ ( tOut.cstr(), R"({ "index" : "test", "query": { "match": { "*" : "test" } }, "_source": ["f"], "limit": 30 })" );
717+
718+
}

0 commit comments

Comments
 (0)