├── .clang-format
├── .gitattributes
├── .gitignore
├── .travis.yml
├── LICENSE
├── Qml.qrc
├── Qml
├── FPSItem.qml
└── main.qml
├── README.md
├── Src
├── Logger.cpp
├── Logger.h
├── LoggerTemplate.h
└── main.cpp
├── TaoLogger.pro
├── appveyor.yml
└── scripts
├── macos
├── build.sh
└── install.sh
└── ubuntu
├── build.sh
└── install.sh
/.clang-format:
--------------------------------------------------------------------------------
1 | ---
2 | Language: Cpp
3 | AccessModifierOffset: -4
4 | AlignAfterOpenBracket: AlwaysBreak
5 | AlignConsecutiveAssignments: false
6 | AlignConsecutiveDeclarations: false
7 | AlignEscapedNewlines: Right
8 | AlignOperands: true
9 | AlignTrailingComments: true
10 | AllowAllParametersOfDeclarationOnNextLine: true
11 | AllowShortBlocksOnASingleLine: false
12 | AllowShortCaseLabelsOnASingleLine: false
13 | AllowShortFunctionsOnASingleLine: Empty
14 | AllowShortIfStatementsOnASingleLine: false
15 | AllowShortLoopsOnASingleLine: false
16 | AlwaysBreakAfterDefinitionReturnType: None
17 | AlwaysBreakAfterReturnType: None
18 | AlwaysBreakBeforeMultilineStrings: false
19 | AlwaysBreakTemplateDeclarations: Yes
20 | BinPackArguments: false
21 | BinPackParameters: false
22 | BraceWrapping:
23 | AfterClass: true
24 | AfterControlStatement: true
25 | AfterEnum: true
26 | AfterFunction: true
27 | AfterNamespace: true
28 | AfterObjCDeclaration: true
29 | AfterStruct: true
30 | AfterUnion: false
31 | AfterExternBlock: true
32 | BeforeCatch: true
33 | BeforeElse: true
34 | IndentBraces: false
35 | SplitEmptyFunction: true
36 | SplitEmptyRecord: true
37 | SplitEmptyNamespace: true
38 | BreakBeforeBinaryOperators: All
39 | BreakBeforeBraces: Allman
40 | BreakBeforeInheritanceComma: false
41 | BreakInheritanceList: BeforeColon
42 | BreakBeforeTernaryOperators: true
43 | BreakConstructorInitializersBeforeComma: false
44 | BreakConstructorInitializers: BeforeComma
45 | BreakAfterJavaFieldAnnotations: false
46 | BreakStringLiterals: true
47 | ColumnLimit: 160
48 | CommentPragmas: '^ IWYU pragma:'
49 | CompactNamespaces: false
50 | ConstructorInitializerAllOnOneLineOrOnePerLine: true
51 | ConstructorInitializerIndentWidth: 4
52 | ContinuationIndentWidth: 4
53 | Cpp11BracedListStyle: false
54 | DerivePointerAlignment: false
55 | DisableFormat: false
56 | ExperimentalAutoDetectBinPacking: false
57 | FixNamespaceComments: true
58 | ForEachMacros:
59 | - foreach
60 | - Q_FOREACH
61 | - BOOST_FOREACH
62 | IncludeBlocks: Preserve
63 | IncludeCategories:
64 | - Regex: '^"(llvm|llvm-c|clang|clang-c)/'
65 | Priority: 2
66 | - Regex: '^(<|"(gtest|gmock|isl|json)/)'
67 | Priority: 3
68 | - Regex: '.*'
69 | Priority: 1
70 | IncludeIsMainRegex: '(Test)?$'
71 | IndentCaseLabels: true
72 | IndentPPDirectives: None
73 | IndentWidth: 4
74 | IndentWrappedFunctionNames: false
75 | JavaScriptQuotes: Leave
76 | JavaScriptWrapImports: true
77 | KeepLineBreaksForNonEmptyLines: false
78 | KeepEmptyLinesAtTheStartOfBlocks: true
79 | MacroBlockBegin: ''
80 | MacroBlockEnd: ''
81 | MaxEmptyLinesToKeep: 1
82 | NamespaceIndentation: Inner
83 | ObjCBinPackProtocolList: Auto
84 | ObjCBlockIndentWidth: 4
85 | ObjCSpaceAfterProperty: true
86 | ObjCSpaceBeforeProtocolList: true
87 | PenaltyBreakAssignment: 2
88 | PenaltyBreakBeforeFirstCallParameter: 19
89 | PenaltyBreakComment: 300
90 | PenaltyBreakFirstLessLess: 120
91 | PenaltyBreakString: 1000
92 | PenaltyBreakTemplateDeclaration: 10
93 | PenaltyExcessCharacter: 1000000
94 | PenaltyReturnTypeOnItsOwnLine: 60
95 | PointerAlignment: Right
96 | ReflowComments: true
97 | SortIncludes: true
98 | SortUsingDeclarations: true
99 | SpaceAfterCStyleCast: false
100 | SpaceAfterTemplateKeyword: true
101 | SpaceBeforeAssignmentOperators: true
102 | SpaceBeforeCpp11BracedList: false
103 | SpaceBeforeCtorInitializerColon: true
104 | SpaceBeforeInheritanceColon: true
105 | SpaceBeforeParens: ControlStatements
106 | SpaceBeforeRangeBasedForLoopColon: true
107 | SpaceInEmptyParentheses: false
108 | SpacesBeforeTrailingComments: 1
109 | SpacesInAngles: false
110 | SpacesInContainerLiterals: true
111 | SpacesInCStyleCastParentheses: false
112 | SpacesInParentheses: false
113 | SpacesInSquareBrackets: false
114 | Standard: Cpp11
115 | TabWidth: 4
116 | UseTab: Never
117 | ...
118 |
--------------------------------------------------------------------------------
/.gitattributes:
--------------------------------------------------------------------------------
1 | ###############################################################################
2 | # Set default behavior to automatically normalize line endings.
3 | ###############################################################################
4 | * text=auto
5 |
6 | ###############################################################################
7 | # Set default behavior for command prompt diff.
8 | #
9 | # This is need for earlier builds of msysgit that does not have it on by
10 | # default for csharp files.
11 | # Note: This is only used by command line
12 | ###############################################################################
13 | #*.cs diff=csharp
14 |
15 | ###############################################################################
16 | # Set the merge driver for project and solution files
17 | #
18 | # Merging from the command prompt will add diff markers to the files if there
19 | # are conflicts (Merging from VS is not affected by the settings below, in VS
20 | # the diff markers are never inserted). Diff markers may cause the following
21 | # file extensions to fail to load in VS. An alternative would be to treat
22 | # these files as binary and thus will always conflict and require user
23 | # intervention with every merge. To do so, just uncomment the entries below
24 | ###############################################################################
25 | #*.sln merge=binary
26 | #*.csproj merge=binary
27 | #*.vbproj merge=binary
28 | #*.vcxproj merge=binary
29 | #*.vcproj merge=binary
30 | #*.dbproj merge=binary
31 | #*.fsproj merge=binary
32 | #*.lsproj merge=binary
33 | #*.wixproj merge=binary
34 | #*.modelproj merge=binary
35 | #*.sqlproj merge=binary
36 | #*.wwaproj merge=binary
37 |
38 | ###############################################################################
39 | # behavior for image files
40 | #
41 | # image files are treated as binary by default.
42 | ###############################################################################
43 | #*.jpg binary
44 | #*.png binary
45 | #*.gif binary
46 |
47 | ###############################################################################
48 | # diff behavior for common document formats
49 | #
50 | # Convert binary document formats to text before diffing them. This feature
51 | # is only available from the command line. Turn it on by uncommenting the
52 | # entries below.
53 | ###############################################################################
54 | #*.doc diff=astextplain
55 | #*.DOC diff=astextplain
56 | #*.docx diff=astextplain
57 | #*.DOCX diff=astextplain
58 | #*.dot diff=astextplain
59 | #*.DOT diff=astextplain
60 | #*.pdf diff=astextplain
61 | #*.PDF diff=astextplain
62 | #*.rtf diff=astextplain
63 | #*.RTF diff=astextplain
64 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | ## Ignore Visual Studio temporary files, build results, and
2 | ## files generated by popular Visual Studio add-ons.
3 |
4 | build/
5 | run/
6 | # User-specific files
7 | *.suo
8 | *.user
9 | *.userosscache
10 | *.sln.docstates
11 |
12 | # User-specific files (MonoDevelop/Xamarin Studio)
13 | *.userprefs
14 |
15 | # Build results
16 | [Dd]ebug/
17 | [Dd]ebugPublic/
18 | [Rr]elease/
19 | [Rr]eleases/
20 | x64/
21 | x86/
22 | bld/
23 | [Bb]in/
24 | [Oo]bj/
25 | [Ll]og/
26 |
27 | # Visual Studio 2015 cache/options directory
28 | .vs/
29 | # Uncomment if you have tasks that create the project's static files in wwwroot
30 | #wwwroot/
31 |
32 | # MSTest test Results
33 | [Tt]est[Rr]esult*/
34 | [Bb]uild[Ll]og.*
35 |
36 | # NUNIT
37 | *.VisualState.xml
38 | TestResult.xml
39 |
40 | # Build Results of an ATL Project
41 | [Dd]ebugPS/
42 | [Rr]eleasePS/
43 | dlldata.c
44 |
45 | # DNX
46 | project.lock.json
47 | project.fragment.lock.json
48 | artifacts/
49 |
50 | *_i.c
51 | *_p.c
52 | *_i.h
53 | *.ilk
54 | *.meta
55 | *.obj
56 | *.pch
57 | *.pdb
58 | *.pgc
59 | *.pgd
60 | *.rsp
61 | *.sbr
62 | *.tlb
63 | *.tli
64 | *.tlh
65 | *.tmp
66 | *.tmp_proj
67 | *.log
68 | *.vspscc
69 | *.vssscc
70 | .builds
71 | *.pidb
72 | *.svclog
73 | *.scc
74 |
75 | # Chutzpah Test files
76 | _Chutzpah*
77 |
78 | # Visual C++ cache files
79 | ipch/
80 | *.aps
81 | *.ncb
82 | *.opendb
83 | *.opensdf
84 | *.sdf
85 | *.cachefile
86 | *.VC.db
87 | *.VC.VC.opendb
88 |
89 | # Visual Studio profiler
90 | *.psess
91 | *.vsp
92 | *.vspx
93 | *.sap
94 |
95 | # TFS 2012 Local Workspace
96 | $tf/
97 |
98 | # Guidance Automation Toolkit
99 | *.gpState
100 |
101 | # ReSharper is a .NET coding add-in
102 | _ReSharper*/
103 | *.[Rr]e[Ss]harper
104 | *.DotSettings.user
105 |
106 | # JustCode is a .NET coding add-in
107 | .JustCode
108 |
109 | # TeamCity is a build add-in
110 | _TeamCity*
111 |
112 | # DotCover is a Code Coverage Tool
113 | *.dotCover
114 |
115 | # NCrunch
116 | _NCrunch_*
117 | .*crunch*.local.xml
118 | nCrunchTemp_*
119 |
120 | # MightyMoose
121 | *.mm.*
122 | AutoTest.Net/
123 |
124 | # Web workbench (sass)
125 | .sass-cache/
126 |
127 | # Installshield output folder
128 | [Ee]xpress/
129 |
130 | # DocProject is a documentation generator add-in
131 | DocProject/buildhelp/
132 | DocProject/Help/*.HxT
133 | DocProject/Help/*.HxC
134 | DocProject/Help/*.hhc
135 | DocProject/Help/*.hhk
136 | DocProject/Help/*.hhp
137 | DocProject/Help/Html2
138 | DocProject/Help/html
139 |
140 | # Click-Once directory
141 | publish/
142 |
143 | # Publish Web Output
144 | *.[Pp]ublish.xml
145 | *.azurePubxml
146 | # TODO: Comment the next line if you want to checkin your web deploy settings
147 | # but database connection strings (with potential passwords) will be unencrypted
148 | #*.pubxml
149 | *.publishproj
150 |
151 | # Microsoft Azure Web App publish settings. Comment the next line if you want to
152 | # checkin your Azure Web App publish settings, but sensitive information contained
153 | # in these scripts will be unencrypted
154 | PublishScripts/
155 |
156 | # NuGet Packages
157 | *.nupkg
158 | # The packages folder can be ignored because of Package Restore
159 | **/packages/*
160 | # except build/, which is used as an MSBuild target.
161 | !**/packages/build/
162 | # Uncomment if necessary however generally it will be regenerated when needed
163 | #!**/packages/repositories.config
164 | # NuGet v3's project.json files produces more ignoreable files
165 | *.nuget.props
166 | *.nuget.targets
167 |
168 | # Microsoft Azure Build Output
169 | csx/
170 | *.build.csdef
171 |
172 | # Microsoft Azure Emulator
173 | ecf/
174 | rcf/
175 |
176 | # Windows Store app package directories and files
177 | AppPackages/
178 | BundleArtifacts/
179 | Package.StoreAssociation.xml
180 | _pkginfo.txt
181 |
182 | # Visual Studio cache files
183 | # files ending in .cache can be ignored
184 | *.[Cc]ache
185 | # but keep track of directories ending in .cache
186 | !*.[Cc]ache/
187 |
188 | # Others
189 | ClientBin/
190 | ~$*
191 | *~
192 | *.dbmdl
193 | *.dbproj.schemaview
194 | *.jfm
195 | *.pfx
196 | *.publishsettings
197 | node_modules/
198 | orleans.codegen.cs
199 |
200 | # Since there are multiple workflows, uncomment next line to ignore bower_components
201 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
202 | #bower_components/
203 |
204 | # RIA/Silverlight projects
205 | Generated_Code/
206 |
207 | # Backup & report files from converting an old project file
208 | # to a newer Visual Studio version. Backup files are not needed,
209 | # because we have git ;-)
210 | _UpgradeReport_Files/
211 | Backup*/
212 | UpgradeLog*.XML
213 | UpgradeLog*.htm
214 |
215 | # SQL Server files
216 | *.mdf
217 | *.ldf
218 |
219 | # Business Intelligence projects
220 | *.rdl.data
221 | *.bim.layout
222 | *.bim_*.settings
223 |
224 | # Microsoft Fakes
225 | FakesAssemblies/
226 |
227 | # GhostDoc plugin setting file
228 | *.GhostDoc.xml
229 |
230 | # Node.js Tools for Visual Studio
231 | .ntvs_analysis.dat
232 |
233 | # Visual Studio 6 build log
234 | *.plg
235 |
236 | # Visual Studio 6 workspace options file
237 | *.opt
238 |
239 | # Visual Studio LightSwitch build output
240 | **/*.HTMLClient/GeneratedArtifacts
241 | **/*.DesktopClient/GeneratedArtifacts
242 | **/*.DesktopClient/ModelManifest.xml
243 | **/*.Server/GeneratedArtifacts
244 | **/*.Server/ModelManifest.xml
245 | _Pvt_Extensions
246 |
247 | # Paket dependency manager
248 | .paket/paket.exe
249 | paket-files/
250 |
251 | # FAKE - F# Make
252 | .fake/
253 |
254 | # JetBrains Rider
255 | .idea/
256 | *.sln.iml
257 |
258 | # CodeRush
259 | .cr/
260 |
261 | # Python Tools for Visual Studio (PTVS)
262 | __pycache__/
263 | *.pyc
264 | /.vscode/settings.json
265 |
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | language: cpp
2 | sudo: required
3 | compiler: gcc
4 | env: QT_BASE="512"
5 | matrix:
6 | include:
7 | - os: linux
8 | dist: xenial
9 | cache:
10 | apt: true
11 | directories:
12 | - /opt/qt512/
13 | - os: osx
14 | osx_image: xcode10.2
15 |
16 | group: deprecated-2019Q1
17 | before_install:
18 | - if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then chmod a+x ./scripts/macos/install.sh; ./scripts/macos/install.sh; fi
19 | - if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then chmod a+x ./scripts/ubuntu/install.sh; ./scripts/ubuntu/install.sh; fi
20 | script:
21 | - if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then chmod a+x ./scripts/macos/build.sh; ./scripts/macos/build.sh; fi
22 | - if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then chmod a+x ./scripts/ubuntu/build.sh; ./scripts/ubuntu/build.sh; fi
23 | notifications:
24 | email: false
25 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2018 贾文涛
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 all
13 | 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 THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/Qml.qrc:
--------------------------------------------------------------------------------
1 |
2 |
3 | Qml/main.qml
4 | Qml/FPSItem.qml
5 |
6 |
7 |
--------------------------------------------------------------------------------
/Qml/FPSItem.qml:
--------------------------------------------------------------------------------
1 | import QtQuick 2.0
2 | import QtQuick.Controls 2.0
3 | Item {
4 | id: fpsRoot
5 | property int fps: 60
6 | property int frameCount: 0
7 | property bool running: true
8 |
9 | Rectangle {
10 | width: 32
11 | height: 32
12 | color: "red"
13 | RotationAnimation on rotation {
14 | from: 0
15 | to: 360
16 | running: true
17 | loops: Animation.Infinite
18 | duration: 1000
19 | }
20 | onRotationChanged: frameCount++
21 | }
22 | Timer {
23 | interval: 1000
24 | repeat: true
25 | running: fpsRoot.running
26 | onRunningChanged: {
27 | if (running) {
28 | fps = 60
29 | frameCount = 0
30 | }
31 | }
32 | onTriggered: {
33 | fps = frameCount
34 | frameCount = 0
35 | }
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/Qml/main.qml:
--------------------------------------------------------------------------------
1 | import QtQuick 2.0
2 | import QtQuick.Controls 2.0
3 | Item {
4 | Text {
5 | text: "TaoLogger " + fpsItem.fps + " fps"
6 | anchors.centerIn: parent
7 | }
8 | FPSItem {
9 | id: fpsItem
10 | }
11 | Button {
12 | y: 100
13 | text: "log"
14 | onClicked: {
15 | console.log("Clicked")
16 | }
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # TaoLogger
2 |
3 | ## 简介
4 |
5 | Qt制作的简易、好看的Log系统
6 |
7 | 代码量极少
8 |
9 | 麻雀虽小五脏俱全
10 |
11 | 
12 |
13 | ## status
14 | | [Ubuntu/MacOS][lin-link] | [Windows][win-link] |[License][license-link] |
15 | | :---------------: | :-----------------: | :-----------------: |
16 | | ![lin-badge] | ![win-badge] | ![license-badge] |
17 |
18 | [lin-badge]: https://travis-ci.org/jaredtao/TaoLogger.svg?branch=master "Travis build status"
19 | [lin-link]: https://travis-ci.org/jaredtao/TaoLogger "Travis build status"
20 | [win-badge]: https://ci.appveyor.com/api/projects/status/biawnp5xfulvkwbw?svg=true "AppVeyor build status"
21 | [win-link]: https://ci.appveyor.com/project/jiawentao/taologger "AppVeyor build status"
22 | [license-link]: https://github.com/jaredtao/TaoLogger/blob/master/LICENSE "LICENSE"
23 | [license-badge]: https://img.shields.io/badge/license-MIT-blue.svg "MIT"
24 |
25 | ## 使用
26 |
27 | 源代码拷过去,在main函数的QCoreApplication/QApplication构造之后,调用一下init函数就行了。
28 |
29 | 例如:
30 | ```C++
31 | #include "TaoLogger.h"
32 | //省略其它头文件
33 | ...
34 | ...
35 | int main(int argc, char *argv[])
36 | {
37 | QApplication app(argc, argv);
38 | initLog();
39 | ...
40 | return app.exec();
41 | }
42 | ```
43 |
44 | initLog函数的定义如下:
45 | ```
46 | void initLog(const QString &logPath = QStringLiteral("Log"), int logMaxCount = 1024, bool async = true);
47 | ```
48 | 其中logPath为log存储路径,默认为Log文件夹。
49 |
50 | logMaxCount最大文件数,默认为1024。
51 |
52 | async为异步存储,默认为true。
53 |
54 | ## 开发环境
55 |
56 | * Qt 5.9.x Windows
57 |
58 | ## 原理
59 | 详细的说明看我博客:
60 | [Qt自制简易好看的日志系统](https://jaredtao.github.io/2019/04/30/Qt%E8%87%AA%E5%88%B6%E7%AE%80%E6%98%93%E5%A5%BD%E7%9C%8B%E7%9A%84%E6%97%A5%E5%BF%97%E7%B3%BB%E7%BB%9F/)
61 |
62 |
63 |
64 | ### 联系方式:
65 |
66 | ***
67 |
68 | | 作者 | 涛哥 |
69 | | ---- | -------------------------------- |
70 | | QQ | 759378563 |
71 | | 微信 | xsd2410421 |
72 | | 邮箱 | jared2020@163.com |
73 | | blog | https://jaredtao.github.io |
74 |
75 | ***
76 |
77 | QQ(TIM)、微信二维码
78 |
79 | 
80 |
81 |
82 | ###### 请放心联系我,乐于提供咨询服务,也可洽谈有偿技术支持相关事宜。
83 |
84 | ***
85 | #### **打赏**
86 | 
87 |
88 | ###### 觉得分享的内容还不错, 就请作者喝杯奶茶吧~~
89 | ***
90 |
--------------------------------------------------------------------------------
/Src/Logger.cpp:
--------------------------------------------------------------------------------
1 | #include "Logger.h"
2 | #include "LoggerTemplate.h"
3 |
4 | #include
5 |
6 | #include
7 | #include
8 | #include
9 | #include
10 |
11 | #include
12 | #ifdef Q_OS_WIN
13 | #include
14 | #else
15 | #include
16 | #endif
17 |
18 | namespace Logger
19 | {
20 | static QString gLogDir;
21 | static int gLogMaxCount;
22 |
23 | static void outputMessage(QtMsgType type, const QMessageLogContext &context, const QString &msg);
24 | static void outputMessageAsync(QtMsgType type, const QMessageLogContext& context, const QString& msg);
25 |
26 | void initLog(const QString &logPath, int logMaxCount, bool async)
27 | {
28 | if (async)
29 | {
30 | qInstallMessageHandler(outputMessageAsync);
31 | }
32 | else
33 | {
34 | qInstallMessageHandler(outputMessage);
35 | }
36 |
37 | gLogDir = QCoreApplication::applicationDirPath() + "/" + logPath;
38 | gLogMaxCount = logMaxCount;
39 | QDir dir(gLogDir);
40 | if (!dir.exists())
41 | {
42 | dir.mkpath(dir.absolutePath());
43 | }
44 | QStringList infoList = dir.entryList(QDir::Files, QDir::Name);
45 | while (infoList.size() > gLogMaxCount)
46 | {
47 | dir.remove(infoList.first());
48 | infoList.removeFirst();
49 | }
50 | }
51 | static void outputMessageAsync(QtMsgType type, const QMessageLogContext &context, const QString &msg)
52 | {
53 | static const QString messageTemp = QString("%2
\r\n");
54 | static const char typeList[] = { 'd', 'w', 'c', 'f', 'i' };
55 | static QMutex mutex;
56 | static QFile file;
57 | static QTextStream textStream;
58 | static uint count = 0;
59 | static const uint maxCount = 512;
60 | Q_UNUSED(context);
61 | QDateTime dt = QDateTime::currentDateTime();
62 | //每小时一个文件
63 | QString fileNameDt = dt.toString("yyyy-MM-dd_hh");
64 |
65 | //每分钟一个文件
66 | //QString fileNameDt = dt.toString("yyyy-MM-dd_hh_mm");
67 |
68 | QString contentDt = dt.toString("yyyy-MM-dd hh:mm:ss");
69 | QString message = QString("%1 %2").arg(contentDt).arg(msg);
70 | QString htmlMessage = messageTemp.arg(typeList[static_cast(type)]).arg(message);
71 | QString newfileName = QString("%1/%2_log.html").arg(gLogDir).arg(fileNameDt);
72 | mutex.lock();
73 | if (file.fileName() != newfileName)
74 | {
75 | if (file.isOpen())
76 | {
77 | file.close();
78 | }
79 | file.setFileName(newfileName);
80 | bool exist = file.exists();
81 | file.open(QIODevice::WriteOnly | QIODevice::Append);
82 | textStream.setDevice(&file);
83 | textStream.setCodec("UTF-8");
84 | if (!exist)
85 | {
86 | textStream << logTemplate << "\r\n";
87 | }
88 | }
89 | textStream << htmlMessage;
90 | textStream.flush();
91 | count += static_cast(htmlMessage.length());
92 | if (count >= maxCount)
93 | {
94 | file.close();
95 | file.open(QIODevice::WriteOnly | QIODevice::Append);
96 | }
97 | mutex.unlock();
98 | #ifdef Q_OS_WIN
99 | ::OutputDebugString(message.toStdWString().data());
100 | ::OutputDebugString(L"\r\n");
101 | #else
102 | fprintf(stderr, message.toStdString().data());
103 | #endif
104 | }
105 | static void outputMessage(QtMsgType type, const QMessageLogContext& context, const QString& msg)
106 | {
107 | static const QString messageTemp = QString("%2
\r\n");
108 | static const char typeList[] = { 'd', 'w', 'c', 'f', 'i' };
109 | static QMutex mutex;
110 |
111 | Q_UNUSED(context);
112 | QDateTime dt = QDateTime::currentDateTime();
113 |
114 | //每小时一个文件
115 | QString fileNameDt = dt.toString("yyyy-MM-dd_hh");
116 |
117 | //每分钟一个文件
118 | //QString fileNameDt = dt.toString("yyyy-MM-dd_hh_mm");
119 |
120 | QString contentDt = dt.toString("yyyy-MM-dd hh:mm:ss");
121 | QString message = QString("%1 %2").arg(contentDt).arg(msg);
122 | QString htmlMessage = messageTemp.arg(typeList[static_cast(type)]).arg(message);
123 | QFile file(QString("%1/%2_log.html").arg(gLogDir).arg(fileNameDt));
124 | mutex.lock();
125 |
126 | bool exist = file.exists();
127 | file.open(QIODevice::WriteOnly | QIODevice::Append);
128 | QTextStream textStream(&file);
129 | textStream.setCodec("UTF-8");
130 | if (!exist)
131 | {
132 | textStream << logTemplate << "\r\n";
133 | }
134 | textStream << htmlMessage;
135 | file.close();
136 | mutex.unlock();
137 | #ifdef Q_OS_WIN
138 | ::OutputDebugString(message.toStdWString().data());
139 | ::OutputDebugString(L"\r\n");
140 | #else
141 | fprintf(stderr, message.toStdString().data());
142 | #endif
143 | }
144 | } // namespace Logger
145 |
--------------------------------------------------------------------------------
/Src/Logger.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 | #include
3 |
4 | namespace Logger
5 | {
6 |
7 | #define LOG_DEBUG qDebug() << __FILE__ << __FUNCTION__ << __LINE__
8 | #define LOG_INFO qInfo() << __FILE__ << __FUNCTION__ << __LINE__
9 | #define LOG_WARN qWarning() << __FILE__ << __FUNCTION__ << __LINE__
10 | #define LOG_CRIT qCritical() << __FILE__ << __FUNCTION__ << __LINE__
11 |
12 | void initLog(const QString &logPath = QStringLiteral("Log"), int logMaxCount = 1024, bool async = true);
13 |
14 | } // namespace Logger
15 |
--------------------------------------------------------------------------------
/Src/LoggerTemplate.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 | #include
3 | #include
4 | namespace Logger
5 | {
6 | const static QString logTemplate = u8R"logTemplate(
7 |
8 |
9 |
10 |
11 |
12 | TaoLogger
13 |
14 |
86 |
87 |
88 |
89 |
90 |
117 |
125 | )logTemplate";
126 | }
127 |
--------------------------------------------------------------------------------
/Src/main.cpp:
--------------------------------------------------------------------------------
1 | #include "Logger.h"
2 |
3 | #include
4 | #include
5 | #include
6 |
7 | #include
8 | #include
9 | #include
10 | #include
11 | #include
12 | #include
13 |
14 | using namespace Logger;
15 | using namespace std;
16 | const int N = 7;
17 |
18 | //原子计数器。不要用普通的int,多线程情况下不准确。
19 | static atomic_int gCount(0);
20 | static QString currentThreadId()
21 | {
22 |
23 | stringstream ss;
24 | ss << this_thread::get_id();
25 | return QString::fromStdString(ss.str());
26 | }
27 | //输出log的函数,随便打印一点信息
28 | static void showSomeLogger()
29 | {
30 | //在文件本身的编码是utf-8的前提下,以下三种方式都可以直接输出中文。
31 | //u8是c++11标准支持的字符串字面量写法,可以参考https://zh.cppreference.com/w/cpp/language/string_literal
32 | //QStringLiteral是Qt特有的宏,用来在编译期生成字符串字面量
33 | //QString::fromLocal8Bit可以在运行过程中,动态处理中文字符串。
34 | for (int i = 0; i < 1000; ++i)
35 | {
36 | gCount++;
37 | int count = gCount;
38 | LOG_DEBUG << currentThreadId() << u8"山有木兮木有枝,心悦君兮君不知。";
39 | LOG_DEBUG << currentThreadId() << QStringLiteral("黄河远上白云间,一片孤城万仞山。");
40 | LOG_DEBUG << currentThreadId() << QString::fromLocal8Bit("人生若只如初见,何事秋风悲画扇。");
41 | LOG_INFO << currentThreadId() << u8"玲珑骰子安红豆,入骨相思知不知。";
42 | LOG_WARN << currentThreadId() << u8"此情可待成追忆,只是当时已惘然。";
43 | LOG_CRIT << currentThreadId() << u8"严重的事情发生了,股票跌了!" << count;
44 | qApp->processEvents();
45 | }
46 | }
47 | static void logThread()
48 | {
49 | vector threads;
50 |
51 | //创建N个线程
52 | for (unsigned long long i = 0; i < N; ++i) {
53 | threads.emplace_back(thread(showSomeLogger));
54 | }
55 |
56 | //join,等线程结束。
57 | for (unsigned long long i = 0; i < N; ++i)
58 | {
59 | threads[i].join();
60 | }
61 | LOG_INFO << currentThreadId() << u8"故事到这就结束了,总共输出log" << gCount;
62 |
63 | }
64 | int main(int argc, char *argv[])
65 | {
66 | QGuiApplication app(argc, argv);
67 | //app创建之后,调一下initLog就行了
68 | initLog();
69 |
70 | LOG_INFO << currentThreadId() << u8"故事就是从这里开始的";
71 | QQuickView view;
72 | view.setResizeMode(QQuickView::SizeRootObjectToView);
73 | view.resize(800, 600);
74 | view.setSource(QUrl(QStringLiteral("qrc:/Qml/main.qml")));
75 | view.show();
76 | // //延迟创建 logger
77 | QTimer::singleShot(2000, [&](){
78 | std::thread logger(logThread);
79 | logger.detach();
80 |
81 | });
82 | app.exec();
83 | }
84 |
--------------------------------------------------------------------------------
/TaoLogger.pro:
--------------------------------------------------------------------------------
1 | QT += quick
2 | CONFIG += c++11 console
3 |
4 | # The following define makes your compiler emit warnings if you use
5 | # any Qt feature that has been marked deprecated (the exact warnings
6 | # depend on your compiler). Refer to the documentation for the
7 | # deprecated API to know how to port your code away from it.
8 | DEFINES += QT_DEPRECATED_WARNINGS
9 |
10 | # You can also make your code fail to compile if it uses deprecated APIs.
11 | # In order to do so, uncomment the following line.
12 | # You can also select to disable deprecated APIs only up to a certain version of Qt.
13 | #DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0
14 |
15 | HEADERS += \
16 | Src/Logger.h \
17 | Src/LoggerTemplate.h
18 |
19 | SOURCES += \
20 | Src/Logger.cpp \
21 | Src/main.cpp
22 |
23 | RESOURCES += Qml.qrc
24 |
25 | # Additional import path used to resolve QML modules in Qt Creator's code model
26 | QML_IMPORT_PATH =
27 |
28 | # Additional import path used to resolve QML modules just for Qt Quick Designer
29 | QML_DESIGNER_IMPORT_PATH =
30 |
31 | OTHER_FILES += README.md \
32 | .clang-format \
33 | LICENSE \
34 | appveyor.yml \
35 | .travis.yml
36 | macos {
37 | OTHER_FILES += \
38 | scripts/macos/install.sh \
39 | scripts/macos/build.sh
40 | }
41 |
42 | linux {
43 | OTHER_FILES += \
44 | scripts/ubuntu/install.sh \
45 | scripts/ubuntu/build.sh \
46 | }
47 |
--------------------------------------------------------------------------------
/appveyor.yml:
--------------------------------------------------------------------------------
1 | version: build{build}
2 |
3 | branches:
4 | except:
5 | - project/travis
6 |
7 | environment:
8 | matrix:
9 | - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015
10 | platform: x86
11 | qt: 5.9
12 | - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015
13 | platform: x64
14 | qt: 5.9
15 | - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017
16 | platform: x64
17 | qt: 5.9
18 | - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015
19 | platform: x64
20 | qt: 5.12
21 | - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017
22 | platform: x64
23 | qt: 5.12
24 | before_build:
25 | - if "%APPVEYOR_BUILD_WORKER_IMAGE%"=="Visual Studio 2015" set msvc=msvc2015
26 | - if "%APPVEYOR_BUILD_WORKER_IMAGE%"=="Visual Studio 2015" set vs=C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC
27 | - if "%APPVEYOR_BUILD_WORKER_IMAGE%"=="Visual Studio 2017" set msvc=msvc2017
28 | - if "%APPVEYOR_BUILD_WORKER_IMAGE%"=="Visual Studio 2017" set vs=C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Auxiliary\Build
29 | - if "%platform%"=="x86" set QTDIR=C:\Qt\%qt%\%msvc%
30 | - if "%platform%"=="x64" set QTDIR=C:\Qt\%qt%\%msvc%_64
31 | - set PATH=%PATH%;%QTDIR%\bin;
32 | - if "%platform%"=="x86" set vcvarsall=%vs%\vcvarsall.bat
33 | - if "%platform%"=="x64" set vcvarsall=%vs%\vcvarsall.bat
34 | - if "%platform%"=="x86" call "%vcvarsall%" x86
35 | - if "%platform%"=="x64" call "%vcvarsall%" x64
36 | build_script:
37 | - qmake
38 | - nmake
39 |
--------------------------------------------------------------------------------
/scripts/macos/build.sh:
--------------------------------------------------------------------------------
1 | #! /bin/bash
2 | /usr/local/opt/qt/bin/qmake
3 | make
4 |
--------------------------------------------------------------------------------
/scripts/macos/install.sh:
--------------------------------------------------------------------------------
1 | #! /bin/bash
2 | brew update
3 | brew install qt
4 |
--------------------------------------------------------------------------------
/scripts/ubuntu/build.sh:
--------------------------------------------------------------------------------
1 | #! /bin/bash
2 | source /opt/qt512/bin/qt512-env.sh
3 | qmake
4 | make -j$(nproc)
--------------------------------------------------------------------------------
/scripts/ubuntu/install.sh:
--------------------------------------------------------------------------------
1 | #! /bin/bash
2 | sudo add-apt-repository ppa:beineri/opt-qt-5.12.3-xenial -y
3 | sudo apt-get update -qq
4 | sudo apt-get install -y libglew-dev libglfw3-dev
5 | sudo apt-get install -y qt512-meta-minimal
6 |
7 |
--------------------------------------------------------------------------------