├── .github └── workflows │ ├── cmake.yml │ ├── codeql-analysis.yml │ └── dist.yml ├── .gitignore ├── .travis.yml ├── CMakeLists.txt ├── LICENSE ├── README.md ├── bin ├── local_coverage.sh ├── log.yaml └── make.sh ├── build_vs.bat ├── check_tests.sh ├── dist └── include │ └── fn-log │ ├── GIT_VERSION │ ├── LICENSE │ ├── README.md │ ├── _config.yml │ ├── default_log.yaml │ └── fn_log.h ├── distribute.sh ├── make.sh ├── src └── include │ ├── fn_channel.h │ ├── fn_core.h │ ├── fn_data.h │ ├── fn_file.h │ ├── fn_fmt.h │ ├── fn_load.h │ ├── fn_log.h │ ├── fn_macro.h │ ├── fn_out_empty_device.h │ ├── fn_out_file_device.h │ ├── fn_out_screen_device.h │ ├── fn_out_udp_device.h │ ├── fn_out_virtual_device.h │ ├── fn_parse.h │ └── fn_stream.h └── tests ├── benchmark_device_30.cpp ├── benchmark_fast.cpp ├── benchmark_filter_empty.cpp ├── benchmark_multi-thread.cpp ├── benchmark_multi-thread_hotupdate.cpp ├── benchmark_multi-thread_nofile.cpp ├── benchmark_multi-thread_sync.cpp ├── benchmark_multi-thread_sync_nofile.cpp ├── benchmark_multi-thread_travis_shm.cpp ├── benchmark_multi-thread_use.cpp ├── benchmark_normal.cpp ├── benchmark_serialize_integer.cpp ├── benchmark_sync_bat_write.cpp ├── benchmark_udp.cpp ├── benchmark_virtual_device.cpp ├── stress_block_in.cpp ├── stress_multi-thread-env_concurrent_reboot.cpp ├── stress_multi-thread-env_main_reboot.cpp ├── test_bitlist.cpp ├── test_buffer.cpp ├── test_buffer_correct.cpp ├── test_channel_normal.cpp ├── test_coverage.cpp ├── test_fast_debug.cpp ├── test_fast_default.cpp ├── test_filter.cpp ├── test_filter_advance.cpp ├── test_filter_mask.cpp ├── test_hex_out.cpp ├── test_hotupdate.cpp ├── test_lex.cpp ├── test_line_no.cpp ├── test_load_config.cpp ├── test_rolling.cpp ├── test_serialize_object.cpp ├── test_shm.cpp ├── test_trans_log.cpp ├── test_udp.cpp └── test_var_define.cpp /.github/workflows/cmake.yml: -------------------------------------------------------------------------------- 1 | name: Build 2 | 3 | on: 4 | push: 5 | branches: [ master ] 6 | pull_request: 7 | branches: [ master ] 8 | 9 | env: 10 | # Customize the CMake build type here (Release, Debug, RelWithDebInfo, etc.) 11 | BUILD_TYPE: Release 12 | 13 | jobs: 14 | build: 15 | # The CMake configure and build commands are platform agnostic and should work equally 16 | # well on Windows or Mac. You can convert this to a matrix build if you need 17 | # cross-platform coverage. 18 | strategy: 19 | matrix: 20 | cc: [gcc, clang] 21 | os: [ubuntu-latest, macos-latest] 22 | #os: [ubuntu-latest, macos-latest, windows-latest] 23 | # See: https://docs.github.com/en/free-pro-team@latest/actions/learn-github-actions/managing-complex-workflows#using-a-build-matrix 24 | runs-on: ${{ matrix.os }} 25 | 26 | steps: 27 | - uses: actions/checkout@v2 28 | env: 29 | CC: ${{ matrix.cc }} 30 | - name: Configure CMake 31 | # Configure CMake in a 'build' subdirectory. `CMAKE_BUILD_TYPE` is only required if you are using a single-configuration generator such as make. 32 | # See https://cmake.org/cmake/help/latest/variable/CMAKE_BUILD_TYPE.html?highlight=cmake_build_type 33 | run: cmake -B ${{github.workspace}}/build -DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}} 34 | 35 | - name: Build 36 | 37 | # Build your program with the given configuration 38 | run: cmake --build ${{github.workspace}}/build --config ${{env.BUILD_TYPE}} 39 | 40 | - name: Test 41 | working-directory: ${{github.workspace}}/build 42 | # Execute tests defined by the CMake configuration. 43 | # See https://cmake.org/cmake/help/latest/manual/ctest.1.html for more detail 44 | run: | 45 | cd ${{github.workspace}}/bin 46 | ./test_lex 47 | ./test_bitlist 48 | ./test_line_no 49 | ./test_buffer 50 | ./test_filter 51 | ./test_filter_advance 52 | ./test_filter_mask 53 | ./test_load_config 54 | ./test_udp 55 | ./test_buffer 56 | ./test_buffer_correct 57 | ./test_fast_debug 58 | ./test_fast_default 59 | ./test_coverage 60 | ./test_hex_out 61 | ./test_channel_normal 62 | ./test_rolling 63 | ./test_serialize_object 64 | ./test_trans_log 65 | ./test_var_define 66 | ./test_hotupdate 67 | ./stress_block_in 68 | ./stress_multi-thread-env_main_reboot 69 | ./stress_multi-thread-env_concurrent_reboot 50000 >/dev/null 2>&1 70 | ./stress_multi-thread-env_concurrent_reboot >/dev/null 2>&1 71 | ./stress_multi-thread-env_main_reboot 72 | ./benchmark_multi-thread 73 | ./benchmark_multi-thread_nofile 74 | ./benchmark_multi-thread_hotupdate 75 | ./benchmark_multi-thread_sync 76 | ./benchmark_multi-thread_sync_nofile 77 | ./benchmark_serialize_integer 78 | ./benchmark_sync_bat_write 79 | ./benchmark_normal 80 | ./benchmark_udp 81 | ./benchmark_fast 82 | ./benchmark_device_30 83 | ./benchmark_virtual_device 84 | if [ "$RUNNER_OS" == "Linux" ]; then 85 | ipcs -m 86 | ipcs -mt 87 | ./test_shm 88 | ipcs -m 89 | ipcs -mt 90 | ./test_shm 91 | ipcs -m 92 | ipcs -mt 93 | ./benchmark_multi-thread_travis_shm 94 | else 95 | echo "$RUNNER_OS not supported full test" 96 | fi 97 | -------------------------------------------------------------------------------- /.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: [ master ] 17 | pull_request: 18 | # The branches below must be a subset of the branches above 19 | branches: [ master ] 20 | schedule: 21 | - cron: '17 6 * * 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' ] 37 | # Learn more: 38 | # https://docs.github.com/en/free-pro-team@latest/github/finding-security-vulnerabilities-and-errors-in-your-code/configuring-code-scanning#changing-the-languages-that-are-analyzed 39 | 40 | steps: 41 | - name: Checkout repository 42 | uses: actions/checkout@v2 43 | 44 | # Initializes the CodeQL tools for scanning. 45 | - name: Initialize CodeQL 46 | uses: github/codeql-action/init@v1 47 | with: 48 | languages: ${{ matrix.language }} 49 | # If you wish to specify custom queries, you can do so here or in a config file. 50 | # By default, queries listed here will override any specified in a config file. 51 | # Prefix the list here with "+" to use these queries and those in the config file. 52 | # queries: ./path/to/local/query, your-org/your-repo/queries@main 53 | 54 | # Autobuild attempts to build any compiled languages (C/C++, C#, or Java). 55 | # If this step fails, then you should remove it and run the build manually (see below) 56 | - name: Autobuild 57 | uses: github/codeql-action/autobuild@v1 58 | 59 | # ℹ️ Command-line programs to run using the OS shell. 60 | # 📚 https://git.io/JvXDl 61 | 62 | # ✏️ If the Autobuild fails above, remove it and uncomment the following three lines 63 | # and modify them (or add more) to build your code if your project 64 | # uses a compiled language 65 | 66 | #- run: | 67 | # make bootstrap 68 | # make release 69 | 70 | - name: Perform CodeQL Analysis 71 | uses: github/codeql-action/analyze@v1 72 | -------------------------------------------------------------------------------- /.github/workflows/dist.yml: -------------------------------------------------------------------------------- 1 | name: auto-dist 2 | on: 3 | push: 4 | branches: 5 | - 'master' 6 | 7 | jobs: 8 | auto-dist: 9 | runs-on: ubuntu-latest 10 | steps: 11 | - name: wait-pagas-build 12 | run: sleep 60s 13 | - name: clone 14 | run: | 15 | git clone https://${{secrets.ACTIONTOKEN}}@github.com/zsummer/fn-log.git fn-log-master 16 | git clone https://${{secrets.ACTIONTOKEN}}@github.com/zsummer/fn-log.git -b dist fn-log-dist 17 | ls 18 | cd fn-log-master 19 | git config --global user.email "yawei.zhang@foxmail.com" 20 | git config --global user.name "zsummer" 21 | git status 22 | cd ../fn-log-dist 23 | git config --global user.email "yawei.zhang@foxmail.com" 24 | git config --global user.name "zsummer" 25 | git status 26 | - name: local-dist 27 | run: | 28 | cd fn-log-master 29 | bash distribute.sh 30 | git add ./dist/ 31 | git commit -a --allow-empty -m "[skip ci] auto dist" 32 | git push 33 | - name: branch-dist 34 | run: | 35 | cd fn-log-master 36 | cp -r dist/* ../fn-log-dist/ 37 | cd ../fn-log-dist/ 38 | git status 39 | git add * 40 | git diff --cached |wc -l 41 | git commit -a --allow-empty -m "[skip ci]auto dist" 42 | git push 43 | 44 | 45 | 46 | 47 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Prerequisites 2 | *.d 3 | 4 | # Compiled Object files 5 | *.slo 6 | *.lo 7 | *.o 8 | *.obj 9 | 10 | # Precompiled Headers 11 | *.gch 12 | *.pch 13 | 14 | # Compiled Dynamic libraries 15 | *.so 16 | *.dylib 17 | *.dll 18 | 19 | # Fortran module files 20 | *.mod 21 | *.smod 22 | 23 | # Compiled Static libraries 24 | *.lai 25 | *.la 26 | *.a 27 | *.lib 28 | 29 | # Compiled Dir 30 | build 31 | build_* 32 | build-* 33 | .DS_Store 34 | .vs 35 | .vscode 36 | xcodes 37 | vs_sln 38 | 39 | 40 | # Executables 41 | *.exe 42 | *.out 43 | *.app 44 | *.bin 45 | bin/test_* 46 | bin/stress_* 47 | bin/benchmark_* 48 | bin/Debug 49 | bin/Release 50 | .gdb_history 51 | 52 | # log 53 | bin/*.log.* 54 | bin/*.log 55 | bin/log 56 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | sudo: true 2 | language: cpp 3 | compiler: 4 | - gcc 5 | - clang 6 | os: 7 | - linux 8 | - osx 9 | 10 | env: 11 | global: 12 | - secure: "To1R20fuYQQnL/d9OsGjTlGdTJ1cGo8Cm0aSf5IngkWIvCgmJHtt5uqO8DbCLONskmH07BlxnKPYZFjTSELe09ifSxggr866/Olnxh7BbBSLYU0xOAZ1C8LcEkFQxdXCfLQC/WrwWL9mosjYh6mozMZipUktBc2i6FopzkIpb41kTINO6+v4sKIHPOb2RLRVXM5gNnMee98QnlCQPI2IySm30R0K8MI/AjooC4RBOUBLTFSbN4DXzuYpJmGdpVofHx7sWrBcSzkpTMkEtQSHJPzXIPslSILAhEk0NGxL+Qikqt6yDXPrAWRJ+tYh/M0fgHwPYUJog9uEIlz9g1OIBjtOZH6yAI7OMv+XATDikqmfgYLT8nUiuvAypC9+0T4+uzh2ogKCCGa7wX9UyrIzCDV38MvehsQNmRSeGdofx8StuIcGE9OWPVhspaNMFm6BF7UpojZdC5b7+fz+ZZ0Q8aKQ0+yokAXYXlHhDbkO/sE7BnG0jiH/6BLKcSJtDzpsmLOKxFqWz9yMKy+i25C2vNATdppMkXbE1eUlsF/i8jLzHFAaT2J9JeTUbUx8gUyW0AVC2waNl/sJaH3vfvjG74LWMer4bZ0zFfyOIDguzdSC1S7oj5DPza3E1txcGjY2TmUAfHcdDcEuNA0+IA8b3YyMwR8N50id+Yi61EZgFsg=" 13 | 14 | before_install: 15 | - echo -n | openssl s_client -connect https://scan.coverity.com:443 | sed -ne '/-BEGIN CERTIFICATE-/,/-END CERTIFICATE-/p' | sudo tee -a /etc/ssl/certs/ca- 16 | - pip install --user cpp-coveralls 17 | 18 | install: 19 | - if [[ "$TRAVIS_OS_NAME" == "linux" && "$TRAVIS_COMPILER" == "gcc" ]]; then sudo apt-get install -y gdb; fi 20 | 21 | before_script: 22 | - if [[ "$TRAVIS_OS_NAME" == "linux" && "$TRAVIS_COMPILER" == "gcc" ]]; then ulimit -c unlimited -S; fi 23 | - if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then sudo sysctl -w kern.sysv.shmmax=419430400; fi 24 | - if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then sudo sysctl -w kern.sysv.shmall=419430400; fi 25 | - if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then sudo sysctl -w kernel.shmmax=419430400; fi 26 | - if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then sudo sysctl -w kernel.shmall=419430400; fi 27 | 28 | - if [[ "$TRAVIS_OS_NAME" == "osx" || "$TRAVIS_OS_NAME" == "linux" ]]; then sysctl -a|grep shm; fi 29 | 30 | - df -m 31 | - ipcs -m 32 | - ipcs -mt 33 | - if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then ipcs -M; fi 34 | - if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then ipcs -lm; fi 35 | - ulimit -a 36 | 37 | 38 | script: 39 | - cmake --version 40 | - mkdir build 41 | - cd build 42 | - cmake -DENABLE_GCOV=TRUE .. 43 | - make -j4 44 | - ls ../bin/* 45 | - cd ../bin 46 | 47 | - ./test_buffer 48 | - ./test_filter 49 | - ./test_load_config 50 | - ./test_udp >/dev/null 2>&1 51 | - ./test_buffer_correct 52 | - ./test_fast_debug 53 | - ./test_fast_default 54 | - ./test_coverage 55 | - ./test_channel_normal 56 | - ./stress_multi-thread-env_main_reboot 57 | - ./stress_multi-thread-env_concurrent_reboot 50000 >/dev/null 2>&1 58 | - cd .. 59 | 60 | - find ./ -name "*.gc*" 61 | - if [[ "$TRAVIS_OS_NAME" == "linux" && "$TRAVIS_COMPILER" == "gcc" ]]; then coveralls; else echo "$TRAVIS_OS_NAME $TRAVIS_COMPILER"; fi 62 | 63 | - ls -la 64 | 65 | - sh merge_header.sh 66 | - mv src/include src/bak 67 | - mkdir src/include 68 | - mv fn_log.h.only src/include/fn_log.h 69 | - mkdir benchmarke-build 70 | - cd benchmarke-build 71 | - cmake -DCMAKE_BUILD_TYPE=Release .. 72 | - make -j4 73 | - cd .. 74 | - rm -fr benchmarke-build 75 | - rm -fr src/include 76 | - mv src/bak src/include 77 | - ls bin/* 78 | - cd bin 79 | 80 | - ./stress_multi-thread-env_concurrent_reboot >/dev/null 2>&1 81 | - ./stress_multi-thread-env_main_reboot 82 | - ./benchmark_multi-thread 83 | - ./benchmark_multi-thread_nofile 84 | - ./benchmark_multi-thread_sync 85 | - ./benchmark_multi-thread_sync_nofile 86 | - ./benchmark_serialize_integer 87 | - ./benchmark_sync_bat_write 88 | - ./benchmark_normal 89 | - ./benchmark_udp 90 | - ./benchmark_fast 91 | 92 | - ipcs -m 93 | - ipcs -mt 94 | - ./test_shm 95 | - ipcs -m 96 | - ipcs -mt 97 | - ./test_shm 98 | - ipcs -m 99 | - ipcs -mt 100 | - ./benchmark_multi-thread_travis_shm 101 | - cd .. 102 | 103 | 104 | - find ./ -name "*.gc*" 105 | - cd .. 106 | 107 | 108 | after_success: 109 | after_failure: 110 | #- COREFILE=$(find . -maxdepth 1 -name "core*" | head -n 1) # find core file 111 | #- if [[ -f "$COREFILE" ]]; then gdb -c "$COREFILE" example -ex "thread apply all bt" -ex "set pagination 0" -batch; fi 112 | 113 | addons: 114 | coverity_scan: 115 | project: 116 | name: "zsummer/fn-log" 117 | description: "fn-log coverity" 118 | notification_email: yawei.zhang@foxmail.com 119 | build_command_prepend: "mkdir coverity; cd coverity; cmake .." 120 | build_command: "make -j2" 121 | branch_pattern: coverity 122 | 123 | 124 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.5) 2 | project(fn-log) 3 | #enable_language(ASM) 4 | 5 | #from github.com/zsummer 6 | 7 | # plat : WIN32 APPLE UNIX (UNIX contain UNIX like) 8 | 9 | # CMAKE_CXX_COMPILER_ID: GNU Intel Clang AppleClang MSVC 10 | # example IF (CMAKE_CXX_COMPILER_ID MATCHES "Clang") ENDIF() 11 | 12 | # jump compiler works check 13 | # if(WIN32) 14 | # set(CMAKE_C_COMPILER_WORKS TRUE) 15 | # set(CMAKE_CXX_COMPILER_WORKS TRUE) 16 | # endif(WIN32) 17 | 18 | # jump this project build when msvc 19 | # set_target_properties(${PROJECT_NAME} PROPERTIES EXCLUDE_FROM_ALL 1 EXCLUDE_FROM_DEFAULT_BUILD 1) 20 | 21 | # set this project setup build when msvc 22 | # set_property(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY VS_STARTUP_PROJECT ${PROJECT_NAME}) 23 | 24 | # show msvc folder 25 | # SET_PROPERTY(GLOBAL PROPERTY USE_FOLDERS ON) 26 | 27 | # use C++ 14 28 | # set(CMAKE_CXX_FLAGS -std=c++14) 29 | 30 | # 31 | # CMAKE_SOURCE_DIR cmake root dir 32 | # CMAKE_CURRENT_SOURCE_DIR current cmakelist.txt dir 33 | # EXECUTABLE_OUTPUT_PATH can set it change bin out dir 34 | # CMAKE_MODULE_PATH can set it change module dir 35 | # PROJECT_NAME cur project name 36 | 37 | # include 38 | # include_directories 39 | # link_directories 40 | # link_libraries 41 | 42 | # 43 | # execute_process 44 | set(CMAKE_VERBOSE_MAKEFILEON ON) 45 | if( NOT CMAKE_CONFIGURATION_TYPES ) 46 | set( CMAKE_CONFIGURATION_TYPES Debug Release ) 47 | endif( NOT CMAKE_CONFIGURATION_TYPES ) 48 | 49 | set(CMAKE_BUILD_TYPE Debug CACHE STRING "cache debug release " ) 50 | set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS ${CMAKE_CONFIGURATION_TYPES} ) 51 | 52 | #分组添加到IDE 53 | MACRO(GROUP_SRC_BY_DIR FILES) 54 | FOREACH(PATH_NAME ${${FILES}}) 55 | STRING(REGEX REPLACE ${CMAKE_CURRENT_SOURCE_DIR}/\(.*\) \\1 RELATIVE_PATH ${PATH_NAME}) 56 | STRING(REGEX MATCH "(.+)/.*" HAS_GROUP ${RELATIVE_PATH}) 57 | IF(HAS_GROUP) 58 | STRING(REGEX REPLACE "(.+)/.*" \\1 GROUP_NAME ${RELATIVE_PATH}) 59 | STRING(REPLACE "/" "\\" GROUP_NAME ${GROUP_NAME}) 60 | MESSAGE(${PATH_NAME} " into " ${GROUP_NAME}) 61 | SOURCE_GROUP(${GROUP_NAME} FILES ${PATH_NAME}) 62 | ELSE() 63 | SOURCE_GROUP("" FILES ${PATH_NAME}) 64 | ENDIF() 65 | ENDFOREACH(PATH_NAME) 66 | ENDMACRO(GROUP_SRC_BY_DIR) 67 | 68 | 69 | FILE(GLOB_RECURSE SOURCES_H ${CMAKE_SOURCE_DIR}/src/include/*.h) 70 | # 自动INCLUDE所有头文件的目录 (可能会影响到include的优先级) 71 | # list(FILTER REGEX ) 72 | 73 | set(SOURCES ${SOURCES_H} ${SOURCES_C}) 74 | GROUP_SRC_BY_DIR(SOURCES) 75 | 76 | 77 | FOREACH(FILE_NAME ${SOURCES_H}) 78 | STRING( REGEX REPLACE "[^/\\\\]+$" " " DIR_NAME ${FILE_NAME} ) 79 | MESSAGE(${FILE_NAME}) 80 | MESSAGE(${DIR_NAME}) 81 | LIST(APPEND DIR_NAME_LIST ${DIR_NAME}) 82 | ENDFOREACH() 83 | 84 | IF(DIR_NAME_LIST) 85 | LIST(REMOVE_DUPLICATES DIR_NAME_LIST) 86 | ENDIF() 87 | 88 | FOREACH(DIR_NAME ${DIR_NAME_LIST}) 89 | MESSAGE("auto include " ${DIR_NAME} ) 90 | INCLUDE_DIRECTORIES(${DIR_NAME}) 91 | ENDFOREACH() 92 | 93 | #通用设置部分 包括启用分组 设置 启动项目 94 | if(WIN32) 95 | ADD_DEFINITIONS(-DWIN32 -W3) 96 | SET_PROPERTY(GLOBAL PROPERTY USE_FOLDERS ON) 97 | #SET_PROPERTY(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY VS_STARTUP_PROJECT ${PROJECT_NAME}) 98 | else() 99 | ADD_DEFINITIONS(-Wall -O2 ) 100 | SET(CMAKE_CXX_FLAGS -std=c++11) 101 | SET(CMAKE_CXX_FLAGS_DEBUG "$ENV{CXXFLAGS} -O0 -Wall -g -ggdb") 102 | SET(CMAKE_CXX_FLAGS_RELEASE "$ENV{CXXFLAGS} -O2 -Wall") 103 | LINK_LIBRARIES(pthread m c) 104 | endif() 105 | 106 | 107 | #输出 108 | set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${PROJECT_SOURCE_DIR}/bin) 109 | SET(CMAKE_RUNTIME_OUTPUT_DIRECTORY_DEBUG "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}") 110 | SET(CMAKE_RUNTIME_OUTPUT_DIRECTORY_RELEASE "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}") 111 | SET(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_SOURCE_DIR}/bin) 112 | SET(CMAKE_LIBRARY_OUTPUT_DIRECTORY_DEBUG "${CMAKE_LIBRARY_OUTPUT_DIRECTORY}") 113 | SET(CMAKE_LIBRARY_OUTPUT_DIRECTORY_RELEASE "${CMAKE_LIBRARY_OUTPUT_DIRECTORY}") 114 | 115 | #自定义部分 116 | execute_process(COMMAND "${CMAKE_COMMAND}" "-E" "environment") 117 | #get_cmake_property(vars VARIABLES) 118 | #foreach (var ${vars}) 119 | # message(STATUS "${var}=${${var}}") 120 | #endforeach() 121 | 122 | 123 | message("-- CMAKE_CXX_COMPILER: ${CMAKE_CXX_COMPILER_ID}") 124 | message("-- CMAKE_C_COMPILER: ${CMAKE_C_COMPILER_ID}") 125 | message("-- CMAKE_C_COMPILER_VERSION: ${CMAKE_C_COMPILER_VERSION}") 126 | message("-- CMAKE_CXX_COMPILER_VERSION: ${CMAKE_CXX_COMPILER_VERSION}") 127 | message("-- CMAKE_BUILD_TYPE: ${CMAKE_BUILD_TYPE}") 128 | 129 | FILE(GLOB_RECURSE TEST_CPP ${CMAKE_SOURCE_DIR}/tests/*.cpp) 130 | FOREACH (FILE_NAME ${TEST_CPP}) 131 | STRING(REGEX REPLACE ".+/(.+)\\..*" "\\1" TEST_NAME ${FILE_NAME}) 132 | ADD_EXECUTABLE(${TEST_NAME} ${FILE_NAME} ${SOURCES}) 133 | if (CMAKE_CXX_COMPILER_ID MATCHES "MSVC") 134 | set_target_properties(${TEST_NAME} PROPERTIES VS_DEBUGGER_WORKING_DIRECTORY ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}) 135 | endif() 136 | 137 | IF (ENABLE_GCOV AND NOT WIN32 AND NOT APPLE) 138 | SET_TARGET_PROPERTIES(${TEST_NAME} 139 | PROPERTIES 140 | COMPILE_FLAGS "-ftest-coverage -fprofile-arcs" 141 | LINK_FLAGS "-lgcov --coverage" 142 | ) 143 | ENDIF() 144 | MESSAGE("TEST " ${TEST_NAME} ) 145 | ENDFOREACH() 146 | 147 | 148 | 149 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (C) 2019 YaweiZhang . 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- /bin/local_coverage.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | if command -v lcov >/dev/null 2>&1; then 3 | echo 'exists lcov' 4 | else 5 | echo 'no exists lcov' 6 | sleep 5 7 | exit 2 8 | fi 9 | 10 | cd .. 11 | bcc=build-check-coverage 12 | if [ ! -d "./$bcc" ]; then 13 | mkdir $bcc 14 | fi 15 | cd $bcc 16 | cmake -DENABLE_GCOV=TRUE -DCMAKE_BUILD_TYPE=Debug .. 17 | make -j4 18 | cd .. 19 | 20 | cd bin 21 | ts=`find ./ -maxdepth 1 -type f |egrep -v "log" | grep "test_" |egrep -v "pdb"` 22 | echo $ts 23 | for t in $ts ; 24 | do 25 | echo begin test $t 26 | $t 27 | if [ $? -eq 0 ]; then 28 | echo test $t success. 29 | else 30 | echo test $t failed 31 | exit $? 32 | fi 33 | 34 | done 35 | cd .. 36 | 37 | echo 38 | echo 39 | echo 40 | echo "all success " 41 | echo 42 | echo 43 | echo 44 | lcov --zerocounters --directory ./ 45 | lcov --capture --initial --directory ./ --output-file $bcc/coverage.info 46 | lcov --no-checksum --directory ./ --capture --output-file $bcc/coverage.info 47 | lcov --extract $bcc/coverage.info '*/src/*' '*/tests/*' -o $bcc/coverage2.info 48 | mv $bcc/coverage2.info $bcc/coverage.info 49 | genhtml --highlight --legend --output-directory $bcc/report $bcc/coverage.info 50 | 51 | -------------------------------------------------------------------------------- /bin/log.yaml: -------------------------------------------------------------------------------- 1 | # 配表文件 2 | #logger_name: 3 | logger_desc: 1.1.4.1 4 | hot_update: true 5 | # 0通道为多线程带文件和屏显输出 6 | - channel: 0 7 | priority: info 8 | category: 0 9 | category_extend: 0 10 | -device: 0 11 | disable: false 12 | out_type: file 13 | priority: info 14 | category: 0 15 | category_extend: 0 16 | path: "./log/" 17 | file: "$PNAME_$YEAR$MON$DAY" 18 | rollback: 4 19 | limit_size: 1000 m #only support M byte 20 | -device: 1 21 | disable: false 22 | out_type: screen 23 | category: 0 24 | category_extend: 0 25 | # 1通道为多线程不挂任何输出端 26 | - channel: 1 27 | 28 | # 2通道为单线程同步写文件 29 | - channel: 2 30 | sync_write: 1 #only support single thread 31 | -device: 0 32 | disable: false 33 | out_type: file 34 | 35 | # 3通道为单线程无输出端 36 | - channel: 3 37 | sync_write: 1 #only support single thread 38 | -------------------------------------------------------------------------------- /bin/make.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | cd .. 3 | sh make.sh 4 | -------------------------------------------------------------------------------- /build_vs.bat: -------------------------------------------------------------------------------- 1 | md vs_sln 2 | cd vs_sln 3 | cmake ../ -G"Visual Studio 17 2022" 4 | cd .. -------------------------------------------------------------------------------- /check_tests.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | if [ ! -d "./build-check" ]; then 3 | mkdir build-check 4 | fi 5 | cd build-check 6 | cmake .. 7 | make -j4 8 | cd .. 9 | 10 | cd bin 11 | ts=`find ./ -maxdepth 1 -type f |egrep -v ".*[a-zA-Z0-9]\..*"` 12 | for t in $ts ; 13 | do 14 | if [[ "$t" == *test_shm ]]; then 15 | echo "jump $t" 16 | continue 17 | fi 18 | echo begin test $t 19 | $t 20 | if [ $? -eq 0 ]; then 21 | echo test $t success. 22 | else 23 | echo test $t failed 24 | exit $? 25 | fi 26 | 27 | done 28 | cd .. 29 | -------------------------------------------------------------------------------- /dist/include/fn-log/GIT_VERSION: -------------------------------------------------------------------------------- 1 | version: 2 | last_sha1(./src)=008eb2ac6ce7d5b0c6e7bec612eeb657933233d2 3 | last_date(./src)=2025-05-29 17:23:23 +0800 4 | 5 | git log -1 --stat ./src: 6 | commit 008eb2ac6ce7d5b0c6e7bec612eeb657933233d2 Author: zsummer Date: Thu May 29 17:23:23 2025 +0800 __GCC_ASM_FLAG_OUTPUTS__ not define under gcc 9 src/include/fn_stream.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 7 | -------------------------------------------------------------------------------- /dist/include/fn-log/LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (C) 2019 YaweiZhang . 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- /dist/include/fn-log/_config.yml: -------------------------------------------------------------------------------- 1 | theme: jekyll-theme-leap-day -------------------------------------------------------------------------------- /dist/include/fn-log/default_log.yaml: -------------------------------------------------------------------------------- 1 | 2 | # 基础语法 3 | ## 缩进 相同scope的field需要保持缩进一致 4 | ## 缩进 子层级field缩进大于父层级field 5 | 6 | ## 数组 以-为前缀 需要放在key之前 7 | ## 注释 任意行内读到#之后会停止该行的解析操作, 即使位于引号内. 8 | ## kv分隔符 : 9 | ## 空白符 通常读到空白符会自动跳过, 但不包括尾随在值中间的空白符 10 | ## key 必须为小写字母和下划线 不允许其他值 11 | ## 值 会自动裁切前缀空白 12 | ## 值 的行尾边界有["#\r\n\0] 13 | ## 值 的内容做了约束 范围为: 字符数字[a-zA-Z0-9] [_-:/.,$~%] 14 | ## 值 的内容需求上为 文件名和路径 数字 字符 因此通过约束可以减少不必要的配置问题 15 | 16 | # 错误码 代码中搜索ParseErrorCode, ErrNo查找对应说明. 17 | 18 | # 宏语义 当前实现方式 原地替换(inplace)**随后**的所有字符串内容 19 | # 宏语义 要注意替换后的内容不能长于原有内容, 可以避免内存重分配开销. 20 | # 宏语义 要注意不要替换掉正常的字符串, 包含值中的内容 21 | 22 | 23 | # 变量 和宏替换类似, 不同点在于执行替换动作时候会增加前缀$进行替换, 并包裹{}重复执行一次. 例如var:{tag0=1} 会替换掉${tag0} 和 $tag0 24 | 25 | # 宏,变量 均不能重复定义 (替换无法再替换) 26 | # 宏,变量 通常为符号名+字面量 用来定义在随后重复使用的数字类编号 category, indentify, mask等 27 | 28 | 29 | 30 | - define: LIST______ 0,1,2,3 # used like c-style; warn: def name len must bigger than content. 31 | - def: EMPTY______ 32 | 33 | - var: id = 234 34 | - var: id0 = 0, id1 =1 # use var $id0 or ${id0} 35 | - var: {key="sss", val=999} 36 | 37 | 38 | 39 | # - shm_key: 33321231 40 | # - hot_update:[true][false] 41 | # - logger_name: string # log content prefix "LOG_PREFIX_NAME" 42 | # - logger_desc: string # log content prefix "LOG_PREFIX_DESC" 43 | - channel: 0 44 | sync: async 45 | #sync: [async][sync][ASYNC][SYNC] 46 | #priority:[trace][debug][info][warn][error][alarm][fatal] 47 | #category: id 48 | #category_extend: count 49 | #category_wmask: 255 (white mask) 50 | #category_wlist: {2,3,43} (white list) 51 | #category_bmask: 255 (black mask) 52 | #category_blist: {1,23,4} (black list) 53 | #identify: id 54 | #identify_extend: count 55 | #identify_wmask: 255 (white mask) 56 | #identify_wlist: {2,3,43} (white list) 57 | #identify_bmask: 255 (black mask) 58 | #identify_blist: {1,23,4} (black list) 59 | - device: 0 60 | disable: false 61 | #disable: [false][true][FALSE][TRUE] 62 | #priority:[trace][debug][info][warn][error][alarm][fatal] 63 | #category: id 64 | #category_extend: count 65 | #category_wmask: 255 (white mask) 66 | #category_wlist: {2-3,43} (white list) 67 | #category_bmask: 255 (black mask) 68 | #category_blist: {1,23,4-5} (black list) 69 | #identify: id 70 | #identify_extend: count 71 | #identify_wmask: 255 (white mask) 72 | #identify_wlist: {2-3,43} (white list) 73 | #identify_bmask: 255 (black mask) 74 | #identify_blist: {1,23,4} (black list) 75 | out_type: file 76 | #out_type:[file][null][udp][screen][virtual] 77 | file: "$PNAME" #in file type it's log file name 78 | path: ./ #in file type it's log file path 79 | rollback: 4 #in file type it's this device log file rollback count. 80 | limit_size: 100 m #in file type it's one log file limit size 81 | #stuff_up: [true][false] #in file type it's 'false' will rollback old file when reopen logger. the 'true' will append exist log file still reach 'limit_size' 82 | #udp_addr: [ip:port] # in udp type 83 | - device: 1 84 | disable: false 85 | out_type: file 86 | priority: error 87 | file: "$PNAME_error" 88 | rollback: 4 89 | limit_size: 100 m #only support M byte 90 | - device: 2 91 | disable: false 92 | out_type: screen 93 | priority: info 94 | - channel: 1 95 | sync: sync 96 | - device: 0 97 | disable: false 98 | out_type: file 99 | file: "$PNAME_sync" 100 | rollback: 4 101 | limit_size: 100 m #only support M byte 102 | - device: 1 103 | disable: false 104 | out_type: file 105 | priority: info 106 | file: "$PNAME_sync_info" 107 | rollback: 4 108 | limit_size: 100 m #only support M byte 109 | - device: 2 110 | disable: false 111 | out_type: screen 112 | priority: info 113 | 114 | -------------------------------------------------------------------------------- /distribute.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | export LANG=C 3 | export LC_CTYPE=C 4 | export LC_ALL=C 5 | 6 | cd $(dirname "$0") 7 | 8 | echo "#ifdef __GNUG__" > fn_log.h 9 | echo "#pragma GCC push_options" >> fn_log.h 10 | echo "#pragma GCC optimize (\"O2\")" >> fn_log.h 11 | echo "#endif" >> fn_log.h 12 | cat src/include/fn_file.h |sed `echo -e 's/\xEF\xBB\xBF//'` >> fn_log.h 13 | cat src/include/fn_data.h |sed `echo -e 's/\xEF\xBB\xBF//'` >> fn_log.h 14 | cat src/include/fn_parse.h |sed `echo -e 's/\xEF\xBB\xBF//'` >> fn_log.h 15 | cat src/include/fn_fmt.h |sed `echo -e 's/\xEF\xBB\xBF//'` >> fn_log.h 16 | cat src/include/fn_load.h |sed `echo -e 's/\xEF\xBB\xBF//'` >> fn_log.h 17 | cat src/include/fn_out_empty_device.h |sed `echo -e 's/\xEF\xBB\xBF//'` >> fn_log.h 18 | cat src/include/fn_out_file_device.h |sed `echo -e 's/\xEF\xBB\xBF//'` >> fn_log.h 19 | cat src/include/fn_out_udp_device.h |sed `echo -e 's/\xEF\xBB\xBF//'` >> fn_log.h 20 | cat src/include/fn_out_screen_device.h |sed `echo -e 's/\xEF\xBB\xBF//'` >> fn_log.h 21 | cat src/include/fn_out_virtual_device.h |sed `echo -e 's/\xEF\xBB\xBF//'` >> fn_log.h 22 | cat src/include/fn_channel.h |sed `echo -e 's/\xEF\xBB\xBF//'` >> fn_log.h 23 | cat src/include/fn_core.h |sed `echo -e 's/\xEF\xBB\xBF//'` >> fn_log.h 24 | cat src/include/fn_stream.h |sed `echo -e 's/\xEF\xBB\xBF//'` >> fn_log.h 25 | cat src/include/fn_macro.h |sed `echo -e 's/\xEF\xBB\xBF//'` >> fn_log.h 26 | cat src/include/fn_log.h |sed `echo -e 's/\xEF\xBB\xBF//'` >> fn_log.h 27 | echo "#ifdef __GNUG__" >> fn_log.h 28 | echo "#pragma GCC pop_options" >> fn_log.h 29 | echo "#endif" >> fn_log.h 30 | cat fn_log.h | sed '/#include.*fn_/d' > fn_log.h.bak 31 | 32 | mv fn_log.h.bak fn_log.h 33 | mv fn_log.h ./dist/include/fn-log/fn_log.h 34 | cp README.md ./dist/include/fn-log/README.md 35 | cp LICENSE ./dist/include/fn-log/LICENSE 36 | 37 | 38 | 39 | last_sha1=`git rev-parse HEAD` 40 | last_date=`git show --pretty=format:"%ci" | head -1` 41 | last_diff=`git log -1 --stat ` 42 | 43 | last_dist_sha1=`git log -1 --stat ./src |grep -E "commit ([0-9a-f]*)" |grep -E -o "[0-9a-f]{10,}"` 44 | last_dist_date=`git show $last_dist_sha1 --pretty=format:"%ci" | head -1` 45 | last_dist_diff=`git log -1 --stat ./src` 46 | 47 | echo "" 48 | echo "[master last commit]:" 49 | echo $last_sha1 50 | echo $last_date 51 | echo "" 52 | echo "[master last diff]:" 53 | echo $last_diff 54 | 55 | 56 | echo "" 57 | echo "[./src last commit]:" 58 | echo $last_dist_sha1 59 | echo $last_dist_date 60 | echo "" 61 | echo "[./src last diff]:" 62 | echo $last_dist_diff 63 | 64 | echo "" 65 | echo "[write versions]" 66 | echo "version:" > ./dist/include/fn-log/GIT_VERSION 67 | echo "last_sha1(./src)=$last_dist_sha1" >> ./dist/include/fn-log/GIT_VERSION 68 | echo "last_date(./src)=$last_dist_date" >> ./dist/include/fn-log/GIT_VERSION 69 | echo "" >> ./dist/include/fn-log/GIT_VERSION 70 | echo "git log -1 --stat ./src:" >> ./dist/include/fn-log/GIT_VERSION 71 | echo $last_dist_diff >> ./dist/include/fn-log/GIT_VERSION 72 | cat ./dist/include/fn-log/GIT_VERSION 73 | 74 | echo "" 75 | echo "[write done]" 76 | 77 | 78 | 79 | 80 | -------------------------------------------------------------------------------- /make.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | if [ ! -d build_linux ]; then 3 | mkdir build_linux 4 | fi 5 | cd build_linux 6 | if [ $# -gt 0 ] && [ $1 = "max" ]; then 7 | echo "has search max version" 8 | if [ -f /usr/bin/g++-8 ]; then 9 | cmake -DCMAKE_C_COMPILER=/usr/bin/gcc-8 -DCMAKE_CXX_COMPILER=/usr/bin/g++-8 $* ../ 10 | elif [ -f /usr/bin/g++-6 ]; then 11 | cmake -DCMAKE_C_COMPILER=/usr/bin/gcc-6 -DCMAKE_CXX_COMPILER=/usr/bin/g++-6 $* ../ 12 | else 13 | cmake $* ../ 14 | fi 15 | else 16 | cmake $* ../ 17 | fi 18 | 19 | make -j2 20 | 21 | -------------------------------------------------------------------------------- /src/include/fn_log.h: -------------------------------------------------------------------------------- 1 | 2 | /* 3 | * Copyright (C) 2019 YaweiZhang . 4 | * All rights reserved 5 | * This file is part of the fn-log, used MIT License. 6 | */ 7 | 8 | 9 | #pragma once 10 | #ifndef _FN_LOG_LOG_H_ 11 | #define _FN_LOG_LOG_H_ 12 | 13 | #include "fn_data.h" 14 | #include "fn_parse.h" 15 | #include "fn_load.h" 16 | #include "fn_core.h" 17 | #include "fn_stream.h" 18 | #include "fn_macro.h" 19 | 20 | namespace FNLog 21 | { 22 | 23 | //inline void EnableAllChannel(Logger& logger, bool enable); 24 | inline void EnableAllFileDevice(Logger& logger, bool enable) { BatchSetDeviceConfig(logger, DEVICE_OUT_FILE, DEVICE_CFG_ABLE, enable); } 25 | inline void EnableAllScreenDevice(Logger& logger, bool enable) { BatchSetDeviceConfig(logger, DEVICE_OUT_SCREEN, DEVICE_CFG_ABLE, enable); } 26 | inline void EnableAllUDPDevice(Logger& logger, bool enable) { BatchSetDeviceConfig(logger, DEVICE_OUT_UDP, DEVICE_CFG_ABLE, enable); } 27 | 28 | inline void SetAllChannelPriority(Logger& logger, LogPriority priority) { BatchSetChannelConfig(logger, CHANNEL_CFG_PRIORITY, priority); } 29 | inline void SetAllFilePriority(Logger& logger, LogPriority priority) { BatchSetDeviceConfig(logger, DEVICE_OUT_FILE, DEVICE_CFG_PRIORITY, priority); } 30 | inline void SetAllScreenPriority(Logger& logger, LogPriority priority) { BatchSetDeviceConfig(logger, DEVICE_OUT_SCREEN, DEVICE_CFG_PRIORITY, priority); } 31 | inline void SetAllUDPPriority(Logger& logger, LogPriority priority) { BatchSetDeviceConfig(logger, DEVICE_OUT_UDP, DEVICE_CFG_PRIORITY, priority); } 32 | 33 | #define BatchSetChannelCategoryMacro(begin, count) \ 34 | BatchSetChannelConfig(logger, CHANNEL_CFG_CATEGORY, begin);\ 35 | BatchSetChannelConfig(logger, CHANNEL_CFG_CATEGORY_EXTEND, count); 36 | #define BatchSetDeviceCategoryMacro(out_type, begin, count) \ 37 | BatchSetDeviceConfig(logger, out_type, DEVICE_CFG_CATEGORY, begin); \ 38 | BatchSetDeviceConfig(logger, out_type, DEVICE_CFG_CATEGORY_EXTEND, count); 39 | 40 | 41 | inline void SetAllChannelCategory(Logger& logger, int begin, int count) { BatchSetChannelCategoryMacro(begin, count);} 42 | inline void SetAllFilePriority(Logger& logger, int begin, int count) { BatchSetDeviceCategoryMacro(DEVICE_OUT_FILE, begin, count); } 43 | inline void SetAllScreenCategory(Logger& logger, int begin, int count) { BatchSetDeviceCategoryMacro(DEVICE_OUT_SCREEN, begin, count); } 44 | inline void SetAllUDPCategory(Logger& logger, int begin, int count) { BatchSetDeviceCategoryMacro(DEVICE_OUT_UDP, begin, count); } 45 | 46 | inline void SetAllFileLimitSize(Logger& logger, int limit) { BatchSetDeviceConfig(logger, DEVICE_OUT_FILE, DEVICE_CFG_FILE_LIMIT_SIZE, limit); } 47 | inline void SetAllFileRollbackCount(Logger& logger, int rb_count) { BatchSetDeviceConfig(logger, DEVICE_OUT_FILE, DEVICE_CFG_FILE_ROLLBACK, rb_count); } 48 | 49 | } 50 | 51 | #endif 52 | -------------------------------------------------------------------------------- /src/include/fn_macro.h: -------------------------------------------------------------------------------- 1 | 2 | /* 3 | * Copyright (C) 2019 YaweiZhang . 4 | * All rights reserved 5 | * This file is part of the fn-log, used MIT License. 6 | */ 7 | 8 | 9 | #pragma once 10 | #ifndef _FN_LOG_MACRO_H_ 11 | #define _FN_LOG_MACRO_H_ 12 | 13 | #include "fn_data.h" 14 | #include "fn_parse.h" 15 | #include "fn_load.h" 16 | #include "fn_core.h" 17 | #include "fn_stream.h" 18 | 19 | namespace FNLog 20 | { 21 | 22 | inline Logger& GetDefaultLogger() 23 | { 24 | static Logger logger; 25 | return logger; 26 | } 27 | 28 | inline int LoadAndStartDefaultLogger(const std::string& config_path) 29 | { 30 | int ret = LoadAndStartLogger(GetDefaultLogger(), config_path); 31 | if (ret != 0) 32 | { 33 | printf("load auto start default logger error. ret:<%d>.\n", ret); 34 | return ret; 35 | } 36 | return 0; 37 | } 38 | 39 | inline int FastStartDefaultLogger(const std::string& config_text) 40 | { 41 | int ret = ParseAndStartLogger(GetDefaultLogger(), config_text); 42 | if (ret != 0) 43 | { 44 | printf("fast start default logger error. ret:<%d>.\n", ret); 45 | return ret; 46 | } 47 | return 0; 48 | } 49 | 50 | 51 | inline int FastStartDefaultLogger() 52 | { 53 | static const std::string default_config_text = 54 | R"----( 55 | # default channel 0 56 | # write full log to pname.log 57 | # write error log to pname_error.log 58 | # view info log to screen 59 | # sync channel 1 60 | # write full log to pname.log 61 | # write info log to pname_info.log 62 | # view info log to screen 63 | 64 | - channel: 0 65 | sync: async 66 | -device: 0 67 | disable: false 68 | out_type: file 69 | file: "$PNAME" 70 | rollback: 4 71 | limit_size: 100 m #only support M byte 72 | -device: 1 73 | disable: false 74 | out_type: file 75 | priority: error 76 | file: "$PNAME_error" 77 | rollback: 4 78 | limit_size: 100 m #only support M byte 79 | -device:2 80 | disable: false 81 | out_type: screen 82 | priority: info 83 | - channel: 1 84 | sync: sync 85 | -device: 0 86 | disable: false 87 | out_type: file 88 | file: "$PNAME_sync" 89 | rollback: 4 90 | limit_size: 100 m #only support M byte 91 | -device: 1 92 | disable: false 93 | out_type: file 94 | priority: info 95 | file: "$PNAME_sync_info" 96 | rollback: 4 97 | limit_size: 100 m #only support M byte 98 | -device:2 99 | disable: false 100 | out_type: screen 101 | priority: info 102 | )----"; 103 | return FastStartDefaultLogger(default_config_text); 104 | } 105 | 106 | inline int FastStartDebugLogger() 107 | { 108 | int ret = FastStartDefaultLogger(); 109 | if (ret == 0) 110 | { 111 | BatchSetDeviceConfig(GetDefaultLogger(), DEVICE_OUT_FILE, DEVICE_CFG_PRIORITY, PRIORITY_TRACE); 112 | SetDeviceConfig(GetDefaultLogger(), 0, 1, DEVICE_CFG_PRIORITY, PRIORITY_ERROR); //error file is still error file 113 | BatchSetDeviceConfig(GetDefaultLogger(), DEVICE_OUT_SCREEN, DEVICE_CFG_PRIORITY, PRIORITY_DEBUG); 114 | } 115 | return ret; 116 | } 117 | } 118 | 119 | //--------------------BASE STREAM MACRO --------------------------- 120 | 121 | //temporary LogStream 122 | #define LOG_STREAM_ORIGIN(logger, channel, priority, category, identify, prefix) \ 123 | FNLog::LogStream(logger, channel, priority, category, identify,\ 124 | __FILE__, sizeof(__FILE__) - 1, \ 125 | __LINE__, __FUNCTION__, sizeof(__FUNCTION__) -1, prefix) 126 | 127 | // 128 | #define LOG_STREAM_ORIGIN_REF(logger, channel, priority, category, identify, prefix) \ 129 | LOG_STREAM_ORIGIN(logger, channel, priority, category, identify, prefix).self() 130 | 131 | #define LOG_STREAM_DEFAULT_LOGGER(channel, priority, category, identify, prefix) \ 132 | LOG_STREAM_ORIGIN_REF(FNLog::GetDefaultLogger(), channel, priority, category, identify, prefix) 133 | 134 | #define LOG_STREAM_DEFAULT_LOGGER_WITH_PREFIX(channel, priority, category, identify) \ 135 | LOG_STREAM_DEFAULT_LOGGER(channel, priority, category, identify, FNLog::LOG_PREFIX_DEFAULT) 136 | 137 | 138 | //--------------------CPP STREAM STYLE FORMAT --------------------------- 139 | #define LogTraceStream(channel_id, category, identify) LOG_STREAM_DEFAULT_LOGGER_WITH_PREFIX(channel_id, FNLog::PRIORITY_TRACE, category, identify) 140 | #define LogDebugStream(channel_id, category, identify) LOG_STREAM_DEFAULT_LOGGER_WITH_PREFIX(channel_id, FNLog::PRIORITY_DEBUG, category, identify) 141 | #define LogInfoStream(channel_id, category, identify) LOG_STREAM_DEFAULT_LOGGER_WITH_PREFIX(channel_id, FNLog::PRIORITY_INFO, category, identify) 142 | #define LogWarnStream(channel_id, category, identify) LOG_STREAM_DEFAULT_LOGGER_WITH_PREFIX(channel_id, FNLog::PRIORITY_WARN, category, identify) 143 | #define LogErrorStream(channel_id, category, identify) LOG_STREAM_DEFAULT_LOGGER_WITH_PREFIX(channel_id, FNLog::PRIORITY_ERROR, category, identify) 144 | #define LogAlarmStream(channel_id, category, identify) LOG_STREAM_DEFAULT_LOGGER_WITH_PREFIX(channel_id, FNLog::PRIORITY_ALARM, category, identify) 145 | #define LogFatalStream(channel_id, category, identify) LOG_STREAM_DEFAULT_LOGGER_WITH_PREFIX(channel_id, FNLog::PRIORITY_FATAL, category, identify) 146 | 147 | #define LogTrace() LogTraceStream(0, 0, 0) 148 | #define LogDebug() LogDebugStream(0, 0, 0) 149 | #define LogInfo() LogInfoStream(0, 0, 0) 150 | #define LogWarn() LogWarnStream(0, 0, 0) 151 | #define LogError() LogErrorStream(0, 0, 0) 152 | #define LogAlarm() LogAlarmStream(0, 0, 0) 153 | #define LogFatal() LogFatalStream(0, 0, 0) 154 | 155 | 156 | //--------------------CPP TEMPLATE STYLE FORMAT --------------------------- 157 | inline FNLog::LogStream& LogTemplatePack(FNLog::LogStream& ls) 158 | { 159 | return ls; 160 | } 161 | template 162 | FNLog::LogStream& LogTemplatePack(FNLog::LogStream& ls, Args&& ... args) 163 | { 164 | char buff[] = { (ls << args, '\0') ... }; 165 | (void)buff; 166 | return ls; 167 | } 168 | 169 | #define LogTracePack(channel_id, category, identify, ...) LogTemplatePack(LOG_STREAM_DEFAULT_LOGGER_WITH_PREFIX(channel_id, FNLog::PRIORITY_TRACE, category, identify), ##__VA_ARGS__) 170 | #define LogDebugPack(channel_id, category, identify, ...) LogTemplatePack(LOG_STREAM_DEFAULT_LOGGER_WITH_PREFIX(channel_id, FNLog::PRIORITY_DEBUG, category, identify), ##__VA_ARGS__) 171 | #define LogInfoPack(channel_id, category, identify, ...) LogTemplatePack(LOG_STREAM_DEFAULT_LOGGER_WITH_PREFIX(channel_id, FNLog::PRIORITY_INFO, category, identify), ##__VA_ARGS__) 172 | #define LogWarnPack(channel_id, category, identify, ...) LogTemplatePack(LOG_STREAM_DEFAULT_LOGGER_WITH_PREFIX(channel_id, FNLog::PRIORITY_WARN, category, identify), ##__VA_ARGS__) 173 | #define LogErrorPack(channel_id, category, identify, ...) LogTemplatePack(LOG_STREAM_DEFAULT_LOGGER_WITH_PREFIX(channel_id, FNLog::PRIORITY_ERROR, category, identify), ##__VA_ARGS__) 174 | #define LogAlarmPack(channel_id, category, identify, ...) LogTemplatePack(LOG_STREAM_DEFAULT_LOGGER_WITH_PREFIX(channel_id, FNLog::PRIORITY_ALARM, category, identify), ##__VA_ARGS__) 175 | #define LogFatalPack(channel_id, category, identify, ...) LogTemplatePack(LOG_STREAM_DEFAULT_LOGGER_WITH_PREFIX(channel_id, FNLog::PRIORITY_FATAL, category, identify), ##__VA_ARGS__) 176 | 177 | #define PackTrace(...) LogTracePack(0, 0, 0, ##__VA_ARGS__) 178 | #define PackDebug(...) LogDebugPack(0, 0, 0, ##__VA_ARGS__) 179 | #define PackInfo( ...) LogInfoPack( 0, 0, 0, ##__VA_ARGS__) 180 | #define PackWarn( ...) LogWarnPack( 0, 0, 0, ##__VA_ARGS__) 181 | #define PackError(...) LogErrorPack(0, 0, 0, ##__VA_ARGS__) 182 | #define PackAlarm(...) LogAlarmPack(0, 0, 0, ##__VA_ARGS__) 183 | #define PackFatal(...) LogFatalPack(0, 0, 0, ##__VA_ARGS__) 184 | 185 | 186 | //--------------------CPP MACRO STREAM STYLE FORMAT --------------------------- 187 | 188 | #define LOG_TRACE(channel_id, category, identify, log) LOG_STREAM_DEFAULT_LOGGER_WITH_PREFIX(channel_id, FNLog::PRIORITY_TRACE, category, identify) << log 189 | #define LOG_DEBUG(channel_id, category, identify, log) LOG_STREAM_DEFAULT_LOGGER_WITH_PREFIX(channel_id, FNLog::PRIORITY_DEBUG, category, identify) << log 190 | #define LOG_INFO(channel_id, category, identify, log) LOG_STREAM_DEFAULT_LOGGER_WITH_PREFIX(channel_id, FNLog::PRIORITY_INFO, category, identify) << log 191 | #define LOG_WARN(channel_id, category, identify, log) LOG_STREAM_DEFAULT_LOGGER_WITH_PREFIX(channel_id, FNLog::PRIORITY_WARN, category, identify) << log 192 | #define LOG_ERROR(channel_id, category, identify, log) LOG_STREAM_DEFAULT_LOGGER_WITH_PREFIX(channel_id, FNLog::PRIORITY_ERROR, category, identify) << log 193 | #define LOG_ALARM(channel_id, category, identify, log) LOG_STREAM_DEFAULT_LOGGER_WITH_PREFIX(channel_id, FNLog::PRIORITY_ALARM, category, identify) << log 194 | #define LOG_FATAL(channel_id, category, identify, log) LOG_STREAM_DEFAULT_LOGGER_WITH_PREFIX(channel_id, FNLog::PRIORITY_FATAL, category, identify) << log 195 | 196 | #define LOGT(log) LOG_TRACE(0, 0, 0, log) 197 | #define LOGD(log) LOG_DEBUG(0, 0, 0, log) 198 | #define LOGI(log) LOG_INFO(0, 0, 0, log) 199 | #define LOGW(log) LOG_WARN(0, 0, 0, log) 200 | #define LOGE(log) LOG_ERROR(0, 0, 0, log) 201 | #define LOGA(log) LOG_ALARM(0, 0, 0, log) 202 | #define LOGF(log) LOG_FATAL(0, 0, 0, log) 203 | 204 | 205 | //--------------------C STYLE FORMAT --------------------------- 206 | 207 | // function format warn: void(int x1, int x2, const char *args, ...) __attribute__((format(printf, 3, 4))); 208 | #define LOG_FORMAT(channel_id, priority, category, identify, prefix, logformat, ...) \ 209 | do{ \ 210 | if (FNLog::BlockInput(FNLog::GetDefaultLogger(), channel_id, priority, category, identify)) \ 211 | { \ 212 | break; \ 213 | } \ 214 | FNLog::LogStream __log_stream(LOG_STREAM_ORIGIN(FNLog::GetDefaultLogger(), channel_id, priority, category, identify, prefix));\ 215 | if (__log_stream.log_data_)\ 216 | {\ 217 | int __log_len = snprintf(__log_stream.log_data_ ->content_ + __log_stream.log_data_ ->content_len_, FNLog::LogData::LOG_SIZE - __log_stream.log_data_->content_len_, logformat, ##__VA_ARGS__); \ 218 | if (__log_len < 0) __log_len = 0; \ 219 | if (__log_len >= FNLog::LogData::LOG_SIZE - __log_stream.log_data_->content_len_) __log_len = FNLog::LogData::LOG_SIZE - __log_stream.log_data_->content_len_ -1; \ 220 | __log_stream.log_data_ ->content_len_ += __log_len; \ 221 | }\ 222 | } while (0) 223 | 224 | 225 | #define LOGFMT_TRACE(channel_id, category, identify, fmt, ...) LOG_FORMAT(channel_id, FNLog::PRIORITY_TRACE, category, identify, FNLog::LOG_PREFIX_DEFAULT, fmt, ##__VA_ARGS__) 226 | #define LOGFMT_DEBUG(channel_id, category, identify, fmt, ...) LOG_FORMAT(channel_id, FNLog::PRIORITY_DEBUG, category, identify, FNLog::LOG_PREFIX_DEFAULT, fmt, ##__VA_ARGS__) 227 | #define LOGFMT_INFO( channel_id, category, identify, fmt, ...) LOG_FORMAT(channel_id, FNLog::PRIORITY_INFO, category, identify, FNLog::LOG_PREFIX_DEFAULT, fmt, ##__VA_ARGS__) 228 | #define LOGFMT_WARN( channel_id, category, identify, fmt, ...) LOG_FORMAT(channel_id, FNLog::PRIORITY_WARN, category, identify, FNLog::LOG_PREFIX_DEFAULT, fmt, ##__VA_ARGS__) 229 | #define LOGFMT_ERROR(channel_id, category, identify, fmt, ...) LOG_FORMAT(channel_id, FNLog::PRIORITY_ERROR, category, identify, FNLog::LOG_PREFIX_DEFAULT, fmt, ##__VA_ARGS__) 230 | #define LOGFMT_ALARM(channel_id, category, identify, fmt, ...) LOG_FORMAT(channel_id, FNLog::PRIORITY_ALARM, category, identify, FNLog::LOG_PREFIX_DEFAULT, fmt, ##__VA_ARGS__) 231 | #define LOGFMT_FATAL(channel_id, category, identify, fmt, ...) LOG_FORMAT(channel_id, FNLog::PRIORITY_FATAL, category, identify, FNLog::LOG_PREFIX_DEFAULT, fmt, ##__VA_ARGS__) 232 | #define LOGFMTT(fmt, ...) LOGFMT_TRACE(0, 0, 0, fmt, ##__VA_ARGS__) 233 | #define LOGFMTD(fmt, ...) LOGFMT_DEBUG(0, 0, 0, fmt, ##__VA_ARGS__) 234 | #define LOGFMTI(fmt, ...) LOGFMT_INFO( 0, 0, 0, fmt, ##__VA_ARGS__) 235 | #define LOGFMTW(fmt, ...) LOGFMT_WARN( 0, 0, 0, fmt, ##__VA_ARGS__) 236 | #define LOGFMTE(fmt, ...) LOGFMT_ERROR(0, 0, 0, fmt, ##__VA_ARGS__) 237 | #define LOGFMTA(fmt, ...) LOGFMT_ALARM(0, 0, 0, fmt, ##__VA_ARGS__) 238 | #define LOGFMTF(fmt, ...) LOGFMT_FATAL(0, 0, 0, fmt, ##__VA_ARGS__) 239 | 240 | 241 | #endif 242 | -------------------------------------------------------------------------------- /src/include/fn_out_empty_device.h: -------------------------------------------------------------------------------- 1 | 2 | /* 3 | * Copyright (C) 2019 YaweiZhang . 4 | * All rights reserved 5 | * This file is part of the fn-log, used MIT License. 6 | */ 7 | 8 | 9 | #pragma once 10 | #ifndef _FN_LOG_OUT_EMPTY_DEVICE_H_ 11 | #define _FN_LOG_OUT_EMPTY_DEVICE_H_ 12 | 13 | #include "fn_data.h" 14 | #include "fn_fmt.h" 15 | 16 | namespace FNLog 17 | { 18 | 19 | inline void EnterProcOutEmptyDevice(Logger& logger, int channel_id, int device_id, LogData& log) 20 | { 21 | Channel& channel = logger.shm_->channels_[channel_id]; 22 | AtomicIncDeviceLog(channel, device_id, DEVICE_LOG_TOTAL_WRITE_LINE, 1); 23 | AtomicIncDeviceLog(channel, device_id, DEVICE_LOG_TOTAL_WRITE_BYTE, log.content_len_); 24 | AtomicIncDeviceLog(channel, device_id, DEVICE_LOG_PRIORITY + log.priority_, log.content_len_); 25 | } 26 | 27 | } 28 | 29 | 30 | #endif 31 | -------------------------------------------------------------------------------- /src/include/fn_out_file_device.h: -------------------------------------------------------------------------------- 1 | 2 | /* 3 | * Copyright (C) 2019 YaweiZhang . 4 | * All rights reserved 5 | * This file is part of the fn-log, used MIT License. 6 | */ 7 | 8 | #pragma once 9 | #ifndef _FN_LOG_OUT_FILE_DEVICE_H_ 10 | #define _FN_LOG_OUT_FILE_DEVICE_H_ 11 | 12 | #include "fn_data.h" 13 | 14 | namespace FNLog 15 | { 16 | 17 | //support 18 | inline std::string PreFmtName(const std::string& fmt_name) 19 | { 20 | if (fmt_name.empty()) 21 | { 22 | return fmt_name; 23 | } 24 | std::string name = fmt_name; 25 | size_t pos = 0; 26 | do 27 | { 28 | bool has_error = false; 29 | pos = name.find('%', pos); 30 | if (pos == std::string::npos) 31 | { 32 | break; 33 | } 34 | if (name.length() - pos < 2)//min(escape) 35 | { 36 | break; 37 | } 38 | 39 | switch (name[pos + 1]) 40 | { 41 | case 'F': 42 | if (true) 43 | { 44 | name.replace(pos, 2, "$YEAR-$MON-$DAY"); 45 | break; 46 | } 47 | has_error = true; 48 | break; 49 | default: 50 | has_error = true; 51 | break; 52 | } 53 | if (has_error) 54 | { 55 | pos++; 56 | } 57 | } while (true); 58 | return name; 59 | } 60 | // 61 | inline std::string FmtName(const std::string& fmt_name, int channel_id, int device_id, const struct tm& t) 62 | { 63 | (void)device_id; 64 | (void)channel_id; 65 | if (fmt_name.empty()) 66 | { 67 | return fmt_name; 68 | } 69 | 70 | std::string name = PreFmtName(fmt_name); 71 | 72 | size_t pos = 0; 73 | do 74 | { 75 | bool has_error = false; 76 | pos = name.find('$', pos); 77 | if (pos == std::string::npos) 78 | { 79 | break; 80 | } 81 | if (name.length() - pos <2)//min(escape) 82 | { 83 | break; 84 | } 85 | 86 | switch (name[pos + 1]) 87 | { 88 | case 'P': 89 | if (name.substr(pos + 2, 4) == "NAME") 90 | { 91 | name.replace(pos, 6, FileHandler::process_name()); 92 | break; 93 | } 94 | if (name.substr(pos + 2, 2) == "ID") 95 | { 96 | name.replace(pos, 4, FileHandler::process_id()); 97 | break; 98 | } 99 | has_error = true; 100 | break; 101 | case 'Y': 102 | if (name.substr(pos + 2, 3) == "EAR") 103 | { 104 | char buff[30] = { 0 }; 105 | snprintf(buff, 30, "%04d", t.tm_year + 1900); 106 | name.replace(pos, 5, buff); 107 | break; 108 | } 109 | has_error = true; 110 | break; 111 | case 'M': 112 | if (name.substr(pos + 2, 2) == "ON") 113 | { 114 | char buff[30] = { 0 }; 115 | snprintf(buff, 30, "%02d", t.tm_mon + 1); 116 | name.replace(pos, 4, buff); 117 | break; 118 | } 119 | if (name.substr(pos + 2, 2) == "IN") 120 | { 121 | char buff[30] = { 0 }; 122 | snprintf(buff, 30, "%02d", t.tm_min); 123 | name.replace(pos, 4, buff); 124 | break; 125 | } 126 | has_error = true; 127 | break; 128 | case 'D': 129 | if (name.substr(pos + 2, 2) == "AY") 130 | { 131 | char buff[30] = { 0 }; 132 | snprintf(buff, 30, "%02d", t.tm_mday); 133 | name.replace(pos, 4, buff); 134 | break; 135 | } 136 | has_error = true; 137 | break; 138 | case 'H': 139 | if (name.substr(pos + 2, 3) == "OUR") 140 | { 141 | char buff[30] = { 0 }; 142 | snprintf(buff, 30, "%02d", t.tm_hour); 143 | name.replace(pos, 5, buff); 144 | break; 145 | } 146 | has_error = true; 147 | break; 148 | case 'S': 149 | if (name.substr(pos + 2, 2) == "EC") 150 | { 151 | char buff[30] = { 0 }; 152 | snprintf(buff, 30, "%02d", t.tm_sec); 153 | name.replace(pos, 4, buff); 154 | break; 155 | } 156 | has_error = true; 157 | break; 158 | default: 159 | has_error = true; 160 | break; 161 | } 162 | 163 | if (has_error) 164 | { 165 | pos++; 166 | } 167 | } while (true); 168 | return name; 169 | } 170 | 171 | 172 | //[$PNAME $PID $YEAR $MON $DAY $HOUR $MIN $SEC] 173 | inline std::string MakeFileName(const std::string& fmt_name, int channel_id, int device_id, const struct tm& t) 174 | { 175 | std::string name = fmt_name; 176 | if (name.empty()) 177 | { 178 | name = "$PNAME_$YEAR$MON$DAY_$PID."; 179 | name += std::to_string(channel_id); 180 | name += std::to_string(device_id); 181 | } 182 | name += ".log"; 183 | return FmtName(name, channel_id, device_id, t); 184 | } 185 | //[$PNAME $PID $YEAR $MON $DAY $HOUR $MIN $SEC] 186 | inline std::string MakePathName(const std::string& fmt_name, int channel_id, int device_id, const struct tm& t) 187 | { 188 | return FmtName(fmt_name, channel_id, device_id, t); 189 | } 190 | 191 | 192 | inline void OpenFileDevice(Logger & logger, Channel & channel, Device & device, FileHandler & writer, LogData & log) 193 | { 194 | (void)logger; 195 | 196 | bool close_file = false; 197 | bool limit_out = false; 198 | 199 | 200 | 201 | do 202 | { 203 | //rollback only limit size && rollback > 0 204 | if (AtomicLoadC(device, DEVICE_CFG_FILE_LIMIT_SIZE) > 0 && AtomicLoadC(device, DEVICE_CFG_FILE_ROLLBACK) > 0 205 | && AtomicLoadDeviceLog(channel, device.device_id_, DEVICE_LOG_CUR_FILE_SIZE) + log.content_len_ > AtomicLoadC(device, DEVICE_CFG_FILE_LIMIT_SIZE)) 206 | { 207 | close_file = true; 208 | limit_out = true; 209 | break; 210 | } 211 | 212 | //daily rolling 213 | if (AtomicLoadC(device, DEVICE_CFG_FILE_ROLLDAILY)) 214 | { 215 | if (log.timestamp_ < AtomicLoadDeviceLog(channel, device.device_id_, DEVICE_LOG_CUR_FILE_CREATE_DAY) 216 | || log.timestamp_ >= AtomicLoadDeviceLog(channel, device.device_id_, DEVICE_LOG_CUR_FILE_CREATE_DAY) + 24 * 3600) 217 | { 218 | close_file = true; 219 | } 220 | break; 221 | } 222 | 223 | //hourly rolling 224 | if (AtomicLoadC(device, DEVICE_CFG_FILE_ROLLHOURLY)) 225 | { 226 | if (log.timestamp_ < AtomicLoadDeviceLog(channel, device.device_id_, DEVICE_LOG_CUR_FILE_CREATE_HOUR) 227 | || log.timestamp_ >= AtomicLoadDeviceLog(channel, device.device_id_, DEVICE_LOG_CUR_FILE_CREATE_HOUR) + 3600) 228 | { 229 | close_file = true; 230 | } 231 | break; 232 | } 233 | 234 | } while (false); 235 | 236 | 237 | if (close_file) 238 | { 239 | AtomicStoreDeviceLog(channel, device.device_id_, DEVICE_LOG_CUR_FILE_SIZE, 0); 240 | if (writer.is_open()) 241 | { 242 | writer.close(); 243 | } 244 | } 245 | 246 | if (writer.is_open()) 247 | { 248 | return; 249 | } 250 | 251 | long long create_day = 0; 252 | long long create_hour = 0; 253 | tm t = FileHandler::time_to_tm(log.timestamp_); 254 | if (true) //process day time 255 | { 256 | tm day = t; 257 | day.tm_min = 0; 258 | day.tm_sec = 0; 259 | create_hour = mktime(&day); 260 | day.tm_hour = 0; 261 | create_day = mktime(&day); 262 | } 263 | 264 | std::string name = MakeFileName(device.out_file_, channel.channel_id_, device.device_id_, t); 265 | std::string path = MakePathName(device.out_path_, channel.channel_id_, device.device_id_, t); 266 | if (!path.empty()) 267 | { 268 | std::for_each(path.begin(), path.end(), [](char& ch) {if (ch == '\\') { ch = '/'; } }); 269 | if (path.back() != '/') { path.push_back('/'); } 270 | 271 | if (!FileHandler::is_dir(path)) 272 | { 273 | FileHandler::create_dir(path); 274 | } 275 | } 276 | 277 | path += name; 278 | 279 | if (path.length() >= Device::MAX_PATH_LEN + Device::MAX_LOGGER_NAME_LEN) 280 | { 281 | AtomicStoreDeviceLog(channel, device.device_id_, DEVICE_LOG_LAST_TRY_CREATE_ERROR, 1); 282 | AtomicStoreDeviceLog(channel, device.device_id_, DEVICE_LOG_LAST_TRY_CREATE_TIMESTAMP, log.timestamp_); 283 | return; 284 | } 285 | 286 | if (AtomicLoadC(device, DEVICE_CFG_FILE_ROLLBACK) > 0 || AtomicLoadC(device, DEVICE_CFG_FILE_LIMIT_SIZE) > 0) 287 | { 288 | bool stuff_up = (bool)AtomicLoadC(device, DEVICE_CFG_FILE_STUFF_UP); 289 | if (!stuff_up || limit_out) 290 | { 291 | //when no rollback but has limit size. need try rollback once. 292 | long long limit_roll = device.config_fields_[DEVICE_CFG_FILE_ROLLBACK]; 293 | limit_roll = limit_roll > 0 ? limit_roll : 1; 294 | FileHandler::rollback(path, 1, (int)limit_roll); 295 | } 296 | } 297 | 298 | struct stat file_stat; 299 | long writed_byte = writer.open(path.c_str(), "ab", file_stat); 300 | if (!writer.is_open()) 301 | { 302 | AtomicStoreDeviceLog(channel, device.device_id_, DEVICE_LOG_LAST_TRY_CREATE_ERROR, 2); 303 | AtomicStoreDeviceLog(channel, device.device_id_, DEVICE_LOG_LAST_TRY_CREATE_TIMESTAMP, log.timestamp_); 304 | return; 305 | } 306 | 307 | AtomicIncDeviceLog(channel, device.device_id_, DEVICE_LOG_LAST_TRY_CREATE_CNT, 1); 308 | 309 | AtomicStoreDeviceLog(channel, device.device_id_, DEVICE_LOG_LAST_TRY_CREATE_ERROR, 0); 310 | AtomicStoreDeviceLog(channel, device.device_id_, DEVICE_LOG_LAST_TRY_CREATE_TIMESTAMP, 0); 311 | AtomicStoreDeviceLog(channel, device.device_id_, DEVICE_LOG_CUR_FILE_CREATE_TIMESTAMP, log.timestamp_); 312 | AtomicStoreDeviceLog(channel, device.device_id_, DEVICE_LOG_CUR_FILE_CREATE_DAY, create_day); 313 | AtomicStoreDeviceLog(channel, device.device_id_, DEVICE_LOG_CUR_FILE_CREATE_HOUR, create_hour); 314 | AtomicStoreDeviceLog(channel, device.device_id_, DEVICE_LOG_CUR_FILE_SIZE, writed_byte); 315 | } 316 | 317 | 318 | 319 | inline void EnterProcOutFileDevice(Logger& logger, int channel_id, int device_id, LogData& log) 320 | { 321 | Channel& channel = logger.shm_->channels_[channel_id]; 322 | Device& device = channel.devices_[device_id]; 323 | FileHandler& writer = logger.file_handles_[channel_id * Channel::MAX_DEVICE_SIZE + device_id]; 324 | 325 | if (!writer.is_open() && AtomicLoadDeviceLog(channel, device_id, DEVICE_LOG_LAST_TRY_CREATE_TIMESTAMP) + 5 > log.timestamp_) 326 | { 327 | return; 328 | } 329 | OpenFileDevice(logger, channel, device, writer, log); 330 | if (!writer.is_open()) 331 | { 332 | return; 333 | } 334 | writer.write(log.content_, log.content_len_); 335 | AtomicIncDeviceLog(channel, device_id, DEVICE_LOG_TOTAL_WRITE_LINE, 1); 336 | AtomicIncDeviceLog(channel, device_id, DEVICE_LOG_TOTAL_WRITE_BYTE, log.content_len_); 337 | AtomicIncDeviceLog(channel, device_id, DEVICE_LOG_CUR_FILE_SIZE, log.content_len_); 338 | AtomicIncDeviceLog(channel, device_id, DEVICE_LOG_PRIORITY + log.priority_, log.content_len_); 339 | } 340 | 341 | 342 | } 343 | 344 | 345 | #endif 346 | -------------------------------------------------------------------------------- /src/include/fn_out_screen_device.h: -------------------------------------------------------------------------------- 1 | 2 | /* 3 | * Copyright (C) 2019 YaweiZhang . 4 | * All rights reserved 5 | * This file is part of the fn-log, used MIT License. 6 | */ 7 | 8 | 9 | #pragma once 10 | #ifndef _FN_LOG_OUT_SCREEN_DEVICE_H_ 11 | #define _FN_LOG_OUT_SCREEN_DEVICE_H_ 12 | 13 | #include "fn_data.h" 14 | #include "fn_fmt.h" 15 | 16 | namespace FNLog 17 | { 18 | 19 | inline void EnterProcOutScreenDevice(Logger& logger, int channel_id, int device_id, LogData& log) 20 | { 21 | Logger::ScreenLockGuard l(logger.screen_lock_); 22 | Channel& channel = logger.shm_->channels_[channel_id]; 23 | 24 | AtomicIncDeviceLog(channel, device_id, DEVICE_LOG_TOTAL_WRITE_LINE, 1); 25 | AtomicIncDeviceLog(channel, device_id, DEVICE_LOG_TOTAL_WRITE_BYTE, log.content_len_); 26 | AtomicIncDeviceLog(channel, device_id, DEVICE_LOG_PRIORITY + log.priority_, log.content_len_); 27 | 28 | int priority = log.priority_; 29 | if (log.priority_ < PRIORITY_INFO) 30 | { 31 | printf("%s", log.content_); 32 | return; 33 | } 34 | if (priority >= PRIORITY_MAX) 35 | { 36 | priority = PRIORITY_ALARM; 37 | } 38 | #ifndef WIN32 39 | printf("%s%s\e[0m", PRIORITY_RENDER[priority].scolor_, log.content_); 40 | #else 41 | 42 | HANDLE sc_handle = ::GetStdHandle(STD_OUTPUT_HANDLE); 43 | if (sc_handle == INVALID_HANDLE_VALUE) 44 | { 45 | printf("%s", log.content_); 46 | return; 47 | } 48 | CONSOLE_SCREEN_BUFFER_INFO old_info; 49 | if (!GetConsoleScreenBufferInfo(sc_handle, &old_info)) 50 | { 51 | printf("%s", log.content_); 52 | return; 53 | } 54 | else 55 | { 56 | SetConsoleTextAttribute(sc_handle, (old_info.wAttributes& ~7u) |PRIORITY_RENDER[priority].color_); 57 | printf("%s", log.content_); 58 | SetConsoleTextAttribute(sc_handle, old_info.wAttributes); 59 | } 60 | #endif 61 | } 62 | 63 | 64 | 65 | } 66 | 67 | 68 | #endif 69 | -------------------------------------------------------------------------------- /src/include/fn_out_udp_device.h: -------------------------------------------------------------------------------- 1 | 2 | /* 3 | * Copyright (C) 2019 YaweiZhang . 4 | * All rights reserved 5 | * This file is part of the fn-log, used MIT License. 6 | */ 7 | 8 | 9 | #pragma once 10 | #ifndef _FN_LOG_OUT_UDP_DEVICE_H_ 11 | #define _FN_LOG_OUT_UDP_DEVICE_H_ 12 | 13 | #include "fn_data.h" 14 | #include "fn_fmt.h" 15 | 16 | namespace FNLog 17 | { 18 | 19 | inline void EnterProcOutUDPDevice(Logger& logger, int channel_id, int device_id, LogData& log) 20 | { 21 | auto& udp = logger.udp_handles_[channel_id * Channel::MAX_DEVICE_SIZE + device_id]; 22 | Channel& channel = logger.shm_->channels_[channel_id]; 23 | Device& device = logger.shm_->channels_[channel_id].devices_[device_id]; 24 | 25 | if (!udp.is_open()) 26 | { 27 | udp.open(); 28 | } 29 | if (!udp.is_open()) 30 | { 31 | AtomicIncDeviceLog(channel, device_id, DEVICE_LOG_TOTAL_LOSE_LINE, 1); 32 | return; 33 | } 34 | 35 | long long ip = AtomicLoadC(device, DEVICE_CFG_UDP_IP); 36 | long long port = AtomicLoadC(device, DEVICE_CFG_UDP_PORT); 37 | int ret = udp.write((unsigned long)ip, (unsigned short)port, log.content_, log.content_len_); 38 | if (ret <= 0) 39 | { 40 | AtomicIncDeviceLog(channel, device_id, DEVICE_LOG_TOTAL_LOSE_LINE, 1); 41 | } 42 | AtomicIncDeviceLog(channel, device_id, DEVICE_LOG_TOTAL_WRITE_LINE, 1); 43 | AtomicIncDeviceLog(channel, device_id, DEVICE_LOG_TOTAL_WRITE_BYTE, log.content_len_); 44 | AtomicIncDeviceLog(channel, device_id, DEVICE_LOG_PRIORITY + log.priority_, log.content_len_); 45 | } 46 | } 47 | 48 | 49 | #endif 50 | -------------------------------------------------------------------------------- /src/include/fn_out_virtual_device.h: -------------------------------------------------------------------------------- 1 | 2 | /* 3 | * Copyright (C) 2019 YaweiZhang . 4 | * All rights reserved 5 | * This file is part of the fn-log, used MIT License. 6 | */ 7 | 8 | 9 | #pragma once 10 | #ifndef _FN_LOG_OUT_VIRTUAL_DEVICE_H_ 11 | #define _FN_LOG_OUT_VIRTUAL_DEVICE_H_ 12 | 13 | #include "fn_data.h" 14 | #include "fn_fmt.h" 15 | 16 | namespace FNLog 17 | { 18 | using VirtualDevicePtr = void (*)(const LogData& log); 19 | 20 | inline VirtualDevicePtr& RefVirtualDevice() 21 | { 22 | static VirtualDevicePtr g_virtual_device_ptr = NULL; 23 | return g_virtual_device_ptr; 24 | } 25 | inline void SetVirtualDevice(VirtualDevicePtr vdp) 26 | { 27 | RefVirtualDevice() = vdp; 28 | } 29 | 30 | //the virtual device like log hook; this virtual device call at the log create time(thread) not at log write thread . 31 | //can used translate log 32 | inline void EnterProcOutVirtualDevice(Logger& logger, int channel_id, int device_id, LogData& log) 33 | { 34 | if (RefVirtualDevice()) 35 | { 36 | Channel& channel = logger.shm_->channels_[channel_id]; 37 | Device::ConfigFields& fields = channel.devices_[device_id].config_fields_; 38 | long long field_begin_category = fields[FNLog::DEVICE_CFG_CATEGORY]; 39 | long long field_category_count = fields[FNLog::DEVICE_CFG_CATEGORY_EXTEND]; 40 | unsigned long long field_category_mask = (unsigned long long)fields[FNLog::DEVICE_CFG_CATEGORY_MASK]; 41 | long long field_begin_identify = fields[FNLog::DEVICE_CFG_IDENTIFY]; 42 | long long field_identify_count = fields[FNLog::DEVICE_CFG_IDENTIFY_EXTEND]; 43 | unsigned long long field_identify_mask = (unsigned long long)fields[FNLog::DEVICE_CFG_IDENTIFY_MASK]; 44 | 45 | if (field_category_count > 0 && (log.category_ < field_begin_category || log.category_ >= field_begin_category + field_category_count)) 46 | { 47 | return; 48 | } 49 | 50 | if (field_identify_count > 0 && (log.identify_ < field_begin_identify || log.identify_ >= field_begin_identify + field_identify_count)) 51 | { 52 | return; 53 | } 54 | if (field_category_mask && (field_category_mask & ((1ULL) << (unsigned int)log.category_)) == 0) 55 | { 56 | return; 57 | } 58 | if (field_identify_mask && (field_identify_mask & ((1ULL) << (unsigned int)log.identify_)) == 0) 59 | { 60 | return; 61 | } 62 | 63 | int content_len_ = FN_MIN(log.content_len_, LogData::LOG_SIZE - 1); 64 | log.content_[content_len_] = '\0'; //virtual device hook maybe direct used content like c-string 65 | 66 | AtomicIncDeviceLog(channel, device_id, DEVICE_LOG_TOTAL_WRITE_LINE, 1); 67 | AtomicIncDeviceLog(channel, device_id, DEVICE_LOG_TOTAL_WRITE_BYTE, log.content_len_); 68 | AtomicIncDeviceLog(channel, device_id, DEVICE_LOG_PRIORITY + log.priority_, log.content_len_); 69 | (*RefVirtualDevice())(log); 70 | } 71 | } 72 | } 73 | 74 | 75 | #endif 76 | -------------------------------------------------------------------------------- /tests/benchmark_device_30.cpp: -------------------------------------------------------------------------------- 1 | 2 | 3 | #define FN_LOG_MAX_DEVICE_SIZE 36 4 | #define FN_LOG_MAX_CHANNEL_SIZE 3 5 | #define FN_LOG_MAX_LOG_SIZE 1000 6 | #define FN_LOG_MAX_LOG_QUEUE_SIZE 100000 7 | 8 | #include "fn_log.h" 9 | 10 | 11 | static const std::string example_config_text = 12 | R"----( 13 | - channel: 0 14 | priority: trace 15 | -device: 0 16 | disable: false 17 | out_type: screen 18 | priority: trace 19 | 20 | - channel: 1 21 | -device:0 22 | disable: false 23 | out_type: empty 24 | priority: debug 25 | category: 20 26 | category_extend: 1 27 | idenfity: 20 28 | idenfity_extend: 1 29 | 30 | - channel: 2 31 | -device:0 32 | disable: false 33 | out_type: empty 34 | priority: error 35 | category: 0 36 | category_extend: 1 37 | idenfity: 0 38 | idenfity_extend: 1 39 | -device:1 40 | disable: false 41 | out_type: empty 42 | priority: info 43 | category: 1 44 | category_extend: 1 45 | idenfity: 1 46 | idenfity_extend: 1 47 | -device:2 48 | disable: false 49 | out_type: empty 50 | category: 2 51 | category_extend: 1 52 | idenfity: 2 53 | idenfity_extend: 1 54 | -device:3 55 | disable: false 56 | out_type: empty 57 | category: 3 58 | category_extend: 1 59 | idenfity: 3 60 | idenfity_extend: 1 61 | -device:4 62 | category: 4 63 | category_extend: 1 64 | idenfity: 4 65 | idenfity_extend: 1 66 | -device:5 67 | disable: false 68 | out_type: empty 69 | category: 5 70 | category_extend: 1 71 | idenfity: 5 72 | idenfity_extend: 1 73 | -device:6 74 | disable: false 75 | out_type: empty 76 | priority: error 77 | category: 6 78 | category_extend: 1 79 | idenfity: 6 80 | idenfity_extend: 1 81 | -device:7 82 | disable: false 83 | out_type: empty 84 | category: 7 85 | category_extend: 1 86 | idenfity: 7 87 | idenfity_extend: 1 88 | -device:8 89 | disable: false 90 | out_type: empty 91 | priority: trace 92 | category: 8 93 | category_extend: 1 94 | idenfity: 8 95 | idenfity_extend: 1 96 | -device:9 97 | disable: false 98 | out_type: empty 99 | category: 9 100 | category_extend: 1 101 | idenfity: 9 102 | idenfity_extend: 1 103 | -device:10 104 | disable: false 105 | out_type: empty 106 | category: 10 107 | category_extend: 1 108 | idenfity: 10 109 | idenfity_extend: 1 110 | -device:11 111 | disable: false 112 | out_type: empty 113 | category: 11 114 | category_extend: 1 115 | idenfity: 11 116 | idenfity_extend: 1 117 | -device:12 118 | disable: false 119 | out_type: empty 120 | category: 12 121 | category_extend: 1 122 | idenfity: 12 123 | idenfity_extend: 1 124 | -device:13 125 | disable: false 126 | out_type: empty 127 | category: 13 128 | category_extend: 1 129 | idenfity: 13 130 | idenfity_extend: 1 131 | -device:14 132 | disable: false 133 | out_type: empty 134 | category: 14 135 | category_extend: 1 136 | idenfity: 14 137 | idenfity_extend: 1 138 | -device:15 139 | disable: false 140 | out_type: empty 141 | category: 15 142 | category_extend: 1 143 | idenfity: 15 144 | idenfity_extend: 1 145 | -device:16 146 | disable: false 147 | out_type: empty 148 | category: 16 149 | category_extend: 1 150 | idenfity: 16 151 | idenfity_extend: 1 152 | -device:17 153 | disable: false 154 | out_type: empty 155 | category: 17 156 | category_extend: 1 157 | idenfity: 17 158 | idenfity_extend: 1 159 | -device:18 160 | disable: false 161 | out_type: empty 162 | category: 18 163 | category_extend: 1 164 | idenfity: 18 165 | idenfity_extend: 1 166 | -device:19 167 | disable: false 168 | out_type: empty 169 | category: 19 170 | category_extend: 1 171 | idenfity: 19 172 | idenfity_extend: 1 173 | -device:20 174 | disable: false 175 | out_type: empty 176 | category: 20 177 | category_extend: 1 178 | idenfity: 20 179 | idenfity_extend: 1 180 | -device:21 181 | disable: false 182 | out_type: empty 183 | category: 21 184 | category_extend: 1 185 | idenfity: 21 186 | idenfity_extend: 1 187 | -device:22 188 | disable: false 189 | out_type: empty 190 | category: 22 191 | category_extend: 1 192 | idenfity: 22 193 | idenfity_extend: 1 194 | -device:23 195 | disable: false 196 | out_type: empty 197 | category: 23 198 | category_extend: 1 199 | idenfity: 23 200 | idenfity_extend: 1 201 | -device:24 202 | disable: false 203 | out_type: empty 204 | category: 24 205 | category_extend: 1 206 | idenfity: 24 207 | idenfity_extend: 1 208 | -device:25 209 | disable: false 210 | out_type: empty 211 | category: 25 212 | category_extend: 1 213 | idenfity: 25 214 | idenfity_extend: 1 215 | -device:26 216 | disable: false 217 | out_type: empty 218 | category: 26 219 | category_extend: 1 220 | idenfity: 26 221 | idenfity_extend: 1 222 | -device:27 223 | disable: false 224 | out_type: empty 225 | category: 27 226 | category_extend: 1 227 | idenfity: 27 228 | idenfity_extend: 1 229 | -device:28 230 | disable: false 231 | out_type: empty 232 | category: 28 233 | category_extend: 1 234 | idenfity: 28 235 | idenfity_extend: 1 236 | -device:29 237 | disable: false 238 | out_type: empty 239 | category: 29 240 | category_extend: 1 241 | idenfity: 29 242 | idenfity_extend: 1 243 | -device:30 244 | disable: false 245 | out_type: empty 246 | category: 30 247 | category_extend: 1 248 | idenfity: 30 249 | idenfity_extend: 1 250 | -device:31 251 | disable: false 252 | out_type: empty 253 | category: 31 254 | category_extend: 1 255 | idenfity: 31 256 | idenfity_extend: 1 257 | -device:32 258 | disable: false 259 | out_type: empty 260 | category: 32 261 | category_extend: 1 262 | idenfity: 32 263 | idenfity_extend: 1 264 | -device:33 265 | disable: false 266 | out_type: empty 267 | category: 33 268 | category_extend: 1 269 | idenfity: 33 270 | idenfity_extend: 1 271 | -device:34 272 | disable: false 273 | out_type: empty 274 | category: 34 275 | category_extend: 1 276 | idenfity: 34 277 | idenfity_extend: 1 278 | -device:35 279 | disable: false 280 | out_type: empty 281 | category: 35 282 | category_extend: 1 283 | idenfity: 35 284 | idenfity_extend: 1 285 | 286 | 287 | 288 | 289 | 290 | )----"; 291 | 292 | std::string ChannelDesc(int channel_type) 293 | { 294 | switch (channel_type) 295 | { 296 | case FNLog::CHANNEL_ASYNC: 297 | return "async thread write"; 298 | case FNLog::CHANNEL_SYNC: 299 | return "sync write"; 300 | } 301 | return "invalid channel"; 302 | } 303 | 304 | #define Now() std::chrono::duration(std::chrono::system_clock::now().time_since_epoch()).count() 305 | 306 | int main(int argc, char *argv[]) 307 | { 308 | int ret = FNLog::FastStartDefaultLogger(example_config_text); 309 | if (ret != 0) 310 | { 311 | return ret; 312 | } 313 | 314 | 315 | FNLog::Logger& logger = FNLog::GetDefaultLogger(); 316 | 317 | unsigned int total_count = 0; 318 | for (int channel_id = 1; channel_id < logger.shm_->channel_size_; channel_id++) 319 | { 320 | total_count = 0; 321 | FNLog::Channel& channel = logger.shm_->channels_[channel_id]; 322 | do 323 | { 324 | int filter = rand() % 64; 325 | LOG_STREAM_DEFAULT_LOGGER(channel_id, FNLog::PRIORITY_DEBUG, filter, filter, FNLog::LOG_PREFIX_NULL) 326 | .write_buffer("rrrrrrrrrrrrrrrrrrrradfads33333333333333rrd", 327 | sizeof("rrrrrrrrrrrrrrrrrrrradfads33333333333333rrd") - 1); 328 | 329 | if (total_count %5000000 == 0) 330 | { 331 | static double last = Now(); 332 | double now = Now(); 333 | if (total_count > 0) 334 | { 335 | LogInfo() << "channel:<" << (long long)channel_id << "> " 336 | << ChannelDesc(channel.channel_type_) << " emtpy write :<" 337 | << channel.device_size_ << "> test " << 5000000 / (now - last) << " line/sec. "; 338 | last = now; 339 | break; 340 | } 341 | } 342 | } while (++total_count); 343 | } 344 | 345 | 346 | for (int channel_id = 1; channel_id < logger.shm_->channel_size_; channel_id++) 347 | { 348 | total_count = 0; 349 | FNLog::Channel& channel = logger.shm_->channels_[channel_id]; 350 | do 351 | { 352 | int filter = 20; 353 | LOG_STREAM_DEFAULT_LOGGER(channel_id, FNLog::PRIORITY_DEBUG, filter, filter, FNLog::LOG_PREFIX_NULL) 354 | .write_buffer("rrrrrrrrrrrrrrrrrrrradfads33333333333333rrd", 355 | sizeof("rrrrrrrrrrrrrrrrrrrradfads33333333333333rrd") - 1); 356 | 357 | if (total_count % 5000000 == 0) 358 | { 359 | static double last = Now(); 360 | double now = Now(); 361 | if (total_count > 0) 362 | { 363 | LogInfo() << "channel:<" << (long long)channel_id << "> " 364 | << ChannelDesc(channel.channel_type_) << " emtpy write :<" 365 | << channel.device_size_ << "> test " << 5000000 / (now - last) << " line/sec. "; 366 | last = now; 367 | break; 368 | } 369 | } 370 | } while (++total_count); 371 | } 372 | 373 | for (int channel_id = 1; channel_id < logger.shm_->channel_size_; channel_id++) 374 | { 375 | total_count = 0; 376 | FNLog::Channel& channel = logger.shm_->channels_[channel_id]; 377 | do 378 | { 379 | int filter = 20; 380 | LOG_STREAM_DEFAULT_LOGGER(channel_id, FNLog::PRIORITY_FATAL, filter, filter, FNLog::LOG_PREFIX_NULL) 381 | .write_buffer("rrrrrrrrrrrrrrrrrrrradfads33333333333333rrd", 382 | sizeof("rrrrrrrrrrrrrrrrrrrradfads33333333333333rrd") - 1); 383 | 384 | if (total_count % 5000000 == 0) 385 | { 386 | static double last = Now(); 387 | double now = Now(); 388 | if (total_count > 0) 389 | { 390 | LogInfo() << "channel:<" << (long long)channel_id << "> " 391 | << ChannelDesc(channel.channel_type_) << " emtpy write :<" 392 | << channel.device_size_ << "> test " << 5000000 / (now - last) << " line/sec. "; 393 | last = now; 394 | break; 395 | } 396 | } 397 | } while (++total_count); 398 | } 399 | 400 | for (int channel_id = 0; channel_id < logger.shm_->channel_size_; channel_id++) 401 | { 402 | FNLog::Channel& channel = logger.shm_->channels_[channel_id]; 403 | for (int field = 0; field < FNLog::CHANNEL_LOG_MAX_ID; field++) 404 | { 405 | if (FNLog::AtomicLoadChannelLog(channel, field) <= 0) 406 | { 407 | continue; 408 | } 409 | LogInfoStream(0, 1, 0) << "channel[" << channel_id << "] log field[" << field << "]:" << FNLog::AtomicLoadChannelLog(channel, field); 410 | } 411 | } 412 | LogAlarmStream(0, 1, 0) << "finish"; 413 | return 0; 414 | } 415 | 416 | -------------------------------------------------------------------------------- /tests/benchmark_fast.cpp: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | #define FN_LOG_MAX_CHANNEL_SIZE 6 5 | #define FN_LOG_MAX_LOG_SIZE 1000 6 | #define FN_LOG_MAX_LOG_QUEUE_SIZE 100000 7 | 8 | #include "fn_log.h" 9 | 10 | 11 | static const std::string example_config_text = 12 | R"----( 13 | # 压测配表 14 | # 0通道为异步模式写文件, info多线程文件输出和一个CATEGORY筛选的屏显输出 15 | - channel: 0 16 | sync: null 17 | priority: trace 18 | category: 0 19 | category_extend: 0 20 | -device: 0 21 | disable: false 22 | out_type: file 23 | priority: trace 24 | category: 0 25 | category_extend: 0 26 | path: "./log/" 27 | file: "$PNAME" 28 | rollback: 4 29 | limit_size: 100 m #only support M byte 30 | -device:1 31 | disable: false 32 | out_type: screen 33 | priority: info 34 | -device:2 35 | disable: false 36 | out_type: screen 37 | category: 2 38 | category_extend: 1 39 | -device:3 40 | disable: false 41 | out_type: screen 42 | category: 2 43 | category_extend: 1 44 | -device:4 45 | disable: false 46 | out_type: screen 47 | category: 2 48 | category_extend: 1 49 | -device:5 50 | disable: false 51 | out_type: screen 52 | category: 2 53 | category_extend: 1 54 | -device:6 55 | disable: false 56 | out_type: screen 57 | category: 2 58 | category_extend: 1 59 | -device:7 60 | disable: false 61 | out_type: screen 62 | category: 2 63 | category_extend: 1 64 | -device:8 65 | disable: false 66 | out_type: screen 67 | category: 2 68 | category_extend: 1 69 | -device:9 70 | disable: false 71 | out_type: screen 72 | category: 2 73 | category_extend: 1 74 | -device:10 75 | disable: false 76 | out_type: screen 77 | category: 2 78 | category_extend: 1 79 | -device:11 80 | disable: false 81 | out_type: screen 82 | category: 2 83 | category_extend: 1 84 | -device:12 85 | disable: false 86 | out_type: screen 87 | category: 2 88 | category_extend: 1 89 | 90 | 91 | - channel: 1 92 | sync: async 93 | -device: 0 94 | disable: false 95 | out_type: empty 96 | priority: trace 97 | 98 | - channel: 2 99 | 100 | 101 | 102 | - channel: 3 103 | sync: sync 104 | -device: 0 105 | disable: false 106 | out_type: file 107 | file: "$PNAME_$YEAR" 108 | rollback: 4 109 | limit_size: 100 m #only support M byte 110 | 111 | - channel: 4 112 | sync: sync 113 | -device: 0 114 | disable: false 115 | out_type: empty 116 | 117 | - channel: 5 118 | sync: sync 119 | 120 | )----"; 121 | 122 | std::string ChannelDesc(int channel_type) 123 | { 124 | switch (channel_type) 125 | { 126 | case FNLog::CHANNEL_ASYNC: 127 | return "async thread write"; 128 | case FNLog::CHANNEL_SYNC: 129 | return "sync write"; 130 | } 131 | return "invalid channel"; 132 | } 133 | 134 | #define Now() std::chrono::duration(std::chrono::system_clock::now().time_since_epoch()).count() 135 | 136 | int main(int argc, char *argv[]) 137 | { 138 | int ret = FNLog::FastStartDefaultLogger(example_config_text); 139 | if (ret != 0) 140 | { 141 | return ret; 142 | } 143 | 144 | 145 | 146 | FNLog::Logger& logger = FNLog::GetDefaultLogger(); 147 | 148 | unsigned int total_count = 0; 149 | for (int channel_id = 0; channel_id < logger.shm_->channel_size_; channel_id++) 150 | { 151 | total_count = 0; 152 | double last = Now(); 153 | FNLog::Channel& channel = logger.shm_->channels_[channel_id]; 154 | do 155 | { 156 | 157 | LogDebugStream(channel_id, 0, 0).write_buffer("rrrrrrrrrrrrrrrrrrrradfads33333333333333rrd", 158 | sizeof("rrrrrrrrrrrrrrrrrrrradfads33333333333333rrd") - 1) 159 | << -23 << ": " << 32.2223 << (void*) nullptr; 160 | 161 | 162 | //LOG_STREAM_DEFAULT_LOGGER(channel_id, FNLog::PRIORITY_DEBUG, 0, 0, FNLog::LOG_PREFIX_NULL) 163 | // .write_buffer("rrrrrrrrrrrrrrrrrrrradfads33333333333333rrd", 164 | // sizeof("rrrrrrrrrrrrrrrrrrrradfads33333333333333rrd") - 1); 165 | 166 | if (total_count %1000000 == 0) 167 | { 168 | double now = Now(); 169 | if (total_count > 0) 170 | { 171 | LogInfo() << "channel:<" << (long long)channel_id << "> " 172 | << ChannelDesc(channel.channel_type_) << " has write :<" 173 | << channel.device_size_ << "> test " << total_count / (now - last) << " line/sec. "; 174 | 175 | long long ticks = FNLog::GetDefaultLogger().tick_count_; 176 | long long sum = FNLog::GetDefaultLogger().tick_sum_; 177 | LogAlarmStream(0, 1, 0) << "logs:" << ticks << ", sum:" << sum 178 | << ", avg:" << sum / (ticks > 0 ? ticks : 1); 179 | 180 | break; 181 | } 182 | } 183 | } while (++total_count); 184 | } 185 | 186 | 187 | for (int channel_id = 0; channel_id < logger.shm_->channel_size_; channel_id++) 188 | { 189 | FNLog::Channel& channel = logger.shm_->channels_[channel_id]; 190 | for (int field = 0; field < FNLog::CHANNEL_LOG_MAX_ID; field++) 191 | { 192 | if (FNLog::AtomicLoadChannelLog(channel, field) <= 0) 193 | { 194 | continue; 195 | } 196 | LogInfoStream(0, 1, 0) << "channel[" << channel_id << "] log field[" << field << "]:" << FNLog::AtomicLoadChannelLog(channel, field); 197 | } 198 | } 199 | 200 | LogAlarmStream(0, 1, 0) << "finish"; 201 | return 0; 202 | } 203 | 204 | -------------------------------------------------------------------------------- /tests/benchmark_filter_empty.cpp: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | #define FN_LOG_MAX_CHANNEL_SIZE 4 5 | #define FN_LOG_MAX_LOG_SIZE 1000 6 | #define FN_LOG_MAX_LOG_QUEUE_SIZE 100000 7 | 8 | #include "fn_log.h" 9 | 10 | 11 | static const std::string example_config_text = 12 | R"----( 13 | # 压测配表 14 | # 0通道为异步模式写文件, info多线程文件输出和一个CATEGORY筛选的屏显输出 15 | - channel: 0 16 | sync: null 17 | priority: debug 18 | category: 0 19 | category_extend: 0 20 | -device: 0 21 | disable: false 22 | out_type: file 23 | priority: debug 24 | category: 0 25 | category_extend: 0 26 | path: "./log/" 27 | file: "$PNAME" 28 | rollback: 4 29 | limit_size: 100 m #only support M byte 30 | -device:1 31 | disable: false 32 | priority: info 33 | out_type: screen 34 | category: 1 35 | category_extend: 1 36 | # 1 异步空 37 | - channel: 1 38 | priority: debug 39 | 40 | # 2通道为同步写文件 41 | - channel: 2 42 | sync: sync #only support single thread 43 | -device: 0 44 | priority: debug 45 | disable: false 46 | out_type: file 47 | file: "$PNAME_$YEAR" 48 | rollback: 4 49 | limit_size: 100 m #only support M byte 50 | 51 | # 3通道为同步空 52 | - channel: 3 53 | sync: sync #only support single thread 54 | 55 | )----"; 56 | 57 | std::string ChannelDesc(int channel_type) 58 | { 59 | switch (channel_type) 60 | { 61 | case FNLog::CHANNEL_ASYNC: 62 | return "async thread write"; 63 | case FNLog::CHANNEL_SYNC: 64 | return "sync write"; 65 | } 66 | return "invalid channel"; 67 | } 68 | 69 | #define Now() std::chrono::duration(std::chrono::system_clock::now().time_since_epoch()).count() 70 | 71 | int main(int argc, char *argv[]) 72 | { 73 | #ifdef RELEASE 74 | int ret = FNLog::FastStartDefaultLogger(" - channel: 0"); 75 | if (ret != 0) 76 | { 77 | return ret; 78 | } 79 | #else 80 | int ret = FNLog::FastStartDefaultLogger(example_config_text); 81 | if (ret != 0) 82 | { 83 | return ret; 84 | } 85 | #endif // NDEBUG 86 | 87 | 88 | 89 | double now = Now(); 90 | 91 | LogAlarmStream(0, 1, 0) << "input format: LogDebug() << xxxx << xxx; test:"; 92 | now = Now(); 93 | for (unsigned long long i = 0; i < 1000000; i++) 94 | { 95 | LogDebugStream(0, 0, 0) << "asdf" << i << ", " << 2.3 << "asdfasdf"; 96 | } 97 | LogAlarmStream(0, 1, 0) << "1000w debug(write) use" << (Now() - now) * (10) << " secend"; 98 | now = Now(); 99 | for (unsigned long long i = 0; i < 1000000; i++) 100 | { 101 | LogTraceStream(0, 0, 0) << "asdf" << i << ", " << 2.3 << "asdfasdf"; 102 | } 103 | LogAlarmStream(0, 1, 0) << "1000w trace(no write) use" << (Now() - now) * (10) << " secend"; 104 | 105 | now = Now(); 106 | for (unsigned long long i = 0; i < 1000000; i++) 107 | { 108 | LogDebugStream(1, 0, 0) << "asdf" << i << ", " << 2.3 << "asdfasdf"; 109 | } 110 | LogAlarmStream(0, 1, 0) << "1000w debug(no device no write) use" << (Now() - now) * (10) << " secend"; 111 | now = Now(); 112 | for (unsigned long long i = 0; i < 1000000; i++) 113 | { 114 | LogTraceStream(1, 0, 0) << "asdf" << i << ", " << 2.3 << "asdfasdf"; 115 | } 116 | LogAlarmStream(0, 1, 0) << "1000w trace(no device no write) use" << (Now() - now) * (10) << " secend"; 117 | 118 | 119 | now = Now(); 120 | for (unsigned long long i = 0; i < 100000; i++) 121 | { 122 | LogDebugStream(2, 0, 0) << "asdf" << i << ", " << 2.3 << "asdfasdf"; 123 | } 124 | LogAlarmStream(0, 1, 0) << "1000w debug(sync write) use" << (Now() - now) * (100) << " secend"; 125 | now = Now(); 126 | for (unsigned long long i = 0; i < 1000000; i++) 127 | { 128 | LogTraceStream(2, 0, 0) << "asdf" << i << ", " << 2.3 << "asdfasdf"; 129 | } 130 | LogAlarmStream(0, 1, 0) << "1000w trace(sync no write) use" << (Now() - now) * (10) << " secend"; 131 | 132 | 133 | LogAlarmStream(0, 1, 0) << "\n\n"; 134 | LogAlarmStream(0, 1, 0) << "input format: LOGFMTD(\"sss\", xxx, xxx); test:"; 135 | now = Now(); 136 | for (unsigned long long i = 0; i < 1000000; i++) 137 | { 138 | LOGFMT_DEBUG(0, 0, 0, "%s, %llu, %g, %s", "asdf" , i , 2.3 , "asdfasdf"); 139 | } 140 | LogAlarmStream(0, 1, 0) << "1000w debug(write) use" << (Now() - now) * (10) << " secend"; 141 | now = Now(); 142 | for (unsigned long long i = 0; i < 1000000; i++) 143 | { 144 | LOGFMT_TRACE(0, 0, 0, "%s, %llu, %g, %s", "asdf", i, 2.3, "asdfasdf"); 145 | } 146 | LogAlarmStream(0, 1, 0) << "1000w trace(no write) use" << (Now() - now) * (10) << " secend"; 147 | 148 | now = Now(); 149 | for (unsigned long long i = 0; i < 1000000; i++) 150 | { 151 | LOGFMT_DEBUG(1, 0, 0, "%s, %llu, %g, %s", "asdf", i, 2.3, "asdfasdf"); 152 | } 153 | LogAlarmStream(0, 1, 0) << "1000w debug(no device no write) use" << (Now() - now) * (10) << " secend"; 154 | now = Now(); 155 | for (unsigned long long i = 0; i < 1000000; i++) 156 | { 157 | LOGFMT_TRACE(1, 0, 0, "%s, %llu, %g, %s", "asdf", i, 2.3, "asdfasdf"); 158 | } 159 | LogAlarmStream(0, 10, 0) << "1000w trace(no device no write) use" << (Now() - now) * (10) << " secend"; 160 | 161 | 162 | now = Now(); 163 | for (unsigned long long i = 0; i < 100000; i++) 164 | { 165 | LOGFMT_DEBUG(2, 0, 0, "%s, %llu, %g, %s", "asdf", i, 2.3, "asdfasdf"); 166 | } 167 | LogAlarmStream(0, 1, 0) << "1000w debug(sync write) use" << (Now() - now) * (100) << " secend"; 168 | now = Now(); 169 | for (unsigned long long i = 0; i < 1000000; i++) 170 | { 171 | LOGFMT_TRACE(2, 0, 0, "%s, %llu, %g, %s", "asdf", i, 2.3, "asdfasdf"); 172 | } 173 | LogAlarmStream(0, 1, 0) << "1000w trace(sync no write) use" << (Now() - now) * (10) << " secend"; 174 | 175 | 176 | long long ticks = FNLog::GetDefaultLogger().tick_count_; 177 | long long sum = FNLog::GetDefaultLogger().tick_sum_; 178 | LogAlarmStream(0, 1, 0) << "logs:" << ticks << ", sum:" << sum 179 | << ", avg:" << sum / (ticks > 0 ? ticks : 1); 180 | 181 | 182 | LogAlarmStream(0, 1, 0) << "finish"; 183 | return 0; 184 | } 185 | 186 | -------------------------------------------------------------------------------- /tests/benchmark_multi-thread.cpp: -------------------------------------------------------------------------------- 1 | 2 | #define FN_LOG_MAX_LOG_SIZE 1000 3 | #define FN_LOG_MAX_LOG_QUEUE_SIZE 100000 4 | #include "fn_log.h" 5 | #include 6 | 7 | 8 | static const std::string default_config_text = 9 | R"----( 10 | # default channel 0 11 | # write full log to pname.log 12 | # write info log to pname_info.log 13 | # view info log to screen 14 | # sync channel 1 15 | # write full log to pname.log 16 | # write info log to pname_info.log 17 | # view info log to screen 18 | 19 | - channel: 0 20 | sync: async 21 | -device: 0 22 | disable: false 23 | out_type: file 24 | file: "$PNAME" 25 | rollback: 4 26 | limit_size: 100 m #only support M byte 27 | -device: 1 28 | disable: false 29 | out_type: file 30 | priority: info 31 | file: "$PNAME_info" 32 | rollback: 4 33 | limit_size: 100 m #only support M byte 34 | -device:2 35 | disable: false 36 | out_type: screen 37 | priority: info 38 | - channel: 1 39 | sync: sync 40 | -device: 0 41 | disable: false 42 | out_type: file 43 | file: "$PNAME_sync" 44 | rollback: 4 45 | limit_size: 100 m #only support M byte 46 | -device: 1 47 | disable: false 48 | out_type: file 49 | priority: info 50 | file: "$PNAME_sync_info" 51 | rollback: 4 52 | limit_size: 100 m #only support M byte 53 | -device:2 54 | disable: false 55 | out_type: screen 56 | priority: info 57 | )----"; 58 | 59 | 60 | enum State 61 | { 62 | WAIT, 63 | WRITE, 64 | END 65 | }; 66 | 67 | State state = WRITE; 68 | 69 | void thread_proc(int index) 70 | { 71 | LogInfo() << "thread:<" << index << "> begin."; 72 | while (state != END) 73 | { 74 | 75 | LogDebug().write_buffer("rrrrrrrrrrrrrrrrrrrradfads33333333333333rrd", 76 | sizeof("rrrrrrrrrrrrrrrrrrrradfads33333333333333rrd") - 1) 77 | << -23 << ": " << 32.2223 << (void*) nullptr; 78 | 79 | } 80 | LogInfo() << "thread:<" << index << "> end."; 81 | } 82 | 83 | const int WRITE_THREAD_COUNT = 6; 84 | std::thread g_multi_proc[WRITE_THREAD_COUNT]; 85 | 86 | void Stop(int signo) 87 | { 88 | printf("%s", "oops! stop!!!\n"); 89 | _exit(0); 90 | } 91 | 92 | 93 | int main(int argc, char* argv[]) 94 | { 95 | signal(SIGINT, Stop); 96 | int ret = FNLog::FastStartDefaultLogger(default_config_text); 97 | if (ret != 0) 98 | { 99 | return ret; 100 | } 101 | 102 | FNLog::Logger& logger = FNLog::GetDefaultLogger(); 103 | int limit_second = 0; 104 | int thread_id = 0; 105 | g_multi_proc[thread_id] = std::thread(thread_proc, thread_id); 106 | 107 | do 108 | { 109 | long long last_writed = FNLog::AtomicLoadChannelLog(logger.shm_->channels_[0], FNLog::CHANNEL_LOG_PROCESSED); 110 | std::this_thread::sleep_for(std::chrono::milliseconds(1000)); 111 | long long now_writed = FNLog::AtomicLoadChannelLog(logger.shm_->channels_[0], FNLog::CHANNEL_LOG_PROCESSED); 112 | LogInfo() << "now thread:" << thread_id + 1 << ": writed:" << now_writed - last_writed; 113 | 114 | if (limit_second / 3 > thread_id && thread_id + 1 < WRITE_THREAD_COUNT) 115 | { 116 | thread_id++; 117 | LogInfo() << "add new thread:" << thread_id; 118 | g_multi_proc[thread_id] = std::thread(thread_proc, thread_id); 119 | } 120 | limit_second++; 121 | } while (limit_second < 15); 122 | 123 | LogAlarm() << "finish"; 124 | state = END; 125 | for (int i = 0; i <= thread_id; i++) 126 | { 127 | if (g_multi_proc[i].joinable()) 128 | { 129 | g_multi_proc[i].join(); 130 | } 131 | } 132 | long long ticks = FNLog::GetDefaultLogger().tick_count_; 133 | long long sum = FNLog::GetDefaultLogger().tick_sum_; 134 | LogInfo() << "logs:" << ticks << ", sum:" << sum 135 | << ", avg:" << sum /(ticks > 0 ? ticks : 1); 136 | 137 | 138 | 139 | return 0; 140 | } 141 | 142 | -------------------------------------------------------------------------------- /tests/benchmark_multi-thread_hotupdate.cpp: -------------------------------------------------------------------------------- 1 | 2 | #define FN_LOG_MAX_LOG_SIZE 1000 3 | #define FN_LOG_MAX_LOG_QUEUE_SIZE 100000 4 | #define FN_LOG_HOTUPDATE_INTERVEL 2 5 | #define FN_LOG_MAX_CHANNEL_SIZE 5 6 | #include "fn_log.h" 7 | #include 8 | 9 | 10 | static const std::string default_config_text = 11 | R"----( 12 | # default channel 0 13 | # write full log to pname.log 14 | # write info log to pname_info.log 15 | # view info log to screen 16 | # sync channel 1 17 | # write full log to pname.log 18 | # write info log to pname_info.log 19 | # view info log to screen 20 | - define: BASE_CHANNEL 0 21 | - define: SECOND_CHANNEL 1 22 | - define: "DEFAULT_ROLL 4" 23 | - define: "DEFAULT_LIMIT 100 m" 24 | hotupdate: true 25 | - channel: BASE_CHANNEL 26 | sync: async 27 | -device: 0 28 | disable: false 29 | out_type: file 30 | file: "$PNAME_base" 31 | rollback: DEFAULT_ROLL 32 | limit_size: 100 m #only support M byte 33 | -device: 1 34 | disable: false 35 | out_type: screen 36 | priority: info 37 | - channel: SECOND_CHANNEL 38 | sync: async 39 | -device: 0 40 | disable: false 41 | out_type: file 42 | file: "$PNAME_second" 43 | rollback: DEFAULT_ROLL 44 | limit_size: 100 m #only support M byte 45 | - channel: 2 46 | sync: async 47 | -device: 0 48 | disable: false 49 | out_type: file 50 | file: "$PNAME_3" 51 | rollback: 1 52 | limit_size: 10 m #only support M byte 53 | - channel: 3 54 | sync: async 55 | -device: 0 56 | disable: false 57 | out_type: file 58 | file: "$PNAME_3" 59 | rollback: 1 60 | limit_size: 10 m #only support M byte 61 | 62 | 63 | )----"; 64 | 65 | 66 | enum State 67 | { 68 | WAIT, 69 | WRITE, 70 | END 71 | }; 72 | 73 | State state = WRITE; 74 | 75 | void thread_proc(int index) 76 | { 77 | LogInfo() << "thread:<" << index << "> begin."; 78 | while (state != END) 79 | { 80 | 81 | LogDebug().write_buffer("rrrrrrrrrrrrrrrrrrrradfads33333333333333rrd", 82 | sizeof("rrrrrrrrrrrrrrrrrrrradfads33333333333333rrd") - 1) 83 | << -23 << ": " << 32.2223 << (void*) nullptr; 84 | LogDebugStream(1, 0, 0).write_buffer("rrrrrrrrrrrrrrrrrrrradfads33333333333333rrd", 85 | sizeof("rrrrrrrrrrrrrrrrrrrradfads33333333333333rrd") - 1) 86 | << -23 << ": " << 32.2223 << (void*) nullptr; 87 | 88 | } 89 | LogInfo() << "thread:<" << index << "> end."; 90 | } 91 | 92 | const int WRITE_THREAD_COUNT = 6; 93 | std::thread g_multi_proc[WRITE_THREAD_COUNT]; 94 | 95 | void Stop(int signo) 96 | { 97 | printf("%s", "oops! stop!!!\n"); 98 | _exit(0); 99 | } 100 | 101 | 102 | struct MyStruct 103 | { 104 | int* a[3]; 105 | }; 106 | //constexpr static int s = sizeof(MyStruct); 107 | 108 | int main(int argc, char* argv[]) 109 | { 110 | signal(SIGINT, Stop); 111 | std::string path = "./hotupdate.yaml"; 112 | FNLog::FileHandler::remove_file(path); 113 | FNLog::FileHandler file; 114 | struct stat s; 115 | file.open(path.c_str(), "rb", s); 116 | if (file.is_open()) 117 | { 118 | printf("%s", "has error"); 119 | return 1; 120 | } 121 | file.close(); 122 | 123 | file.open(path.c_str(), "wb", s); 124 | if (!file.is_open()) 125 | { 126 | printf("%s", "write file error"); 127 | return 1; 128 | } 129 | file.write(default_config_text.c_str(), default_config_text.length()); 130 | file.close(); 131 | //FNLog::FileHandler::write(); 132 | int ret = FNLog::LoadAndStartDefaultLogger(path); 133 | if (ret != 0) 134 | { 135 | return ret; 136 | } 137 | 138 | FNLog::Logger& logger = FNLog::GetDefaultLogger(); 139 | int limit_second = 0; 140 | int thread_id = 0; 141 | g_multi_proc[thread_id] = std::thread(thread_proc, thread_id); 142 | 143 | do 144 | { 145 | long long last_writed = FNLog::AtomicLoadChannelLog(logger.shm_->channels_[0], FNLog::CHANNEL_LOG_PROCESSED); 146 | std::this_thread::sleep_for(std::chrono::milliseconds(1000)); 147 | long long now_writed = FNLog::AtomicLoadChannelLog(logger.shm_->channels_[0], FNLog::CHANNEL_LOG_PROCESSED); 148 | LogInfo() << "now thread:" << thread_id + 1 << ": writed:" << now_writed - last_writed; 149 | 150 | 151 | file.open(path.c_str(), "wb", s); 152 | if (!file.is_open()) 153 | { 154 | printf("%s", "write file error"); 155 | return 1; 156 | } 157 | file.write(default_config_text.c_str(), default_config_text.length()); 158 | file.close(); 159 | 160 | if (limit_second / 3 > thread_id && thread_id + 1 < WRITE_THREAD_COUNT) 161 | { 162 | thread_id++; 163 | LogInfo() << "add new thread:" << thread_id; 164 | g_multi_proc[thread_id] = std::thread(thread_proc, thread_id); 165 | } 166 | limit_second++; 167 | } while (limit_second < 15); 168 | 169 | LogAlarm() << "finish"; 170 | 171 | for (int channel_id = 0; channel_id < logger.shm_->channel_size_; channel_id++) 172 | { 173 | FNLog::Channel& channel = logger.shm_->channels_[channel_id]; 174 | for (int field = 0; field < FNLog::CHANNEL_LOG_MAX_ID; field++) 175 | { 176 | if (FNLog::AtomicLoadChannelLog(channel, field) <= 0) 177 | { 178 | continue; 179 | } 180 | LogInfoStream(0, 1, 0) << "channel[" << channel_id << "] log field[" << field << "]:" << FNLog::AtomicLoadChannelLog(channel, field); 181 | } 182 | } 183 | 184 | state = END; 185 | for (int i = 0; i <= thread_id; i++) 186 | { 187 | if (g_multi_proc[i].joinable()) 188 | { 189 | g_multi_proc[i].join(); 190 | } 191 | } 192 | LogAlarm() << "all thread exit"; 193 | return 0; 194 | } 195 | 196 | -------------------------------------------------------------------------------- /tests/benchmark_multi-thread_nofile.cpp: -------------------------------------------------------------------------------- 1 | 2 | #define FN_LOG_MAX_LOG_SIZE 1000 3 | #define FN_LOG_MAX_LOG_QUEUE_SIZE 100000 4 | #include "fn_log.h" 5 | #include 6 | 7 | 8 | static const std::string default_config_text = 9 | R"----( 10 | # default channel 0 11 | # write full log to pname.log 12 | # write info log to pname_info.log 13 | # view info log to screen 14 | # sync channel 1 15 | # write full log to pname.log 16 | # write info log to pname_info.log 17 | # view info log to screen 18 | 19 | - channel: 0 20 | sync: async 21 | -device: 0 22 | disable: false 23 | out_type: file 24 | file: "$PNAME" 25 | rollback: 4 26 | limit_size: 100 m #only support M byte 27 | -device: 1 28 | disable: false 29 | out_type: file 30 | priority: info 31 | file: "$PNAME_info" 32 | rollback: 4 33 | limit_size: 100 m #only support M byte 34 | -device:2 35 | disable: false 36 | out_type: screen 37 | priority: info 38 | - channel: 1 39 | sync: sync 40 | -device: 0 41 | disable: false 42 | out_type: file 43 | file: "$PNAME_sync" 44 | rollback: 4 45 | limit_size: 100 m #only support M byte 46 | -device: 1 47 | disable: false 48 | out_type: file 49 | priority: info 50 | file: "$PNAME_sync_info" 51 | rollback: 4 52 | limit_size: 100 m #only support M byte 53 | -device:2 54 | disable: false 55 | out_type: screen 56 | priority: info 57 | )----"; 58 | 59 | 60 | enum State 61 | { 62 | WAIT, 63 | WRITE, 64 | END 65 | }; 66 | 67 | State state = WRITE; 68 | 69 | void thread_proc(int index) 70 | { 71 | LogInfo() << "thread:<" << index << "> begin."; 72 | while (state != END) 73 | { 74 | 75 | LogDebug().write_buffer("rrrrrrrrrrrrrrrrrrrradfads33333333333333rrd", 76 | sizeof("rrrrrrrrrrrrrrrrrrrradfads33333333333333rrd") - 1) 77 | << -23 << ": " << 32.2223 << (void*) nullptr; 78 | 79 | } 80 | LogInfo() << "thread:<" << index << "> end."; 81 | } 82 | 83 | const int WRITE_THREAD_COUNT = 6; 84 | std::thread g_multi_proc[WRITE_THREAD_COUNT]; 85 | 86 | void Stop(int signo) 87 | { 88 | printf("%s", "oops! stop!!!\n"); 89 | _exit(0); 90 | } 91 | 92 | 93 | int main(int argc, char* argv[]) 94 | { 95 | signal(SIGINT, Stop); 96 | int ret = FNLog::FastStartDefaultLogger(default_config_text); 97 | if (ret != 0) 98 | { 99 | return ret; 100 | } 101 | 102 | FNLog::Logger& logger = FNLog::GetDefaultLogger(); 103 | FNLog::SetDeviceConfig(logger, 0, 0, FNLog::DEVICE_CFG_ABLE, 0); 104 | int limit_second = 0; 105 | int thread_id = 0; 106 | g_multi_proc[thread_id] = std::thread(thread_proc, thread_id); 107 | 108 | do 109 | { 110 | long long last_writed = AtomicLoadChannelLog(logger.shm_->channels_[0], FNLog::CHANNEL_LOG_PROCESSED); 111 | std::this_thread::sleep_for(std::chrono::milliseconds(1000)); 112 | long long now_writed = AtomicLoadChannelLog(logger.shm_->channels_[0], FNLog::CHANNEL_LOG_PROCESSED); 113 | LogInfo() << "now thread:" << thread_id+1 << ": writed:" << now_writed - last_writed ; 114 | 115 | if (limit_second/3 > thread_id && thread_id+1 < WRITE_THREAD_COUNT) 116 | { 117 | thread_id++; 118 | LogInfo() << "add new thread:" << thread_id; 119 | g_multi_proc[thread_id] = std::thread(thread_proc, thread_id); 120 | } 121 | limit_second++; 122 | } while (limit_second < 15); 123 | 124 | LogAlarm() << "finish"; 125 | state = END; 126 | for (int i = 0; i <= thread_id; i++) 127 | { 128 | if (g_multi_proc[i].joinable()) 129 | { 130 | g_multi_proc[i].join(); 131 | } 132 | } 133 | return 0; 134 | } 135 | 136 | -------------------------------------------------------------------------------- /tests/benchmark_multi-thread_sync.cpp: -------------------------------------------------------------------------------- 1 | 2 | #define FN_LOG_MAX_LOG_SIZE 1000 3 | #define FN_LOG_MAX_LOG_QUEUE_SIZE 100000 4 | #include "fn_log.h" 5 | #include 6 | 7 | 8 | static const std::string default_config_text = 9 | R"----( 10 | # default channel 0 11 | # write full log to pname.log 12 | # write info log to pname_info.log 13 | # view info log to screen 14 | # sync channel 1 15 | # write full log to pname.log 16 | # write info log to pname_info.log 17 | # view info log to screen 18 | 19 | - channel: 0 20 | sync: async 21 | -device: 0 22 | disable: false 23 | out_type: file 24 | file: "$PNAME" 25 | rollback: 4 26 | limit_size: 100 m #only support M byte 27 | -device: 1 28 | disable: false 29 | out_type: file 30 | priority: info 31 | file: "$PNAME_info" 32 | rollback: 4 33 | limit_size: 100 m #only support M byte 34 | -device:2 35 | disable: false 36 | out_type: screen 37 | priority: info 38 | - channel: 1 39 | sync: sync 40 | -device: 0 41 | disable: false 42 | out_type: file 43 | file: "$PNAME_sync" 44 | rollback: 4 45 | limit_size: 100 m #only support M byte 46 | -device: 1 47 | disable: false 48 | out_type: file 49 | priority: info 50 | file: "$PNAME_sync_info" 51 | rollback: 4 52 | limit_size: 100 m #only support M byte 53 | -device:2 54 | disable: false 55 | out_type: screen 56 | priority: info 57 | )----"; 58 | 59 | 60 | enum State 61 | { 62 | WAIT, 63 | WRITE, 64 | END 65 | }; 66 | 67 | State state = WRITE; 68 | 69 | void thread_proc(int index) 70 | { 71 | LogInfo() << "thread:<" << index << "> begin."; 72 | while (state != END) 73 | { 74 | 75 | LogDebugStream(1, 0, 0).write_buffer("rrrrrrrrrrrrrrrrrrrradfads33333333333333rrd", 76 | sizeof("rrrrrrrrrrrrrrrrrrrradfads33333333333333rrd") - 1) 77 | << -23 << ": " << 32.2223 << (void*) nullptr; 78 | 79 | } 80 | LogInfo() << "thread:<" << index << "> end."; 81 | } 82 | 83 | const int WRITE_THREAD_COUNT = 6; 84 | std::thread g_multi_proc[WRITE_THREAD_COUNT]; 85 | 86 | void Stop(int signo) 87 | { 88 | printf("%s", "oops! stop!!!\n"); 89 | _exit(0); 90 | } 91 | 92 | 93 | int main(int argc, char* argv[]) 94 | { 95 | signal(SIGINT, Stop); 96 | int ret = FNLog::FastStartDefaultLogger(default_config_text); 97 | if (ret != 0) 98 | { 99 | return ret; 100 | } 101 | 102 | FNLog::Logger& logger = FNLog::GetDefaultLogger(); 103 | int limit_second = 0; 104 | int thread_id = 0; 105 | g_multi_proc[thread_id] = std::thread(thread_proc, thread_id); 106 | 107 | do 108 | { 109 | long long last_writed = AtomicLoadChannelLog(logger.shm_->channels_[1], FNLog::CHANNEL_LOG_PROCESSED); 110 | std::this_thread::sleep_for(std::chrono::milliseconds(1000)); 111 | long long now_writed = AtomicLoadChannelLog(logger.shm_->channels_[1], FNLog::CHANNEL_LOG_PROCESSED); 112 | LogInfo() << "now thread:" << thread_id + 1 << ": writed:" << now_writed - last_writed; 113 | 114 | if (limit_second / 3 > thread_id && thread_id + 1 < WRITE_THREAD_COUNT) 115 | { 116 | thread_id++; 117 | LogInfo() << "add new thread:" << thread_id; 118 | g_multi_proc[thread_id] = std::thread(thread_proc, thread_id); 119 | } 120 | limit_second++; 121 | } while (limit_second < 15); 122 | 123 | LogAlarm() << "finish"; 124 | state = END; 125 | for (int i = 0; i <= thread_id; i++) 126 | { 127 | if (g_multi_proc[i].joinable()) 128 | { 129 | g_multi_proc[i].join(); 130 | } 131 | } 132 | return 0; 133 | } 134 | 135 | -------------------------------------------------------------------------------- /tests/benchmark_multi-thread_sync_nofile.cpp: -------------------------------------------------------------------------------- 1 | 2 | #define FN_LOG_MAX_LOG_SIZE 1000 3 | #define FN_LOG_MAX_LOG_QUEUE_SIZE 100000 4 | #include "fn_log.h" 5 | #include 6 | 7 | 8 | static const std::string default_config_text = 9 | R"----( 10 | # default channel 0 11 | # write full log to pname.log 12 | # write info log to pname_info.log 13 | # view info log to screen 14 | # sync channel 1 15 | # write full log to pname.log 16 | # write info log to pname_info.log 17 | # view info log to screen 18 | 19 | - channel: 0 20 | sync: async 21 | -device: 0 22 | disable: false 23 | out_type: file 24 | file: "$PNAME" 25 | rollback: 4 26 | limit_size: 100 m #only support M byte 27 | -device: 1 28 | disable: false 29 | out_type: file 30 | priority: info 31 | file: "$PNAME_info" 32 | rollback: 4 33 | limit_size: 100 m #only support M byte 34 | -device:2 35 | disable: false 36 | out_type: screen 37 | priority: info 38 | - channel: 1 39 | sync: sync 40 | -device: 0 41 | disable: false 42 | out_type: file 43 | file: "$PNAME_sync" 44 | rollback: 4 45 | limit_size: 100 m #only support M byte 46 | -device: 1 47 | disable: false 48 | out_type: file 49 | priority: info 50 | file: "$PNAME_sync_info" 51 | rollback: 4 52 | limit_size: 100 m #only support M byte 53 | -device:2 54 | disable: false 55 | out_type: screen 56 | priority: info 57 | )----"; 58 | 59 | 60 | enum State 61 | { 62 | WAIT, 63 | WRITE, 64 | END 65 | }; 66 | 67 | State state = WRITE; 68 | 69 | void thread_proc(int index) 70 | { 71 | LogInfo() << "thread:<" << index << "> begin."; 72 | while (state != END) 73 | { 74 | 75 | LogDebugStream(1, 0, 0).write_buffer("rrrrrrrrrrrrrrrrrrrradfads33333333333333rrd", 76 | sizeof("rrrrrrrrrrrrrrrrrrrradfads33333333333333rrd") - 1) 77 | << -23 << ": " << 32.2223 << (void*) nullptr; 78 | 79 | } 80 | LogInfo() << "thread:<" << index << "> end."; 81 | } 82 | 83 | const int WRITE_THREAD_COUNT = 6; 84 | std::thread g_multi_proc[WRITE_THREAD_COUNT]; 85 | 86 | void Stop(int signo) 87 | { 88 | printf("%s", "oops! stop!!!\n"); 89 | _exit(0); 90 | } 91 | 92 | 93 | int main(int argc, char* argv[]) 94 | { 95 | signal(SIGINT, Stop); 96 | int ret = FNLog::FastStartDefaultLogger(default_config_text); 97 | if (ret != 0) 98 | { 99 | return ret; 100 | } 101 | 102 | FNLog::Logger& logger = FNLog::GetDefaultLogger(); 103 | FNLog::SetDeviceConfig(logger, 0, 0, FNLog::DEVICE_CFG_ABLE, 0); 104 | int limit_second = 0; 105 | int thread_id = 0; 106 | g_multi_proc[thread_id] = std::thread(thread_proc, thread_id); 107 | 108 | do 109 | { 110 | long long last_writed = AtomicLoadChannelLog(logger.shm_->channels_[1], FNLog::CHANNEL_LOG_PROCESSED); 111 | std::this_thread::sleep_for(std::chrono::milliseconds(1000)); 112 | long long now_writed = AtomicLoadChannelLog(logger.shm_->channels_[1], FNLog::CHANNEL_LOG_PROCESSED); 113 | LogInfo() << "now thread:" << thread_id + 1 << ": writed:" << now_writed - last_writed; 114 | 115 | if (limit_second / 3 > thread_id && thread_id + 1 < WRITE_THREAD_COUNT) 116 | { 117 | thread_id++; 118 | LogInfo() << "add new thread:" << thread_id; 119 | g_multi_proc[thread_id] = std::thread(thread_proc, thread_id); 120 | } 121 | limit_second++; 122 | } while (limit_second < 15); 123 | 124 | LogAlarm() << "finish"; 125 | state = END; 126 | for (int i = 0; i <= thread_id; i++) 127 | { 128 | if (g_multi_proc[i].joinable()) 129 | { 130 | g_multi_proc[i].join(); 131 | } 132 | } 133 | return 0; 134 | } 135 | 136 | -------------------------------------------------------------------------------- /tests/benchmark_multi-thread_travis_shm.cpp: -------------------------------------------------------------------------------- 1 | #define FN_LOG_MAX_LOG_SIZE 1000 2 | #define FN_LOG_MAX_LOG_QUEUE_SIZE 100000 3 | 4 | #include "fn_log.h" 5 | #include 6 | 7 | static const std::string default_config_text = 8 | R"----( 9 | # default is mult-thread async write channel. 10 | # the first device is write rollback file 11 | # the second device is print to screen. 12 | - channel: 0 13 | sync: null 14 | -device: 0 15 | disable: false 16 | out_type: file 17 | file: "$PNAME" 18 | rollback: 1 19 | limit_size: 100 m #only support M byte 20 | -device:1 21 | disable: false 22 | out_type: screen 23 | priority: info 24 | - channel: 1 25 | sync: sync 26 | -device: 0 27 | disable: false 28 | out_type: file 29 | file: "$PNAME_SYNC" 30 | rollback: 1 31 | limit_size: 100 m #only support M byte 32 | -device:1 33 | disable: false 34 | out_type: screen 35 | priority: info 36 | )----"; 37 | 38 | 39 | enum State 40 | { 41 | WAIT, 42 | WRITE, 43 | END 44 | }; 45 | 46 | State state = WRITE; 47 | 48 | void thread_proc(int index) 49 | { 50 | LogInfo() << "thread:<" << index << "> begin."; 51 | while (state != END) 52 | { 53 | if (state == WRITE) 54 | { 55 | LogDebug().write_buffer("rrrrrrrrrrrrrrrrrrrradfads33333333333333rrd", 56 | sizeof("rrrrrrrrrrrrrrrrrrrradfads33333333333333rrd") - 1) 57 | << -23 << ": " << 32.2223 << (void*) nullptr; 58 | } 59 | else 60 | { 61 | std::this_thread::sleep_for(std::chrono::milliseconds(100)); 62 | } 63 | } 64 | LogInfo() << "thread:<" << index << "> end."; 65 | } 66 | 67 | const int WRITE_THREAD_COUNT = 6; 68 | std::thread g_multi_proc[WRITE_THREAD_COUNT]; 69 | 70 | void Stop(int signo) 71 | { 72 | printf("%s", "oops! stop!!!\n"); 73 | _exit(0); 74 | } 75 | 76 | 77 | int main(int argc, char* argv[]) 78 | { 79 | signal(SIGINT, Stop); 80 | int ret = FNLog::FastStartDefaultLogger(default_config_text); 81 | if (ret != 0) 82 | { 83 | return ret; 84 | } 85 | 86 | FNLog::Logger& logger = FNLog::GetDefaultLogger(); 87 | 88 | int limit_second = 0; 89 | int thread_id = 0; 90 | g_multi_proc[thread_id] = std::thread(thread_proc, thread_id); 91 | 92 | do 93 | { 94 | long long last_writed = AtomicLoadChannelLog(logger.shm_->channels_[0], FNLog::CHANNEL_LOG_PROCESSED); 95 | std::this_thread::sleep_for(std::chrono::milliseconds(1000)); 96 | long long now_writed = AtomicLoadChannelLog(logger.shm_->channels_[0], FNLog::CHANNEL_LOG_PROCESSED); 97 | LogInfo() << "now thread:" << thread_id+1 << ": writed:" << now_writed - last_writed ; 98 | 99 | if (limit_second/3 > thread_id && thread_id+1 < WRITE_THREAD_COUNT) 100 | { 101 | thread_id++; 102 | LogInfo() << "add new thread:" << thread_id; 103 | g_multi_proc[thread_id] = std::thread(thread_proc, thread_id); 104 | } 105 | limit_second++; 106 | } while (limit_second < 15); 107 | 108 | LogAlarm() << "finish"; 109 | state = END; 110 | for (int i = 0; i <= thread_id; i++) 111 | { 112 | if (g_multi_proc[i].joinable()) 113 | { 114 | g_multi_proc[i].join(); 115 | } 116 | } 117 | return 0; 118 | } 119 | 120 | -------------------------------------------------------------------------------- /tests/benchmark_multi-thread_use.cpp: -------------------------------------------------------------------------------- 1 | 2 | 3 | #include "fn_log.h" 4 | #include 5 | 6 | 7 | void thread_proc(int index) 8 | { 9 | int proc_count = 10; 10 | int* brk = new int; 11 | int* mm = (int*)new int[1024 * 1024*10]; 12 | LogInfo() << "thread:<" << index << "> addr:<" << &proc_count << "> begin. brk:<" << brk << "> mm:<" << mm << ">."; 13 | while (proc_count-- > 0) 14 | { 15 | //LogDebug() << "thread:<" << index << "> addr:<" << &proc_count << "> proc:<" << proc_count << ">."; 16 | std::this_thread::sleep_for(std::chrono::milliseconds(1000)); 17 | } 18 | LogInfo() << "thread:<" << index << "> addr:<" << &proc_count << "> end.brk:<" << brk << "> mm:<" << mm << ">."; 19 | delete brk; 20 | delete[]mm; 21 | } 22 | 23 | const int WRITE_THREAD_COUNT = 5; 24 | std::thread g_multi_proc[WRITE_THREAD_COUNT]; 25 | 26 | void Stop(int signo) 27 | { 28 | printf("%s", "oops! stop!!!\n"); 29 | _exit(0); 30 | } 31 | 32 | 33 | int main(int argc, char* argv[]) 34 | { 35 | signal(SIGINT, Stop); 36 | int ret = FNLog::FastStartDebugLogger(); 37 | if (ret != 0) 38 | { 39 | return ret; 40 | } 41 | int proc_count = 10; 42 | int* brk = new int; 43 | int* mm = (int*)new int[1024 * 1024]; 44 | void* patoi = (void*)&atoi; 45 | LogInfo() << " main addr:<" << &proc_count << "> begin. brk:<" << brk << "> mm:<" << mm << "> atoi:<" << patoi << ">."; 46 | 47 | for (int i = 0; i < WRITE_THREAD_COUNT; i++) 48 | { 49 | g_multi_proc[i] = std::thread(thread_proc, i); 50 | } 51 | 52 | for (int i = 0; i < WRITE_THREAD_COUNT; i++) 53 | { 54 | if (g_multi_proc[i].joinable()) 55 | { 56 | g_multi_proc[i].join(); 57 | } 58 | } 59 | 60 | 61 | 62 | LogInfo() << " main addr:<" << &proc_count << "> end. brk:<" << brk << "> mm:<" << mm << ">."; 63 | delete brk; 64 | delete[]mm; 65 | return 0; 66 | } 67 | 68 | -------------------------------------------------------------------------------- /tests/benchmark_normal.cpp: -------------------------------------------------------------------------------- 1 | 2 | #define FN_LOG_MAX_CHANNEL_SIZE 5 3 | #define FN_LOG_MAX_LOG_SIZE 1000 4 | #define FN_LOG_MAX_LOG_QUEUE_SIZE 100000 5 | #include "fn_log.h" 6 | 7 | static const std::string example_config_text = 8 | R"----( 9 | # 压测配表 10 | # 0通道为异步模式写文件, info多线程文件输出和一个CATEGORY筛选的屏显输出 11 | - channel: 0 12 | sync: null 13 | priority: trace 14 | category: 0 15 | category_extend: 0 16 | -device: 0 17 | disable: false 18 | out_type: file 19 | priority: trace 20 | category: 0 21 | category_extend: 0 22 | path: "./log/" 23 | file: "$PNAME" 24 | rollback: 4 25 | limit_size: 100 m #only support M byte 26 | -device:1 27 | disable: false 28 | out_type: screen 29 | category: 1 30 | category_extend: 1 31 | # 1 异步空 32 | - channel: 1 33 | 34 | # 2通道为同步写文件 35 | - channel: 2 36 | sync: sync #only support single thread 37 | -device: 0 38 | disable: false 39 | out_type: file 40 | file: "$PNAME_$YEAR" 41 | rollback: 4 42 | limit_size: 100 m #only support M byte 43 | 44 | # 3通道为同步空 45 | - channel: 3 46 | sync: sync #only support single thread 47 | 48 | 49 | # 4通道为异步,输出到虚拟设备 50 | - channel: 4 51 | sync: null #only support single thread 52 | -device: 0 53 | disable: false 54 | out_type: virtual 55 | file: "$PNAME_virtual" 56 | rollback: 4 57 | limit_size: 100 m #only support M byte 58 | )----"; 59 | 60 | std::string ChannelDesc(int channel_type) 61 | { 62 | switch (channel_type) 63 | { 64 | case FNLog::CHANNEL_ASYNC: 65 | return "async thread write"; 66 | case FNLog::CHANNEL_SYNC: 67 | return "sync write"; 68 | } 69 | return "invalid channel"; 70 | } 71 | 72 | 73 | void MyVirtualDevice(const FNLog::LogData& log) 74 | { 75 | //printf("%s", log.content_ + log.prefix_len_); 76 | } 77 | 78 | int main(int argc, char *argv[]) 79 | { 80 | int ret = FNLog::FastStartDefaultLogger(example_config_text); 81 | if (ret != 0) 82 | { 83 | return ret; 84 | } 85 | FNLog::SetVirtualDevice(&MyVirtualDevice); 86 | FNLog::Logger& logger = FNLog::GetDefaultLogger(); 87 | 88 | unsigned int total_count = 0; 89 | for (int i = 0; i < logger.shm_->channel_size_; i++) 90 | { 91 | total_count = 0; 92 | long long last = std::chrono::duration_cast(std::chrono::system_clock::now().time_since_epoch()).count(); 93 | do 94 | { 95 | LogDebugStream(i, 0, 0).write_buffer("rrrrrrrrrrrrrrrrrrrradfads33333333333333rrd", 96 | sizeof("rrrrrrrrrrrrrrrrrrrradfads33333333333333rrd") - 1) 97 | << -23 << ": " << 32.2223 << (void*) nullptr; 98 | 99 | if (total_count %1000000 == 0) 100 | { 101 | 102 | long long now = std::chrono::duration_cast(std::chrono::system_clock::now().time_since_epoch()).count(); 103 | if (total_count > 0) 104 | { 105 | LogInfoStream(0, 1, 0) << "channel:<" << (long long)i << "> " 106 | << ChannelDesc(logger.shm_->channels_[i].channel_type_) << " <" 107 | << logger.shm_->channels_[i].device_size_ << "> test " << total_count * 1000 / (now - last) << " line/sec. "; 108 | 109 | long long ticks = FNLog::GetDefaultLogger().tick_count_; 110 | long long sum = FNLog::GetDefaultLogger().tick_sum_; 111 | LogAlarmStream(0, 1, 0) << "logs:" << ticks << ", sum:" << sum 112 | << ", avg:" << sum / (ticks > 0 ? ticks : 1); 113 | 114 | break; 115 | } 116 | } 117 | } while (++total_count); 118 | } 119 | 120 | LogAlarmStream(0, 1, 0) << "finish"; 121 | return 0; 122 | } 123 | 124 | -------------------------------------------------------------------------------- /tests/benchmark_serialize_integer.cpp: -------------------------------------------------------------------------------- 1 | #include "fn_log.h" 2 | 3 | 4 | 5 | 6 | static const std::string example_config_text = 7 | R"----( 8 | - channel: 0 9 | sync: sync 10 | -device: 0 11 | disable: false 12 | out_type: screen 13 | priority: info 14 | 15 | )----"; 16 | 17 | int main(int argc, char *argv[]) 18 | { 19 | int ret = FNLog::FastStartDefaultLogger(example_config_text); 20 | if (ret != 0) 21 | { 22 | return ret; 23 | } 24 | 25 | 26 | unsigned int total_count = 0; 27 | 28 | total_count = 0; 29 | volatile unsigned long long active = 0; 30 | do 31 | { 32 | char buf[30]; 33 | 34 | FNLog::write_dec_unsafe<2>(buf, (long long)rand()); 35 | active += buf[3]; 36 | if (total_count %10000000 == 0) 37 | { 38 | static long long last = std::chrono::duration_cast(std::chrono::system_clock::now().time_since_epoch()).count(); 39 | long long now = std::chrono::duration_cast(std::chrono::system_clock::now().time_since_epoch()).count(); 40 | if (total_count > 0) 41 | { 42 | LogAlarm() << " test " << 10000000*1000ULL / (now - last) << " line/sec. "; 43 | last = now; 44 | break; 45 | } 46 | } 47 | } while (++total_count); 48 | 49 | 50 | LogAlarm() << "finish"; 51 | return 0; 52 | } 53 | 54 | -------------------------------------------------------------------------------- /tests/benchmark_sync_bat_write.cpp: -------------------------------------------------------------------------------- 1 | #include "fn_log.h" 2 | 3 | 4 | 5 | 6 | static const std::string example_config_text = 7 | R"----( 8 | - channel: 0 9 | sync: sync 10 | -device: 0 11 | disable: false 12 | out_type: screen 13 | priority: info 14 | 15 | )----"; 16 | 17 | int main(int argc, char *argv[]) 18 | { 19 | int ret = FNLog::FastStartDefaultLogger(example_config_text); 20 | if (ret != 0) 21 | { 22 | return ret; 23 | } 24 | 25 | unsigned int total_count = 0; 26 | 27 | total_count = 0; 28 | do 29 | { 30 | LogDebug().write_buffer("rrrrrrrrrrrrrrrrrrrradfads33333333333333rrd", 31 | sizeof("rrrrrrrrrrrrrrrrrrrradfads33333333333333rrd") - 1) 32 | << -23 << ": " << 32.2223 << (void*) nullptr; 33 | 34 | if (total_count %10000000 == 0) 35 | { 36 | static long long last = std::chrono::duration_cast(std::chrono::system_clock::now().time_since_epoch()).count(); 37 | long long now = std::chrono::duration_cast(std::chrono::system_clock::now().time_since_epoch()).count(); 38 | if (total_count > 0) 39 | { 40 | LogAlarm() << " test " << 10000000*1000ULL / (now - last) << " line/sec."; 41 | last = now; 42 | break; 43 | } 44 | } 45 | } while (++total_count); 46 | 47 | 48 | LogAlarm() << "finish"; 49 | return 0; 50 | } 51 | 52 | -------------------------------------------------------------------------------- /tests/benchmark_udp.cpp: -------------------------------------------------------------------------------- 1 | #define FN_LOG_MAX_CHANNEL_SIZE 4 2 | #include "fn_log.h" 3 | 4 | static const std::string example_config_text = 5 | R"----( 6 | # 压测配表 7 | # 异步UDP 8 | - channel: 0 9 | sync: null 10 | priority: trace 11 | category: 0 12 | category_extend: 0 13 | -device: 0 14 | disable: false 15 | out_type: udp 16 | udp_addr: 127.0.0.1:9909 17 | priority: trace 18 | category: 0 19 | category_extend: 0 20 | path: "./log/" 21 | file: "$PNAME_$YEAR$MON$DAY" 22 | rollback: 4 23 | limit_size: 100 m #only support M byte 24 | -device:1 25 | disable: false 26 | out_type: screen 27 | category: 1 28 | category_extend: 1 29 | # 1通道为异步空设备 30 | - channel: 1 31 | 32 | # 2通道为同步UDP 33 | - channel: 2 34 | sync: sync #only support single thread 35 | -device: 0 36 | disable: false 37 | out_type: udp 38 | udp_addr: 127.0.0.1:9909 39 | file: "$PNAME_$YEAR" 40 | rollback: 4 41 | limit_size: 100 m #only support M byte 42 | 43 | # 3通道为同步空设备 44 | - channel: 3 45 | sync: sync #only support single thread 46 | 47 | )----"; 48 | 49 | std::string ChannelDesc(int channel_type) 50 | { 51 | switch (channel_type) 52 | { 53 | case FNLog::CHANNEL_ASYNC: 54 | return "async thread write"; 55 | case FNLog::CHANNEL_SYNC: 56 | return "sync write"; 57 | } 58 | return "invalid channel"; 59 | } 60 | 61 | #define Now() std::chrono::duration(std::chrono::system_clock::now().time_since_epoch()).count() 62 | 63 | int main(int argc, char *argv[]) 64 | { 65 | int ret = FNLog::FastStartDefaultLogger(example_config_text); 66 | if (ret != 0) 67 | { 68 | return ret; 69 | } 70 | #ifdef WIN32 71 | 72 | WSADATA wsaData; 73 | if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0) 74 | { 75 | printf("%s", "WSAStartup error.\n"); 76 | return -1; 77 | } 78 | #endif 79 | FNLog::Logger& logger = FNLog::GetDefaultLogger(); 80 | LogAlarmStream(0, 1, 0) << "begin"; 81 | unsigned int total_count = 0; 82 | double begin = Now(); 83 | double last = Now(); 84 | for (int i = 0; i < logger.shm_->channel_size_; i++) 85 | { 86 | total_count = 0; 87 | do 88 | { 89 | LogDebugStream(i, 0, 0).write_buffer("rrrrrrrrrrrrrrrrrrrradfads33333333333333rrd", 90 | sizeof("rrrrrrrrrrrrrrrrrrrradfads33333333333333rrd") - 1) 91 | << -23 << ": " << 32.2223 << (void*) nullptr; 92 | 93 | if (total_count %100000 == 0) 94 | { 95 | double now = Now(); 96 | if (total_count > 0 && now - last > 0.0001f) 97 | { 98 | LogInfoStream(0, 1, 0) << "channel:<" << (long long)i << "> " 99 | << ChannelDesc(logger.shm_->channels_[i].channel_type_) << " <" 100 | << logger.shm_->channels_[i].device_size_ << "> test " << 100000ULL / (now - last) << "line/sec."; 101 | 102 | 103 | double now = Now(); 104 | FNLog::Channel& channel = FNLog::GetDefaultLogger().shm_->channels_[i]; 105 | 106 | long long sc = FNLog::AtomicLoadDeviceLog(channel, 0, FNLog::DEVICE_LOG_TOTAL_WRITE_LINE); 107 | long long sl = FNLog::AtomicLoadDeviceLog(channel, 0, FNLog::DEVICE_LOG_TOTAL_LOSE_LINE); 108 | if (sc > 0) 109 | { 110 | LogInfoStream(0, 1, 0) << "channel:<" << (long long)i << "> " 111 | << ChannelDesc(logger.shm_->channels_[i].channel_type_) << " <" 112 | << logger.shm_->channels_[i].device_size_ << ">" 113 | << " lose/total:" << sl << "/" << sc << ", lose:" << sl * 100.0 / sc << "%, real per second:" << (sc - sl) / ((now - begin)); 114 | } 115 | 116 | break; 117 | } 118 | } 119 | 120 | } while (++total_count); 121 | } 122 | 123 | 124 | 125 | 126 | LogAlarmStream(0, 1, 0) << "finish"; 127 | return 0; 128 | } 129 | 130 | -------------------------------------------------------------------------------- /tests/benchmark_virtual_device.cpp: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | #define FN_LOG_MAX_CHANNEL_SIZE 4 5 | #define FN_LOG_MAX_LOG_SIZE 1000 6 | #define FN_LOG_MAX_LOG_QUEUE_SIZE 100000 7 | 8 | #include "fn_log.h" 9 | 10 | 11 | static const std::string example_config_text = 12 | R"----( 13 | # 压测配表 14 | # 0通道为异步模式写文件, info多线程文件输出和一个CATEGORY筛选的屏显输出 15 | - channel: 0 16 | sync: null 17 | priority: trace 18 | category: 0 19 | category_extend: 0 20 | -device: 0 21 | disable: false 22 | out_type: file 23 | priority: trace 24 | category: 0 25 | category_extend: 0 26 | path: "./log/" 27 | file: "$PNAME" 28 | rollback: 4 29 | limit_size: 100 m #only support M byte 30 | -device:1 31 | disable: false 32 | out_type: screen 33 | category: 1 34 | category_extend: 1 35 | -device:2 36 | disable: false 37 | out_type: screen 38 | category: 10 39 | category_extend: 1 40 | -device:3 41 | disable: false 42 | out_type: screen 43 | category: 100 44 | category_extend: 1 45 | -device:4 46 | disable: false 47 | out_type: screen 48 | category: 10 49 | category_extend: 1 50 | -device:5 51 | disable: false 52 | out_type: screen 53 | category: 10 54 | category_extend: 1 55 | -device:6 56 | disable: false 57 | out_type: screen 58 | category: 10 59 | category_extend: 1 60 | -device:7 61 | disable: false 62 | out_type: screen 63 | category: 10 64 | category_extend: 1 65 | -device:8 66 | disable: false 67 | out_type: screen 68 | category: 10 69 | category_extend: 1 70 | -device:9 71 | disable: false 72 | out_type: screen 73 | category: 100 74 | category_extend: 1 75 | -device:10 76 | disable: false 77 | out_type: screen 78 | category: 10 79 | category_extend: 1 80 | -device:11 81 | disable: false 82 | out_type: screen 83 | category: 11 84 | category_extend: 1 85 | -device:12 86 | disable: false 87 | out_type: screen 88 | category: 12 89 | category_extend: 1 90 | 91 | # 1 异步空 92 | - channel: 1 93 | -device: 0 94 | disable: false 95 | out_type: vm 96 | priority: trace 97 | category: 0 98 | category_extend: 0 99 | # 2通道为同步写文件 100 | - channel: 2 101 | sync: sync #only support single thread 102 | priority: trace 103 | -device: 0 104 | disable: false 105 | out_type: file 106 | priority: trace 107 | file: "$PNAME_$YEAR" 108 | rollback: 4 109 | limit_size: 100 m #only support M byte 110 | 111 | # 3通道为同步空 112 | - channel: 3 113 | sync: sync #only support single thread 114 | 115 | )----"; 116 | 117 | std::string ChannelDesc(int channel_type) 118 | { 119 | switch (channel_type) 120 | { 121 | case FNLog::CHANNEL_ASYNC: 122 | return "async thread write"; 123 | case FNLog::CHANNEL_SYNC: 124 | return "sync write"; 125 | } 126 | return "invalid channel"; 127 | } 128 | 129 | #define Now() std::chrono::duration(std::chrono::system_clock::now().time_since_epoch()).count() 130 | 131 | long long g_virtual_device_write_count = 0; 132 | void VirtualDevice(const FNLog::LogData& log) 133 | { 134 | FNLog::TransmitChannel(FNLog::GetDefaultLogger(), 0, log.category_, log.identify_, log); 135 | } 136 | 137 | int main(int argc, char *argv[]) 138 | { 139 | int ret = FNLog::FastStartDefaultLogger(example_config_text); 140 | if (ret != 0) 141 | { 142 | return ret; 143 | } 144 | FNLog::SetVirtualDevice(&VirtualDevice); 145 | 146 | LogAlarmStream(0, 1, 0) << "begin test. screen channel 0, 1, 0 "; 147 | 148 | long long loop_count = 500000; 149 | 150 | double now = Now(); 151 | 152 | now = Now(); 153 | for (long long i = 0; i < loop_count; i++) 154 | { 155 | LogTraceStream(0, 0, 0) << "asdf" << i << ", " << 2.3 << "asdfasdf from channel 2" << "asdfasdf from channel 1"; 156 | } 157 | LogAlarmStream(0, 1, 0) << "loop:" << loop_count << ", per log used:" << (Now() - now) * 1000 * 1000 * 1000 / loop_count << " ns"; 158 | now = Now(); 159 | 160 | if (true) 161 | { 162 | now = Now(); 163 | FNLog::LogStream ls(std::move(LogTraceStream(1, 0, 0) << "s")); 164 | ls << "asdf" << 0 << ", " << 2.3 << "asdfasdf from channel 2" << "asdfasdf from channel 1"; 165 | for (long long i = 0; i < loop_count; i++) 166 | { 167 | (*FNLog::RefVirtualDevice())(*ls.log_data_); 168 | } 169 | LogAlarmStream(0, 1, 0) << "loop:" << loop_count << ", per log used:" << (Now() - now) * 1000 * 1000 * 1000 / loop_count << " ns"; 170 | now = Now(); 171 | } 172 | 173 | 174 | 175 | 176 | 177 | now = Now(); 178 | for (long long i = 0; i < loop_count; i++) 179 | { 180 | LogTraceStream(1, 0, 0) << "asdf" << i << ", " << 2.3 << "asdfasdf from channel 2" << "asdfasdf from channel 1"; 181 | } 182 | LogAlarmStream(0, 1, 0) << "loop:" << loop_count <<", per log used:" << (Now() - now)*1000*1000*1000/ loop_count << " ns"; 183 | now = Now(); 184 | for (long long i = 0; i < loop_count; i++) 185 | { 186 | LOG_TRACE(1, 0, 0, "asdf" << i << ", " << 2.3 << "asdfasdf from channel 1"); 187 | } 188 | LogAlarmStream(0, 1, 0) << "loop:" << loop_count << ", per log used:" << (Now() - now) * 1000 * 1000 * 1000 / loop_count << " ns"; 189 | now = Now(); 190 | for (long long i = 0; i < loop_count; i++) 191 | { 192 | LogTracePack(1, 0, 0, "asdf" , i , ", " , 2.3 , "asdfasdf. from channel 1" ); 193 | } 194 | LogAlarmStream(0, 1, 0) << "loop:" << loop_count << ", per log used:" << (Now() - now) * 1000 * 1000 * 1000 / loop_count << " ns"; 195 | 196 | FNLog::Logger& logger = FNLog::GetDefaultLogger(); 197 | 198 | 199 | for (int i = 0; i < logger.shm_->channel_size_; i++) 200 | { 201 | unsigned int total_count = 0; 202 | now = Now(); 203 | do 204 | { 205 | 206 | LOG_STREAM_DEFAULT_LOGGER(i, FNLog::PRIORITY_DEBUG, 0, 0, FNLog::LOG_PREFIX_NULL) 207 | .write_buffer("rrrrrrrrrrrrrrrrrrrradfads33333333333333rrd", 208 | sizeof("rrrrrrrrrrrrrrrrrrrradfads33333333333333rrd") - 1); 209 | 210 | //LOG_TRACE(i, 0, 0, "asdf" << i << ", " << 2.3 << "asdfasdf from channel 2"); 211 | 212 | if (total_count % loop_count == 0 && total_count != 0) 213 | { 214 | LogInfoStream(0, 1, 0) << "channel:<" << (long long)i << "> " 215 | << ChannelDesc(logger.shm_->channels_[i].channel_type_) << " write file:<" 216 | << logger.shm_->channels_[i].device_size_ << "> prof: " << (Now() - now) * 1000.0 * 1000.0 * 1000.0 / total_count << " ns. "; 217 | break; 218 | } 219 | } while (++total_count); 220 | } 221 | 222 | LogAlarmStream(0, 1, 0) << "finish"; 223 | return 0; 224 | } 225 | 226 | -------------------------------------------------------------------------------- /tests/stress_block_in.cpp: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | #define FN_LOG_MAX_CHANNEL_SIZE 4 5 | #define FN_LOG_MAX_LOG_SIZE 1000 6 | #define FN_LOG_MAX_LOG_QUEUE_SIZE 100000 7 | 8 | #include "fn_log.h" 9 | 10 | 11 | static const std::string example_config_text = 12 | R"----( 13 | # 压测配表 14 | # 0通道为异步模式写文件, info多线程文件输出和一个CATEGORY筛选的屏显输出 15 | - channel: 0 16 | sync: null 17 | priority: trace 18 | category: 0 19 | category_extend: 0 20 | -device: 0 21 | disable: false 22 | out_type: screen 23 | priority: trace 24 | category: 0 25 | category_extend: 1 26 | path: "./log/" 27 | file: "$PNAME_00" 28 | rollback: 4 29 | limit_size: 100 m #only support M byte 30 | -device: 1 31 | disable: false 32 | out_type: file 33 | priority: debug 34 | category: 1 35 | category_extend: 1 36 | path: "./log/" 37 | file: "$PNAME_01" 38 | rollback: 4 39 | limit_size: 100 m #only support M byte 40 | -device: 2 41 | disable: false 42 | out_type: file 43 | priority: trace 44 | category: 8 45 | category_extend: 9 46 | path: "./log/" 47 | file: "$PNAME_02" 48 | rollback: 4 49 | limit_size: 100 m #only support M byte 50 | -device: 3 51 | disable: false 52 | out_type: file 53 | priority: trace 54 | category: 3 55 | category_extend: 3 56 | path: "./log/" 57 | file: "$PNAME_03" 58 | rollback: 4 59 | limit_size: 100 m #only support M byte 60 | -device: 4 61 | disable: false 62 | out_type: file 63 | priority: trace 64 | category_wlist: 0, 4,5 65 | path: "./log/" 66 | file: "$PNAME_04" 67 | rollback: 4 68 | limit_size: 100 m #only support M byte 69 | -device: 5 70 | disable: false 71 | out_type: file 72 | priority: trace 73 | category_wlist: 4,5 74 | identify_wlist: 0,1,4,7,16,36,46 75 | path: "./log/" 76 | file: "$PNAME_05" 77 | rollback: 4 78 | limit_size: 100 m #only support M byte 79 | -device: 6 80 | disable: false 81 | out_type: file 82 | priority: trace 83 | category_wlist: 4,8 84 | category_wlist: 0,1,4,7,16,36,46 85 | path: "./log/" 86 | file: "$PNAME_06" 87 | rollback: 4 88 | limit_size: 100 m #only support M byte 89 | -device: 7 90 | disable: false 91 | out_type: file 92 | priority: trace 93 | identify: 6 94 | identify_extend: 1 95 | path: "./log/" 96 | file: "$PNAME_07" 97 | rollback: 4 98 | limit_size: 100 m #only support M byte 99 | -device: 8 100 | disable: false 101 | out_type: file 102 | priority: trace 103 | category: 0 104 | category_extend: 1 105 | identify: 6 106 | identify_extend: 1 107 | path: "./log/" 108 | file: "$PNAME_08" 109 | rollback: 4 110 | limit_size: 100 m #only support M byte 111 | -device: 9 112 | disable: false 113 | out_type: file 114 | priority: trace 115 | category: 9 116 | category_extend: 10 117 | identify: 9 118 | identify_extend: 10 119 | path: "./log/" 120 | file: "$PNAME_09" 121 | rollback: 4 122 | limit_size: 100 m #only support M byte 123 | -device: 10 124 | disable: false 125 | out_type: file 126 | priority: trace 127 | category: 9 128 | category_extend: 10 129 | identify: 69 130 | identify_extend: 10 131 | path: "./log/" 132 | file: "$PNAME_10" 133 | rollback: 4 134 | limit_size: 100 m #only support M byte 135 | -device: 11 136 | disable: false 137 | out_type: file 138 | priority: trace 139 | category: 9 140 | category_extend: 10 141 | identify: 19 142 | identify_extend: 10 143 | path: "./log/" 144 | file: "$PNAME_11" 145 | rollback: 4 146 | limit_size: 100 m #only support M byte 147 | -device: 12 148 | disable: false 149 | out_type: file 150 | priority: debug 151 | category: 9 152 | category_extend: 10 153 | identify: 999 154 | identify_extend: 10 155 | path: "./log/" 156 | file: "$PNAME_12" 157 | rollback: 4 158 | limit_size: 100 m #only support M byte 159 | -device: 13 160 | disable: false 161 | out_type: file 162 | priority: trace 163 | category: 9 164 | category_extend: 10 165 | identify: 9999 166 | identify_extend: 10 167 | path: "./log/" 168 | file: "$PNAME_13" 169 | rollback: 4 170 | limit_size: 100 m #only support M byte 171 | -device: 14 172 | disable: false 173 | out_type: file 174 | priority: trace 175 | category: 9 176 | category_extend: 10 177 | identify: 79 178 | identify_extend: 10 179 | path: "./log/" 180 | file: "$PNAME_14" 181 | rollback: 4 182 | limit_size: 100 m #only support M byte 183 | -device: 15 184 | disable: false 185 | out_type: file 186 | priority: trace 187 | category: 69 188 | category_extend: 10 189 | identify: 9 190 | identify_extend: 10 191 | path: "./log/" 192 | file: "$PNAME_15" 193 | rollback: 4 194 | limit_size: 100 m #only support M byte 195 | -device: 16 196 | disable: false 197 | out_type: file 198 | priority: trace 199 | category: 59 200 | category_extend: 10 201 | identify: 9 202 | identify_extend: 10 203 | path: "./log/" 204 | file: "$PNAME_16" 205 | rollback: 4 206 | limit_size: 100 m #only support M byte 207 | 208 | # 1 异步空 209 | - channel: 1 210 | 211 | # 2通道为同步写文件 212 | - channel: 2 213 | sync: sync #only support single thread 214 | -device: 0 215 | disable: false 216 | out_type: file 217 | file: "$PNAME_$YEAR" 218 | rollback: 4 219 | limit_size: 100 m #only support M byte 220 | 221 | # 3通道为同步空 222 | - channel: 3 223 | sync: sync #only support single thread 224 | 225 | )----"; 226 | 227 | std::string ChannelDesc(int channel_type) 228 | { 229 | switch (channel_type) 230 | { 231 | case FNLog::CHANNEL_ASYNC: 232 | return "async thread write"; 233 | case FNLog::CHANNEL_SYNC: 234 | return "sync write"; 235 | } 236 | return "invalid channel"; 237 | } 238 | 239 | #define Now() std::chrono::duration(std::chrono::system_clock::now().time_since_epoch()).count() 240 | 241 | int main(int argc, char *argv[]) 242 | { 243 | int ret = FNLog::FastStartDefaultLogger(example_config_text); 244 | if (ret != 0) 245 | { 246 | return ret; 247 | } 248 | 249 | //base test 250 | if (true) 251 | { 252 | long long loop_count = 1000000; 253 | double now = Now(); 254 | for (long long i = 0; i < loop_count; i++) 255 | { 256 | LogInfoStream(0, 1, 0) << "asdf" << i << ", " << 2.3 << "asdfasdffffffffffffffffffffffffffffffffffffffff"; 257 | } 258 | LogAlarmStream(0, 0, 0) << "per log used " << (Now() - now) * 1000 * 1000 * 1000 / loop_count << "ns"; 259 | 260 | loop_count = 10000000; 261 | now = Now(); 262 | for (long long i = 0; i < loop_count; i++) 263 | { 264 | LogTraceStream(0, 567, 986) << "asdf" << i << ", " << 2.3 << "asdfasdffffffffffffffffffffffffffffffffffffffff"; 265 | } 266 | LogAlarmStream(0, 0, 0) << "per empty log used " << (Now() - now) * 1000 * 1000 * 1000 / loop_count << "ns"; 267 | } 268 | 269 | LogAlarmStream(0, 0, 0) << "finish"; 270 | return 0; 271 | } 272 | 273 | -------------------------------------------------------------------------------- /tests/stress_multi-thread-env_concurrent_reboot.cpp: -------------------------------------------------------------------------------- 1 | #include "fn_log.h" 2 | #include 3 | 4 | 5 | 6 | static const std::string example_config_text = 7 | R"----( 8 | # info and high priority log print to screen 9 | - channel: 0 10 | sync: null 11 | -device:0 12 | disable: false 13 | out_type: screen 14 | priority: info 15 | 16 | - channel: 1 17 | 18 | )----"; 19 | 20 | int total_loop_ = 80000; 21 | int cur_loop_ = 0; 22 | std::atomic stop_cnt(0); 23 | std::atomic stop_ok(0); 24 | std::atomic start_cnt(0); 25 | std::atomic start_ok(0); 26 | void thread_proc(int index) 27 | { 28 | LogInfo() << "thread:<" << index << "> begin."; 29 | FNLog::Logger& logger = FNLog::GetDefaultLogger(); 30 | while (cur_loop_ < total_loop_) 31 | { 32 | if (logger.logger_state_ == FNLog::LOGGER_STATE_RUNNING) 33 | { 34 | cur_loop_++; 35 | } 36 | LogDebug().write_buffer("rrrrrrrrrrrrrrrrrrrradfads33333333333333rrd", 37 | sizeof("rrrrrrrrrrrrrrrrrrrradfads33333333333333rrd") - 1); 38 | if (cur_loop_%200 == 0) 39 | { 40 | LogInfo() << "already loop:" << cur_loop_; 41 | if (logger.logger_state_ == FNLog::LOGGER_STATE_RUNNING) 42 | { 43 | int ret = FNLog::StopLogger(FNLog::GetDefaultLogger()); 44 | if (ret == FNLog::E_SUCCESS) 45 | { 46 | stop_ok += 1; 47 | } 48 | stop_cnt += 1; 49 | } 50 | } 51 | if (logger.logger_state_ == FNLog::LOGGER_STATE_UNINIT) 52 | { 53 | int ret = FNLog::FastStartDefaultLogger(); 54 | if (ret == FNLog::E_SUCCESS) 55 | { 56 | start_ok += 1; 57 | } 58 | start_cnt += 1; 59 | } 60 | } 61 | LogInfo() << "thread:<" << index << "> end."; 62 | } 63 | 64 | const int WRITE_THREAD_COUNT = 6; 65 | std::thread g_multi_proc[WRITE_THREAD_COUNT]; 66 | 67 | void Stop(int signo) 68 | { 69 | printf("%s", "oops! stop!!!\n"); 70 | _exit(0); 71 | } 72 | 73 | #ifndef WIN32 74 | #define _dup dup 75 | #define _dup2 dup2 76 | #define _fileno fileno 77 | #endif // WIN32 78 | 79 | 80 | int main(int argc, char* argv[]) 81 | { 82 | signal(SIGINT, Stop); 83 | 84 | FNLog::FastStartDefaultLogger(); 85 | LogInfo() << "begin test..."; 86 | std::this_thread::sleep_for(std::chrono::milliseconds(500)); 87 | 88 | 89 | //int fd = _dup(_fileno(stdout)); 90 | int fd = _dup(1); 91 | #ifndef WIN32 92 | int n = open("/dev/null", O_WRONLY); 93 | _dup2(n, 1); 94 | #else 95 | int n = open("NUL", _O_WRONLY); 96 | _dup2(n, 1); 97 | #endif // WIN32 98 | 99 | 100 | 101 | //freopen("./printf.log", "a+", stdout); 102 | 103 | if (argc > 1) 104 | { 105 | total_loop_ = atoi(argv[1]); 106 | } 107 | for (int i = 0; i < WRITE_THREAD_COUNT; i++) 108 | { 109 | g_multi_proc[i] = std::thread(thread_proc, i); 110 | } 111 | 112 | for (int i = 0; i < WRITE_THREAD_COUNT; i++) 113 | { 114 | if (g_multi_proc[i].joinable()) 115 | { 116 | g_multi_proc[i].join(); 117 | } 118 | } 119 | 120 | _dup2(fd, 1); 121 | 122 | FNLog::FastStartDefaultLogger(); 123 | 124 | LogInfo() << "start ok/total:" << (int)start_ok << "/" << (int)start_cnt << ", start ok rate:" << start_ok * 100 / start_cnt << "%"; 125 | LogInfo() << "stop ok/total:" << (int)stop_ok << "/" << (int)stop_cnt << ", stop ok rate:" << stop_ok * 100 / stop_cnt << "%"; 126 | if (start_ok <= 0 || stop_ok <= 0) 127 | { 128 | return -1; 129 | } 130 | return 0; 131 | } 132 | 133 | -------------------------------------------------------------------------------- /tests/stress_multi-thread-env_main_reboot.cpp: -------------------------------------------------------------------------------- 1 | #include "fn_log.h" 2 | #include 3 | 4 | 5 | 6 | static const std::string example_config_text = 7 | R"----( 8 | # info and high priority log print to screen 9 | - channel: 0 10 | sync: null 11 | -device:0 12 | disable: false 13 | out_type: screen 14 | priority: info 15 | 16 | - channel: 1 17 | 18 | )----"; 19 | 20 | 21 | 22 | enum State 23 | { 24 | WAIT, 25 | WRITE, 26 | END 27 | }; 28 | 29 | State state = WRITE; 30 | 31 | void thread_proc(int index) 32 | { 33 | LogInfo() << "thread:<" << index << "> begin."; 34 | while (state != END) 35 | { 36 | if (state == WRITE) 37 | { 38 | LogDebug().write_buffer("rrrrrrrrrrrrrrrrrrrradfads33333333333333rrd", 39 | sizeof("rrrrrrrrrrrrrrrrrrrradfads33333333333333rrd") - 1) 40 | << -23 << ": " << 32.2223 << (void*) nullptr; 41 | } 42 | else 43 | { 44 | std::this_thread::sleep_for(std::chrono::milliseconds(100)); 45 | } 46 | } 47 | LogInfo() << "thread:<" << index << "> end."; 48 | } 49 | 50 | const int WRITE_THREAD_COUNT = 6; 51 | std::thread g_multi_proc[WRITE_THREAD_COUNT]; 52 | 53 | void Stop(int signo) 54 | { 55 | printf("%s", "oops! stop!!!\n"); 56 | _exit(0); 57 | } 58 | 59 | 60 | int main(int argc, char* argv[]) 61 | { 62 | signal(SIGINT, Stop); 63 | int ret = FNLog::FastStartDefaultLogger(); 64 | if (ret != 0) 65 | { 66 | return ret; 67 | } 68 | 69 | FNLog::Logger& logger = FNLog::GetDefaultLogger(); 70 | 71 | int limit_second = 12; 72 | for (int i = 0; i < WRITE_THREAD_COUNT; i++) 73 | { 74 | g_multi_proc[i] = std::thread(thread_proc, i); 75 | } 76 | 77 | for (int i = 0; i < limit_second; i++) 78 | { 79 | long long last_writed = AtomicLoadChannelLog(logger.shm_->channels_[0], FNLog::CHANNEL_LOG_PROCESSED); 80 | std::this_thread::sleep_for(std::chrono::milliseconds(1000)); 81 | long long now_writed = AtomicLoadChannelLog(logger.shm_->channels_[0], FNLog::CHANNEL_LOG_PROCESSED); 82 | LogInfo() << "writed:" << now_writed - last_writed ; 83 | 84 | if (i%3 == 0) 85 | { 86 | int ret = FNLog::StopLogger(logger); 87 | if (ret != 0) 88 | { 89 | return -1; 90 | } 91 | ret = FNLog::FastStartDefaultLogger(); 92 | if (ret != 0) 93 | { 94 | return -2; 95 | } 96 | } 97 | } 98 | 99 | LogAlarm() << "finish"; 100 | state = END; 101 | for (int i = 0; i < WRITE_THREAD_COUNT; i++) 102 | { 103 | if (g_multi_proc[i].joinable()) 104 | { 105 | g_multi_proc[i].join(); 106 | } 107 | } 108 | return 0; 109 | } 110 | 111 | -------------------------------------------------------------------------------- /tests/test_bitlist.cpp: -------------------------------------------------------------------------------- 1 | #include "fn_log.h" 2 | #define FNLOG_ASSERT(expr, prefix) \ 3 | { \ 4 | if (expr) \ 5 | { \ 6 | LogInfo() << "test " << prefix << " success."; \ 7 | } \ 8 | else \ 9 | { \ 10 | LogError() << "test " << prefix << " failed."; \ 11 | return __LINE__ * -1; \ 12 | } \ 13 | } 14 | 15 | static const std::string test_text = 16 | R"----( 17 | # info log print screen and all write file 18 | 19 | - channel: 0 20 | sync: sync 21 | - device:0 22 | disable: false 23 | out_type: screen 24 | priority: debug 25 | )----"; 26 | 27 | using namespace FNLog; 28 | int main(int argc, char* argv[]) 29 | { 30 | int ret = FastStartDefaultLogger(test_text); 31 | if (ret != 0 ) 32 | { 33 | return ret ; 34 | } 35 | 36 | 37 | 38 | unsigned long long bitmap; 39 | std::string buf; 40 | 41 | 42 | LogInfo() << "begin:" << LogTimestamp(); 43 | 44 | buf = "0"; 45 | bitmap = FNLog::ParseBitArray(buf.c_str(), buf.c_str() + buf.length()); 46 | FNLOG_ASSERT(bitmap == 1, ""); 47 | 48 | 49 | buf = "0,1"; 50 | bitmap = FNLog::ParseBitArray(buf.c_str(), buf.c_str() + buf.length()); 51 | FNLOG_ASSERT(bitmap == 3, ""); 52 | 53 | 54 | buf = "0,1,2"; 55 | bitmap = FNLog::ParseBitArray(buf.c_str(), buf.c_str() + buf.length()); 56 | FNLOG_ASSERT(bitmap == 7, ""); 57 | 58 | buf = "0-2"; 59 | bitmap = FNLog::ParseBitArray(buf.c_str(), buf.c_str() + buf.length()); 60 | FNLOG_ASSERT(bitmap == 7, ""); 61 | 62 | 63 | buf = "2-0"; 64 | bitmap = FNLog::ParseBitArray(buf.c_str(), buf.c_str() + buf.length()); 65 | FNLOG_ASSERT(bitmap == 7, ""); 66 | 67 | 68 | 69 | 70 | buf = "2-2"; 71 | bitmap = FNLog::ParseBitArray(buf.c_str(), buf.c_str() + buf.length()); 72 | FNLOG_ASSERT(bitmap == 4, ""); 73 | 74 | buf = "2"; 75 | bitmap = FNLog::ParseBitArray(buf.c_str(), buf.c_str() + buf.length()); 76 | FNLOG_ASSERT(bitmap == 4, ""); 77 | 78 | 79 | buf = " 2 - 0 , 2 - 3"; 80 | bitmap = FNLog::ParseBitArray(buf.c_str(), buf.c_str() + buf.length()); 81 | FNLOG_ASSERT(bitmap == 15, ""); 82 | 83 | buf = " , 2 - 0 , 2 - 3, "; 84 | bitmap = FNLog::ParseBitArray(buf.c_str(), buf.c_str() + buf.length()); 85 | FNLOG_ASSERT(bitmap == 15, ""); 86 | 87 | buf = " 0-18, 19- 24 "; 88 | bitmap = FNLog::ParseBitArray(buf.c_str(), buf.c_str() + buf.length()); 89 | FNLOG_ASSERT(bitmap == (1ULL << 25)-1, ""); 90 | 91 | buf = " 0-18, 19, 20, 24, 23, 22, 24, 21 "; 92 | bitmap = FNLog::ParseBitArray(buf.c_str(), buf.c_str() + buf.length()); 93 | FNLOG_ASSERT(bitmap == (1ULL << 25) - 1, ""); 94 | 95 | 96 | 97 | buf = " 0-18, 20- 24 "; 98 | bitmap = FNLog::ParseBitArray(buf.c_str(), buf.c_str() + buf.length()); 99 | FNLOG_ASSERT(bitmap != (1ULL << 25) - 1, ""); 100 | 101 | return 0; 102 | } 103 | -------------------------------------------------------------------------------- /tests/test_buffer.cpp: -------------------------------------------------------------------------------- 1 | #include "fn_log.h" 2 | 3 | static const std::string example_config_text = 4 | R"----( 5 | # info log print screen and all write file 6 | - channel: 0 7 | sync: null 8 | -device: 0 9 | disable: false 10 | out_type: file 11 | priority: trace 12 | path: "./log/" 13 | file: "$PNAME_$YEAR$MON$DAY" 14 | rollback: 4 15 | limit_size: 100 m #only support M byte 16 | -device:1 17 | disable: false 18 | out_type: screen 19 | priority: info 20 | 21 | )----"; 22 | 23 | int main(int argc, char* argv[]) 24 | { 25 | int ret = FNLog::FastStartDefaultLogger(example_config_text); 26 | if (ret != 0 ) 27 | { 28 | return ret ; 29 | } 30 | 31 | LogAlarm() << "log init success"; //sync write 32 | 33 | for (int i = 0; i < 1000; i++) 34 | { 35 | auto ls(std::move(LogDebug())); 36 | ls << "log begin test buffer"; 37 | int rd = 0; 38 | int last_len = 0; 39 | for (int j = 0; j < FNLog::LogData::LOG_SIZE; j++) 40 | { 41 | rd = rand() % 10; 42 | last_len = ls.log_data_->content_len_; 43 | switch (rd) 44 | { 45 | case 0: 46 | ls.write_hex_text("aaa", 3); 47 | break; 48 | case 1: 49 | ls.write_buffer("bbb", 3); 50 | break; 51 | case 2: 52 | ls << std::map({ {1,0.2}, {2, 0.3}, {4, 0.4} }); 53 | break; 54 | case 3: 55 | ls << 3.24; 56 | break; 57 | case 4: 58 | ls << 3.14f; 59 | break; 60 | case 5: 61 | ls << 'c'; 62 | break; 63 | case 6: 64 | ls << (unsigned char)('c'); 65 | break; 66 | case 7: 67 | ls << -5555523; 68 | break; 69 | case 8: 70 | ls << -92342342342LL; 71 | break; 72 | case 9: 73 | ls << 3242343242342ULL; 74 | break; 75 | default: 76 | break; 77 | } 78 | int length = ls.log_data_->content_len_; 79 | if (length > FNLog::LogData::LOG_SIZE) 80 | { 81 | LogFatal() << "error len:" << length; 82 | return -1; 83 | } 84 | } 85 | (void) rd; 86 | (void) last_len; 87 | 88 | } 89 | LogAlarm() << "finish"; 90 | 91 | return 0; 92 | } 93 | -------------------------------------------------------------------------------- /tests/test_buffer_correct.cpp: -------------------------------------------------------------------------------- 1 | #include "fn_log.h" 2 | 3 | using namespace FNLog; 4 | 5 | #define FNLOG_ASSERT(expr, prefix) \ 6 | { \ 7 | if (expr) \ 8 | { \ 9 | LogInfo() << "test " << prefix << " success."; \ 10 | } \ 11 | else \ 12 | { \ 13 | LogError() << "test " << prefix << " failed."; \ 14 | return __LINE__ * -1; \ 15 | } \ 16 | } 17 | 18 | int main(int argc, char* argv[]) 19 | { 20 | int ret = FNLog::FastStartDefaultLogger(); 21 | if (ret != 0) 22 | { 23 | return ret; 24 | } 25 | 26 | char buffer[100]; 27 | 28 | memset(buffer, 0, sizeof(buffer)); 29 | FNLOG_ASSERT((write_dec_unsafe<2>(buffer, 2ULL) == 2), "write integer wide1"); 30 | FNLOG_ASSERT(buffer[0] == '0', nullptr); 31 | FNLOG_ASSERT(buffer[1] == '2', nullptr); 32 | 33 | memset(buffer, 0, sizeof(buffer)); 34 | FNLOG_ASSERT((write_dec_unsafe<3>(buffer, -2LL) == 3), "write integer wide2"); 35 | FNLOG_ASSERT(buffer[0] == '-', nullptr); 36 | FNLOG_ASSERT(buffer[1] == '0', nullptr); 37 | FNLOG_ASSERT(buffer[2] == '2', nullptr); 38 | 39 | memset(buffer, 0, sizeof(buffer)); 40 | FNLOG_ASSERT((write_hex_unsafe<3>(buffer, (unsigned long long)UINT64_MAX) == 16), "write integer hex UINT64 MAX"); 41 | FNLOG_ASSERT(buffer[0] == 'F', nullptr); 42 | FNLOG_ASSERT(buffer[7] == 'F', nullptr); 43 | FNLOG_ASSERT(buffer[16] == '\0', nullptr); 44 | 45 | memset(buffer, 0, sizeof(buffer)); 46 | FNLOG_ASSERT((write_hex_unsafe<3>(buffer, (unsigned long long)UINT64_MAX/2) == 16), "write integer hex UINT64 HALF"); 47 | FNLOG_ASSERT(buffer[0] == '7', nullptr); 48 | FNLOG_ASSERT(buffer[7] == 'F', nullptr); 49 | FNLOG_ASSERT(buffer[16] == '\0', nullptr); 50 | 51 | memset(buffer, 0, sizeof(buffer)); 52 | FNLOG_ASSERT((write_hex_unsafe<3>(buffer, ~((unsigned long long)0xf0000000 << 32)) == 15), "write integer hex 63 "); 53 | FNLOG_ASSERT(buffer[0] == 'F', nullptr); 54 | FNLOG_ASSERT(buffer[7] == 'F', nullptr); 55 | FNLOG_ASSERT(buffer[15] == '\0', nullptr); 56 | 57 | memset(buffer, 0, sizeof(buffer)); 58 | FNLOG_ASSERT((write_hex_unsafe<3>(buffer, ~((unsigned long long)0xe0000000 << 32)) == 16), "write integer hex 63 "); 59 | FNLOG_ASSERT(buffer[0] == '1', nullptr); 60 | FNLOG_ASSERT(buffer[7] == 'F', nullptr); 61 | FNLOG_ASSERT(buffer[16] == '\0', nullptr); 62 | 63 | memset(buffer, 0, sizeof(buffer)); 64 | //18446744073709551615 65 | FNLOG_ASSERT((write_dec_unsafe<0>(buffer, (unsigned long long)UINT64_MAX) == 20), "write integer dec UINT64 MAX"); 66 | FNLOG_ASSERT(buffer[0] == '1', nullptr); 67 | FNLOG_ASSERT(buffer[1] == '8', nullptr); 68 | FNLOG_ASSERT(buffer[19] == '5', nullptr); 69 | 70 | memset(buffer, 0, sizeof(buffer)); 71 | //-9223372036854775808 72 | FNLOG_ASSERT((write_dec_unsafe<0>(buffer, (long long)INT64_MIN) == 20), "write integer dec INT64_MIN MAX"); 73 | FNLOG_ASSERT(buffer[0] == '-', nullptr); 74 | FNLOG_ASSERT(buffer[1] == '9', nullptr); 75 | FNLOG_ASSERT(buffer[19] == '8', nullptr); 76 | 77 | 78 | memset(buffer, 0, sizeof(buffer)); 79 | FNLOG_ASSERT((write_float_unsafe(buffer, 3.14f) == 4), "write float pi"); 80 | FNLOG_ASSERT(buffer[0] == '3', nullptr); 81 | FNLOG_ASSERT(buffer[1] == '.', nullptr); 82 | FNLOG_ASSERT(buffer[2] == '1', nullptr); 83 | memset(buffer, 0, sizeof(buffer)); 84 | FNLOG_ASSERT((write_float_unsafe(buffer, 3.1426f) == 6), "write float pi"); 85 | memset(buffer, 0, sizeof(buffer)); 86 | FNLOG_ASSERT((write_float_unsafe(buffer, 3.141f) == 5), "write float pi"); 87 | memset(buffer, 0, sizeof(buffer)); 88 | FNLOG_ASSERT((write_float_unsafe(buffer, 3.14268f) == 6), "write float pi"); 89 | memset(buffer, 0, sizeof(buffer)); 90 | FNLOG_ASSERT((write_float_unsafe(buffer, -3.14268f) == 7), "write float -pi"); 91 | memset(buffer, 0, sizeof(buffer)); 92 | FNLOG_ASSERT((write_float_unsafe(buffer, -3.14268E-15f) > 3), "write float -pi"); 93 | FNLOG_ASSERT(std::regex_match(buffer, std::regex("-3\\.14.*15")), "write float -pi"); 94 | memset(buffer, 0, sizeof(buffer)); 95 | FNLOG_ASSERT((write_float_unsafe(buffer, 3.14268E-15f) > 3), "write float pi"); 96 | FNLOG_ASSERT(std::regex_match(buffer, std::regex("3\\.14.*15")), "write float pi"); 97 | memset(buffer, 0, sizeof(buffer)); 98 | FNLOG_ASSERT((write_float_unsafe(buffer, 3.14268E15f) > 10), "write float pi"); 99 | FNLOG_ASSERT(std::regex_match(buffer, std::regex("314.*")), "write float pi"); 100 | memset(buffer, 0, sizeof(buffer)); 101 | FNLOG_ASSERT((write_float_unsafe(buffer, 3.14268E35f) > 10), "write float pi"); 102 | FNLOG_ASSERT(std::regex_match(buffer, std::regex("3\\.14.*35")), "write float pi"); 103 | memset(buffer, 0, sizeof(buffer)); 104 | FNLOG_ASSERT((write_double_unsafe(buffer, 3.14f) == 4), "write double pi"); 105 | FNLOG_ASSERT(buffer[0] == '3', nullptr); 106 | FNLOG_ASSERT(buffer[1] == '.', nullptr); 107 | FNLOG_ASSERT(buffer[2] == '1', nullptr); 108 | 109 | FNLOG_ASSERT((write_double_unsafe(buffer, 3.1426) == 6), "write double pi"); 110 | FNLOG_ASSERT((write_double_unsafe(buffer, 3.141) == 5), "write double pi"); 111 | FNLOG_ASSERT((write_double_unsafe(buffer, 3.14268) == 6), "write double pi"); 112 | FNLOG_ASSERT((write_double_unsafe(buffer, -3.14268) == 7), "write double -pi"); 113 | FNLOG_ASSERT((write_double_unsafe(buffer, -3.14268E-15) > 3), "write double -pi"); 114 | FNLOG_ASSERT(std::regex_match(buffer, std::regex("-3\\.14.*15")), "write double -pi"); 115 | FNLOG_ASSERT((write_double_unsafe(buffer, 3.14268E-15) > 3), "write double pi"); 116 | FNLOG_ASSERT(std::regex_match(buffer, std::regex("3\\.14.*15")), "write double pi"); 117 | FNLOG_ASSERT((write_double_unsafe(buffer, 3.14268E15) > 3), "write double pi"); 118 | FNLOG_ASSERT(!std::regex_match(buffer, std::regex("3\\.14.*15")), "write double pi"); 119 | FNLOG_ASSERT((write_double_unsafe(buffer, 3.14268E150) > 3), "write double pi"); 120 | FNLOG_ASSERT(std::regex_match(buffer, std::regex("3\\.14.*150")), "write double pi"); 121 | 122 | FNLOG_ASSERT((write_pointer_unsafe(buffer, nullptr) == 4), "write nullptr"); 123 | 124 | FNLOG_ASSERT((write_pointer_unsafe(buffer, (void*)1) == 3), "write 0x1"); 125 | 126 | if (true) 127 | { 128 | auto log = std::move(LOG_STREAM_DEFAULT_LOGGER(0, FNLog::PRIORITY_INFO, 0, 0, 0)); 129 | log.write_number<2>(1); 130 | FNLOG_ASSERT((log.log_data_->content_[0] == '0'), "0"); 131 | FNLOG_ASSERT((log.log_data_->content_[1] == '1'), "0"); 132 | } 133 | 134 | if (true) 135 | { 136 | FNLOG_ASSERT(FNLog::short_path("a/b/c", 5) == 0, "0"); 137 | FNLOG_ASSERT(FNLog::short_path("/a/b/c", 6) == 1, "0"); 138 | FNLOG_ASSERT(FNLog::short_path("a/b/c/d", 7) == 2, "0"); 139 | 140 | } 141 | 142 | if (true) 143 | { 144 | std::string str; 145 | for (size_t i = 0; i < 100*1000; i++) 146 | { 147 | str += "0123"; 148 | } 149 | LogInfo() << FNLog::LogHexText(str.c_str(), str.length()); 150 | } 151 | 152 | return 0; 153 | } 154 | -------------------------------------------------------------------------------- /tests/test_channel_normal.cpp: -------------------------------------------------------------------------------- 1 | #define FN_LOG_MAX_CHANNEL_SIZE 4 2 | #include "fn_log.h" 3 | 4 | 5 | static const std::string example_config_text = 6 | R"----( 7 | # 压测配表 8 | # 0通道为多线程文件输出和一个CATEGORY筛选的屏显输出 9 | - channel: 0 10 | sync: null 11 | priority: trace 12 | category: 0 13 | category_extend: 0 14 | -device: 0 15 | disable: false 16 | out_type: file 17 | priority: trace 18 | category: 0 19 | category_extend: 0 20 | path: "./log/" 21 | file: "$PNAME_multi" 22 | rollback: 4 23 | limit_size: 100 m #only support M byte 24 | -device:1 25 | disable: false 26 | out_type: screen 27 | category: 1 28 | category_extend: 1 29 | # 1通道为多线程不挂任何输出端 30 | - channel: 1 31 | 32 | # 2通道为单线程同步写文件 33 | - channel: 2 34 | sync: sync #only support single thread 35 | -device: 0 36 | disable: false 37 | out_type: file 38 | file: "$PNAME_sync" 39 | rollback: 4 40 | limit_size: 100 m #only support M byte 41 | 42 | # 3通道为单线程无输出端 43 | - channel: 3 44 | sync: sync #only support single thread 45 | 46 | )----"; 47 | 48 | std::string ChannelDesc(int channel_type) 49 | { 50 | switch (channel_type) 51 | { 52 | case FNLog::CHANNEL_ASYNC: 53 | return "async thread write"; 54 | case FNLog::CHANNEL_SYNC: 55 | return "sync write"; 56 | } 57 | return "invalid channel"; 58 | } 59 | 60 | int main(int argc, char *argv[]) 61 | { 62 | int ret = FNLog::FastStartDefaultLogger(example_config_text); 63 | if (ret != 0) 64 | { 65 | return ret; 66 | } 67 | 68 | FNLog::Logger& logger = FNLog::GetDefaultLogger(); 69 | 70 | unsigned int total_count = 0; 71 | for (int i = 0; i < logger.shm_->channel_size_; i++) 72 | { 73 | total_count = 0; 74 | do 75 | { 76 | LogDebugStream(i, 0, 0).write_buffer("rrrrrrrrrrrrrrrrrrrradfads33333333333333rrd", 77 | sizeof("rrrrrrrrrrrrrrrrrrrradfads33333333333333rrd") - 1) 78 | << -23 << ": " << 32.2223 << (void*) nullptr; 79 | 80 | if (total_count % 1000000 == 0) 81 | { 82 | static long long last = std::chrono::duration_cast(std::chrono::system_clock::now().time_since_epoch()).count(); 83 | long long now = std::chrono::duration_cast(std::chrono::system_clock::now().time_since_epoch()).count(); 84 | if (total_count > 0) 85 | { 86 | LogInfoStream(0, 1, 0) << "channel:<" << (long long)i << "> " 87 | << ChannelDesc(logger.shm_->channels_[i].channel_type_) << " <" 88 | << logger.shm_->channels_[i].device_size_ << "> test " << 1000000*1000 / (now - last) << " line/sec. "; 89 | last = now; 90 | break; 91 | } 92 | } 93 | } while (++total_count); 94 | } 95 | 96 | LogAlarmStream(0, 1, 0) << "finish"; 97 | return 0; 98 | } 99 | 100 | -------------------------------------------------------------------------------- /tests/test_coverage.cpp: -------------------------------------------------------------------------------- 1 | #include "fn_log.h" 2 | #define FNLOG_ASSERT(expr, prefix) \ 3 | { \ 4 | if (expr) \ 5 | { \ 6 | LogInfo() << "test " << prefix << " success."; \ 7 | } \ 8 | else \ 9 | { \ 10 | LogError() << "test " << prefix << " failed."; \ 11 | return __LINE__ * -1; \ 12 | } \ 13 | } 14 | 15 | static const std::string test_text = 16 | R"----( 17 | # info log print screen and all write file 18 | - define: "tag0 0" 19 | - define: "tag2 2" 20 | - channel: 0 21 | sync: null 22 | - device:0 23 | disable: false 24 | out_type: screen 25 | priority: xxxxxxx 26 | - device:1 27 | disable: false 28 | out_type: screen 29 | priority: null 30 | - device:2 31 | disable: false 32 | out_type: screen 33 | priority: trace 34 | - device:3 35 | disable: false 36 | out_type: screen 37 | priority: debug 38 | - device:4 39 | disable: false 40 | out_type: screen 41 | priority: info 42 | - device:5 43 | disable: false 44 | out_type: screen 45 | priority: warn 46 | - device:6 47 | disable: false 48 | out_type: screen 49 | priority: error 50 | - device:7 51 | disable: false 52 | out_type: screen 53 | priority: alarm 54 | - device:8 55 | disable: false 56 | out_type: screen 57 | priority: fatal 58 | 59 | )----"; 60 | 61 | using namespace FNLog; 62 | int main(int argc, char* argv[]) 63 | { 64 | int ret = FastStartDefaultLogger(); 65 | if (ret != 0 ) 66 | { 67 | return ret ; 68 | } 69 | 70 | 71 | LogAlarm() << "log init success"; //sync write 72 | if (true) 73 | { 74 | time_t now = time(NULL); 75 | struct tm* ptm = localtime(&now); 76 | std::string result = MakeFileName("$PID$YEAR$MON$DAY$HOUR$MIN$SEC", 0, 0, *ptm); 77 | FNLOG_ASSERT(std::regex_match(result, std::regex("[0-9]*\\.log")), "filename fmt"); 78 | result = MakeFileName("$PNAME", 0, 0, *ptm); 79 | FNLOG_ASSERT(std::regex_match(result, std::regex("test_coverage\\.log")), "filename fmt"); 80 | result = MakeFileName("", 0, 0, *ptm); 81 | FNLOG_ASSERT(std::regex_match(result, std::regex("test_coverage.*log")), "filename fmt"); 82 | result = MakeFileName("$a$dddddd$PID$", 0, 0, *ptm); 83 | FNLOG_ASSERT(std::regex_search(result, std::regex("\\$a")), "filename fmt"); 84 | FNLOG_ASSERT(!std::regex_search(result, std::regex("PID")), "filename fmt"); 85 | result = MakeFileName("dddd", 0, 0, *ptm); 86 | FNLOG_ASSERT(std::regex_match(result, std::regex("dddd\\.log")), "filename fmt"); 87 | } 88 | 89 | if (true) 90 | { 91 | char* pbig = new char[FN_LOG_MAX_LOG_SIZE + 100]; 92 | for (int i = 0; i < FN_LOG_MAX_LOG_SIZE + 100; i++) 93 | { 94 | pbig[i] = '1'; 95 | } 96 | pbig[FN_LOG_MAX_LOG_SIZE + 99] = '\0'; 97 | LOGFMTI("%s", pbig); 98 | LogInfo() << pbig; 99 | PackInfo(pbig); 100 | 101 | } 102 | 103 | if (true) 104 | { 105 | static Logger logger; 106 | int ret = InitFromYMAL(logger, "ddddddd", ""); 107 | FNLOG_ASSERT(ret != 0, "init error"); 108 | ret = InitFromYMAL(logger, test_text, ""); 109 | FNLOG_ASSERT(ret == 0, "init error"); 110 | FNLOG_ASSERT(GetDeviceConfig(logger, 0, 0, DEVICE_CFG_PRIORITY) == PRIORITY_TRACE, "parse priority"); 111 | FNLOG_ASSERT(GetDeviceConfig(logger, 0, 1, DEVICE_CFG_PRIORITY) == PRIORITY_TRACE, "parse priority"); 112 | FNLOG_ASSERT(GetDeviceConfig(logger, 0, 2, DEVICE_CFG_PRIORITY) == PRIORITY_TRACE, "parse priority"); 113 | FNLOG_ASSERT(GetDeviceConfig(logger, 0, 3, DEVICE_CFG_PRIORITY) == PRIORITY_DEBUG, "parse priority"); 114 | FNLOG_ASSERT(GetDeviceConfig(logger, 0, 4, DEVICE_CFG_PRIORITY) == PRIORITY_INFO, "parse priority"); 115 | FNLOG_ASSERT(GetDeviceConfig(logger, 0, 5, DEVICE_CFG_PRIORITY) == PRIORITY_WARN, "parse priority"); 116 | FNLOG_ASSERT(GetDeviceConfig(logger, 0, 6, DEVICE_CFG_PRIORITY) == PRIORITY_ERROR, "parse priority"); 117 | FNLOG_ASSERT(GetDeviceConfig(logger, 0, 7, DEVICE_CFG_PRIORITY) == PRIORITY_ALARM, "parse priority"); 118 | FNLOG_ASSERT(GetDeviceConfig(logger, 0, 8, DEVICE_CFG_PRIORITY) == PRIORITY_FATAL, "parse priority"); 119 | } 120 | 121 | 122 | LogInfo() << 1.23f / 0.000000001; 123 | LogInfo() << 1.23f / 0.00000001; 124 | LogInfo() << 1.23f / 0.0000001; 125 | LogInfo() << 1.23f / 0.000001; 126 | LogInfo() << 1.23f / 0.00001; 127 | LogInfo() << 1.23f / 0.0001; 128 | LogInfo() << 1.23f / 0.001; 129 | LogInfo() << 1.23f / 0.1; 130 | LogInfo() << 1.23f / 1; 131 | LogInfo() << 1.23f / 10; 132 | LogInfo() << 1.23f / 100; 133 | LogInfo() << 1.23f / 1000; 134 | LogInfo() << 1.23f / 10000; 135 | LogInfo() << 1.23f / 100000; 136 | LogInfo() << 1.23f / 1000000; 137 | LogInfo() << 1.23f / 10000000; 138 | LogInfo() << 1.23f / 100000000; 139 | LogInfo() << 1.23 / 0.000000001; 140 | LogInfo() << 1.23 / 0.00000001; 141 | LogInfo() << 1.23 / 0.0000001; 142 | LogInfo() << 1.23 / 0.000001; 143 | LogInfo() << 1.23 / 0.00001; 144 | LogInfo() << 1.23 / 0.0001; 145 | LogInfo() << 1.23 / 0.001; 146 | LogInfo() << 1.23 / 0.1; 147 | LogInfo() << 1.23 / 1; 148 | LogInfo() << 1.23 / 10; 149 | LogInfo() << 1.23 / 100; 150 | LogInfo() << 1.23 / 1000; 151 | LogInfo() << 1.23 / 10000; 152 | LogInfo() << 1.23 / 100000; 153 | LogInfo() << 1.23 / 1000000; 154 | LogInfo() << 1.23 / 10000000; 155 | LogInfo() << 1.23 / 100000000; 156 | 157 | LogInfo() << LogPercent(1.23 / 0.000000001); 158 | LogInfo() << LogPercent(1.23 / 0.00000001); 159 | LogInfo() << LogPercent(1.23 / 0.0000001); 160 | LogInfo() << LogPercent(1.23 / 0.000001); 161 | LogInfo() << LogPercent(1.23 / 0.00001); 162 | LogInfo() << LogPercent(1.23 / 0.0001); 163 | LogInfo() << LogPercent(1.23 / 0.001); 164 | LogInfo() << LogPercent(1.23 / 0.1); 165 | LogInfo() << LogPercent(1.23 / 1); 166 | LogInfo() << LogPercent(1.23 / 10); 167 | LogInfo() << LogPercent(1.23 / 100); 168 | LogInfo() << LogPercent(1.23 / 1000); 169 | LogInfo() << LogPercent(1.23 / 10000); 170 | LogInfo() << LogPercent(1.23 / 100000); 171 | LogInfo() << LogPercent(1.23 / 1000000); 172 | LogInfo() << LogPercent(1.23 / 10000000); 173 | LogInfo() << LogPercent(1.23 / 100000000); 174 | LogInfo() << LogPercent(1.23 / 1000000000) ; 175 | 176 | 177 | LogInfo() << "now:" << LogTimestamp(); 178 | LogInfo() << "now:" << LogTimestamp(0); 179 | LogAlarm() << "finish"; 180 | 181 | return 0; 182 | } 183 | -------------------------------------------------------------------------------- /tests/test_fast_debug.cpp: -------------------------------------------------------------------------------- 1 | #include "fn_log.h" 2 | 3 | using X = char; 4 | 5 | 6 | int main(int argc, char* argv[]) 7 | { 8 | int ret = FNLog::FastStartDebugLogger(); 9 | if (ret != 0) 10 | { 11 | return ret; 12 | } 13 | 14 | LogAlarm() << "log init success. shm size:" 15 | << sizeof(FNLog::SHMLogger) << ", logger size:" << sizeof(FNLog::Logger); 16 | //FNLog::SetAllChannelCategory(FNLog::GetDefaultLogger(), 100, 1); 17 | //FNLog::SetAllScreenCategory(FNLog::GetDefaultLogger(), 100, 1); 18 | LogTrace() << "now time:" << time(nullptr) << ";"; 19 | LogDebug() << "now time:" << time(nullptr) << ";"; 20 | LogInfo() << "now time:" << time(nullptr) << ";"; 21 | LogWarn() << "now time:" << time(nullptr) << ";"; 22 | LogError() << "now time:" << time(nullptr) << ";"; 23 | LogAlarm() << "now time:" << time(nullptr) << ";"; 24 | LogFatal() << "now time:" << time(nullptr) << ";"; 25 | //FNLog::SetAllChannelCategory(FNLog::GetDefaultLogger(), 0, 0); 26 | //FNLog::SetAllScreenCategory(FNLog::GetDefaultLogger(), 0, 0); 27 | LOGT("now time:" << time(nullptr) << ";"); 28 | LOGD("now time:" << time(nullptr) << ";"); 29 | LOGI("now time:" << time(nullptr) << ";"); 30 | LOGW("now time:" << time(nullptr) << ";"); 31 | LOGE("now time:" << time(nullptr) << ";"); 32 | LOGA("now time:" << time(nullptr) << ";"); 33 | LOGF("now time:" << time(nullptr) << ";"); 34 | 35 | LOGFMTT("now time:<%llu>", (unsigned long long)time(nullptr)); 36 | LOGFMTD("now time:<%llu>", (unsigned long long)time(nullptr)); 37 | LOGFMTI("now time:<%llu>", (unsigned long long)time(nullptr)); 38 | LOGFMTW("now time:<%llu>", (unsigned long long)time(nullptr)); 39 | LOGFMTE("now time:<%llu>", (unsigned long long)time(nullptr)); 40 | LOGFMTA("now time:<%llu>", (unsigned long long)time(nullptr)); 41 | LOGFMTF("now time:<%llu>", (unsigned long long)time(nullptr)); 42 | 43 | 44 | PackTrace("now time:", time(nullptr), ";"); 45 | PackDebug("now time:", time(nullptr), ";"); 46 | PackInfo("now time:", time(nullptr), ";"); 47 | PackWarn("now time:", time(nullptr), ";"); 48 | PackError("now time:", time(nullptr), ";"); 49 | PackAlarm("now time:", time(nullptr), ";"); 50 | PackFatal("now time:", time(nullptr), ";"); 51 | 52 | LogInfo() << "random1:" << ((unsigned long long)rand() * rand()) << FNLog::LogBlankAlign<110>() << "random2:" << ((unsigned long long)rand() * rand()) << ";"; 53 | LogInfo() << "random1:" << ((unsigned long long)rand() * rand()) << FNLog::LogBlankAlign<110>() << "random2:" << ((unsigned long long)rand() * rand()) << ";"; 54 | LogInfo() << "random1:" << ((unsigned long long)rand() * rand()) << FNLog::LogBlankAlign<110>() << "random2:" << ((unsigned long long)rand() * rand()) << ";"; 55 | LogInfo() << "random1:" << ((unsigned long long)rand() * rand()) << FNLog::LogBlankAlign<110>() << "random2:" << ((unsigned long long)rand() * rand()) << ";"; 56 | LogInfo() << "random1:" << ((unsigned long long)rand() * rand()) << FNLog::LogBlankAlign<110>() << "random2:" << ((unsigned long long)rand() * rand()) << ";"; 57 | LogInfo() << "random1:" << ((unsigned long long)rand() * rand()) << FNLog::LogBlankAlign<110>() << "random2:" << ((unsigned long long)rand() * rand()) << ";"; 58 | LogInfo() << "random1:" << ((unsigned long long)rand() * rand()) << FNLog::LogBlankAlign<110>() << "random2:" << ((unsigned long long)rand() * rand()) << ";"; 59 | 60 | LogAlarm() << "finish"; 61 | 62 | 63 | LogAlarm() << (const X*)"finish"; 64 | 65 | return 0; 66 | } 67 | 68 | 69 | 70 | 71 | -------------------------------------------------------------------------------- /tests/test_fast_default.cpp: -------------------------------------------------------------------------------- 1 | #include "fn_log.h" 2 | 3 | int main(int argc, char* argv[]) 4 | { 5 | int ret = FNLog::FastStartDefaultLogger(); 6 | if (ret != 0) 7 | { 8 | return ret; 9 | } 10 | 11 | LogAlarm() << "log init success. shm size:" 12 | << sizeof(FNLog::SHMLogger) << ", logger size:" << sizeof(FNLog::Logger); 13 | 14 | LogTrace() << "now time:" << time(nullptr) << ";"; 15 | LogDebug() << "now time:" << time(nullptr) << ";"; 16 | LogInfo() << "now time:" << time(nullptr) << ";"; 17 | LogWarn() << "now time:" << time(nullptr) << ";"; 18 | LogError() << "now time:" << time(nullptr) << ";"; 19 | LogAlarm() << "now time:" << time(nullptr) << ";"; 20 | LogFatal() << "now time:" << time(nullptr) << ";"; 21 | 22 | LOGT("now time:" << time(nullptr) << ";"); 23 | LOGD("now time:" << time(nullptr) << ";"); 24 | LOGI("now time:" << time(nullptr) << ";"); 25 | LOGW("now time:" << time(nullptr) << ";"); 26 | LOGE("now time:" << time(nullptr) << ";"); 27 | LOGA("now time:" << time(nullptr) << ";"); 28 | LOGF("now time:" << time(nullptr) << ";"); 29 | 30 | LOGFMTT("now time:<%llu>", (unsigned long long)time(nullptr)); 31 | LOGFMTD("now time:<%llu>", (unsigned long long)time(nullptr)); 32 | LOGFMTI("now time:<%llu>", (unsigned long long)time(nullptr)); 33 | LOGFMTW("now time:<%llu>", (unsigned long long)time(nullptr)); 34 | LOGFMTE("now time:<%llu>", (unsigned long long)time(nullptr)); 35 | LOGFMTA("now time:<%llu>", (unsigned long long)time(nullptr)); 36 | LOGFMTF("now time:<%llu>", (unsigned long long)time(nullptr)); 37 | 38 | PackTrace("now time:", time(nullptr), ";"); 39 | PackDebug("now time:", time(nullptr), ";"); 40 | PackInfo("now time:", time(nullptr), ";"); 41 | PackWarn("now time:", time(nullptr), ";"); 42 | PackError("now time:", time(nullptr), ";"); 43 | PackAlarm("now time:", time(nullptr), ";"); 44 | PackFatal("now time:", time(nullptr), ";"); 45 | 46 | 47 | LogAlarm() << "finish"; 48 | 49 | 50 | return 0; 51 | } -------------------------------------------------------------------------------- /tests/test_filter.cpp: -------------------------------------------------------------------------------- 1 | #include "fn_log.h" 2 | 3 | static const std::string default_config_text = 4 | R"----( 5 | # default is sync write channel. 6 | - channel: 0 7 | sync: sync 8 | -device:0 9 | disable: false 10 | out_type: file 11 | -device:1 12 | disable: false 13 | out_type: file 14 | - channel: 1 15 | sync: sync 16 | -device:0 17 | disable: false 18 | out_type: screen 19 | )----"; 20 | 21 | #define FNLOG_ASSERT(expr, prefix) \ 22 | { \ 23 | if (expr) \ 24 | { \ 25 | LogInfoStream(1, 0, 0) << "test " << prefix << " success."; \ 26 | } \ 27 | else \ 28 | { \ 29 | LogErrorStream(1, 0, 0) << "test " << prefix << " failed."; \ 30 | return __LINE__ * -1; \ 31 | } \ 32 | } 33 | 34 | long long ChannelWrite(int channel_id) 35 | { 36 | return FNLog::GetChannelLog(FNLog::GetDefaultLogger(), channel_id, FNLog::CHANNEL_LOG_PROCESSED); 37 | } 38 | long long DeviceWrite(int channel_id, int device_id) 39 | { 40 | return FNLog::GetDeviceLog(FNLog::GetDefaultLogger(), 41 | channel_id, device_id, FNLog::DEVICE_LOG_TOTAL_WRITE_LINE); 42 | } 43 | using namespace FNLog; 44 | int main(int argc, char* argv[]) 45 | { 46 | int ret = FNLog::FastStartDefaultLogger(default_config_text); 47 | if (ret != 0) 48 | { 49 | return ret; 50 | } 51 | LogAlarmStream(1, 0, 0) << "1"; 52 | LogAlarmStream(0, 0, 0) << "1"; 53 | FNLOG_ASSERT(ChannelWrite(0) == DeviceWrite(1, 0), "channel begin"); 54 | FNLOG_ASSERT(ChannelWrite(0) > 0, "channel begin"); 55 | FNLOG_ASSERT(ChannelWrite(0) == DeviceWrite(0, 0), "channel begin"); 56 | FNLOG_ASSERT(ChannelWrite(0) == DeviceWrite(0, 1), "channel begin"); 57 | 58 | long long last_channel_write = ChannelWrite(0); 59 | long long last_device_write = DeviceWrite(0, 0); 60 | LogTraceStream(0, 0, 0); 61 | LogDebugStream(0, 1, 0); 62 | LogInfoStream(0, 2, 0); 63 | LogWarnStream(0, 3, 0); 64 | LogErrorStream(0, 4, 0); 65 | LogAlarmStream(0, 5, 0); 66 | LogFatalStream(0, 6, 0); 67 | FNLOG_ASSERT(ChannelWrite(0) - last_channel_write == 7, "all log stream test "); 68 | FNLOG_ASSERT(DeviceWrite(0, 0) - last_device_write == 7, "all log stream test "); 69 | FNLOG_ASSERT(DeviceWrite(0, 0) == ChannelWrite(0), "all log stream test "); 70 | 71 | last_channel_write = ChannelWrite(0); 72 | last_device_write = DeviceWrite(0, 0); 73 | SetDeviceConfig(GetDefaultLogger(), 0, 0, DEVICE_CFG_PRIORITY, PRIORITY_ERROR); 74 | LogTraceStream(0, 0, 0); 75 | LogDebugStream(0, 1, 0); 76 | LogInfoStream(0, 2, 0); 77 | LogWarnStream(0, 3, 0); 78 | LogErrorStream(0, 4, 0); 79 | LogAlarmStream(0, 5, 0); 80 | LogFatalStream(0, 6, 0); 81 | FNLOG_ASSERT(ChannelWrite(0) - last_channel_write == 7, "priority test "); 82 | FNLOG_ASSERT(DeviceWrite(0, 0) - last_device_write == 3, "priority test "); 83 | 84 | SetDeviceConfig(GetDefaultLogger(), 0, 0, DEVICE_CFG_PRIORITY, PRIORITY_TRACE); 85 | SetDeviceConfig(GetDefaultLogger(), 0, 0, DEVICE_CFG_CATEGORY, 1); 86 | SetDeviceConfig(GetDefaultLogger(), 0, 0, DEVICE_CFG_CATEGORY_EXTEND, 1); 87 | last_channel_write = ChannelWrite(0); 88 | last_device_write = DeviceWrite(0, 0); 89 | LogTraceStream(0, 0, 0); 90 | LogDebugStream(0, 1, 0); 91 | LogInfoStream(0, 2, 0); 92 | FNLOG_ASSERT(ChannelWrite(0) - last_channel_write == 3, "category test "); 93 | FNLOG_ASSERT(DeviceWrite(0, 0) - last_device_write == 1, "category test "); 94 | 95 | SetDeviceConfig(GetDefaultLogger(), 0, 0, DEVICE_CFG_CATEGORY_EXTEND, 2); 96 | last_channel_write = ChannelWrite(0); 97 | last_device_write = DeviceWrite(0, 0); 98 | LogTraceStream(0, 0, 0); 99 | LogDebugStream(0, 1, 0); 100 | LogInfoStream(0, 2, 0); 101 | FNLOG_ASSERT(ChannelWrite(0) - last_channel_write == 3, "category test "); 102 | FNLOG_ASSERT(DeviceWrite(0, 0) - last_device_write == 2, "category test "); 103 | 104 | SetDeviceConfig(GetDefaultLogger(), 0, 0, DEVICE_CFG_CATEGORY, 0); 105 | last_channel_write = ChannelWrite(0); 106 | last_device_write = DeviceWrite(0, 0); 107 | LogTraceStream(0, 0, 0); 108 | FNLOG_ASSERT(DeviceWrite(0, 0) - last_device_write == 1, "category test "); 109 | LogDebugStream(0, 1, 0); 110 | FNLOG_ASSERT(DeviceWrite(0, 0) - last_device_write == 2, "category test "); 111 | LogInfoStream(0, 2, 0); 112 | FNLOG_ASSERT(ChannelWrite(0) - last_channel_write == 3, "category test "); 113 | FNLOG_ASSERT(DeviceWrite(0, 0) - last_device_write == 2, "category test "); 114 | 115 | SetChannelConfig(GetDefaultLogger(), 0, CHANNEL_CFG_CATEGORY, 2); 116 | SetChannelConfig(GetDefaultLogger(), 0, CHANNEL_CFG_CATEGORY_EXTEND, 3); 117 | SetChannelConfig(GetDefaultLogger(), 0, CHANNEL_CFG_PRIORITY, PRIORITY_ERROR); 118 | last_channel_write = ChannelWrite(0); 119 | last_device_write = DeviceWrite(0, 0); 120 | LogTraceStream(0, 0, 0); 121 | LogDebugStream(0, 1, 0); 122 | LogInfoStream(0, 2, 0); 123 | LogWarnStream(0, 3, 0); 124 | LogErrorStream(0, 4, 0); 125 | LogAlarmStream(0, 5, 0); 126 | LogFatalStream(0, 6, 0); 127 | FNLOG_ASSERT(ChannelWrite(0) - last_channel_write == 1, "channel category and priority test "); 128 | FNLOG_ASSERT(DeviceWrite(0, 0) - last_device_write == 0, "channel category and priority test "); 129 | 130 | SetChannelConfig(GetDefaultLogger(), 0, CHANNEL_CFG_CATEGORY, 0); 131 | SetChannelConfig(GetDefaultLogger(), 0, CHANNEL_CFG_PRIORITY, PRIORITY_TRACE); 132 | 133 | 134 | last_channel_write = ChannelWrite(0); 135 | last_device_write = DeviceWrite(0, 0); 136 | LogTrace(); 137 | LogDebug(); 138 | LogInfo(); 139 | LogWarn(); 140 | LogError(); 141 | LogAlarm(); 142 | LogFatal(); 143 | 144 | LogTrace()<< "dd" << 0.1f << 2; 145 | LogDebug()<< "dd" << 0.1f << 2; 146 | LogInfo() << "dd" << 0.1f << 2; 147 | LogWarn() << "dd" << 0.1f << 2; 148 | LogError()<< "dd" << 0.1f << 2; 149 | LogAlarm()<< "dd" << 0.1f << 2; 150 | LogFatal()<< "dd" << 0.1f << 2; 151 | 152 | LogTracePack(0, 0, 0); 153 | LogDebugPack(0, 0, 0); 154 | LogInfoPack(0, 0, 0); 155 | LogWarnPack(0, 0, 0); 156 | LogErrorPack(0, 0, 0); 157 | LogAlarmPack(0, 0, 0); 158 | LogFatalPack(0, 0, 0); 159 | 160 | LogTracePack(0, 0, 0, "aa:", -2.3f, "int:", 3); 161 | LogDebugPack(0, 0, 0, "aa:", -2.3f, "int:", 3); 162 | LogInfoPack(0, 0, 0, "aa:", -2.3f, "int:", 3); 163 | LogWarnPack(0, 0, 0, "aa:", -2.3f, "int:", 3); 164 | LogErrorPack(0, 0, 0, "aa:", -2.3f, "int:", 3); 165 | LogAlarmPack(0, 0, 0, "aa:", -2.3f, "int:", 3); 166 | LogFatalPack(0, 0, 0, "aa:", -2.3f, "int:", 3); 167 | 168 | LOGT("dd" << 3.0 << nullptr); 169 | LOGD("dd" << 3.0 << nullptr); 170 | LOGI("dd" << 3.0 << nullptr); 171 | LOGW("dd" << 3.0 << nullptr); 172 | LOGE("dd" << 3.0 << nullptr); 173 | LOGA("dd" << 3.0 << nullptr); 174 | LOGF("dd" << 3.0 << nullptr); 175 | 176 | LOGFMTT("dd:%s, ch:<%c>", "ee", 'c'); 177 | LOGFMTD("dd:%s, ch:<%c>", "ee", 'c'); 178 | LOGFMTI("dd:%s, ch:<%c>", "ee", 'c'); 179 | LOGFMTW("dd:%s, ch:<%c>", "ee", 'c'); 180 | LOGFMTE("dd:%s, ch:<%c>", "ee", 'c'); 181 | LOGFMTA("dd:%s, ch:<%c>", "ee", 'c'); 182 | LOGFMTF("dd:%s, ch:<%c>", "ee", 'c'); 183 | 184 | FNLOG_ASSERT(ChannelWrite(0) - last_channel_write == 42, "all style test "); 185 | FNLOG_ASSERT(DeviceWrite(0, 0) - last_device_write == 42, "all style test "); 186 | 187 | 188 | 189 | 190 | 191 | LogInfoStream(1, 0, 0) << "log filter test success"; 192 | 193 | LogInfoStream(1, 0, 0).write_hex_text("fn-log", sizeof("fn-log") - 1); 194 | 195 | 196 | 197 | 198 | 199 | 200 | return 0; 201 | } -------------------------------------------------------------------------------- /tests/test_filter_advance.cpp: -------------------------------------------------------------------------------- 1 | #include "fn_log.h" 2 | 3 | static const std::string default_config_text = 4 | R"----( 5 | # default is sync write channel. 6 | - channel: 0 7 | sync: sync 8 | -device:0 9 | disable: false 10 | priority: debug 11 | out_type: vm 12 | - channel: 1 13 | sync: sync 14 | -device:0 15 | disable: false 16 | out_type: screen 17 | -device:1 18 | disable: false 19 | out_type: file 20 | )----"; 21 | 22 | #define FNLOG_ASSERT(expr, prefix) \ 23 | { \ 24 | if (expr) \ 25 | { \ 26 | LogInfoStream(1, 0, 0) << "test " << prefix << " success."; \ 27 | } \ 28 | else \ 29 | { \ 30 | LogErrorStream(1, 0, 0) << "test " << prefix << " failed."; \ 31 | return __LINE__ * -1; \ 32 | } \ 33 | } 34 | 35 | 36 | long long g_virtual_device_write_count = 0; 37 | void VirtualDevice(const FNLog::LogData& log) 38 | { 39 | g_virtual_device_write_count++; 40 | } 41 | 42 | 43 | long long ChannelWrite(int channel_id) 44 | { 45 | return FNLog::GetChannelLog(FNLog::GetDefaultLogger(), channel_id, FNLog::CHANNEL_LOG_PROCESSED); 46 | } 47 | long long DeviceWrite(int channel_id, int device_id) 48 | { 49 | return FNLog::GetDeviceLog(FNLog::GetDefaultLogger(), 50 | channel_id, device_id, FNLog::DEVICE_LOG_TOTAL_WRITE_LINE); 51 | } 52 | 53 | 54 | using namespace FNLog; 55 | int main(int argc, char* argv[]) 56 | { 57 | int ret = FNLog::FastStartDefaultLogger(default_config_text); 58 | if (ret != 0) 59 | { 60 | return ret; 61 | } 62 | FNLog::SetVirtualDevice(&VirtualDevice); 63 | long long old_write = DeviceWrite(0, 0); 64 | LogInfoStream(0, 0, 0) << "1"; 65 | FNLOG_ASSERT(DeviceWrite(0, 0) == old_write + 1, "check normal"); 66 | 67 | old_write = DeviceWrite(0, 0); 68 | LogTraceStream(0, 0, 0) << "1"; 69 | FNLOG_ASSERT(DeviceWrite(0, 0) == old_write, "check trace"); 70 | 71 | old_write = DeviceWrite(0, 0); 72 | LogInfoStream(0, 1, 0) << "1"; 73 | LogInfoStream(0, 8, 0) << "1"; 74 | FNLOG_ASSERT(DeviceWrite(0, 0) == old_write + 2, "check normal category"); 75 | 76 | old_write = DeviceWrite(0, 0); 77 | FNLog::SetDeviceConfig(FNLog::GetDefaultLogger(), 0, 0, FNLog::DEVICE_CFG_CATEGORY, 0); 78 | FNLog::SetDeviceConfig(FNLog::GetDefaultLogger(), 0, 0, FNLog::DEVICE_CFG_CATEGORY_EXTEND, 2); 79 | LogInfoStream(0, 1, 0) << "1"; 80 | LogInfoStream(0, 8, 0) << "1"; 81 | FNLOG_ASSERT(DeviceWrite(0, 0) == old_write + 1, "check device category"); 82 | 83 | //clear 84 | FNLog::SetDeviceConfig(FNLog::GetDefaultLogger(), 0, 0, FNLog::DEVICE_CFG_CATEGORY_EXTEND, 0); 85 | 86 | old_write = DeviceWrite(0, 0); 87 | FNLog::SetDeviceConfig(FNLog::GetDefaultLogger(), 0, 0, FNLog::DEVICE_CFG_CATEGORY_MASK, (1ULL <<8)); 88 | LogInfoStream(0, 1, 0) << "1"; 89 | LogInfoStream(0, 8, 0) << "1"; 90 | FNLOG_ASSERT(DeviceWrite(0, 0) == old_write + 1, "check block category"); 91 | 92 | old_write = DeviceWrite(0, 0); 93 | FNLog::SetDeviceConfig(FNLog::GetDefaultLogger(), 0, 0, FNLog::DEVICE_CFG_CATEGORY_MASK, ((1ULL <<8) | (1ULL << 1))); 94 | LogInfoStream(0, 1, 0) << "1"; 95 | LogInfoStream(0, 8, 0) << "1"; 96 | FNLOG_ASSERT(DeviceWrite(0, 0) == old_write + 2, "check block category"); 97 | 98 | old_write = DeviceWrite(0, 0); 99 | FNLog::SetDeviceConfig(FNLog::GetDefaultLogger(), 0, 0, FNLog::DEVICE_CFG_CATEGORY_MASK, (1ULL << 63)); 100 | LogInfoStream(0, 1, 0) << "1"; 101 | LogInfoStream(0, 8, 0) << "1"; 102 | FNLOG_ASSERT(DeviceWrite(0, 0) == old_write, "check block category"); 103 | 104 | old_write = DeviceWrite(0, 0); 105 | FNLog::SetDeviceConfig(FNLog::GetDefaultLogger(), 0, 0, FNLog::DEVICE_CFG_CATEGORY_MASK, (0)); 106 | LogInfoStream(0, 1, 0) << "1"; 107 | LogInfoStream(0, 8, 0) << "1"; 108 | FNLOG_ASSERT(DeviceWrite(0, 0) == old_write + 2, "check block category"); 109 | 110 | 111 | return 0; 112 | } -------------------------------------------------------------------------------- /tests/test_filter_mask.cpp: -------------------------------------------------------------------------------- 1 | #include "fn_log.h" 2 | 3 | static const std::string config_text_249 = 4 | R"----( 5 | # default is sync write channel. 6 | - channel: 0 7 | sync: sync 8 | -device:0 9 | disable: false 10 | priority: debug 11 | out_type: file 12 | file: $PNAME_debug 13 | category_wmask: 249 14 | - channel: 1 15 | sync: sync 16 | -device:0 17 | disable: false 18 | out_type: screen 19 | )----"; 20 | 21 | static const std::string config_text_249_list = 22 | R"----( 23 | # default is sync write channel. 24 | - channel: 0 25 | sync: sync 26 | -device:0 27 | disable: false 28 | priority: debug 29 | out_type: file 30 | file: $PNAME_debug 31 | category_wlist: "0, 3, 4,5,6,7" 32 | - channel: 1 33 | sync: sync 34 | -device:0 35 | disable: false 36 | out_type: screen 37 | )----"; 38 | 39 | 40 | static const std::string config_text_249_blist = 41 | R"----( 42 | # default is sync write channel. 43 | - channel: 0 44 | sync: sync 45 | -device:0 46 | disable: false 47 | priority: debug 48 | out_type: file 49 | file: $PNAME_debug 50 | category_blist: "0, 3, 4,5,6,7" 51 | - channel: 1 52 | sync: sync 53 | -device:0 54 | disable: false 55 | out_type: screen 56 | )----"; 57 | 58 | static const std::string config_text_249_bmask = 59 | R"----( 60 | # default is sync write channel. 61 | - channel: 0 62 | sync: sync 63 | -device:0 64 | disable: false 65 | priority: debug 66 | out_type: file 67 | file: $PNAME_debug 68 | category_wmask: 6 69 | - channel: 1 70 | sync: sync 71 | -device:0 72 | disable: false 73 | out_type: screen 74 | )----"; 75 | 76 | static const std::string config_text_249_channel = 77 | R"----( 78 | # default is sync write channel. 79 | - channel: 0 80 | category_wmask: 249 81 | category_wlist: "0, 3, 4,5,6,7" 82 | sync: sync 83 | -device:0 84 | disable: false 85 | priority: debug 86 | out_type: file 87 | file: $PNAME_debug 88 | 89 | - channel: 1 90 | sync: sync 91 | -device:0 92 | disable: false 93 | out_type: screen 94 | )----"; 95 | 96 | 97 | 98 | 99 | #define FNLOG_ASSERT(expr, prefix) \ 100 | { \ 101 | if (expr) \ 102 | { \ 103 | LogInfoStream(1, 0, 0) << "test " << prefix << " success."; \ 104 | } \ 105 | else \ 106 | { \ 107 | LogErrorStream(1, 0, 0) << "test " << prefix << " failed."; \ 108 | return __LINE__ * -1; \ 109 | } \ 110 | } 111 | 112 | 113 | 114 | 115 | 116 | using namespace FNLog; 117 | int main(int argc, char* argv[]) 118 | { 119 | FNLOG_ASSERT(FNLog::FastStartDefaultLogger(config_text_249_list) == 0, "start"); 120 | FNLOG_ASSERT(FNLog::GetDefaultLogger().shm_->channels_[0].devices_[0].config_fields_[FNLog::DEVICE_CFG_CATEGORY_MASK] == 249, ""); 121 | 122 | FNLog::StopLogger(FNLog::GetDefaultLogger()); 123 | FNLOG_ASSERT(FNLog::FastStartDefaultLogger(config_text_249) == 0, "start"); 124 | FNLOG_ASSERT(FNLog::GetDefaultLogger().shm_->channels_[0].devices_[0].config_fields_[FNLog::DEVICE_CFG_CATEGORY_MASK] == 249, ""); 125 | LogInfoStream(0, 0, 0); //ok 126 | FNLOG_ASSERT(FNLog::AtomicLoadDeviceLog(FNLog::GetDefaultLogger().shm_->channels_[0], 0, FNLog::DEVICE_LOG_TOTAL_WRITE_LINE) == 1, ""); 127 | LogInfoStream(0, 1, 0); //block 128 | FNLOG_ASSERT(FNLog::AtomicLoadDeviceLog(FNLog::GetDefaultLogger().shm_->channels_[0], 0, FNLog::DEVICE_LOG_TOTAL_WRITE_LINE) == 1, ""); 129 | 130 | LogInfoStream(0, 2, 0); //block 131 | FNLOG_ASSERT(FNLog::AtomicLoadDeviceLog(FNLog::GetDefaultLogger().shm_->channels_[0], 0, FNLog::DEVICE_LOG_TOTAL_WRITE_LINE) == 1, ""); 132 | 133 | LogInfoStream(0, 3, 0); //ok 134 | FNLOG_ASSERT(FNLog::AtomicLoadDeviceLog(FNLog::GetDefaultLogger().shm_->channels_[0], 0, FNLog::DEVICE_LOG_TOTAL_WRITE_LINE) == 2, ""); 135 | 136 | 137 | FNLog::StopLogger(FNLog::GetDefaultLogger()); 138 | FNLOG_ASSERT(FNLog::FastStartDefaultLogger(config_text_249_bmask) == 0, "start"); 139 | FNLOG_ASSERT((FNLog::GetDefaultLogger().shm_->channels_[0].devices_[0].config_fields_[FNLog::DEVICE_CFG_CATEGORY_MASK] & 249) == 0, ""); 140 | FNLOG_ASSERT((FNLog::GetDefaultLogger().shm_->channels_[0].devices_[0].config_fields_[FNLog::DEVICE_CFG_CATEGORY_MASK] & 6) == 6, ""); 141 | 142 | FNLog::StopLogger(FNLog::GetDefaultLogger()); 143 | FNLOG_ASSERT(FNLog::FastStartDefaultLogger(config_text_249_blist) == 0, "start"); 144 | FNLOG_ASSERT((FNLog::GetDefaultLogger().shm_->channels_[0].devices_[0].config_fields_[FNLog::DEVICE_CFG_CATEGORY_MASK] & 249) == 0, ""); 145 | FNLOG_ASSERT((FNLog::GetDefaultLogger().shm_->channels_[0].devices_[0].config_fields_[FNLog::DEVICE_CFG_CATEGORY_MASK] & 6) == 6, ""); 146 | 147 | 148 | 149 | FNLog::StopLogger(FNLog::GetDefaultLogger()); 150 | FNLOG_ASSERT(FNLog::FastStartDefaultLogger(config_text_249_channel) == 0, "start"); 151 | FNLOG_ASSERT(FNLog::GetDefaultLogger().shm_->channels_[0].config_fields_[FNLog::CHANNEL_CFG_CATEGORY_MASK] == 249, ""); 152 | 153 | LogInfoStream(0, 0, 0); //ok 154 | FNLOG_ASSERT(FNLog::AtomicLoadDeviceLog(FNLog::GetDefaultLogger().shm_->channels_[0], 0, FNLog::DEVICE_LOG_TOTAL_WRITE_LINE) == 3, ""); 155 | LogInfoStream(0, 1, 0); //block 156 | FNLOG_ASSERT(FNLog::AtomicLoadDeviceLog(FNLog::GetDefaultLogger().shm_->channels_[0], 0, FNLog::DEVICE_LOG_TOTAL_WRITE_LINE) == 3, ""); 157 | 158 | LogInfoStream(0, 2, 0); //block 159 | FNLOG_ASSERT(FNLog::AtomicLoadDeviceLog(FNLog::GetDefaultLogger().shm_->channels_[0], 0, FNLog::DEVICE_LOG_TOTAL_WRITE_LINE) == 3, ""); 160 | 161 | LogInfoStream(0, 3, 0); //ok 162 | FNLOG_ASSERT(FNLog::AtomicLoadDeviceLog(FNLog::GetDefaultLogger().shm_->channels_[0], 0, FNLog::DEVICE_LOG_TOTAL_WRITE_LINE) == 4, ""); 163 | 164 | 165 | 166 | return 0; 167 | } -------------------------------------------------------------------------------- /tests/test_hex_out.cpp: -------------------------------------------------------------------------------- 1 | #include "fn_log.h" 2 | #define FNLOG_ASSERT(expr, prefix) \ 3 | { \ 4 | if (expr) \ 5 | { \ 6 | LogInfo() << "test " << prefix << " success."; \ 7 | } \ 8 | else \ 9 | { \ 10 | LogError() << "test " << prefix << " failed."; \ 11 | return __LINE__ * -1; \ 12 | } \ 13 | } 14 | 15 | static const std::string test_text = 16 | R"----( 17 | # info log print screen and all write file 18 | - channel: 0 19 | sync: null 20 | - device:0 21 | disable: false 22 | out_type: screen 23 | priority: debug 24 | 25 | )----"; 26 | 27 | struct HexHead 28 | { 29 | char a[10] = "head"; 30 | short b = 127; 31 | int c = 7; 32 | long long e= -1; 33 | double f = -1.04; 34 | }; 35 | 36 | using namespace FNLog; 37 | int main(int argc, char* argv[]) 38 | { 39 | int ret = FastStartDefaultLogger(); 40 | if (ret != 0 ) 41 | { 42 | return ret ; 43 | } 44 | 45 | 46 | 47 | 48 | LogAlarm() << "log init success"; //sync write 49 | HexHead head; 50 | LogAlarm() << FNLog::LogHexText(&head, sizeof(head)); 51 | LogAlarm() << FNLog::LogHexText(head); 52 | LogAlarm() << FNLog::LogBinText(&head, sizeof(head)); 53 | LogAlarm() << FNLog::LogBinText(head); 54 | 55 | 56 | LogAlarm() << "finish"; 57 | 58 | return 0; 59 | } 60 | -------------------------------------------------------------------------------- /tests/test_hotupdate.cpp: -------------------------------------------------------------------------------- 1 | 2 | #define FN_LOG_MAX_LOG_SIZE 1000 3 | #define FN_LOG_MAX_LOG_QUEUE_SIZE 10000 4 | #define FN_LOG_HOTUPDATE_INTERVEL 3 5 | #define FN_LOG_MAX_CHANNEL_SIZE 2 6 | #include "fn_log.h" 7 | #include 8 | #include 9 | #include 10 | 11 | 12 | static const std::string default_config_text = 13 | R"----( 14 | # default channel 0 15 | # write full log to pname.log 16 | # write info log to pname_info.log 17 | # view info log to screen 18 | # sync channel 1 19 | # write full log to pname.log 20 | # write info log to pname_info.log 21 | # view info log to screen 22 | - define: BASE_CHANNEL 0 23 | - define: SECOND_CHANNEL 1 24 | - define: "DEFAULT_ROLL 4" 25 | - define: "DEFAULT_LIMIT 100 m" 26 | hotupdate: true 27 | - channel: BASE_CHANNEL 28 | sync: async 29 | -device: 0 30 | disable: false 31 | out_type: file 32 | file: "$PNAME_base" 33 | rollback: DEFAULT_ROLL 34 | limit_size: 100 m #only support M byte 35 | -device: 1 36 | disable: false 37 | out_type: screen 38 | priority: info 39 | 40 | 41 | 42 | )----"; 43 | 44 | 45 | 46 | #define FNLOG_ASSERT(expr, prefix) \ 47 | { \ 48 | if (expr) \ 49 | { \ 50 | LogInfoStream(0, 0, 0) << "test " << prefix << " success."; \ 51 | } \ 52 | else \ 53 | { \ 54 | LogErrorStream(0, 0, 0) << "test " << prefix << " failed."; \ 55 | return __LINE__ * -1; \ 56 | } \ 57 | } 58 | 59 | 60 | void Stop(int signo) 61 | { 62 | printf("%s", "oops! stop!!!\n"); 63 | _exit(0); 64 | } 65 | 66 | 67 | 68 | int main(int argc, char* argv[]) 69 | { 70 | signal(SIGINT, Stop); 71 | std::string path = "./hotupdate.yaml"; 72 | FNLog::FileHandler::remove_file(path); 73 | FNLog::FileHandler file; 74 | struct stat s; 75 | file.open(path.c_str(), "rb", s); 76 | if (file.is_open()) 77 | { 78 | printf("%s", "has error"); 79 | return 1; 80 | } 81 | file.close(); 82 | 83 | file.open(path.c_str(), "wb", s); 84 | if (!file.is_open()) 85 | { 86 | printf("%s", "write file error"); 87 | return 1; 88 | } 89 | file.write(default_config_text.c_str(), default_config_text.length()); 90 | file.close(); 91 | //FNLog::FileHandler::write(); 92 | int ret = FNLog::LoadAndStartDefaultLogger(path); 93 | if (ret != 0) 94 | { 95 | return ret; 96 | } 97 | 98 | LogInfo() << "hotupdate begin "; 99 | 100 | 101 | FNLog::Logger& logger = FNLog::GetDefaultLogger(); 102 | FNLog::Channel& channel = logger.shm_->channels_[0]; 103 | 104 | for (int i = 0; i < 40; i++) 105 | { 106 | std::this_thread::sleep_for(std::chrono::milliseconds(100)); 107 | } 108 | 109 | long long old_checks = FNLog::AtomicLoadChannelLog(channel, FNLog::CHANNEL_LOG_HOTUPDATE_CHECK); 110 | long long old_changes = FNLog::AtomicLoadChannelLog(channel, FNLog::CHANNEL_LOG_HOTUPDATE_CHANGE); 111 | LogInfo() << "hotupdate checks:" << old_checks << ", changes:" << old_changes ; 112 | FNLOG_ASSERT(old_checks > 0, ""); 113 | FNLOG_ASSERT(old_checks <= 4, ""); //not key decision. app env has some pollution when in mac-OS @github action 114 | FNLOG_ASSERT(old_changes == 0, ""); 115 | 116 | 117 | 118 | LogInfo() << "apend blank to " << path << " ... "; 119 | file.open(path.c_str(), "ab", s); 120 | if (!file.is_open()) 121 | { 122 | printf("%s", "write file error"); 123 | return 1; 124 | } 125 | file.write(" ", 1); 126 | file.close(); 127 | 128 | 129 | LogInfo() << "apended blank to " << path; 130 | 131 | for (int i = 0; i < 40; i++) 132 | { 133 | std::this_thread::sleep_for(std::chrono::milliseconds(100)); 134 | } 135 | 136 | long long checks = FNLog::AtomicLoadChannelLog(channel, FNLog::CHANNEL_LOG_HOTUPDATE_CHECK) - old_checks; 137 | long long changes = FNLog::AtomicLoadChannelLog(channel, FNLog::CHANNEL_LOG_HOTUPDATE_CHANGE) - old_changes; 138 | LogInfo() << "check state: inc checks:" << checks <<", inc changes:" << changes; 139 | FNLOG_ASSERT(checks > 0, ""); 140 | FNLOG_ASSERT(checks <= 2, ""); 141 | FNLOG_ASSERT(changes == 1, ""); 142 | LogInfo() << "hotupdate checks: ok"; 143 | 144 | LogAlarm() << "all thread exit"; 145 | return 0; 146 | } 147 | 148 | -------------------------------------------------------------------------------- /tests/test_line_no.cpp: -------------------------------------------------------------------------------- 1 | 2 | 3 | #define FN_LOG_MAX_DEVICE_SIZE 36 4 | #define FN_LOG_MAX_CHANNEL_SIZE 3 5 | #define FN_LOG_MAX_LOG_SIZE 1000 6 | #define FN_LOG_MAX_LOG_QUEUE_SIZE 100000 7 | 8 | #include "fn_log.h" 9 | 10 | static const std::string config_text1 = 11 | R"----( # line1 12 | - channel: 0 13 | priority: trace 14 | -device: 0 15 | disable: false 16 | out_type: screen 17 | 1priority: trace #line = 17 -11 + 1 = 7 18 | )----"; 19 | 20 | static const std::string config_text2 = 21 | R"----( # line1 22 | - channel: 0 23 | priority: trace 24 | -device: 0 25 | disable: false 26 | out_type: screen 27 | 1priority: trace #line = 17 -11 + 1 = 7 )----"; 28 | 29 | static const std::string config_text3 = 30 | R"----( # line1 31 | - channel: 0 32 | priority: trace 33 | -device: 0 34 | disable: false 35 | out_type: screen 36 | priority: trace 37 | -1device: #error line 8 38 | )----"; 39 | 40 | 41 | static const std::string config_text4 = 42 | R"----( # line1 43 | - channel: 0 44 | priority: trace 45 | -device: 0 46 | disable: false 47 | out_type: screen 48 | priority: trace 49 | -device: 1 50 | - 1channel: # error line 9 51 | )----"; 52 | 53 | 54 | static const std::string config_text5 = 55 | R"----( # line1 56 | - channel: 0 57 | priority: trace 58 | -device: 0 59 | disable: false 60 | out_type: screen 61 | priority: trace 62 | 63 | - 1channel: # error line 9 64 | )----"; 65 | 66 | 67 | 68 | 69 | 70 | static const std::string config_text10 = 71 | R"----(#line1 72 | - channel: 0 73 | priority: trace 74 | -device: 0 75 | disable: false 76 | out_type: screen 77 | priority: trace 78 | 79 | - channel: 1 80 | -device:0 81 | disable: false 82 | out_type: empty 83 | priority: debug 84 | category: 20 85 | category_extend: 1 86 | idenfity: 20 87 | idenfity_extend: 1 88 | 89 | - channel: 2 90 | -device:0 91 | disable: false 92 | out_type: empty 93 | priority: error 94 | category: 0 95 | category_extend: 1 96 | idenfity: 0 97 | idenfity_extend: 1 98 | 99 | 100 | 101 | - def:xxxxx 102 | )----"; 103 | 104 | 105 | 106 | 107 | #define Now() std::chrono::duration(std::chrono::system_clock::now().time_since_epoch()).count() 108 | 109 | #define FNLOG_ASSERT(expr, prefix) \ 110 | { \ 111 | if (expr) \ 112 | { \ 113 | LogInfo() << "test " << prefix << " success."; \ 114 | } \ 115 | else \ 116 | { \ 117 | LogError() << "test " << prefix << " failed. "; \ 118 | return __LINE__ * -1; \ 119 | } \ 120 | } 121 | 122 | 123 | int main(int argc, char* argv[]) 124 | { 125 | int ret = FNLog::FastStartDefaultLogger(); 126 | if (ret != 0) 127 | { 128 | return ret; 129 | } 130 | 131 | std::unique_ptr ls(new FNLog::LexState); 132 | std::string text; 133 | 134 | 135 | text = ""; 136 | ret = FNLog::ParseLogger(*ls, text); 137 | FNLOG_ASSERT(ret == 0, ""); 138 | FNLOG_ASSERT(ls->line_no_ == 1, ""); 139 | 140 | text = " "; 141 | ret = FNLog::ParseLogger(*ls, text); 142 | FNLOG_ASSERT(ret == 0, ""); 143 | FNLOG_ASSERT(ls->line_no_ == 2, ""); 144 | 145 | 146 | text = "\n"; 147 | ret = FNLog::ParseLogger(*ls, text); 148 | FNLOG_ASSERT(ret == 0, ""); 149 | FNLOG_ASSERT(ls->line_no_ == 2, ""); 150 | 151 | text = "\r\n"; 152 | ret = FNLog::ParseLogger(*ls, text); 153 | FNLOG_ASSERT(ret == 0, ""); 154 | FNLOG_ASSERT(ls->line_no_ == 2, ""); 155 | 156 | text = "\n\r"; 157 | ret = FNLog::ParseLogger(*ls, text); 158 | FNLOG_ASSERT(ret == 0, ""); 159 | FNLOG_ASSERT(ls->line_no_ == 2, ""); 160 | 161 | text = "\n\n"; 162 | ret = FNLog::ParseLogger(*ls, text); 163 | FNLOG_ASSERT(ret == 0, ""); 164 | FNLOG_ASSERT(ls->line_no_ == 3, ""); 165 | 166 | text = "\r\r"; 167 | ret = FNLog::ParseLogger(*ls, text); 168 | FNLOG_ASSERT(ret == 0, ""); 169 | FNLOG_ASSERT(ls->line_no_ == 3, ""); 170 | 171 | text = "\r\n\r"; 172 | ret = FNLog::ParseLogger(*ls, text); 173 | FNLOG_ASSERT(ret == 0, ""); 174 | FNLOG_ASSERT(ls->line_no_ == 3, ""); 175 | 176 | text = "\n\r\n"; 177 | ret = FNLog::ParseLogger(*ls, text); 178 | FNLOG_ASSERT(ret == 0, ""); 179 | FNLOG_ASSERT(ls->line_no_ == 3, ""); 180 | 181 | 182 | text = " #line1 \n\r line2 #line 2 error "; 183 | ret = FNLog::ParseLogger(*ls, text); 184 | FNLOG_ASSERT(ret != 0, ""); 185 | FNLOG_ASSERT(ls->line_no_ == 2, ""); 186 | 187 | 188 | text = " #line1 \n\r #line2 \r\n #line 3 \r #line 4 \n #line5 \n\n\r\n #line8 \n fdasfasdfasdf #line 9 error"; 189 | ret = FNLog::ParseLogger(*ls, text); 190 | FNLOG_ASSERT(ret != 0, ""); 191 | FNLOG_ASSERT(ls->line_no_ == 9, ""); 192 | 193 | 194 | text = " #line1 \n\r #line2 \r\n #line 3 \r #line 4 \n #line5 \n\n\r\n #line8 \n fdasfasdfasdf #line 9 error\n\r\n\n"; 195 | ret = FNLog::ParseLogger(*ls, text); 196 | FNLOG_ASSERT(ret != 0, ""); 197 | FNLOG_ASSERT(ls->line_no_ == 9, ""); 198 | 199 | 200 | text = " #line1 \n\r -def:xxx #line2 \r\n \n\r\n\n"; 201 | ret = FNLog::ParseLogger(*ls, text); 202 | FNLOG_ASSERT(ret != 0, ""); 203 | FNLOG_ASSERT(ls->line_no_ == 2, ""); 204 | 205 | text = " #line1 \n\r -var:xxx #line2 \r\n \n\r\n\n"; 206 | ret = FNLog::ParseLogger(*ls, text); 207 | FNLOG_ASSERT(ret != 0, ""); 208 | FNLOG_ASSERT(ls->line_no_ == 2, ""); 209 | 210 | text = " #line1 \n\r channel:999 #line2 \r\n \n\r\n\n"; 211 | ret = FNLog::ParseLogger(*ls, text); 212 | FNLOG_ASSERT(ret != 0, ""); 213 | FNLOG_ASSERT(ls->line_no_ == 2, ""); 214 | 215 | text = "channel:0#line1\n\r -device:999 #line2 \r\n \n\r\n\n"; 216 | ret = FNLog::ParseLogger(*ls, text); 217 | FNLOG_ASSERT(ret != 0, ""); 218 | FNLOG_ASSERT(ls->line_no_ == 2, ""); 219 | 220 | text = "channel:0#line1\n\r -device:0 #line2 \r\n disable:false\n udp_addr:xxx \n\r\n\n"; 221 | ret = FNLog::ParseLogger(*ls, text); 222 | FNLOG_ASSERT(ret != 0, ""); 223 | FNLOG_ASSERT(ls->line_no_ == 4, ""); 224 | 225 | 226 | text = config_text1; 227 | ret = FNLog::ParseLogger(*ls, text); 228 | FNLOG_ASSERT(ret != 0, ""); 229 | FNLOG_ASSERT(ls->line_no_ == 7, ""); 230 | 231 | text = config_text2; 232 | ret = FNLog::ParseLogger(*ls, text); 233 | FNLOG_ASSERT(ret != 0, ""); 234 | FNLOG_ASSERT(ls->line_no_ == 7, ""); 235 | 236 | text = config_text3; 237 | ret = FNLog::ParseLogger(*ls, text); 238 | FNLOG_ASSERT(ret != 0, ""); 239 | FNLOG_ASSERT(ls->line_no_ == 8, ""); 240 | 241 | text = config_text4; 242 | ret = FNLog::ParseLogger(*ls, text); 243 | FNLOG_ASSERT(ret != 0, ""); 244 | FNLOG_ASSERT(ls->line_no_ == 9, ""); 245 | 246 | text = config_text5; 247 | ret = FNLog::ParseLogger(*ls, text); 248 | FNLOG_ASSERT(ret != 0, ""); 249 | FNLOG_ASSERT(ls->line_no_ == 9, ""); 250 | 251 | text = config_text10; 252 | ret = FNLog::ParseLogger(*ls, text); 253 | FNLOG_ASSERT(ret != 0, ""); 254 | FNLOG_ASSERT(ls->line_no_ == 31, ""); 255 | 256 | return 0; 257 | } 258 | 259 | -------------------------------------------------------------------------------- /tests/test_load_config.cpp: -------------------------------------------------------------------------------- 1 | #define FN_LOG_MAX_CHANNEL_SIZE 4 2 | #define FN_LOG_HOTUPDATE_INTERVEL 1 3 | 4 | #include "fn_log.h" 5 | #include 6 | 7 | 8 | #define LOG_CONFIG_FILE "./log.yaml" 9 | 10 | 11 | int main(int argc, char* argv[]) 12 | { 13 | int ret = FNLog::LoadAndStartDefaultLogger(LOG_CONFIG_FILE); 14 | if (ret != 0) 15 | { 16 | return ret; 17 | } 18 | 19 | int limit_second = 15; 20 | while (limit_second > 0) 21 | { 22 | if (limit_second % 4 == 0) 23 | { 24 | FNLog::FileHandler file; 25 | struct stat stt; 26 | file.open(LOG_CONFIG_FILE, "rb+", stt); 27 | if (file.is_open()) 28 | { 29 | std::string content = file.read_content(); 30 | file.close(); 31 | if (std::regex_search(content, std::regex("priority: trace", std::regex_constants::grep))) 32 | { 33 | content = std::regex_replace(content, std::regex("priority: trace"), "priority: info"); 34 | LogAlarm() << "change log config file priority to info."; 35 | } 36 | else 37 | { 38 | content = std::regex_replace(content, std::regex("priority: info"), "priority: trace"); 39 | LogAlarm() << "change log config file priority to trace."; 40 | } 41 | file.open(LOG_CONFIG_FILE, "wb", stt); 42 | if (file.is_open()) 43 | { 44 | file.write(content.c_str(), content.length()); 45 | file.close(); 46 | } 47 | } 48 | } 49 | LogDebug() << "default channel debug."; 50 | LogInfo() << "default channel info."; 51 | LogDebugStream(1, 0, 0) << "channel:1, category:0."; 52 | std::this_thread::sleep_for(std::chrono::milliseconds(1000)); 53 | limit_second--; 54 | } 55 | 56 | 57 | LogAlarm() << "finish"; 58 | return 0; 59 | } 60 | 61 | -------------------------------------------------------------------------------- /tests/test_rolling.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zsummer/fn-log/b467d7f0d863d5c29e8bf51e0b1118df9248839f/tests/test_rolling.cpp -------------------------------------------------------------------------------- /tests/test_serialize_object.cpp: -------------------------------------------------------------------------------- 1 | #include "fn_log.h" 2 | 3 | class Base 4 | { 5 | public: 6 | virtual ~Base() {} 7 | virtual std::string name() const 8 | { 9 | return "base"; 10 | } 11 | }; 12 | 13 | class Derived : public Base 14 | { 15 | public: 16 | virtual std::string name() const 17 | { 18 | return "derived"; 19 | } 20 | }; 21 | 22 | //declare 23 | 24 | //impl 25 | FNLog::LogStream& operator << (FNLog::LogStream&& ls, const Base& base) 26 | { 27 | return ls << base.name(); 28 | } 29 | 30 | FNLog::LogStream& operator << (FNLog::LogStream& ls, const Base& base) 31 | { 32 | return ls << base.name(); 33 | } 34 | 35 | 36 | int main(int argc, char* argv[]) 37 | { 38 | (void)argc; 39 | (void)argv; 40 | int ret = FNLog::FastStartDebugLogger(); 41 | if (ret != 0) 42 | { 43 | return ret; 44 | } 45 | 46 | Base b; 47 | Derived d; 48 | 49 | LogInfo() << "Base name:" << b << ", Derived name:" << d; 50 | 51 | LogInfo() << "Base name:" << Base() << ", Derived name:" << Derived(); 52 | 53 | 54 | LogInfo() << b << d << b; 55 | FNLog::LogStream (std::move(LogInfo())) << b << d << b; 56 | 57 | FNLog::LogStream(std::move(LogInfo() << "d")) << b << d << b; 58 | FNLog::LogStream(std::move(LogInfo() << b)) << b << d << b; 59 | 60 | 61 | 62 | LogAlarm() << "finish"; 63 | return 0; 64 | } 65 | 66 | -------------------------------------------------------------------------------- /tests/test_shm.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include "fn_log.h" 3 | 4 | using namespace FNLog; 5 | 6 | 7 | int main(int argc, char* argv[]) 8 | { 9 | static const std::string default_config_text = 10 | R"----( 11 | # default channel 0 12 | # write full log to pname.log 13 | # write error log to pname_error.log 14 | # view info log to screen 15 | # sync channel 1 16 | # write full log to pname.log 17 | # write info log to pname_info.log 18 | # view info log to screen 19 | shm_key: 0x998822 20 | - channel: 0 21 | sync: async 22 | -device: 0 23 | disable: false 24 | out_type: file 25 | file: "$PNAME" 26 | rollback: 4 27 | limit_size: 100 m #only support M byte 28 | -device: 1 29 | disable: false 30 | out_type: file 31 | priority: error 32 | file: "$PNAME_error" 33 | rollback: 4 34 | limit_size: 100 m #only support M byte 35 | -device:2 36 | disable: false 37 | out_type: screen 38 | priority: info 39 | - channel: 1 40 | sync: sync 41 | -device: 0 42 | disable: false 43 | out_type: file 44 | file: "$PNAME_sync" 45 | rollback: 4 46 | limit_size: 100 m #only support M byte 47 | -device: 1 48 | disable: false 49 | out_type: file 50 | priority: info 51 | file: "$PNAME_sync_info" 52 | rollback: 4 53 | limit_size: 100 m #only support M byte 54 | -device:2 55 | disable: false 56 | out_type: screen 57 | priority: info 58 | )----"; 59 | int ret = FastStartDefaultLogger(default_config_text); 60 | if (ret != 0) 61 | { 62 | return ret; 63 | } 64 | 65 | LogAlarm() << "log init success:" << FNLog::GetChannelLog(FNLog::GetDefaultLogger(), 0, FNLog::CHANNEL_LOG_PUSH); 66 | 67 | do 68 | { 69 | long long proc_count = FNLog::GetChannelLog(FNLog::GetDefaultLogger(), 0, FNLog::CHANNEL_LOG_PUSH); 70 | if (proc_count % 100000 == 0) 71 | { 72 | auto ss(std::move(LogInfo())); 73 | ss << "now write:" << proc_count; 74 | if (proc_count == 800000) 75 | { 76 | _exit(0); 77 | } 78 | ss << " line."; 79 | } 80 | else 81 | { 82 | LogDebug() << "now write:" << proc_count << " line."; 83 | } 84 | if (proc_count > 1600000) 85 | { 86 | LogAlarm() << "now finish:" << proc_count << " line."; 87 | return 0; 88 | } 89 | } while (true); 90 | 91 | LogAlarm() << "finish:" << FNLog::GetChannelLog(FNLog::GetDefaultLogger(), 0, FNLog::CHANNEL_LOG_PUSH); 92 | 93 | return 0; 94 | } -------------------------------------------------------------------------------- /tests/test_trans_log.cpp: -------------------------------------------------------------------------------- 1 |  2 | #define FN_LOG_MAX_CHANNEL_SIZE 4 3 | #include "fn_log.h" 4 | 5 | static const std::string default_config_text = 6 | R"----( 7 | # default is sync write channel. 8 | - channel: 0 9 | -device:0 # default screen , info and high priority will trans to one file. 10 | disable: false 11 | priority: info 12 | out_type: vm 13 | -device:1 14 | disable: false 15 | priority: debug 16 | out_type: screen 17 | 18 | - channel: 1 19 | -device:0 20 | disable: false 21 | out_type: screen 22 | -device:1 23 | disable: false 24 | out_type: vm 25 | 26 | - channel: 2 27 | -device:0 28 | disable: false 29 | out_type: file 30 | file: "$PNAME_$YEAR" 31 | path: ./log/ 32 | )----"; 33 | 34 | #define FNLOG_ASSERT(expr, prefix) \ 35 | { \ 36 | if (expr) \ 37 | { \ 38 | LogInfoStream(1, 0, 0) << "test " << prefix << " success."; \ 39 | } \ 40 | else \ 41 | { \ 42 | LogErrorStream(1, 0, 0) << "test " << prefix << " failed."; \ 43 | return __LINE__ * -1; \ 44 | } \ 45 | } 46 | 47 | 48 | long long g_virtual_device_write_count = 0; 49 | void VirtualDevice(const FNLog::LogData& log) 50 | { 51 | FNLog::TransmitChannel(FNLog::GetDefaultLogger(), 2, log.category_, log.identify_, log); 52 | } 53 | 54 | 55 | long long ChannelWrite(int channel_id) 56 | { 57 | return FNLog::GetChannelLog(FNLog::GetDefaultLogger(), channel_id, FNLog::CHANNEL_LOG_PROCESSED); 58 | } 59 | 60 | long long DeviceWrite(int channel_id, int device_id) 61 | { 62 | return FNLog::GetDeviceLog(FNLog::GetDefaultLogger(), 63 | channel_id, device_id, FNLog::DEVICE_LOG_TOTAL_WRITE_LINE); 64 | } 65 | 66 | 67 | using namespace FNLog; 68 | int main(int argc, char* argv[]) 69 | { 70 | int ret = FNLog::FastStartDefaultLogger(default_config_text); 71 | if (ret != 0) 72 | { 73 | return ret; 74 | } 75 | FNLog::SetVirtualDevice(&VirtualDevice); 76 | for (int i = 0; i < 100; i+=2) 77 | { 78 | LogInfoStream(0, 0, 0) << "channel 0, log:" << i; 79 | LogInfoStream(1, 0, 0) << "channel 0, log:" << i+1; 80 | } 81 | std::this_thread::sleep_for(std::chrono::milliseconds(500)); 82 | 83 | FNLOG_ASSERT(DeviceWrite(2, 0) == 100, "check write"); 84 | 85 | return 0; 86 | } -------------------------------------------------------------------------------- /tests/test_udp.cpp: -------------------------------------------------------------------------------- 1 | 2 | 3 | #define FN_LOG_MAX_LOG_SIZE 10000 4 | #define FN_LOG_MAX_LOG_QUEUE_SIZE 10000 5 | #include "fn_log.h" 6 | 7 | using namespace FNLog; 8 | 9 | static const std::string example_config_text = 10 | R"----( 11 | # desc 12 | - channel: 0 13 | -device: 0 14 | disable: false 15 | priority: info 16 | out_type: screen 17 | -device:1 18 | disable: false 19 | out_type: udp 20 | priority: debug 21 | udp_addr: localhost:9909 22 | - channel: 1 23 | -device:0 24 | disable: false 25 | in_type: udp 26 | out_type: file 27 | udp_addr: localhost:9909 28 | out_type: file 29 | path: "./" 30 | file: "$PNAME_receiver" 31 | rollback: 4 32 | limit_size: 100 m #only support M byte 33 | 34 | )----"; 35 | 36 | 37 | #define Now() std::chrono::duration(std::chrono::system_clock::now().time_since_epoch()).count() 38 | int main(int argc, char* argv[]) 39 | { 40 | #ifdef WIN32 41 | 42 | WSADATA wsaData; 43 | if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0) 44 | { 45 | printf("%s", "WSAStartup error.\n"); 46 | return -1; 47 | } 48 | #endif 49 | 50 | int ret = FNLog::FastStartDefaultLogger(example_config_text); 51 | if (ret != 0) 52 | { 53 | return ret; 54 | } 55 | 56 | LogInfo() << "log init success"; 57 | 58 | //to listen udp 59 | std::this_thread::sleep_for(std::chrono::milliseconds(100)); 60 | 61 | int total_count = 0; 62 | 63 | constexpr int max_count = 50000; 64 | 65 | double begin_s = Now(); 66 | 67 | while (total_count++ < max_count) 68 | { 69 | LogDebugStream(0, 0, 0) << "udpdata.1233330000000000000000000000000000000000000000000000000000000"; 70 | } 71 | double end_1s = Now(); 72 | double end_2s = Now(); 73 | 74 | FNLog::Channel& channel0 = FNLog::GetDefaultLogger().shm_->channels_[0]; 75 | FNLog::Channel& channel1 = FNLog::GetDefaultLogger().shm_->channels_[1]; 76 | 77 | 78 | long long lines = FNLog::AtomicLoadDeviceLog(channel1, 0, FNLog::DEVICE_LOG_TOTAL_WRITE_LINE); 79 | do 80 | { 81 | std::this_thread::sleep_for(std::chrono::milliseconds(100)); 82 | long long news = FNLog::AtomicLoadDeviceLog(channel1, 0, FNLog::DEVICE_LOG_TOTAL_WRITE_LINE); 83 | 84 | if (news == lines) 85 | { 86 | break; 87 | } 88 | lines = news; 89 | end_2s = Now(); 90 | } while (true); 91 | 92 | 93 | 94 | 95 | LogInfo() << "sender:" << FNLog::AtomicLoadDeviceLog(channel0, 1, FNLog::DEVICE_LOG_TOTAL_WRITE_LINE); 96 | if (FNLog::AtomicLoadDeviceLog(channel0, 1, FNLog::DEVICE_LOG_TOTAL_WRITE_LINE) > 0) 97 | { 98 | LogInfo() << "sender lose:" << FNLog::AtomicLoadDeviceLog(channel0, 1, FNLog::DEVICE_LOG_TOTAL_LOSE_LINE) * 100.0 / FNLog::AtomicLoadDeviceLog(channel0, 1, FNLog::DEVICE_LOG_TOTAL_WRITE_LINE) <<"%"; 99 | } 100 | LogInfo() << "receiver:" << FNLog::AtomicLoadDeviceLog(channel1, 0, FNLog::DEVICE_LOG_TOTAL_WRITE_LINE); 101 | LogInfo() << "receiver lose:" << (max_count - lines) * 100.0 / max_count << "%"; 102 | 103 | LogInfo() << "test pass:" << lines * 100 / max_count <<"%"; 104 | LogInfo() << "per second file write and send:" << lines / (end_1s - begin_s); 105 | LogInfo() << "per second udp recv:" << lines / (end_2s - begin_s); 106 | 107 | 108 | if (lines*100.0/max_count < 5) 109 | { 110 | //lose 90% 111 | LogFatal() << "lose udp logs. lines:" << lines <<", lose:" << (max_count - lines) <<", total:" << max_count 112 | <<", pass rate:" << lines * 100.0 / max_count <<"%" <<" too little."; 113 | return -1; 114 | } 115 | 116 | 117 | LogAlarmStream(0, 1, 0) << "finish"; 118 | 119 | return 0; 120 | } --------------------------------------------------------------------------------