aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFrancesco Abbate <francesco.bbt@gmail.com>2022-01-23 20:10:46 +0100
committerFrancesco Abbate <francesco.bbt@gmail.com>2022-01-23 20:10:46 +0100
commit13c94464d5a5efd19fef4d27cb685dd2a1199495 (patch)
tree80266a89c749a6187a97ab394401d25a5cc57f71
parent68ba21ae9e5711fddfda1ae77667b49e61b350cf (diff)
downloadlite-xl-zlog-dmon-logging.tar.gz
lite-xl-zlog-dmon-logging.zip
Import zlog into the projectzlog-dmon-logging
-rw-r--r--lib/zlog/meson.build4
-rw-r--r--lib/zlog/zlog-config.h18
-rw-r--r--lib/zlog/zlog.c289
-rw-r--r--lib/zlog/zlog.h60
-rw-r--r--meson.build5
-rw-r--r--src/meson.build2
-rw-r--r--subprojects/zlog.wrap4
7 files changed, 374 insertions, 8 deletions
diff --git a/lib/zlog/meson.build b/lib/zlog/meson.build
new file mode 100644
index 00000000..e64f20eb
--- /dev/null
+++ b/lib/zlog/meson.build
@@ -0,0 +1,4 @@
+libzlog = static_library('zlog', 'zlog.c', dependencies: threads_dep)
+
+lite_includes += include_directories('.')
+
diff --git a/lib/zlog/zlog-config.h b/lib/zlog/zlog-config.h
new file mode 100644
index 00000000..d77bc6b1
--- /dev/null
+++ b/lib/zlog/zlog-config.h
@@ -0,0 +1,18 @@
+#ifndef ZLOG_CONFIG_H_
+# define ZLOG_CONFIG_H_
+
+// #define ZLOG_DISABLE_LOG 1
+#define ZLOG_BUFFER_STR_MAX_LEN 512
+#define ZLOG_BUFFER_SIZE (0x1 << 20)
+// ZLOG_BUFFER_TIME_STR_MAX_LEN must < ZLOG_BUFFER_STR_MAX_LEN
+#define ZLOG_BUFFER_TIME_STR_MAX_LEN 64
+
+// only for debug, enabling this will slow down the log
+// #define ZLOG_FORCE_FLUSH_BUFFER
+
+#define ZLOG_FLUSH_INTERVAL_SEC 180
+#define ZLOG_SLEEP_TIME_SEC 10
+// In practice: flush size < .8 * BUFFER_SIZE
+#define ZLOG_BUFFER_FLUSH_SIZE (0.8 * ZLOG_BUFFER_SIZE)
+
+#endif
diff --git a/lib/zlog/zlog.c b/lib/zlog/zlog.c
new file mode 100644
index 00000000..96a5d1d4
--- /dev/null
+++ b/lib/zlog/zlog.c
@@ -0,0 +1,289 @@
+/*
+ * Zlog utility
+ * By: Eric Ma https://www.ericzma.com
+ * Released under Unlicense
+ */
+
+#include <stdio.h>
+#include <stdarg.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include <sys/time.h>
+#include <string.h>
+#include <time.h>
+#include <pthread.h>
+#include <errno.h>
+
+#ifdef _WIN32
+#include <windows.h>
+#endif
+
+#include "zlog-config.h"
+#include "zlog.h"
+
+#ifdef _WIN32
+
+// Adapted from: https://stackoverflow.com/questions/10905892/equivalent-of-gettimeday-for-windows
+static int zlog_write_timestamp(char *buffer, char *buffer_end) {
+ const size_t size = buffer_end - buffer;
+ char timebuf[ZLOG_BUFFER_TIME_STR_MAX_LEN];
+ SYSTEMTIME system_time;
+
+ GetLocalTime(&system_time);
+
+ snprintf(timebuf, ZLOG_BUFFER_TIME_STR_MAX_LEN, "%d:%02d:%d", system_time.wHour, system_time.wMinute, system_time.wSecond);
+ snprintf(buffer, size, "[%s.%06lds] ", timebuf, (long) system_time.wMilliseconds * 1000);
+ return strlen(timebuf) + 11; // space for time
+}
+#else
+static int zlog_write_timestamp(char *buffer, char *buffer_end) {
+ const size_t size = buffer_end - buffer;
+ char timebuf[ZLOG_BUFFER_TIME_STR_MAX_LEN];
+ struct timeval tv;
+ struct tm *tm;
+
+ gettimeofday(&tv, NULL);
+ tm = localtime(&tv.tv_sec);
+ snprintf(timebuf, ZLOG_BUFFER_TIME_STR_MAX_LEN, "%d:%02d:%d", tm->tm_hour, tm->tm_min, tm->tm_sec);
+ snprintf(buffer, size, "[%s.%06lds] ", timebuf, tv.tv_usec);
+ return strlen(timebuf) + 11; // space for time
+}
+#endif
+
+// --------------------------------------------------------------
+// zlog utilities
+FILE* zlog_fout = NULL;
+const char* zlog_file_log_name = NULL;
+
+char _zlog_buffer[ZLOG_BUFFER_SIZE][ZLOG_BUFFER_STR_MAX_LEN];
+int _zlog_buffer_size = 0;
+
+pthread_mutex_t _zlog_buffer_mutex = PTHREAD_MUTEX_INITIALIZER;
+// --------------------------------------------------------------
+
+static inline void _zlog_buffer_lock(void)
+{
+ pthread_mutex_lock(&_zlog_buffer_mutex);
+}
+
+static inline void _zlog_buffer_unlock(void)
+{
+ pthread_mutex_unlock(&_zlog_buffer_mutex);
+}
+
+static void _zlog_flush_buffer(void)
+{
+ int i = 0;
+ for (i = 0; i < _zlog_buffer_size; i++) {
+ fprintf(zlog_fout, "%s", _zlog_buffer[i]);
+ }
+ fflush(zlog_fout);
+ _zlog_buffer_size = 0;
+}
+
+// first zlog_get_buffer, write to @return
+// then zlog_finish_buffer
+//
+// zlog_get_buffer may flush the buffer, which require I/O ops
+static inline char* zlog_get_buffer(void)
+{
+ _zlog_buffer_lock();
+ if (_zlog_buffer_size == ZLOG_BUFFER_SIZE) {
+ _zlog_flush_buffer();
+ }
+
+ // allocate buffer
+ _zlog_buffer_size++;
+ return _zlog_buffer[_zlog_buffer_size-1];
+}
+
+static inline void zlog_finish_buffer(void)
+{
+#ifdef ZLOG_FORCE_FLUSH_BUFFER
+ _zlog_flush_buffer();
+#endif
+ _zlog_buffer_unlock();
+}
+
+// Error reporting
+static inline void print_error(const char *function_name, char *error_msg){
+ fprintf(stderr, "Error in function %s: %s\n", function_name, error_msg);
+}
+
+// --------------------------------------------------------------
+
+void zlog_init(char const* log_file)
+{
+ zlog_file_log_name = strdup(log_file);
+
+ zlog_fout = fopen(log_file, "a+");
+
+ if(!zlog_fout){
+ print_error(__func__, strerror(errno));
+ }
+}
+
+void zlog_init_stdout(void)
+{
+ zlog_fout = stdout;
+}
+
+void zlog_init_stderr(void)
+{
+ zlog_fout = stderr;
+}
+
+static void* zlog_buffer_flush_thread(void *_unused)
+{
+ struct timeval tv;
+ time_t lasttime;
+ time_t curtime;
+
+ gettimeofday(&tv, NULL);
+
+ lasttime = tv.tv_sec;
+
+ do {
+ sleep(ZLOG_SLEEP_TIME_SEC);
+ gettimeofday(&tv, NULL);
+ curtime = tv.tv_sec;
+ if ( (curtime - lasttime) >= ZLOG_FLUSH_INTERVAL_SEC ) {
+ // ZLOG_LOG_LEVEL is used to make the buffer flushing
+ // seamlessly for the users. It does not matter what level
+ // the messages are at this point because, if they do
+ // not meet message level requirement, that wouldn't
+ // have been buffered in the first place.
+ zlogf_time(ZLOG_LOG_LEVEL, "Flush buffer.\n");
+ zlog_flush_buffer();
+ lasttime = curtime;
+ } else {
+ _zlog_buffer_lock();
+ if (_zlog_buffer_size >= ZLOG_BUFFER_FLUSH_SIZE ) {
+ _zlog_flush_buffer();
+ }
+ _zlog_buffer_unlock();
+ }
+ } while (1);
+ return NULL;
+}
+
+void zlog_init_flush_thread(void)
+{
+ pthread_t thr;
+ pthread_create(&thr, NULL, zlog_buffer_flush_thread, NULL);
+ zlogf_time(ZLOG_LOG_LEVEL, "Flush thread is created.\n");
+}
+
+void zlog_flush_buffer(void)
+{
+ _zlog_buffer_lock();
+ _zlog_flush_buffer();
+ _zlog_buffer_unlock();
+}
+
+void zlog_finish(void)
+{
+ zlog_flush_buffer();
+ if (zlog_fout != stdout || zlog_fout != stderr) {
+ fclose(zlog_fout);
+ zlog_fout = stdout;
+ }
+
+}
+
+inline void zlogf(int msg_level, char const * fmt, ...)
+{
+#ifdef ZLOG_DISABLE_LOG
+ return ;
+#endif
+ if(msg_level <= ZLOG_LOG_LEVEL){
+ va_list va;
+ char* buffer = NULL;
+
+ buffer = zlog_get_buffer();
+
+ va_start(va, fmt);
+ vsnprintf(buffer, ZLOG_BUFFER_STR_MAX_LEN, fmt, va);
+ zlog_finish_buffer();
+ va_end(va);
+ }
+}
+
+void zlogf_time(int msg_level, char const * fmt, ...)
+{
+#ifdef ZLOG_DISABLE_LOG
+ return ;
+#endif
+
+ if(msg_level <= ZLOG_LOG_LEVEL){
+ va_list va;
+ char *buffer = zlog_get_buffer();
+ char * const buffer_end = buffer + ZLOG_BUFFER_STR_MAX_LEN;
+
+ buffer += zlog_write_timestamp(buffer, buffer_end);
+
+ va_start(va, fmt);
+ vsnprintf(buffer, buffer_end - buffer, fmt, va);
+ zlog_finish_buffer();
+ va_end(va);
+ }
+}
+
+static int zlog_write_location(char *buffer, char *buffer_end, char *filename, int line) {
+ const size_t size = buffer_end - buffer;
+ int write_size = snprintf(buffer, size, "[@%s:%d] ", filename, line);
+ if (write_size >= 0 && (size_t) write_size >= size) {
+ write_size = size - 1;
+ buffer[write_size] = 0;
+ }
+ return write_size;
+}
+
+void zlog_time(int msg_level, char* filename, int line, char const * fmt, ...)
+{
+#ifdef ZLOG_DISABLE_LOG
+ return ;
+#endif
+ if(msg_level <= ZLOG_LOG_LEVEL){
+ va_list va;
+ char *buffer = zlog_get_buffer();
+ char * const buffer_end = buffer + ZLOG_BUFFER_STR_MAX_LEN;
+
+ buffer += zlog_write_timestamp(buffer, buffer_end);
+ buffer += zlog_write_location(buffer, buffer_end, filename, line);
+
+ va_start(va, fmt);
+ vsnprintf(buffer, buffer_end - buffer, fmt, va);
+ zlog_finish_buffer();
+ va_end(va);
+ }
+}
+
+void zlog(int msg_level, char* filename, int line, char const * fmt, ...)
+{
+#ifdef ZLOG_DISABLE_LOG
+ return ;
+#endif
+ if(msg_level <= ZLOG_LOG_LEVEL){
+ va_list va;
+ char *buffer = zlog_get_buffer();
+ char *const buffer_end = buffer + ZLOG_BUFFER_STR_MAX_LEN;
+
+ buffer += zlog_write_location(buffer, buffer_end, filename, line);
+
+ va_start(va, fmt);
+ vsnprintf(buffer, buffer_end - buffer, fmt, va);
+ zlog_finish_buffer();
+ va_end(va);
+ }
+}
+
+const char* zlog_get_log_file_name(void){
+#ifdef ZLOG_DISABLE_LOG
+ return ;
+#endif
+ return zlog_file_log_name;
+}
+
+// End zlog utilities
+
diff --git a/lib/zlog/zlog.h b/lib/zlog/zlog.h
new file mode 100644
index 00000000..fc85f440
--- /dev/null
+++ b/lib/zlog/zlog.h
@@ -0,0 +1,60 @@
+/*
+ * Zlog utility
+ * By: Eric Ma https://www.ericzma.com
+ * Released under Unlicense
+ */
+
+#ifndef ZLOG_H_
+# define ZLOG_H_
+
+#include<stdio.h>
+
+#define ZLOG_LOC __FILE__, __LINE__
+
+#define ZLOG_DEBUG_LOG_MSG 1
+#define ZLOG_INFO_LOG_MSG 0
+
+#ifdef DEBUG
+ #define ZLOG_LOG_LEVEL 1
+#else
+ #define ZLOG_LOG_LEVEL 0
+#endif
+
+extern FILE* zlog_fout;
+extern const char* zlog_file_log_name;
+
+// Start API
+
+// initialize zlog: flush to a log file
+void zlog_init(char const* log_file);
+// initialize zlog: flush to a STDOUT
+void zlog_init_stdout(void);
+// initialize zlog: flush to a STDERR
+void zlog_init_stderr(void);
+// creating a flushing thread
+void zlog_init_flush_thread(void);
+// finish using the zlog; clean up
+void zlog_finish(void);
+// Explicitly flush the buffer in memory
+void zlog_flush_buffer(void);
+
+// log an entry; using the printf format
+void zlogf(int msg_level, char const * fmt, ...);
+
+// log an entry with a timestamp
+void zlogf_time(int msg_level, char const * fmt, ...);
+
+// log an entry with the filename and location;
+// the first 2 arguments can be replaced by ZLOG_LOC which
+// will be filled by the compiler
+void zlog(int msg_level, char* filename, int line, char const * fmt, ...);
+
+// log an entry with the filename and location with a timestamp
+void zlog_time(int msg_level, char* filename, int line, char const * fmt, ...);
+
+// return where logs are being written (file absolute path)
+const char* zlog_get_log_file_name(void);
+
+// End API
+
+#endif
diff --git a/meson.build b/meson.build
index 1f101fc6..1ffb9a64 100644
--- a/meson.build
+++ b/meson.build
@@ -47,8 +47,6 @@ if not get_option('source-only')
libm = cc.find_library('m', required : false)
libdl = cc.find_library('dl', required : false)
threads_dep = dependency('threads')
- zlog_proj = subproject('zlog')
- zlog_dep = zlog_proj.get_variable('zlog_dep')
lua_dep = dependency('lua5.2', fallback: ['lua', 'lua_dep'],
default_options: ['shared=false', 'use_readline=false', 'app=false']
)
@@ -61,7 +59,7 @@ if not get_option('source-only')
]
)
- lite_deps = [zlog_dep, lua_dep, sdl_dep, reproc_dep, pcre2_dep, libm, libdl, threads_dep]
+ lite_deps = [lua_dep, sdl_dep, reproc_dep, pcre2_dep, libm, libdl, threads_dep]
if host_machine.system() == 'windows'
# Note that we need to explicitly add the windows socket DLL because
@@ -124,6 +122,7 @@ configure_file(
if not get_option('source-only')
subdir('lib/font_renderer')
subdir('lib/dmon')
+ subdir('lib/zlog')
subdir('src')
subdir('scripts')
endif
diff --git a/src/meson.build b/src/meson.build
index 503fdc48..3f13cfdc 100644
--- a/src/meson.build
+++ b/src/meson.build
@@ -30,7 +30,7 @@ executable('lite-xl',
dependencies: lite_deps,
c_args: lite_cargs,
objc_args: lite_cargs,
- link_with: libfontrenderer,
+ link_with: [libfontrenderer, libzlog],
link_args: lite_link_args,
install_dir: lite_bindir,
install: true,
diff --git a/subprojects/zlog.wrap b/subprojects/zlog.wrap
deleted file mode 100644
index da0ee8c7..00000000
--- a/subprojects/zlog.wrap
+++ /dev/null
@@ -1,4 +0,0 @@
-[wrap-git]
-directory = zlog
-url = https://github.com/zma/zlog.git
-revision = fbe36fb7cd46fc4edd6b9c616c6bcbab46da2ac8