SQLiteLogDb.cpp
Go to the documentation of this file.
1 // this is for emacs file handling -*- mode: c++; indent-tabs-mode: nil -*-
2 
3 // -- BEGIN LICENSE BLOCK ----------------------------------------------
4 // This file is part of FZIs ic_workspace.
5 //
6 // This program is free software licensed under the LGPL
7 // (GNU LESSER GENERAL PUBLIC LICENSE Version 3).
8 // You can find a copy of this license in LICENSE folder in the top
9 // directory of the source code.
10 //
11 // © Copyright 2016 FZI Forschungszentrum Informatik, Karlsruhe, Germany
12 //
13 // -- END LICENSE BLOCK ------------------------------------------------
14 
15 //----------------------------------------------------------------------
22 //----------------------------------------------------------------------
23 #include "SQLiteLogDb.h"
24 
25 #include <iostream>
26 
27 namespace icl_core {
28 namespace logging {
29 
31  "CREATE TABLE log_entries (seq INTEGER PRIMARY KEY, app_id TEXT, "
32  "timestamp TIMESTAMP, log_stream TEXT, log_level TEXT, filename TEXT, "
33  "line INTEGER, class_name TEXT, object_name TEXT, function_name TEXT, message TEXT)";
35  "INSERT INTO log_entries (app_id, timestamp, log_stream, log_level, "
36  "filename, line, class_name, object_name, function_name, message) "
37  "VALUES (:app_id, :timestamp, :log_stream, :log_level, :filename, "
38  ":line, :class_name, :object_name, :function_name, :message)";
39 
40 SQLiteLogDb::SQLiteLogDb(const icl_core::String& db_filename, bool rotate)
41  : m_db_filename(db_filename),
42  m_db(NULL),
43  m_insert_stmt(NULL),
44  m_rotate(rotate),
45  m_last_rotation(icl_core::TimeStamp::now().days())
46 {
47 }
48 
50 {
51  closeDatabase();
52 }
53 
55 {
56  char *error = NULL;
57 
58  if (m_db_filename != "")
59  {
60  int res = SQLITE_OK;
61  sqlite3_stmt *query_sql = NULL;
62 
63  // Try to open the database.
64  res = sqlite3_open(m_db_filename.c_str(), &m_db);
65  if (res != SQLITE_OK)
66  {
67  std::cerr << "SQLite log output: Could not open SQLite database "
68  << m_db_filename << ": " << sqlite3_errmsg(m_db) << std::endl;
69  goto fail_return;
70  }
71 
72  res = sqlite3_prepare_v2(m_db,
73  "SELECT sql FROM sqlite_master WHERE type='table' AND name='log_entries'",
74  -1, &query_sql, NULL);
75  if (res != SQLITE_OK)
76  {
77  std::cerr << "SQLite log output: Could not check if the log table exists in "
78  << m_db_filename << ": " << sqlite3_errmsg(m_db) << std::endl;
79  goto fail_return;
80  }
81 
82  res = sqlite3_step(query_sql);
83  if (res == SQLITE_DONE)
84  {
85  if (sqlite3_exec(m_db, m_create_sql.c_str(), NULL, NULL, &error) != SQLITE_OK)
86  {
87  std::cerr << "SQLite log output: Could not create the log table: " << error << std::endl;
88  sqlite3_free(error);
89  sqlite3_finalize(query_sql);
90  goto fail_return;
91  }
92  }
93 
94  sqlite3_finalize(query_sql);
95 
96  // If we reach this point then the database is ready for action,
97  // so we prepare the insert statement.
98  res = sqlite3_prepare_v2(m_db, m_insert_sql.c_str(), -1, &m_insert_stmt, NULL);
99  if (res != SQLITE_OK)
100  {
101  std::cerr << "SQLite log output: Could not prepare the insert statement: "
102  << sqlite3_errmsg(m_db) << std::endl;
103  goto fail_return;
104  }
105 
106  // Finally, we set some PRAGMAs to speed up operation.
107  error = NULL;
108  res = sqlite3_exec(m_db, "PRAGMA synchronous=OFF", NULL, NULL, &error);
109  if (res != SQLITE_OK)
110  {
111  std::cerr << "SQLite log output: Could not set PRAGMA synchronous=OFF: " << error << std::endl;
112  }
113 
114  error = NULL;
115  res = sqlite3_exec(m_db, "PRAGMA temp_store=MEMORY", NULL, NULL, &error);
116  if (res != SQLITE_OK)
117  {
118  std::cerr << "SQLite log output: Could not set PRAGMA temp_store=MEMORY: " << error << std::endl;
119  }
120  }
121 
122  return;
123 fail_return:
124  closeDatabase();
125 }
126 
128 {
129  if (m_insert_stmt != NULL)
130  {
131  sqlite3_finalize(m_insert_stmt);
132  m_insert_stmt = NULL;
133  }
134 
135  if (m_db != NULL)
136  {
137  sqlite3_close(m_db);
138  m_db = NULL;
139  }
140 }
141 
142 void SQLiteLogDb::writeLogLine(const char *app_id, const char *timestamp, const char *log_stream,
143  const char *log_level, const char *filename,
144  size_t line, const char *class_name, const char *object_name,
145  const char *function_name, const char *message_text)
146 {
147  if (m_rotate)
148  {
149  int64_t current_day = icl_core::TimeStamp::now().days();
150  if (m_last_rotation != current_day)
151  {
152  m_last_rotation = current_day;
153 
154  closeDatabase();
155 
156  char time_str[11];
157  icl_core::TimeStamp::now().strfTime(time_str, 11, "%Y-%m-%d");
158  rename(m_db_filename.c_str(), (m_db_filename + "." + time_str).c_str());
159 
160  openDatabase();
161  }
162  }
163 
164  if (m_db != NULL && m_insert_stmt != NULL)
165  {
166  int res = SQLITE_OK;
167 
168  // Bind the statement parameters.
169  res = sqlite3_bind_text(m_insert_stmt, 1, app_id, -1, SQLITE_TRANSIENT);
170  if (res != SQLITE_OK)
171  {
172  std::cerr << "SQLite log output: Could not bind column 'app_id': "
173  << sqlite3_errmsg(m_db) << std::endl;
174  }
175  res = sqlite3_bind_text(m_insert_stmt, 2, timestamp, -1, SQLITE_TRANSIENT);
176  if (res != SQLITE_OK)
177  {
178  std::cerr << "SQLite log output: Could not bind column 'timestamp': "
179  << sqlite3_errmsg(m_db) << std::endl;
180  }
181  res = sqlite3_bind_text(m_insert_stmt, 3, log_stream, -1, SQLITE_TRANSIENT);
182  if (res != SQLITE_OK)
183  {
184  std::cerr << "SQLite log output: Could not bind column 'log_stream': "
185  << sqlite3_errmsg(m_db) << std::endl;
186  }
187  res = sqlite3_bind_text(m_insert_stmt, 4, log_level, -1, SQLITE_TRANSIENT);
188  if (res != SQLITE_OK)
189  {
190  std::cerr << "SQLite log output: Could not bind column 'log_level': "
191  << sqlite3_errmsg(m_db) << std::endl;
192  }
193  res = sqlite3_bind_text(m_insert_stmt, 5, filename, -1, SQLITE_TRANSIENT);
194  if (res != SQLITE_OK)
195  {
196  std::cerr << "SQLite log output: Could not bind column 'filename': "
197  << sqlite3_errmsg(m_db) << std::endl;
198  }
199  res = sqlite3_bind_int(m_insert_stmt, 6, line);
200  if (res != SQLITE_OK)
201  {
202  std::cerr << "SQLite log output: Could not bind column 'lin': "
203  << sqlite3_errmsg(m_db) << std::endl;
204  }
205  res = sqlite3_bind_text(m_insert_stmt, 7, class_name, -1, SQLITE_TRANSIENT);
206  if (res != SQLITE_OK)
207  {
208  std::cerr << "SQLite log output: Could not bind column 'class_name': "
209  << sqlite3_errmsg(m_db) << std::endl;
210  }
211  res = sqlite3_bind_text(m_insert_stmt, 8, object_name, -1, SQLITE_TRANSIENT);
212  if (res != SQLITE_OK)
213  {
214  std::cerr << "SQLite log output: Could not bind column 'object_name': "
215  << sqlite3_errmsg(m_db) << std::endl;
216  }
217  res = sqlite3_bind_text(m_insert_stmt, 9, function_name, -1, SQLITE_TRANSIENT);
218  if (res != SQLITE_OK)
219  {
220  std::cerr << "SQLite log output: Could not bind column 'function_name': "
221  << sqlite3_errmsg(m_db) << std::endl;
222  }
223  res = sqlite3_bind_text(m_insert_stmt, 10, message_text, -1, SQLITE_TRANSIENT);
224  if (res != SQLITE_OK)
225  {
226  std::cerr << "SQLite log output: Could not bind column 'message': "
227  << sqlite3_errmsg(m_db) << std::endl;
228  }
229 
230  // Execute the statement.
231  res = sqlite3_step(m_insert_stmt);
232  if (res != SQLITE_DONE)
233  {
234  std::cerr << "SQLite log output: Could not insert log line: "
235  << sqlite3_errmsg(m_db) << std::endl;
236  }
237 
238  // Reset the prepared statement.
239  sqlite3_reset(m_insert_stmt);
240  }
241 }
242 
243 }
244 }
static icl_core::String m_create_sql
Definition: SQLiteLogDb.h:58
Represents absolute times.
Definition: TimeStamp.h:61
static TimeStamp now()
Definition: TimeStamp.cpp:111
int64_t days() const
Use this function if you want to express the time in days.
Definition: TimeBase.h:107
static icl_core::String m_insert_sql
Definition: SQLiteLogDb.h:59
signed __int64 int64_t
Definition: msvc_stdint.h:102
icl_core::String m_db_filename
Definition: SQLiteLogDb.h:51
SQLiteLogDb(const icl_core::String &db_filename, bool rotate)
Definition: SQLiteLogDb.cpp:40
void writeLogLine(const char *app_id, const char *timestamp, const char *log_stream, const char *log_level, const char *filename, size_t line, const char *class_name, const char *object_name, const char *function_name, const char *message_text)
ThreadStream & endl(ThreadStream &stream)
Definition: ThreadStream.h:249
int rename(const char *old_filename, const char *new_filename)
Definition: os_fs.h:47
void strfTime(char *dest, size_t max_len, const char *format) const
Definition: TimeStamp.cpp:203
std::string String
Definition: BaseTypes.h:43
Contains icl_logging::SQLiteLogDb.


fzi_icl_core
Author(s):
autogenerated on Mon Jun 10 2019 13:17:58