Skip to content

Commit a16aef7

Browse files
authored
Merge pull request #218 from intel-innersource/rdobrowo/add_json_output_support
Add json output to pcm-raw
2 parents c33fa7d + 6665aa2 commit a16aef7

File tree

4 files changed

+119
-37
lines changed

4 files changed

+119
-37
lines changed

.github/workflows/ci-test.yml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,3 +63,9 @@ jobs:
6363
with:
6464
name: test-log-raw-tr-wi_ext-single_header-${{ github.sha }}
6565
path: build/bin/raw_tr_wi_ext_single_header.csv
66+
67+
- name: upload-artifact
68+
uses: actions/upload-artifact@v2
69+
with:
70+
name: test-log-raw-json-${{ github.sha }}
71+
path: build/bin/raw_json.json

src/pcm-raw.cpp

Lines changed: 83 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,8 @@ void print_usage(const string progname)
5656
cerr << " -r | --reset | /reset => reset PMU configuration (at your own risk)\n";
5757
cerr << " -csv[=file.csv] | /csv[=file.csv] => output compact CSV format to screen or\n"
5858
<< " to a file, in case filename is provided\n";
59+
cerr << " -json[=file.json] | /json[=file.json] => output json format to screen or\n"
60+
<< " to a file, in case filename is provided\n";
5961
cerr << " -out filename | /out filename => write all output (stdout and stderr) to specified file\n";
6062
cerr << " event description example: -e core/config=0x30203,name=LD_BLOCKS.STORE_FORWARD/ -e core/fixed,config=0x333/ \n";
6163
cerr << " -e cha/config=0,name=UNC_CHA_CLOCKTICKS/ -e imc/fixed,name=DRAM_CLOCKS/\n";
@@ -944,7 +946,9 @@ bool transpose = false;
944946
bool extendPrintout = false;
945947
bool singleHeader = false;
946948
std::string separator = ",";
949+
const std::string jsonSeparator = "\":";
947950
bool sampleSeparator = false;
951+
bool outputToJson = false;
948952

949953
struct PrintOffset {
950954
const std::string entry;
@@ -963,21 +967,41 @@ int getPrintOffsetIdx(const std::string &value) {
963967
return -1;
964968
}
965969

966-
void printRowBegin(const std::string & EventName, const CoreCounterState & BeforeState, const CoreCounterState & AfterState, PCM* m)
970+
void printNewLine(const CsvOutputType outputType) {
971+
if (outputType == Data)
972+
cout << "\n";
973+
else if (outputType == Json)
974+
cout << "}\n";
975+
}
976+
977+
void printRowBeginCSV(const std::string & EventName, const CoreCounterState & BeforeState, const CoreCounterState & AfterState, PCM* m)
967978
{
968979
printDateForCSV(CsvOutputType::Data, separator);
969980
cout << EventName << separator << (1000ULL * getInvariantTSC(BeforeState, AfterState)) / m->getNominalFrequency() << separator << getInvariantTSC(BeforeState, AfterState);
970981
}
971982

972-
973-
template <class MetricFunc>
974-
void printRow(const std::string & EventName, MetricFunc metricFunc, const std::vector<CoreCounterState>& BeforeState, const std::vector<CoreCounterState>& AfterState, PCM* m, const CsvOutputType outputType, PrintOffset& printOffset)
983+
void printRowBeginJson(const std::string & EventName, const CoreCounterState & BeforeState, const CoreCounterState & AfterState, PCM* m)
975984
{
985+
cout << "{\"";
986+
printDateForJson(separator, jsonSeparator);
987+
cout << "Event" << jsonSeparator << "\"" << EventName << "\"" << separator << "ms" << jsonSeparator << (1000ULL * getInvariantTSC(BeforeState, AfterState)) / m->getNominalFrequency()
988+
<< separator << "InvariantTSC" << jsonSeparator << getInvariantTSC(BeforeState, AfterState);
989+
}
990+
991+
void printRowBegin(const std::string & EventName, const CoreCounterState & BeforeState, const CoreCounterState & AfterState, PCM* m, const CsvOutputType outputType, PrintOffset& printOffset) {
976992
if (outputType == Data) {
977-
printRowBegin(EventName, BeforeState[0], AfterState[0], m);
993+
printRowBeginCSV(EventName, BeforeState, AfterState, m);
978994
for (int i = 0 ; i < printOffset.start ; i++)
979995
std::cout << separator;
996+
} else if (outputType == Json) {
997+
printRowBeginJson(EventName, BeforeState, AfterState, m);
980998
}
999+
}
1000+
1001+
template <class MetricFunc>
1002+
void printRow(const std::string & EventName, MetricFunc metricFunc, const std::vector<CoreCounterState>& BeforeState, const std::vector<CoreCounterState>& AfterState, PCM* m, const CsvOutputType outputType, PrintOffset& printOffset)
1003+
{
1004+
printRowBegin(EventName, BeforeState[0], AfterState[0], m, outputType, printOffset);
9811005

9821006
for (uint32 core = 0; core < m->getNumCores(); ++core)
9831007
{
@@ -995,13 +1019,15 @@ void printRow(const std::string & EventName, MetricFunc metricFunc, const std::v
9951019
cout << separator << "core_SKT" << m->getSocketId(core) << "_CORE" << core;
9961020
printOffset.end++;
9971021
}
998-
else
1022+
else if (outputType == Json) {
1023+
cout << separator << "core_SKT" << m->getSocketId(core) << "_CORE" << core <<
1024+
jsonSeparator << metricFunc(BeforeState[core], AfterState[core]);
1025+
} else
9991026
assert(!"unknown output type");
10001027
}
10011028
}
10021029

1003-
if (outputType == Data)
1004-
cout << "\n";
1030+
printNewLine(outputType);
10051031
};
10061032

10071033
typedef uint64 (*UncoreMetricFunc)(const uint32 u, const uint32 i, const ServerUncoreCounterState& before, const ServerUncoreCounterState& after);
@@ -1079,11 +1105,7 @@ void printTransposed(const PCM::RawPMUConfigs& curPMUConfigs,
10791105
{
10801106
if (fixedEvents.size())
10811107
{
1082-
if (outputType == Data) {
1083-
printRowBegin(miscName, BeforeState[0], AfterState[0], m);
1084-
for (int off = 0 ; off < printOffset.start; off++)
1085-
cout << separator;
1086-
}
1108+
printRowBegin(miscName, BeforeState[0], AfterState[0], m, outputType, printOffset);
10871109

10881110
for (uint32 s = 0; s < m->getNumSockets(); ++s)
10891111
{
@@ -1101,6 +1123,9 @@ void printTransposed(const PCM::RawPMUConfigs& curPMUConfigs,
11011123
else if (outputType == Header21) {
11021124
cout << separator << type << "_SKT" << s << "_" << miscName << u;
11031125
printOffset.end++;
1126+
} else if (outputType == Json) {
1127+
cout << separator << type << "_SKT" << s << "_" << miscName << u
1128+
<< jsonSeparator << fixedMetricFunc(u, BeforeUncoreState[s], AfterUncoreState[s]);
11041129
} else
11051130
assert(!"unknown output type");
11061131
}
@@ -1109,8 +1134,7 @@ void printTransposed(const PCM::RawPMUConfigs& curPMUConfigs,
11091134
if (is_header)
11101135
is_header_printed = true;
11111136

1112-
if (outputType == Data)
1113-
cout << "\n";
1137+
printNewLine(outputType);
11141138
}
11151139
uint32 i = 0;
11161140
for (auto& event : events)
@@ -1120,11 +1144,7 @@ void printTransposed(const PCM::RawPMUConfigs& curPMUConfigs,
11201144
if (is_header && is_header_printed)
11211145
break;
11221146

1123-
if (outputType == Data) {
1124-
printRowBegin(name, BeforeState[0], AfterState[0], m);
1125-
for (int off = 0 ; off < printOffset.start; off++)
1126-
cout << separator;
1127-
}
1147+
printRowBegin(name, BeforeState[0], AfterState[0], m, outputType, printOffset);
11281148

11291149
for (uint32 s = 0; s < m->getNumSockets(); ++s)
11301150
{
@@ -1148,6 +1168,11 @@ void printTransposed(const PCM::RawPMUConfigs& curPMUConfigs,
11481168
cout << separator << type << "_SKT" << s << "_" << miscName << u;
11491169
printOffset.end++;
11501170
}
1171+
else if (outputType == Json)
1172+
{
1173+
cout << separator << type << "_SKT" << s << "_" << miscName << u
1174+
<< jsonSeparator << metricFunc(u, i, BeforeUncoreState[s], AfterUncoreState[s]);
1175+
}
11511176
else
11521177
{
11531178
assert(!"unknown output type");
@@ -1159,8 +1184,7 @@ void printTransposed(const PCM::RawPMUConfigs& curPMUConfigs,
11591184
is_header_printed = true;
11601185

11611186
++i;
1162-
if (outputType == Data)
1163-
cout << "\n";
1187+
printNewLine(outputType);
11641188
}
11651189
};
11661190
auto printMSRRows = [&](const MSRScope& scope)
@@ -1174,11 +1198,7 @@ void printTransposed(const PCM::RawPMUConfigs& curPMUConfigs,
11741198
if (is_header && is_header_printed)
11751199
return false;
11761200

1177-
if (outputType == Data) {
1178-
printRowBegin(name, BeforeState[0], AfterState[0], m);
1179-
for (int off = 0; off < printOffset.start; off++)
1180-
cout << separator;
1181-
}
1201+
printRowBegin(name, BeforeState[0], AfterState[0], m, outputType, printOffset);
11821202

11831203
switch (scope)
11841204
{
@@ -1203,6 +1223,10 @@ void printTransposed(const PCM::RawPMUConfigs& curPMUConfigs,
12031223
cout << separator << type << "_SKT" << s ;
12041224
printOffset.end++;
12051225
}
1226+
else if (outputType == Json) {
1227+
cout << separator << type << "_SKT" << s
1228+
<< jsonSeparator << getMSREvent(index, msrType, BeforeSocketState[s], AfterSocketState[s]);
1229+
}
12061230
else
12071231
{
12081232
assert(!"unknown output type");
@@ -1230,6 +1254,10 @@ void printTransposed(const PCM::RawPMUConfigs& curPMUConfigs,
12301254
cout << separator << type << "_SKT" << m->getSocketId(core) << "_CORE" << core;
12311255
printOffset.end++;
12321256
}
1257+
else if (outputType == Json) {
1258+
cout << separator << type << "_SKT" << m->getSocketId(core) << "_CORE" << core
1259+
<< jsonSeparator << getMSREvent(index, msrType, BeforeState[core], AfterState[core]);
1260+
}
12331261
else
12341262
{
12351263
assert(!"unknown output type");
@@ -1241,8 +1269,7 @@ void printTransposed(const PCM::RawPMUConfigs& curPMUConfigs,
12411269
if (is_header)
12421270
is_header_printed = true;
12431271

1244-
if (outputType == Data)
1245-
cout << "\n";
1272+
printNewLine(outputType);
12461273

12471274
return true;
12481275
};
@@ -1325,15 +1352,15 @@ void printTransposed(const PCM::RawPMUConfigs& curPMUConfigs,
13251352
choose(outputType,
13261353
[&]() { printUncoreRows(nullptr, (uint32) m->getQPILinksPerSocket(), "LINK"); },
13271354
[&]() { printUncoreRows(nullptr, (uint32) m->getQPILinksPerSocket(), type); },
1328-
[&]() { printUncoreRows([](const uint32 u, const uint32 i, const ServerUncoreCounterState& before, const ServerUncoreCounterState& after) { return getM3UPICounter(u, i, before, after); }, (uint32) m->getQPILinksPerSocket());
1355+
[&]() { printUncoreRows([](const uint32 u, const uint32 i, const ServerUncoreCounterState& before, const ServerUncoreCounterState& after) { return getM3UPICounter(u, i, before, after); }, (uint32) m->getQPILinksPerSocket(), "LINK");
13291356
});
13301357
}
13311358
else if (type == "xpi" || type == "upi" || type == "qpi")
13321359
{
13331360
choose(outputType,
13341361
[&]() { printUncoreRows(nullptr, (uint32) m->getQPILinksPerSocket(), "LINK"); },
13351362
[&]() { printUncoreRows(nullptr, (uint32) m->getQPILinksPerSocket(), type); },
1336-
[&]() { printUncoreRows([](const uint32 u, const uint32 i, const ServerUncoreCounterState& before, const ServerUncoreCounterState& after) { return getXPICounter(u, i, before, after); }, (uint32) m->getQPILinksPerSocket());
1363+
[&]() { printUncoreRows([](const uint32 u, const uint32 i, const ServerUncoreCounterState& before, const ServerUncoreCounterState& after) { return getXPICounter(u, i, before, after); }, (uint32) m->getQPILinksPerSocket(), "LINK");
13371364
});
13381365
}
13391366
else if (type == "imc")
@@ -1350,15 +1377,15 @@ void printTransposed(const PCM::RawPMUConfigs& curPMUConfigs,
13501377
choose(outputType,
13511378
[&]() { printUncoreRows(nullptr, (uint32) m->getMCPerSocket(), "MC"); },
13521379
[&]() { printUncoreRows(nullptr, (uint32) m->getMCPerSocket(), type); },
1353-
[&]() { printUncoreRows([](const uint32 u, const uint32 i, const ServerUncoreCounterState& before, const ServerUncoreCounterState& after) { return getM2MCounter(u, i, before, after); }, (uint32)m->getMCPerSocket());
1380+
[&]() { printUncoreRows([](const uint32 u, const uint32 i, const ServerUncoreCounterState& before, const ServerUncoreCounterState& after) { return getM2MCounter(u, i, before, after); }, (uint32)m->getMCPerSocket(), "MC");
13541381
});
13551382
}
13561383
else if (type == "pcu")
13571384
{
13581385
choose(outputType,
13591386
[&]() { printUncoreRows(nullptr, 1U, ""); },
13601387
[&]() { printUncoreRows(nullptr, 1U, type); },
1361-
[&]() { printUncoreRows([](const uint32, const uint32 i, const ServerUncoreCounterState& before, const ServerUncoreCounterState& after) { return getPCUCounter(i, before, after); }, 1U);
1388+
[&]() { printUncoreRows([](const uint32, const uint32 i, const ServerUncoreCounterState& before, const ServerUncoreCounterState& after) { return getPCUCounter(i, before, after); }, 1U, "");
13621389
});
13631390
}
13641391
else if (type == "ubox")
@@ -1375,23 +1402,23 @@ void printTransposed(const PCM::RawPMUConfigs& curPMUConfigs,
13751402
choose(outputType,
13761403
[&]() { printUncoreRows(nullptr, (uint32) m->getMaxNumOfCBoxes(), "C"); },
13771404
[&]() { printUncoreRows(nullptr, (uint32) m->getMaxNumOfCBoxes(), type); },
1378-
[&]() { printUncoreRows([](const uint32 u, const uint32 i, const ServerUncoreCounterState& before, const ServerUncoreCounterState& after) { return getCBOCounter(u, i, before, after); }, (uint32)m->getMaxNumOfCBoxes());
1405+
[&]() { printUncoreRows([](const uint32 u, const uint32 i, const ServerUncoreCounterState& before, const ServerUncoreCounterState& after) { return getCBOCounter(u, i, before, after); }, (uint32)m->getMaxNumOfCBoxes(), "C");
13791406
});
13801407
}
13811408
else if (type == "irp")
13821409
{
13831410
choose(outputType,
13841411
[&]() { printUncoreRows(nullptr, (uint32) m->getMaxNumOfIIOStacks(), "IRP"); },
13851412
[&]() { printUncoreRows(nullptr, (uint32) m->getMaxNumOfIIOStacks(), type); },
1386-
[&]() { printUncoreRows([](const uint32 u, const uint32 i, const ServerUncoreCounterState& before, const ServerUncoreCounterState& after) { return getIRPCounter(u, i, before, after); }, (uint32)m->getMaxNumOfIIOStacks());
1413+
[&]() { printUncoreRows([](const uint32 u, const uint32 i, const ServerUncoreCounterState& before, const ServerUncoreCounterState& after) { return getIRPCounter(u, i, before, after); }, (uint32)m->getMaxNumOfIIOStacks(), "IRP");
13871414
});
13881415
}
13891416
else if (type == "iio")
13901417
{
13911418
choose(outputType,
13921419
[&]() { printUncoreRows(nullptr, (uint32) m->getMaxNumOfIIOStacks(), "IIO"); },
13931420
[&]() { printUncoreRows(nullptr, (uint32) m->getMaxNumOfIIOStacks(), type); },
1394-
[&]() { printUncoreRows([](const uint32 u, const uint32 i, const ServerUncoreCounterState& before, const ServerUncoreCounterState& after) { return getIIOCounter(u, i, before, after); }, (uint32)m->getMaxNumOfIIOStacks());
1421+
[&]() { printUncoreRows([](const uint32 u, const uint32 i, const ServerUncoreCounterState& before, const ServerUncoreCounterState& after) { return getIIOCounter(u, i, before, after); }, (uint32)m->getMaxNumOfIIOStacks(), "IIO");
13951422
});
13961423
}
13971424
else
@@ -1725,6 +1752,11 @@ void printAll(const PCM::RawPMUConfigs& curPMUConfigs,
17251752
std::vector<PCM::RawPMUConfigs>& PMUConfigs,
17261753
const bool & isLastGroup)
17271754
{
1755+
if (outputToJson) {
1756+
printTransposed(curPMUConfigs, m, BeforeState, AfterState, BeforeUncoreState, AfterUncoreState, BeforeSocketState, AfterSocketState, Json, isLastGroup);
1757+
return;
1758+
}
1759+
17281760
static bool displayHeader = true;
17291761

17301762
if (!extendPrintout && transpose)
@@ -1833,6 +1865,21 @@ int main(int argc, char* argv[])
18331865
}
18341866
continue;
18351867
}
1868+
else if (strncmp(*argv, "-json", 5) == 0 ||
1869+
strncmp(*argv, "/json", 5) == 0)
1870+
{
1871+
separator = ",\"";
1872+
outputToJson = true;
1873+
string cmd = string(*argv);
1874+
size_t found = cmd.find('=', 5);
1875+
if (found != string::npos) {
1876+
string filename = cmd.substr(found + 1);
1877+
if (!filename.empty()) {
1878+
m->setOutput(filename);
1879+
}
1880+
}
1881+
continue;
1882+
}
18361883
else if (mainLoop.parseArg(*argv))
18371884
{
18381885
continue;

src/utils.h

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -225,7 +225,8 @@ enum CsvOutputType
225225
Header1,
226226
Header2,
227227
Data,
228-
Header21 // merged headers 2 and 1
228+
Header21, // merged headers 2 and 1
229+
Json
229230
};
230231

231232
template <class H1, class H2, class D>
@@ -241,6 +242,7 @@ inline void choose(const CsvOutputType outputType, H1 h1Func, H2 h2Func, D dataF
241242
h2Func();
242243
break;
243244
case Data:
245+
case Json:
244246
dataFunc();
245247
break;
246248
default:
@@ -275,6 +277,26 @@ inline void printDateForCSV(const CsvOutputType outputType, std::string separato
275277
});
276278
}
277279

280+
inline void printDateForJson(const std::string& separator, const std::string &jsonSeparator)
281+
{
282+
std::pair<tm, uint64> tt{ pcm_localtime() };
283+
std::cout.precision(3);
284+
char old_fill = std::cout.fill('0');
285+
std::cout <<
286+
"Date" << jsonSeparator << "\"" <<
287+
std::setw(4) << 1900 + tt.first.tm_year << '-' <<
288+
std::setw(2) << 1 + tt.first.tm_mon << '-' <<
289+
std::setw(2) << tt.first.tm_mday << "\"" << separator <<
290+
"Time" << jsonSeparator << "\"" <<
291+
std::setw(2) << tt.first.tm_hour << ':' <<
292+
std::setw(2) << tt.first.tm_min << ':' <<
293+
std::setw(2) << tt.first.tm_sec << '.' <<
294+
std::setw(3) << tt.second << "\"" << separator; // milliseconds
295+
std::cout.fill(old_fill);
296+
std::cout.setf(std::ios::fixed);
297+
std::cout.precision(2);
298+
}
299+
278300
std::vector<std::string> split(const std::string & str, const char delim);
279301

280302
class PCM;

tests/test.sh

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -327,4 +327,11 @@ if [ "$?" -ne "0" ]; then
327327
exit 1
328328
fi
329329

330+
echo Testing pcm-raw with -json
331+
./pcm-raw -el event_file_test.txt -json=raw_json.json -i=4 0.25
332+
if [ "$?" -ne "0" ]; then
333+
echo "Error in pcm-raw"
334+
exit 1
335+
fi
336+
330337
popd

0 commit comments

Comments
 (0)