Hazelcast C++ Client
Hazelcast C++ Client Library
logger.cpp
1 /*
2  * Copyright (c) 2008-2022, Hazelcast, Inc. All Rights Reserved.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include <iomanip>
18 #include <iostream>
19 #include <sstream>
20 #include <chrono>
21 #include <ctime>
22 #include <thread>
23 
24 #include "hazelcast/logger.h"
25 #include "hazelcast/client/hazelcast_client.h"
26 
27 namespace hazelcast {
28 
29 std::ostream&
30 operator<<(std::ostream& os, logger::level lvl)
31 {
32  switch (lvl) {
33  case logger::level::severe:
34  os << "SEVERE";
35  break;
36  case logger::level::warning:
37  os << "WARNING";
38  break;
39  case logger::level::info:
40  os << "INFO";
41  break;
42  case logger::level::fine:
43  os << "FINE";
44  break;
45  case logger::level::finer:
46  os << "FINER";
47  break;
48  case logger::level::finest:
49  os << "FINEST";
50  break;
51  default:
52  os << static_cast<int>(lvl);
53  break;
54  }
55  return os;
56 }
57 
58 logger::logger(std::string instance_name,
59  std::string cluster_name,
60  level level,
61  handler_type handler)
62  : instance_name_{ std::move(instance_name) }
63  , cluster_name_{ std::move(cluster_name) }
64  , level_{ level }
65  , handler_{ std::move(handler) }
66 {}
67 
68 bool
69 logger::enabled(level lvl) noexcept
70 {
71  return lvl >= level_;
72 }
73 
74 void
75 logger::log(level lvl, const std::string& msg) noexcept
76 {
77  handler_(instance_name_, cluster_name_, lvl, msg);
78 }
79 
80 namespace {
81 
82 std::tm
83 time_t_to_localtime(const std::time_t& t)
84 {
85  std::tm lt;
86 
87 #if defined(WIN32) || defined(_WIN32) || defined(WIN64) || defined(_WIN64)
88  ::localtime_s(&lt, &t);
89 #else
90  ::localtime_r(&t, &lt);
91 #endif
92 
93  return lt;
94 }
95 
96 } // namespace
97 
98 std::mutex logger::cout_lock_;
99 
100 void
101 logger::default_handler(const std::string& instance_name,
102  const std::string& cluster_name,
103  level lvl,
104  const std::string& msg) noexcept
105 {
106 
107  auto tp = std::chrono::system_clock::now();
108  auto t = std::chrono::system_clock::to_time_t(tp);
109  auto local_t = time_t_to_localtime(t);
110 
111  auto dur = tp.time_since_epoch();
112  auto sec = std::chrono::duration_cast<std::chrono::seconds>(dur);
113 
114  auto ms =
115  std::chrono::duration_cast<std::chrono::milliseconds>(dur - sec).count();
116 
117  std::ostringstream sstrm;
118 
119  char time_buffer[80];
120  std::strftime(
121  time_buffer, sizeof(time_buffer), "%d/%m/%Y %H:%M:%S.", &local_t);
122  sstrm << time_buffer << std::setfill('0') << std::setw(3) << ms << ' '
123  << lvl << ": [" << std::this_thread::get_id() << "] " << instance_name
124  << '[' << cluster_name << "] [" << client::version() << "] " << msg
125  << '\n';
126 
127  {
128  std::lock_guard<std::mutex> g(cout_lock_);
129  std::cout << sstrm.str() << std::flush;
130  }
131 }
132 
133 } // namespace hazelcast