1 // This file is written in D programming language
2 /**
3 *   The example demonstrates using a custom logger with daemonize.
4 *
5 *   If SIGTERM is received, daemon terminates. If SIGHUP is received,
6 *   daemon prints "Hello World!" message to logg.
7 *
8 *   Daemon will auto-terminate after 5 minutes of running.
9 *
10 *   Copyright: © 2014 Anton Gushcha
11 *   License: Subject to the terms of the MIT license, as written in the included LICENSE file.
12 *   Authors: NCrashed <ncrashed@gmail.com>
13 */
14 module example04;
15 
16 import std.datetime;
17 
18 import daemonize.d;
19 
20 synchronized class MyLogger : IDaemonLogger
21 {
22     private string file;
23 
24     this(string filePath) @trusted
25     {
26         file = filePath;
27     }
28 
29     void logDebug(string message) nothrow
30     {
31         logInfo(message);
32     }
33 
34     void logInfo(lazy string message) nothrow
35     {
36         static if( __VERSION__ > 2071 )
37         {
38             import std.stdio : toFile;
39             try message.toFile(file);
40             catch (Exception) {}
41         }
42     }
43 
44     void logWarning(lazy string message) nothrow
45     {
46         logInfo(message);
47     }
48 
49     void logError(lazy string message) @trusted nothrow
50     {
51         logInfo(message);
52     }
53 
54     DaemonLogLevel minLogLevel() @property
55     {
56         return DaemonLogLevel.Notice;
57     }
58 
59     void minLogLevel(DaemonLogLevel level) @property {}
60 
61     DaemonLogLevel minOutputLevel() @property
62     {
63         return DaemonLogLevel.Notice;
64     }
65 
66     void minOutputLevel(DaemonLogLevel level) @property {}
67     void finalize() @trusted nothrow {}
68     void reload() {}
69 }
70 
71 // First you need to describe your daemon via template
72 alias daemon = Daemon!(
73     "DaemonizeExample4", // unique name
74 
75     // Setting associative map signal -> callbacks
76     KeyValueList!(
77         // You can bind same delegate for several signals by Composition template
78         // delegate can take additional argument to know which signal is caught
79         Composition!(Signal.Terminate, Signal.Quit, Signal.Shutdown, Signal.Stop), (logger, signal)
80         {
81             logger.logInfo("Exiting...");
82             return false; // returning false will terminate daemon
83         },
84         Composition!(Signal.HangUp,Signal.Pause,Signal.Continue), (logger)
85         {
86             logger.logInfo("Hello World!");
87             return true; // continue execution
88         }
89     ),
90 
91     // Main function where your code is
92     (logger, shouldExit) {
93         // will stop the daemon in 5 minutes
94         auto time = Clock.currSystemTick + cast(TickDuration)5.dur!"minutes";
95         while(!shouldExit() && time > Clock.currSystemTick) {  }
96 
97         logger.logInfo("Exiting main function!");
98 
99         return 0;
100     }
101 );
102 
103 int main()
104 {
105     // For windows is important to use absolute path for logging
106     version(Windows) string logFilePath = "C:\\logfile.log";
107     else string logFilePath = "logfile.log";
108 
109     return buildDaemon!daemon.run(new shared MyLogger(logFilePath));
110 }