OSVR Framework (Internal Development Docs)  0.6-1962-g59773924
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Modules Pages
Log.cpp
Go to the documentation of this file.
1 
12 // Copyright 2016 Sensics, Inc.
13 //
14 // Licensed under the Apache License, Version 2.0 (the "License");
15 // you may not use this file except in compliance with the License.
16 // You may obtain a copy of the License at
17 //
18 // http://www.apache.org/licenses/LICENSE-2.0
19 //
20 // Unless required by applicable law or agreed to in writing, software
21 // distributed under the License is distributed on an "AS IS" BASIS,
22 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
23 // See the License for the specific language governing permissions and
24 // limitations under the License.
25 
26 // Internal Includes
27 #include "LogSinks.h"
29 #include <osvr/Util/Log.h>
30 #include <osvr/Util/Logger.h>
31 #include <osvr/Util/LogConfig.h> // for OSVR_UTIL_LOG_SINGLETON
33 
34 #ifdef OSVR_UTIL_LOG_SINGLETON
35 #include "LogUtils.h"
36 #include <osvr/Util/LogRegistry.h>
37 #endif
38 
39 // Library/third-party includes
40 #include <boost/filesystem.hpp>
41 #include <spdlog/spdlog.h>
42 
43 // Standard includes
44 #include <memory> // for std::make_shared, std::shared_ptr
45 #include <string> // for std::string
46 
47 namespace osvr {
48 namespace util {
49  namespace log {
50 
51 #ifdef OSVR_UTIL_LOG_SINGLETON
52  bool tryInitializingLoggingWithBaseName(std::string const &baseName) {
53  auto sanitized = sanitizeFilenamePiece(baseName);
54  // try initialization
55  auto &inst = LogRegistry::instance(&sanitized);
56  // test for success
57  return (inst.getLogFileBaseName() == sanitized);
58  }
59 
60  LoggerPtr make_logger(const std::string &logger_name) {
61  return LogRegistry::instance().getOrCreateLogger(logger_name);
62  }
63 
64  void drop(const std::string &logger_name) {
65  LogRegistry::instance().drop(logger_name);
66  }
67 
68  void dropAll() { LogRegistry::instance().dropAll(); }
69 
70  void flush() { LogRegistry::instance().flush(); }
71 #else
72  /*
73  * This implementation avoids using a singleton. The downside is that
74  * each call to make_logger() will generate a new logger instead of
75  * reusing an existing logger of the same name (and loggers do not have
76  * custom dual sinks, etc.)
77  *
78  * It is recommended that you store the LoggerPtr locally to avoid the
79  * performance penalty if you must compile without the singleton.
80  */
81  LoggerPtr make_logger(const std::string &logger_name) {
84  auto sink = std::make_shared<stdout_sink_mt>();
85  auto spd_logger =
86  std::make_shared< ::spdlog::logger>(logger_name, sink);
87  spd_logger->set_pattern("%b %d %T.%e %l %n: %v");
88  return Logger::makeFromExistingImplementation(logger_name,
89  spd_logger);
90  }
91 
92  void drop(const std::string &logger_name) {
93  // no-op in the absence of a logger registry.
94  }
95 
96  void dropAll() {
97  // no-op in the absence of a logger registry.
98  }
99 
100  void flush() {
101  // no-op in the absence of a logger registry.
102  }
103 
104  bool tryInitializingLoggingWithBaseName(std::string const &) {
105  // no singleton, no file sink.
106  return false;
107  }
108 #endif
109 
110  std::string getLoggingDirectory(bool make_dir) {
111  namespace fs = boost::filesystem;
113  fs::path log_dir;
114 
115 #if defined(OSVR_LINUX)
116  // There's currently no great location for storing log files in the
117  // XDG system. (See the STATE proposal by Debian
118  // <https://wiki.debian.org/XDGBaseDirectorySpecification#Proposal:_STATE_directory>.)
119  // So for now, we'll store our log files in the $XDG_CACHE_HOME
120  // directory.
121  //
122  // $XDG_CACHE_HOME defines the base directory relative to which user
123  // specific non-essential data files should be stored. If
124  // $XDG_CACHE_HOME is either not set or empty, a default equal to
125  // $HOME/.cache should be used.
126  auto xdg_cache_dir = getEnvironmentVariable("XDG_CACHE_HOME");
127  if (xdg_cache_dir) {
128  log_dir = *xdg_cache_dir;
129  } else {
130  auto home_dir = getEnvironmentVariable("HOME");
131  log_dir = fs::path(*home_dir) / ".cache";
132  }
133  log_dir /= fs::path("osvr") / "logs";
134 #elif defined(OSVR_MACOSX)
135  auto home_dir = getEnvironmentVariable("HOME");
136  if (home_dir) {
137  log_dir = *home_dir;
138  }
139  log_dir /= "Library" / fs::path("Logs") / "OSVR";
140 #elif defined(OSVR_WINDOWS)
141  auto local_app_dir = getEnvironmentVariable("LocalAppData");
144  if (local_app_dir) {
145  log_dir = *local_app_dir;
146  } else {
147  log_dir = "c:/";
148  }
149  log_dir /= fs::path("OSVR") / "Logs";
150 #endif
151 
152  if (fs::is_directory(log_dir))
153  return log_dir.string();
154 
155  if (make_dir) {
156  auto success = fs::create_directories(log_dir);
157  if (!success) {
158  log_dir.clear();
159  }
160  }
161 
162  return log_dir.string();
163  }
164 
165  } // end namespace log
166 } // end namespace util
167 } // end namespace osvr
static LoggerPtr makeFromExistingImplementation(std::string const &name, std::shared_ptr< spdlog::logger > logger)
Definition: Logger.cpp:89
Compile-time logging configuration.
Header for basic internal log reference. To actually log to the produced loggers, include
Header.
Auto-configured header.
Regstry to maintain instantiated loggers and global settings.
boost::optional< std::string > getEnvironmentVariable(std::string const &var)
Gets an environment variable's value. On systems that don't distinguish between having a variable def...
Header to include for OSVR-internal usage of the logging mechanism: provides the needed definition of...
Header.