1 /*******************************************************************************
2  * thrill/common/json_logger.cpp
3  *
4  * Logger for statistical output in JSON format for post-processing.
5  *
6  * Part of Project Thrill - http://project-thrill.org
7  *
8  * Copyright (C) 2016 Timo Bingmann <tb@panthema.net>
9  *
10  * All rights reserved. Published under the BSD-2 license in the LICENSE file.
11  ******************************************************************************/
12 
13 #include <thrill/common/json_logger.hpp>
14 #include <thrill/common/logger.hpp>
15 #include <thrill/common/string.hpp>
16 
17 #include <tlx/die.hpp>
18 
19 #include <cerrno>
20 #include <chrono>
21 #include <cstring>
22 #include <fstream>
23 #include <iostream>
24 #include <string>
25 #include <vector>
26 
27 namespace thrill {
28 namespace common {
29 
30 /******************************************************************************/
31 // JsonLogger
32 
JsonLogger(const std::string & path)33 JsonLogger::JsonLogger(const std::string& path) {
34     if (path.empty() || path == "/dev/null") {
35         // os_ remains nullptr
36         return;
37     }
38     if (path == "/dev/stdout") {
39         os_ = std::make_unique<std::ostream>(std::cout.rdbuf());
40         return;
41     }
42     if (path == "/dev/stderr") {
43         os_ = std::make_unique<std::ostream>(std::cerr.rdbuf());
44         return;
45     }
46 
47     os_ = std::make_unique<std::ofstream>(path.c_str());
48     if (!os_->good()) {
49         die("Could not open json log output: "
50             << path << " : " << strerror(errno));
51     }
52 }
53 
JsonLogger(JsonLogger * super)54 JsonLogger::JsonLogger(JsonLogger* super)
55     : super_(super) { }
56 
line()57 JsonLine JsonLogger::line() {
58     if (super_ != nullptr) {
59         JsonLine out = super_->line();
60 
61         // append common key:value pairs
62         if (!common_.str_.empty())
63             out << common_;
64 
65         return out;
66     }
67 
68     if (!os_) {
69         static std::ofstream dummy_of_;
70         return JsonLine(this, dummy_of_);
71     }
72 
73     JsonLine out(this, *os_);
74     *os_ << '{';
75 
76     // output timestamp in microseconds
77     out << "ts"
78         << std::chrono::duration_cast<std::chrono::microseconds>(
79         std::chrono::system_clock::now().time_since_epoch()).count();
80 
81     // append common key:value pairs
82     if (!common_.str_.empty())
83         out << common_;
84 
85     return out;
86 }
87 
88 } // namespace common
89 } // namespace thrill
90 
91 /******************************************************************************/
92