BitShares-Core  5.0.0
BitShares blockchain implementation and command-line interface software
log_message.cpp
Go to the documentation of this file.
1 #include <fc/log/log_message.hpp>
3 #include <fc/variant.hpp>
4 #include <fc/time.hpp>
5 #include <fc/thread/thread.hpp>
6 #include <fc/thread/task.hpp>
7 #include <fc/filesystem.hpp>
8 #include <fc/io/stdio.hpp>
9 #include <fc/io/json.hpp>
10 
11 namespace fc
12 {
13  namespace detail
14  {
16  {
17  public:
19  string file;
20  uint64_t line;
21  string method;
22  string thread_name;
23  string task_name;
24  string hostname;
25  string context;
27  };
28 
30  {
31  public:
33  :context( std::move(ctx) ){}
35 
37  string format;
39  };
40  }
41 
42 
43 
45  :my( std::make_shared<detail::log_context_impl>() ){}
46 
47  log_context::log_context( log_level ll, const char* file, uint64_t line,
48  const char* method )
49  :my( std::make_shared<detail::log_context_impl>() )
50  {
51  my->level = ll;
52  my->file = fc::path(file).filename().generic_string(); // TODO truncate filename
53  my->line = line;
54  my->method = method;
55  my->timestamp = time_point::now();
56  my->thread_name = fc::thread::current().name();
57  const char* current_task_desc = fc::thread::current().current_task_desc();
58  my->task_name = current_task_desc ? current_task_desc : "?unnamed?";
59  }
60 
61  log_context::log_context( const variant& v, uint32_t max_depth )
62  :my( std::make_shared<detail::log_context_impl>() )
63  {
64  auto obj = v.get_object();
65  my->level = obj["level"].as<log_level>(max_depth);
66  my->file = obj["file"].as_string();
67  my->line = obj["line"].as_uint64();
68  my->method = obj["method"].as_string();
69  my->hostname = obj["hostname"].as_string();
70  my->thread_name = obj["thread_name"].as_string();
71  if (obj.contains("task_name"))
72  my->task_name = obj["task_name"].as_string();
73  my->timestamp = obj["timestamp"].as<time_point>(max_depth);
74  if( obj.contains( "context" ) )
75  my->context = obj["context"].as<string>(max_depth);
76  }
77 
78  std::string log_context::to_string()const
79  {
80  return my->thread_name + " " + my->file + ":" + fc::to_string(my->line) + " " + my->method;
81 
82  }
83 
84  void log_context::append_context( const std::string& s )
85  {
86  if (!my->context.empty())
87  my->context += " -> ";
88  my->context += s;
89  }
90 
92 
93 
94  void to_variant( const log_context& l, variant& v, uint32_t max_depth )
95  {
96  v = l.to_variant(max_depth);
97  }
98 
99  void from_variant( const variant& l, log_context& c, uint32_t max_depth )
100  {
101  c = log_context(l, max_depth);
102  }
103 
104  void from_variant( const variant& l, log_message& c, uint32_t max_depth )
105  {
106  c = log_message(l, max_depth);
107  }
108  void to_variant( const log_message& m, variant& v, uint32_t max_depth )
109  {
110  v = m.to_variant( max_depth );
111  }
112 
113  void to_variant( log_level e, variant& v, uint32_t max_depth )
114  {
115  switch( e )
116  {
117  case log_level::all:
118  v = "all";
119  return;
120  case log_level::debug:
121  v = "debug";
122  return;
123  case log_level::info:
124  v = "info";
125  return;
126  case log_level::warn:
127  v = "warn";
128  return;
129  case log_level::error:
130  v = "error";
131  return;
132  case log_level::off:
133  v = "off";
134  return;
135  }
136  }
137  void from_variant( const variant& v, log_level& e, uint32_t max_depth )
138  {
139  try
140  {
141  if( v.as_string() == "all" ) e = log_level::all;
142  else if( v.as_string() == "debug" ) e = log_level::debug;
143  else if( v.as_string() == "info" ) e = log_level::info;
144  else if( v.as_string() == "warn" ) e = log_level::warn;
145  else if( v.as_string() == "error" ) e = log_level::error;
146  else if( v.as_string() == "off" ) e = log_level::off;
147  else FC_THROW_EXCEPTION( bad_cast_exception, "Failed to cast from Variant to log_level" );
148  } FC_RETHROW_EXCEPTIONS( error,
149  "Expected 'all|debug|info|warn|error|off', but got '${variant}'",
150  ("variant",v) );
151  }
152 
153 
154 
155  string log_context::get_file()const { return my->file; }
156  uint64_t log_context::get_line_number()const { return my->line; }
157  string log_context::get_method()const { return my->method; }
158  string log_context::get_thread_name()const { return my->thread_name; }
159  string log_context::get_task_name()const { return my->task_name; }
160  string log_context::get_host_name()const { return my->hostname; }
161  time_point log_context::get_timestamp()const { return my->timestamp; }
162  log_level log_context::get_log_level()const{ return my->level; }
163  string log_context::get_context()const { return my->context; }
164 
165 
166  variant log_context::to_variant(uint32_t max_depth)const
167  {
169  o( "level", variant(my->level, max_depth) )
170  ( "file", my->file )
171  ( "line", my->line )
172  ( "method", my->method )
173  ( "hostname", my->hostname )
174  ( "thread_name", my->thread_name )
175  ( "timestamp", variant(my->timestamp, max_depth) );
176 
177  if( my->context.size() )
178  o( "context", my->context );
179 
180  return o;
181  }
182 
185  :my( std::make_shared<detail::log_message_impl>() ){}
186 
187  log_message::log_message( log_context ctx, std::string format, variant_object args )
188  :my( std::make_shared<detail::log_message_impl>(std::move(ctx)) )
189  {
190  my->format = std::move(format);
191  my->args = std::move(args);
192  }
193 
194  log_message::log_message( const variant& v, uint32_t max_depth )
195  :my( std::make_shared<detail::log_message_impl>( log_context( v.get_object()["context"], max_depth ) ) )
196  {
197  my->format = v.get_object()["format"].as_string();
198  my->args = v.get_object()["data"].get_object();
199  }
200 
201  variant log_message::to_variant(uint32_t max_depth)const
202  {
203  return limited_mutable_variant_object(max_depth)
204  ( "context", my->context )
205  ( "format", my->format )
206  ( "data", my->args );
207  }
208 
209  log_context log_message::get_context()const { return my->context; }
210  string log_message::get_format()const { return my->format; }
211  variant_object log_message::get_data()const { return my->args; }
212 
214  {
215  return format_string( my->format, my->args );
216  }
217 
218 
219 } // fc
220 
std::string get_file() const
std::string format_string(const std::string &, const variant_object &, uint32_t max_object_depth=200)
std::string get_task_name() const
std::string get_thread_name() const
uint64_t get_line_number() const
Defines types and helper macros necessary for generating log messages.
variant to_variant(uint32_t max_depth) const
std::string get_message() const
An order-perserving dictionary of variant&#39;s.
std::string to_string() const
Definition: log_message.cpp:78
const char * current_task_desc() const
Definition: thread.cpp:154
std::string get_host_name() const
#define FC_RETHROW_EXCEPTIONS(LOG_LEVEL, FORMAT,...)
Catchs all exception&#39;s, std::exceptions, and ... and rethrows them after appending the provided log m...
Definition: exception.hpp:463
fc::path filename() const
Definition: filesystem.cpp:151
variant to_variant(uint32_t max_depth) const
std::string generic_string() const
Definition: filesystem.cpp:95
log_level get_log_level() const
variant_object & get_object()
Definition: variant.cpp:554
std::string get_format() const
static thread & current()
Definition: thread.cpp:125
provides information about where and when a log message was generated.
Definition: log_message.hpp:56
stores null, int64, uint64, double, bool, string, std::vector<variant>, and variant_object&#39;s.
Definition: variant.hpp:198
#define FC_THROW_EXCEPTION(EXCEPTION, FORMAT,...)
Definition: exception.hpp:378
log_context get_context() const
void append_context(const std::string &c)
Definition: log_message.cpp:84
log_message_impl(log_context &&ctx)
Definition: log_message.cpp:32
Defines exception&#39;s used by fc.
time_point get_timestamp() const
void from_variant(const variant &var, flat_set< T, A... > &vo, uint32_t _max_depth)
Definition: flat.hpp:116
std::string get_context() const
std::string to_string(double)
Definition: string.cpp:73
const string & name() const
returns the name given by set_name() for this thread
Definition: thread.cpp:138
aggregates a message along with the context and associated meta-information.
Definition: api.hpp:15
variant_object get_data() const
static time_point now()
Definition: time.cpp:13
wraps boost::filesystem::path to provide platform independent path manipulation.
Definition: filesystem.hpp:28
std::string get_method() const
std::string as_string() const
Definition: variant.cpp:469
An order-perserving dictionary of variant&#39;s.