1 /** 
2  * Module which defines the default provider's main class.
3  */
4 module slf4d.default_provider.provider;
5 
6 import slf4d.provider;
7 import slf4d.level;
8 import slf4d.handler;
9 import slf4d.default_provider.factory;
10 import slf4d.default_provider.serializers;
11 import slf4d.default_provider.writers;
12 
13 /** 
14  * The default provider class. It simply contains a shared logger factory
15  * which is used to get loggers, using a single shared log handler to handle
16  * any log messages.
17  */
18 shared class DefaultProvider : LoggingProvider {
19     private DefaultLoggerFactory loggerFactory;
20 
21     /** 
22      * Constructs the default provider.
23      * Params:
24      *   handler = The log handler that will handle all log messages.
25      *   rootLoggingLevel = The root logging level for all Loggers created by
26      *     this provider's factory.
27      */
28     this(
29         shared LogHandler handler,
30         Level rootLoggingLevel = Levels.INFO
31     ) {
32         this.loggerFactory = new DefaultLoggerFactory(handler, rootLoggingLevel);
33     }
34 
35     this(Level rootLoggingLevel = Levels.INFO) {
36         auto handler = new SerializingLogHandler(
37             new ConsoleTextLogSerializer(),
38             [new StdoutLogWriter()]
39         );
40         this.loggerFactory = new DefaultLoggerFactory(handler, rootLoggingLevel);
41     }
42     
43     /** 
44      * Getter method to get this provider's internal factory.
45      * Returns: The logger factory.
46      */
47     public DefaultLoggerFactory getLoggerFactory() shared {
48         return this.loggerFactory;
49     }
50 
51     /**
52      * Gets a builder for creating a customized logging provider.
53      * Returns: The builder.
54      */
55     static DefaultProviderBuilder builder() {
56         return new DefaultProviderBuilder();
57     }
58 }
59 
60 /** 
61  * A fluent-style builder for creating a customized logging provider from
62  * various components offered by SLF4D's default provider module.
63  */
64 private shared class DefaultProviderBuilder {
65     import slf4d.writer;
66 
67     private LogWriter[] writers;
68     private LogSerializer serializer;
69     private Level rootLoggingLevel = Levels.INFO;
70 
71     /**
72      * Configures the logging provider to use the given serializer to convert
73      * log messages to strings for writing.
74      */
75     auto withSerializer(LogSerializer serializer) {
76         this.serializer = cast(shared(LogSerializer)) serializer;
77         return this;
78     }
79 
80     /**
81      * Configures the logging provider to use a basic console serializer.
82      * Params:
83      *   colored = Whether to use colored output in the console.
84      *   loggerNameLengthLimit = The maximum length of logger names to display.
85      */
86     auto withConsoleSerializer(bool colored = true, size_t loggerNameLengthLimit = 24) {
87         this.serializer = new ConsoleTextLogSerializer(colored, loggerNameLengthLimit);
88         return this;
89     }
90 
91     /**
92      * Configures the logging provider to send serialized log messages to the
93      * given writer for output. Note that this can be called multiple times to
94      * add multiple writers.
95      * Params:
96      *   writer = The writer to use.
97      */
98     auto withLogWriter(shared LogWriter writer) {
99         this.writers ~= writer;
100         return this;
101     }
102 
103     /**
104      * Configures the root logging level for the provider, which is the default
105      * logging level assigned to all loggers created by this provider's factory
106      * unless a module-specific logging level overrides it.
107      * Params:
108      *   level = The logging level to set.
109      */
110     auto withRootLoggingLevel(Level level) {
111         this.rootLoggingLevel = level;
112         return this;
113     }
114 
115     /**
116      * Builds the logging provider with the configured settings.
117      * Returns: The logging provider.
118      */
119     DefaultProvider build() {
120         if (this.serializer is null) {
121             this.serializer = new shared ConsoleTextLogSerializer();
122         }
123         if (this.writers.length == 0) {
124             this.writers ~= new StdoutLogWriter();
125         }
126         return new DefaultProvider(
127             new SerializingLogHandler(this.serializer, this.writers),
128             this.rootLoggingLevel
129         );
130     }
131 }
132 
133 unittest {
134     import slf4d.logger;
135     DefaultProvider provider = DefaultProvider.builder()
136         .withRootLoggingLevel(Levels.INFO)
137         .build();
138     auto factory = provider.getLoggerFactory();
139     factory.setRootLevel(Levels.TRACE);
140     Logger log = factory.getLogger();
141     log.error("Testing default provider error message.");
142     log.warn("Testing default provider warn message.");
143     log.info("Testing default provider info message.");
144     log.debug_("Testing default provider debug message.");
145     log.trace("Testing default provider trace message.");
146     log.traceF!"Testing default provider traceF message. %d"(42);
147     log.info("ATTENTION! An exception and its stack trace will be shown. THIS IS EXPECTED.");
148 
149     try {
150         throw new Exception("Oh no!");
151     } catch (Exception e) {
152         log.error(e);
153     }
154 
155     log.info("Testing default provider with attributes.", null, [
156         "attribute1": "value1",
157         "attribute2": "value2",
158         "attribute3": "value3",
159         "attribute4": "This is a very long attribute value."
160     ]);
161 }