1 /****************************************************************************** 2 * Copyright (c) 2011, Howard Butler, hobu.inc@gmail.com 3 * 4 * All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following 8 * conditions are met: 9 * 10 * * Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * * Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in 14 * the documentation and/or other materials provided 15 * with the distribution. 16 * * Neither the name of Hobu, Inc. or Flaxen Geo Consulting nor the 17 * names of its contributors may be used to endorse or promote 18 * products derived from this software without specific prior 19 * written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 22 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 23 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 24 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 25 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 26 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 27 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS 28 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 29 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 30 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 31 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY 32 * OF SUCH DAMAGE. 33 ****************************************************************************/ 34 35 #pragma once 36 37 #include <cassert> 38 #include <memory> // shared_ptr 39 #include <stack> 40 #include <chrono> 41 42 #include <pdal/pdal_internal.hpp> 43 #include <pdal/util/NullOStream.hpp> 44 45 // Adapted from http://drdobbs.com/cpp/201804215 46 47 namespace pdal 48 { 49 class Log; 50 51 typedef std::shared_ptr<Log> LogPtr; 52 53 /// pdal::Log is a logging object that is provided by pdal::Stage to 54 /// facilitate logging operations. 55 class PDAL_DLL Log 56 { 57 private: 58 /// Constructs a pdal::Log instance. 59 /// @param leaderString A string to presage all log entries with 60 /// @param outputName A filename or one of 'stdout', 'stdlog', or 'stderr' 61 /// to use for outputting log information. 62 /// @param timing Set to true to get timing output with log messages. 63 Log(std::string const& leaderString, std::string const& outputName, 64 bool timing = false); 65 66 /// Constructs a pdal::Log instance. 67 /// @param leaderString A string to presage all log entries with 68 /// @param v An existing std::ostream to use for logging (instead of the 69 /// the instance creating its own) 70 /// @param timing Set to true to get timing output with log messages. 71 Log(std::string const& leaderString, std::ostream* v, bool timing = false); 72 73 public: 74 static LogPtr makeLog(std::string const& leaderString, 75 std::string const& outputName, bool timing = false); 76 77 static LogPtr makeLog(std::string const& leaderString, 78 std::ostream* v, bool timing = false); 79 80 /** @name Destructor 81 */ 82 /// The destructor will clean up its own internal log stream, but it will 83 /// not touch one that is given via the constructor 84 ~Log(); 85 86 /** @name Logging level 87 */ 88 /// @return the logging level of the pdal::Log instance getLevel()89 LogLevel getLevel() 90 { 91 return m_level; 92 } 93 94 /// Sets the logging level of the pdal::Log instance 95 /// @param v logging level to use for get() comparison operations setLevel(LogLevel v)96 void setLevel(LogLevel v) 97 { 98 assert(v != LogLevel::None); 99 m_level = v; 100 } 101 102 /// Set the leader string (deprecated). 103 /// \param[in] leader Leader string. setLeader(const std::string & leader)104 void setLeader(const std::string& leader) 105 { pushLeader(leader); } 106 107 /// Push the leader string onto the stack. 108 /// \param leader Leader string pushLeader(const std::string & leader)109 void pushLeader(const std::string& leader) 110 { m_leaders.push(leader); } 111 112 /// Get the leader string. 113 /// \return The current leader string. leader() const114 std::string leader() const 115 { return m_leaders.empty() ? std::string() : m_leaders.top(); } 116 117 /// Pop the current leader string. popLeader()118 void popLeader() 119 { 120 if (!m_leaders.empty()) 121 m_leaders.pop(); 122 } 123 124 /// @return A string representing the LogLevel 125 std::string getLevelString(LogLevel v) const; 126 127 /** @name Log stream operations 128 */ 129 /// @return the stream object that is currently being used to for log 130 /// operations regardless of logging level of the instance. getLogStream()131 std::ostream* getLogStream() 132 { 133 return m_log; 134 } 135 136 /// Returns the log stream given the logging level. 137 /// @param level logging level to request 138 /// If the logging level asked for with 139 /// pdal::Log::get is less than the logging level of the pdal::Log instance 140 std::ostream& get(LogLevel level = LogLevel::Info); 141 142 /// Sets the floating point precision 143 void floatPrecision(int level); 144 145 /// Clears the floating point precision settings of the streams 146 void clearFloat(); 147 148 protected: 149 std::ostream *m_log; 150 151 private: 152 Log(const Log&) = delete; 153 Log& operator =(const Log&) = delete; 154 std::string now() const; 155 156 LogLevel m_level; 157 bool m_deleteStreamOnCleanup; 158 std::stack<std::string> m_leaders; 159 NullOStream m_nullStream; 160 bool m_timing; 161 std::chrono::steady_clock m_clock; 162 std::chrono::steady_clock::time_point m_start; 163 }; 164 165 } // namespace pdal 166 167