├── Makefile
├── SECURITY.md
├── zlog-config.h
├── LICENSE
├── README.md
├── zlog.h
├── example.c
├── .github
└── workflows
│ ├── codacy.yml
│ ├── codeql.yml
│ └── codeql-analysis.yml
├── meson.build
└── zlog.c
/Makefile:
--------------------------------------------------------------------------------
1 | # In order to compile in DEBUG mode, simply add -D DEBUG flag to gcc.
2 | # If you dont want debug mode, simply delete it.
3 |
4 | default: info
5 |
6 | info:
7 | gcc -Wall -Wextra example.c zlog.c -o example -lpthread
8 | ./example
9 |
10 | debug:
11 | gcc -Wall -Wextra example.c zlog.c -o example -lpthread -D DEBUG
12 | ./example
--------------------------------------------------------------------------------
/SECURITY.md:
--------------------------------------------------------------------------------
1 | # Security Policy
2 |
3 | ## Supported Versions
4 |
5 | Which versions of your project are
6 | currently being supported with security updates.
7 |
8 | | Version | Supported |
9 | | ------- | ------------------ |
10 | | main | :white_check_mark: |
11 |
12 | ## Reporting a Vulnerability
13 |
14 | Please email/message https://github.com/zma .
15 |
--------------------------------------------------------------------------------
/zlog-config.h:
--------------------------------------------------------------------------------
1 | #ifndef ZLOG_CONFIG_H_
2 | # define ZLOG_CONFIG_H_
3 |
4 | // #define ZLOG_DISABLE_LOG 1
5 | #define ZLOG_BUFFER_STR_MAX_LEN 512
6 | #define ZLOG_BUFFER_SIZE (0x1 << 22)
7 | // ZLOG_BUFFER_TIME_STR_MAX_LEN must < ZLOG_BUFFER_STR_MAX_LEN
8 | #define ZLOG_BUFFER_TIME_STR_MAX_LEN 64
9 |
10 | // only for debug, enabling this will slow down the log
11 | // #define ZLOG_FORCE_FLUSH_BUFFER
12 |
13 | #define ZLOG_FLUSH_INTERVAL_SEC 180
14 | #define ZLOG_SLEEP_TIME_SEC 10
15 | // In practice: flush size < .8 * BUFFER_SIZE
16 | #define ZLOG_BUFFER_FLUSH_SIZE (0.8 * ZLOG_BUFFER_SIZE)
17 |
18 | #endif
19 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | This is free and unencumbered software released into the public domain.
2 |
3 | Anyone is free to copy, modify, publish, use, compile, sell, or
4 | distribute this software, either in source code form or as a compiled
5 | binary, for any purpose, commercial or non-commercial, and by any
6 | means.
7 |
8 | In jurisdictions that recognize copyright laws, the author or authors
9 | of this software dedicate any and all copyright interest in the
10 | software to the public domain. We make this dedication for the benefit
11 | of the public at large and to the detriment of our heirs and
12 | successors. We intend this dedication to be an overt act of
13 | relinquishment in perpetuity of all present and future rights to this
14 | software under copyright law.
15 |
16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
19 | IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
20 | OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
21 | ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22 | OTHER DEALINGS IN THE SOFTWARE.
23 |
24 | For more information, please refer to
25 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # zlog - a C In-memory Logging Library
2 |
3 | Hompage: https://www.ericzma.com/projects/zlog/
4 |
5 | ## Introduction ##
6 |
7 | zlog is a C in-memory logging library. It allocates a buffer in memory for logging, and flush the buffer to the log file (or stdout) when the buffer is full, or it is instructed explicitly by the program or flushing thread.
8 |
9 | ### Usage example ###
10 |
11 | Example.c represents an use example of zlog library containing both INFO
12 | and DEBUG messages. If you want to include DEBUG messages you must compile
13 | with *-D DEBUG* flag.
14 |
15 | Makefile contains the corresponding gcc compilation commands to both INFO
16 | and DEBUG mode. Please keep in mind that DEBUG mode will log INFO and
17 | DEBUG messages whilst INFO mode will discard all DEBUG messages. The
18 | following Make commands can be used to compile either in DEBUG or INFO modes:
19 |
20 | * ``make`` or ``make info`` for **INFO** mode compilation.
21 | * ``make debug`` for **DEBUG** mode compilation.
22 |
23 | ## Source code ##
24 |
25 | Source code of zlog can be downloaded from http://github.com/zma/zlog/ . The source code is released into the public domain.
26 |
27 | ## Authors and contributors ##
28 |
29 | - Eric Ma (https://www.ericzma.com).
30 | - RazviOverflow (https://github.com/RazviOverflow)
31 |
32 |
--------------------------------------------------------------------------------
/zlog.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Zlog utility
3 | * By: Eric Ma https://www.ericzma.com
4 | * Released under Unlicense
5 | */
6 |
7 | #ifndef ZLOG_H_
8 | # define ZLOG_H_
9 |
10 | #include
11 |
12 | #define ZLOG_LOC __FILE__, __LINE__
13 |
14 | #define ZLOG_DEBUG_LOG_MSG 1
15 | #define ZLOG_INFO_LOG_MSG 0
16 |
17 | #ifdef DEBUG
18 | #define ZLOG_LOG_LEVEL 1
19 | #else
20 | #define ZLOG_LOG_LEVEL 0
21 | #endif
22 |
23 | extern FILE* zlog_fout;
24 | extern const char* zlog_file_log_name;
25 |
26 | // Start API
27 |
28 | // initialize zlog: flush to a log file
29 | void zlog_init(char const* log_file);
30 | // initialize zlog: flush to a STDOUT
31 | void zlog_init_stdout(void);
32 | // initialize zlog: flush to a STDERR
33 | void zlog_init_stderr(void);
34 | // creating a flushing thread
35 | void zlog_init_flush_thread(void);
36 | // create flush thread with flush interval
37 | void zlog_init_flush_thread_with_interval(int interval_sec);
38 | // finish using the zlog; clean up
39 | void zlog_finish(void);
40 | // Explicitly flush the buffer in memory
41 | void zlog_flush_buffer(void);
42 |
43 | // log an entry; using the printf format
44 | void zlogf(int msg_level, char const * fmt, ...);
45 |
46 | // log an entry with a timestamp
47 | void zlogf_time(int msg_level, char const * fmt, ...);
48 |
49 | // log an entry with the filename and location;
50 | // the first 2 arguments can be replaced by ZLOG_LOC which
51 | // will be filled by the compiler
52 | void zlog(int msg_level, char* filename, int line, char const * fmt, ...);
53 |
54 | // log an entry with the filename and location with a timestamp
55 | void zlog_time(int msg_level, char* filename, int line, char const * fmt, ...);
56 |
57 | // return where logs are being written (file absolute path)
58 | const char* zlog_get_log_file_name(void);
59 |
60 | // End API
61 |
62 | #endif
63 |
--------------------------------------------------------------------------------
/example.c:
--------------------------------------------------------------------------------
1 | /*
2 | * Bug reports to: Zhiqiang Ma (http://www.ericzma.com)
3 | * An example of zlog usage
4 | */
5 |
6 | #include
7 | #include
8 | #include
9 | #include
10 |
11 | #include "zlog.h"
12 |
13 | int main(int argc, char* argv[])
14 | {
15 | int i = 0;
16 |
17 | // log to stdout
18 | zlog_init_stdout();
19 |
20 | // or log to file
21 | // zlog_init("/tmp/zlog.log");
22 |
23 | // Optional: create flushing thread that flush the log
24 | // for each period of time
25 | // Otherwise, the in-memory log is flushed when the buffer
26 | // if full
27 | zlog_init_flush_thread();
28 |
29 | // start to use the in-memory log
30 |
31 | // with timestamp
32 | zlogf_time(ZLOG_DEBUG_LOG_MSG, "zlog is initialized (debug)\n");
33 | zlogf_time(ZLOG_INFO_LOG_MSG, "zlog is initialized (info)\n");
34 |
35 | // without timestamp
36 | zlogf(ZLOG_INFO_LOG_MSG, "Command line: \n");
37 | for (i = 0; i < argc; i++) {
38 | // use the directives as the format of printf
39 | zlogf(ZLOG_INFO_LOG_MSG, "argv[%d]: %s \n", i, argv[i]);
40 | zlogf(ZLOG_DEBUG_LOG_MSG, "(DEBUG) argv[%d]: %s \n", i, argv[i]);
41 | }
42 | zlogf(ZLOG_INFO_LOG_MSG, "\n\n");
43 |
44 | zlogf_time(ZLOG_INFO_LOG_MSG, "I flush the buffer explicitly.\n");
45 |
46 | zlogf(ZLOG_INFO_LOG_MSG, "This is just a ## [+] debug message [+] ##\n");
47 | zlog_flush_buffer();
48 |
49 | // with source code file and line info, and timestamp
50 | zlog_time(ZLOG_INFO_LOG_MSG, ZLOG_LOC, "Log with file and line. TIMESTAMPED.\n");
51 | zlog_time(ZLOG_DEBUG_LOG_MSG, ZLOG_LOC, "(DEBUG) Log with file and line. TIMESTAMPED.\n");
52 |
53 | // with source code file and line info, and without timestamp
54 | zlog(ZLOG_INFO_LOG_MSG, ZLOG_LOC, "Log with file and line. NO TIMESTAMP.\n");
55 |
56 | // Example only: let the flushing thread work
57 | printf("FOR TEST: I will sleep for 200 seconds... Please be patient.\n");
58 | sleep(200);
59 |
60 | zlogf_time(ZLOG_INFO_LOG_MSG, "finish using zlog\n");
61 |
62 | // Before quit, finish zlog which will flush all the
63 | // logs in memory
64 | zlog_finish();
65 |
66 | return 0;
67 | }
68 |
69 |
--------------------------------------------------------------------------------
/.github/workflows/codacy.yml:
--------------------------------------------------------------------------------
1 | # This workflow uses actions that are not certified by GitHub.
2 | # They are provided by a third-party and are governed by
3 | # separate terms of service, privacy policy, and support
4 | # documentation.
5 |
6 | # This workflow checks out code, performs a Codacy security scan
7 | # and integrates the results with the
8 | # GitHub Advanced Security code scanning feature. For more information on
9 | # the Codacy security scan action usage and parameters, see
10 | # https://github.com/codacy/codacy-analysis-cli-action.
11 | # For more information on Codacy Analysis CLI in general, see
12 | # https://github.com/codacy/codacy-analysis-cli.
13 |
14 | name: Codacy Security Scan
15 |
16 | on:
17 | push:
18 | branches: [ main ]
19 | pull_request:
20 | # The branches below must be a subset of the branches above
21 | branches: [ main ]
22 | schedule:
23 | - cron: '29 8 * * 2'
24 |
25 | permissions:
26 | contents: read
27 |
28 | jobs:
29 | codacy-security-scan:
30 | permissions:
31 | contents: read # for actions/checkout to fetch code
32 | security-events: write # for github/codeql-action/upload-sarif to upload SARIF results
33 | name: Codacy Security Scan
34 | runs-on: ubuntu-latest
35 | steps:
36 | # Checkout the repository to the GitHub Actions runner
37 | - name: Checkout code
38 | uses: actions/checkout@v3
39 |
40 | # Execute Codacy Analysis CLI and generate a SARIF output with the security issues identified during the analysis
41 | - name: Run Codacy Analysis CLI
42 | uses: codacy/codacy-analysis-cli-action@d840f886c4bd4edc059706d09c6a1586111c540b
43 | with:
44 | # Check https://github.com/codacy/codacy-analysis-cli#project-token to get your project token from your Codacy repository
45 | # You can also omit the token and run the tools that support default configurations
46 | project-token: ${{ secrets.CODACY_PROJECT_TOKEN }}
47 | verbose: true
48 | output: results.sarif
49 | format: sarif
50 | # Adjust severity of non-security issues
51 | gh-code-scanning-compat: true
52 | # Force 0 exit code to allow SARIF file generation
53 | # This will handover control about PR rejection to the GitHub side
54 | max-allowed-issues: 2147483647
55 |
56 | # Upload the SARIF file generated in the previous step
57 | - name: Upload SARIF results file
58 | uses: github/codeql-action/upload-sarif@v2
59 | with:
60 | sarif_file: results.sarif
61 |
--------------------------------------------------------------------------------
/meson.build:
--------------------------------------------------------------------------------
1 | ###################################################################################
2 | # #
3 | # NAME: meson.build #
4 | # #
5 | # AUTHOR: Zhiqiang Ma. #
6 | # WRITTEN BY: Michael Brockus. #
7 | # #
8 | # License: Unlicense #
9 | # #
10 | ###################################################################################
11 |
12 | project('zlog', 'c',
13 | license : 'Unlicense',
14 | meson_version : '>=0.52.0',
15 | default_options :
16 | [
17 | 'werror=true',
18 | 'optimization=3',
19 | 'warning_level=3'
20 | ]
21 | )
22 | lang = 'c'
23 | cc = meson.get_compiler(lang)
24 |
25 |
26 | ##
27 | #
28 | # Meson: Add compiler flags
29 | #
30 | ##
31 | if cc.get_id() == 'clang'
32 | add_project_arguments(cc.get_supported_arguments(
33 | [
34 | '-Wweak-vtables', '-Wexit-time-destructors',
35 | '-Wglobal-constructors', '-Wmissing-noreturn'
36 | ]
37 | ), language: lang)
38 | endif
39 |
40 | if cc.get_argument_syntax() == 'gcc'
41 | add_project_arguments(cc.get_supported_arguments(
42 | [
43 | '-Wformat', '-Waddress', '-Winit-self', '-Wno-multichar',
44 | '-Wpointer-arith' , '-Wwrite-strings' ,
45 | '-Wno-parentheses' , '-Wno-type-limits' ,
46 | '-Wformat-security' , '-Wunreachable-code' ,
47 | '-Waggregate-return' , '-Wformat-nonliteral' ,
48 | '-Wmissing-prototypes' , '-Wold-style-definition' ,
49 | '-Wmissing-declarations', '-Wmissing-include-dirs' ,
50 | '-Wno-unused-parameter' , '-Wdeclaration-after-statement'
51 | ]
52 | ), language: lang)
53 | endif
54 |
55 | if cc.get_id() == 'msvc'
56 | add_project_arguments(cc.get_supported_arguments(
57 | [
58 | '/w44265', '/w44061', '/w44062',
59 | '/wd4018', '/wd4146', '/wd4244',
60 | '/wd4305',
61 | ]
62 | ), language: lang)
63 | endif
64 |
65 |
66 | thread_dep = dependency('threads')
67 |
68 |
69 | zlog_lib = static_library(meson.project_name(),
70 | sources: ['zlog.c'],
71 | dependencies: thread_dep,
72 | include_directories: include_directories('.'))
73 |
74 | zlog_dep = declare_dependency(
75 | link_with: zlog_lib,
76 | include_directories: include_directories('.'))
77 |
--------------------------------------------------------------------------------
/.github/workflows/codeql.yml:
--------------------------------------------------------------------------------
1 | # For most projects, this workflow file will not need changing; you simply need
2 | # to commit it to your repository.
3 | #
4 | # You may wish to alter this file to override the set of languages analyzed,
5 | # or to provide custom queries or build logic.
6 | #
7 | # ******** NOTE ********
8 | # We have attempted to detect the languages in your repository. Please check
9 | # the `language` matrix defined below to confirm you have the correct set of
10 | # supported CodeQL languages.
11 | #
12 | name: "CodeQL"
13 |
14 | on:
15 | push:
16 | branches: [ main ]
17 | pull_request:
18 | # The branches below must be a subset of the branches above
19 | branches: [ main ]
20 | schedule:
21 | - cron: '44 5 * * 2'
22 |
23 | jobs:
24 | analyze:
25 | name: Analyze
26 | runs-on: ubuntu-latest
27 | permissions:
28 | actions: read
29 | contents: read
30 | security-events: write
31 |
32 | strategy:
33 | fail-fast: false
34 | matrix:
35 | language: [ 'cpp' ]
36 | # CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python', 'ruby' ]
37 | # Learn more about CodeQL language support at https://aka.ms/codeql-docs/language-support
38 |
39 | steps:
40 | - name: Checkout repository
41 | uses: actions/checkout@v3
42 |
43 | # Initializes the CodeQL tools for scanning.
44 | - name: Initialize CodeQL
45 | uses: github/codeql-action/init@v2
46 | with:
47 | languages: ${{ matrix.language }}
48 | # If you wish to specify custom queries, you can do so here or in a config file.
49 | # By default, queries listed here will override any specified in a config file.
50 | # Prefix the list here with "+" to use these queries and those in the config file.
51 |
52 | # Details on CodeQL's query packs refer to : https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-code-scanning#using-queries-in-ql-packs
53 | # queries: security-extended,security-and-quality
54 |
55 |
56 | # Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
57 | # If this step fails, then you should remove it and run the build manually (see below)
58 | - name: Autobuild
59 | uses: github/codeql-action/autobuild@v2
60 |
61 | # ℹ️ Command-line programs to run using the OS shell.
62 | # 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun
63 |
64 | # If the Autobuild fails above, remove it and uncomment the following three lines.
65 | # modify them (or add more) to build your code if your project, please refer to the EXAMPLE below for guidance.
66 |
67 | # - run: |
68 | # echo "Run, Build Application using script"
69 | # ./location_of_script_within_repo/buildscript.sh
70 |
71 | - name: Perform CodeQL Analysis
72 | uses: github/codeql-action/analyze@v2
73 |
--------------------------------------------------------------------------------
/.github/workflows/codeql-analysis.yml:
--------------------------------------------------------------------------------
1 | # For most projects, this workflow file will not need changing; you simply need
2 | # to commit it to your repository.
3 | #
4 | # You may wish to alter this file to override the set of languages analyzed,
5 | # or to provide custom queries or build logic.
6 | #
7 | # ******** NOTE ********
8 | # We have attempted to detect the languages in your repository. Please check
9 | # the `language` matrix defined below to confirm you have the correct set of
10 | # supported CodeQL languages.
11 | #
12 | name: "CodeQL"
13 |
14 | on:
15 | push:
16 | branches: [ main ]
17 | pull_request:
18 | # The branches below must be a subset of the branches above
19 | branches: [ main ]
20 | schedule:
21 | - cron: '45 12 * * 6'
22 |
23 | jobs:
24 | analyze:
25 | name: Analyze
26 | runs-on: ubuntu-latest
27 | permissions:
28 | actions: read
29 | contents: read
30 | security-events: write
31 |
32 | strategy:
33 | fail-fast: false
34 | matrix:
35 | language: [ 'cpp' ]
36 | # CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python', 'ruby' ]
37 | # Learn more about CodeQL language support at https://aka.ms/codeql-docs/language-support
38 |
39 | steps:
40 | - name: Checkout repository
41 | uses: actions/checkout@v3
42 |
43 | # Initializes the CodeQL tools for scanning.
44 | - name: Initialize CodeQL
45 | uses: github/codeql-action/init@v2
46 | with:
47 | languages: ${{ matrix.language }}
48 | # If you wish to specify custom queries, you can do so here or in a config file.
49 | # By default, queries listed here will override any specified in a config file.
50 | # Prefix the list here with "+" to use these queries and those in the config file.
51 |
52 | # Details on CodeQL's query packs refer to : https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-code-scanning#using-queries-in-ql-packs
53 | # queries: security-extended,security-and-quality
54 |
55 |
56 | # Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
57 | # If this step fails, then you should remove it and run the build manually (see below)
58 | - name: Autobuild
59 | uses: github/codeql-action/autobuild@v2
60 |
61 | # ℹ️ Command-line programs to run using the OS shell.
62 | # 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun
63 |
64 | # If the Autobuild fails above, remove it and uncomment the following three lines.
65 | # modify them (or add more) to build your code if your project, please refer to the EXAMPLE below for guidance.
66 |
67 | # - run: |
68 | # echo "Run, Build Application using script"
69 | # ./location_of_script_within_repo/buildscript.sh
70 |
71 | - name: Perform CodeQL Analysis
72 | uses: github/codeql-action/analyze@v2
73 |
--------------------------------------------------------------------------------
/zlog.c:
--------------------------------------------------------------------------------
1 | /*
2 | * Zlog utility
3 | * By: Eric Ma https://www.ericzma.com
4 | * Released under Unlicense
5 | */
6 |
7 | #include
8 | #include
9 | #include
10 | #include
11 | #include
12 | #include
13 | #include
14 | #include
15 | #include
16 | #include
17 |
18 | #include "zlog-config.h"
19 | #include "zlog.h"
20 |
21 | // --------------------------------------------------------------
22 | // zlog utilities
23 | FILE* zlog_fout = NULL;
24 | const char* zlog_file_log_name = NULL;
25 |
26 | char _zlog_buffer[ZLOG_BUFFER_SIZE][ZLOG_BUFFER_STR_MAX_LEN];
27 | int _zlog_buffer_size = 0;
28 |
29 | pthread_mutex_t _zlog_buffer_mutex = PTHREAD_MUTEX_INITIALIZER;
30 | // --------------------------------------------------------------
31 |
32 | static inline void _zlog_buffer_lock(void)
33 | {
34 | pthread_mutex_lock(&_zlog_buffer_mutex);
35 | }
36 |
37 | static inline void _zlog_buffer_unlock(void)
38 | {
39 | pthread_mutex_unlock(&_zlog_buffer_mutex);
40 | }
41 |
42 | static void _zlog_flush_buffer(void)
43 | {
44 | int i = 0;
45 | for (i = 0; i < _zlog_buffer_size; i++) {
46 | fprintf(zlog_fout, "%s", _zlog_buffer[i]);
47 | }
48 | fflush(zlog_fout);
49 | _zlog_buffer_size = 0;
50 | }
51 |
52 | // first zlog_get_buffer, write to @return
53 | // then zlog_finish_buffer
54 | //
55 | // zlog_get_buffer may flush the buffer, which require I/O ops
56 | static inline char* zlog_get_buffer(void)
57 | {
58 | _zlog_buffer_lock();
59 | if (_zlog_buffer_size == ZLOG_BUFFER_SIZE) {
60 | _zlog_flush_buffer();
61 | }
62 |
63 | // allocate buffer
64 | _zlog_buffer_size++;
65 | return _zlog_buffer[_zlog_buffer_size-1];
66 | }
67 |
68 | static inline void zlog_finish_buffer(void)
69 | {
70 | #ifdef ZLOG_FORCE_FLUSH_BUFFER
71 | _zlog_flush_buffer();
72 | #endif
73 | _zlog_buffer_unlock();
74 | }
75 |
76 | // Error reporting
77 | static inline void print_error(const char *function_name, char *error_msg){
78 | fprintf(stderr, "Error in function %s: %s\n", function_name, error_msg);
79 | }
80 |
81 | // --------------------------------------------------------------
82 |
83 | void zlog_init(char const* log_file)
84 | {
85 | zlog_file_log_name = strdup(log_file);
86 |
87 | zlog_fout = fopen(log_file, "a+");
88 |
89 | if(!zlog_fout){
90 | print_error(__func__, strerror(errno));
91 | }
92 | }
93 |
94 | void zlog_init_stdout(void)
95 | {
96 | zlog_fout = stdout;
97 | }
98 |
99 | void zlog_init_stderr(void)
100 | {
101 | zlog_fout = stderr;
102 | }
103 |
104 | static void* zlog_buffer_flush_thread(void* interval_sec)
105 | {
106 | struct timeval tv;
107 | time_t lasttime;
108 | time_t curtime;
109 | int flush_interval = *(int*)interval_sec;
110 | free(interval_sec);
111 | int sleep_time_sec = ZLOG_SLEEP_TIME_SEC > flush_interval ? flush_interval : ZLOG_SLEEP_TIME_SEC;
112 |
113 | gettimeofday(&tv, NULL);
114 |
115 | lasttime = tv.tv_sec;
116 |
117 | do {
118 | sleep(sleep_time_sec);
119 | gettimeofday(&tv, NULL);
120 | curtime = tv.tv_sec;
121 | if ( (curtime - lasttime) >= flush_interval ) {
122 | // ZLOG_LOG_LEVEL is used to make the buffer flushing
123 | // seamlessly for the users. It does not matter what level
124 | // the messages are at this point because, if they do
125 | // not meet message level requirement, that wouldn't
126 | // have been buffered in the first place.
127 | zlog_flush_buffer();
128 | lasttime = curtime;
129 | } else {
130 | _zlog_buffer_lock();
131 | if (_zlog_buffer_size >= ZLOG_BUFFER_FLUSH_SIZE ) {
132 | _zlog_flush_buffer();
133 | }
134 | _zlog_buffer_unlock();
135 | }
136 | } while (1);
137 | return NULL;
138 | }
139 |
140 | void zlog_init_flush_thread(void)
141 | {
142 | zlog_init_flush_thread_with_interval(ZLOG_FLUSH_INTERVAL_SEC);
143 | }
144 |
145 | void zlog_init_flush_thread_with_interval(int interval_sec)
146 | {
147 | pthread_t thr;
148 | int* interval = (int*)malloc(sizeof(int));
149 | *interval = interval_sec;
150 | pthread_create(&thr, NULL, zlog_buffer_flush_thread, (void*)interval);
151 | zlogf_time(ZLOG_LOG_LEVEL, "Flush thread is created.\n");
152 | }
153 |
154 | void zlog_flush_buffer(void)
155 | {
156 | _zlog_buffer_lock();
157 | _zlog_flush_buffer();
158 | _zlog_buffer_unlock();
159 | }
160 |
161 | void zlog_finish(void)
162 | {
163 | zlog_flush_buffer();
164 | if (zlog_fout != stdout || zlog_fout != stderr) {
165 | fclose(zlog_fout);
166 | zlog_fout = stdout;
167 | }
168 |
169 | }
170 |
171 | inline void zlogf(int msg_level, char const * fmt, ...)
172 | {
173 | #ifdef ZLOG_DISABLE_LOG
174 | return ;
175 | #endif
176 | if(msg_level <= ZLOG_LOG_LEVEL){
177 | va_list va;
178 | char* buffer = NULL;
179 |
180 | va_start(va, fmt);
181 | buffer = zlog_get_buffer();
182 |
183 | vsnprintf(buffer, ZLOG_BUFFER_STR_MAX_LEN, fmt, va);
184 | zlog_finish_buffer();
185 | va_end(va);
186 | }
187 | }
188 |
189 | void zlogf_time(int msg_level, char const * fmt, ...)
190 | {
191 | #ifdef ZLOG_DISABLE_LOG
192 | return ;
193 | #endif
194 |
195 | if(msg_level <= ZLOG_LOG_LEVEL){
196 | char timebuf[ZLOG_BUFFER_TIME_STR_MAX_LEN];
197 | struct timeval tv;
198 | //time_t curtime;
199 | char* buffer = NULL;
200 |
201 | // time_t ltime;
202 | // ltime = time(NULL);
203 |
204 | va_list va;
205 |
206 | gettimeofday(&tv, NULL);
207 | //curtime=tv.tv_sec;
208 | struct tm *tm_struct = localtime(&tv.tv_sec);
209 | snprintf(timebuf, ZLOG_BUFFER_TIME_STR_MAX_LEN, "%d:%02d:%d", tm_struct->tm_hour, tm_struct->tm_min, tm_struct->tm_sec);
210 | buffer = zlog_get_buffer();
211 | snprintf(buffer, ZLOG_BUFFER_STR_MAX_LEN, "[%s.%06lds] ", timebuf, tv.tv_usec);
212 | buffer += strlen(timebuf) + 11; // space for time
213 |
214 | va_start(va, fmt);
215 | vsnprintf(buffer, ZLOG_BUFFER_STR_MAX_LEN, fmt, va);
216 | zlog_finish_buffer();
217 | va_end(va);
218 | }
219 | }
220 |
221 | void zlog_time(int msg_level, char* filename, int line, char const * fmt, ...)
222 | {
223 | #ifdef ZLOG_DISABLE_LOG
224 | return ;
225 | #endif
226 | if(msg_level <= ZLOG_LOG_LEVEL){
227 | static char timebuf[ZLOG_BUFFER_TIME_STR_MAX_LEN];
228 | struct timeval tv;
229 | time_t curtime;
230 | char* buffer = NULL;
231 |
232 | va_list va;
233 |
234 | gettimeofday(&tv, NULL);
235 | curtime=tv.tv_sec;
236 | struct tm *tm_struct = localtime(&tv.tv_sec);
237 | snprintf(timebuf, ZLOG_BUFFER_TIME_STR_MAX_LEN, "%ld", curtime);
238 | snprintf(timebuf, ZLOG_BUFFER_TIME_STR_MAX_LEN, "%d:%02d:%d", tm_struct->tm_hour, tm_struct->tm_min, tm_struct->tm_sec);
239 |
240 | buffer = zlog_get_buffer();
241 | snprintf(buffer, ZLOG_BUFFER_STR_MAX_LEN, "[%s.%06lds] [@%s:%d] ", timebuf, tv.tv_usec, filename, line);
242 | buffer += strlen(buffer); // print at most 5 digit of line
243 |
244 | va_start(va, fmt);
245 | vsnprintf(buffer, ZLOG_BUFFER_STR_MAX_LEN, fmt, va);
246 | zlog_finish_buffer();
247 | va_end(va);
248 | }
249 | }
250 |
251 | void zlog(int msg_level, char* filename, int line, char const * fmt, ...)
252 | {
253 | #ifdef ZLOG_DISABLE_LOG
254 | return ;
255 | #endif
256 | if(msg_level <= ZLOG_LOG_LEVEL){
257 | char* buffer = NULL;
258 | va_list va;
259 |
260 | buffer = zlog_get_buffer();
261 | snprintf(buffer, ZLOG_BUFFER_STR_MAX_LEN, "[@%s:%d] ", filename, line);
262 | buffer += strlen(buffer);
263 | va_start(va, fmt);
264 |
265 | vsnprintf(buffer, ZLOG_BUFFER_STR_MAX_LEN, fmt, va);
266 | zlog_finish_buffer();
267 | va_end(va);
268 | }
269 | }
270 |
271 | const char* zlog_get_log_file_name(void){
272 | #ifdef ZLOG_DISABLE_LOG
273 | return ;
274 | #endif
275 | return zlog_file_log_name;
276 | }
277 |
278 | // End zlog utilities
279 |
280 |
--------------------------------------------------------------------------------