logging: add a StandardLogHandlerFactory helper class
[folly.git] / folly / experimental / logging / StandardLogHandlerFactory.cpp
1 /*
2  * Copyright 2004-present Facebook, Inc.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *   http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 #include <folly/experimental/logging/StandardLogHandlerFactory.h>
17
18 #include <folly/MapUtil.h>
19 #include <folly/String.h>
20 #include <folly/experimental/logging/GlogStyleFormatter.h>
21 #include <folly/experimental/logging/StandardLogHandler.h>
22
23 using std::string;
24
25 namespace folly {
26
27 class GlogFormatterFactory
28     : public StandardLogHandlerFactory::FormatterFactory {
29  public:
30   bool processOption(StringPiece /* name */, StringPiece /* value */) override {
31     return false;
32   }
33   std::shared_ptr<LogFormatter> createFormatter() override {
34     return std::make_shared<GlogStyleFormatter>();
35   }
36 };
37
38 std::shared_ptr<StandardLogHandler> StandardLogHandlerFactory::createHandler(
39     StringPiece type,
40     WriterFactory* writerFactory,
41     const Options& options) {
42   std::unique_ptr<FormatterFactory> formatterFactory;
43
44   // Get the log formatter type
45   auto* formatterType = get_ptr(options, "formatter");
46   if (!formatterType || *formatterType == "glog") {
47     formatterFactory = std::make_unique<GlogFormatterFactory>();
48   } else {
49     throw std::invalid_argument(
50         to<string>("unknown log formatter type \"", *formatterType, "\""));
51   }
52
53   // Process the log formatter and log handler options
54   std::vector<string> errors;
55   for (const auto& entry : options) {
56     bool handled = false;
57     try {
58       // Allow both the formatterFactory and writerFactory to consume an
59       // option.  In general they probably should have mutually exclusive
60       // option names, but we don't give precedence to one over the other here.
61       handled |= formatterFactory->processOption(entry.first, entry.second);
62       handled |= writerFactory->processOption(entry.first, entry.second);
63     } catch (const std::exception& ex) {
64       errors.push_back(to<string>(
65           "error processing option \"", entry.first, "\": ", ex.what()));
66       continue;
67     }
68
69     // We explicitly processed the "formatter" option above.
70     handled |= handled || (entry.first == "formatter");
71
72     // Complain about unknown options.
73     if (!handled) {
74       errors.push_back(to<string>("unknown option \"", entry.first, "\""));
75     }
76   }
77
78   if (!errors.empty()) {
79     throw std::invalid_argument(join(", ", errors));
80   }
81
82   // Construct the formatter and writer
83   auto formatter = formatterFactory->createFormatter();
84   auto writer = writerFactory->createWriter();
85
86   return std::make_shared<StandardLogHandler>(
87       LogHandlerConfig{type, options}, formatter, writer);
88 }
89
90 } // namespace folly