2 * Copyright 2004-present Facebook, Inc.
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
16 #include <folly/experimental/logging/FileHandlerFactory.h>
20 #include <folly/Conv.h>
21 #include <folly/MapUtil.h>
22 #include <folly/experimental/logging/AsyncFileWriter.h>
23 #include <folly/experimental/logging/GlogStyleFormatter.h>
24 #include <folly/experimental/logging/ImmediateFileWriter.h>
25 #include <folly/experimental/logging/StandardLogHandler.h>
27 using std::make_shared;
28 using std::shared_ptr;
33 std::shared_ptr<LogHandler> FileHandlerFactory::createHandler(
34 const Options& options) {
35 // Raise an error if we receive unexpected options
37 std::set<std::string>{"path", "stream", "async", "max_buffer_size"};
38 for (const auto& entry : options) {
39 if (knownOptions.find(entry.first) == knownOptions.end()) {
40 throw std::invalid_argument(to<string>(
41 "unknown parameter \"", entry.first, "\" for FileHandlerFactory"));
45 // Construct the formatter
46 // TODO: We should eventually support parameters to control the formatter
48 auto formatter = make_shared<GlogStyleFormatter>();
50 // Get the output file to use
52 auto* path = get_ptr(options, "path");
53 auto* stream = get_ptr(options, "stream");
55 throw std::invalid_argument(
56 "cannot specify both \"path\" and \"stream\" "
57 "parameters for FileHandlerFactory");
59 outputFile = File{*path, O_WRONLY | O_APPEND | O_CREAT};
61 if (*stream == "stderr") {
62 outputFile = File{STDERR_FILENO, /* ownsFd */ false};
63 } else if (*stream == "stdout") {
64 outputFile = File{STDOUT_FILENO, /* ownsFd */ false};
66 throw std::invalid_argument(to<string>(
67 "unknown stream for FileHandlerFactory: \"",
69 "\" expected one of stdout or stderr"));
72 throw std::invalid_argument(
73 "must specify a \"path\" or \"stream\" "
74 "parameter for FileHandlerFactory");
77 // Determine whether we should use ImmediateFileWriter or AsyncFileWriter
78 shared_ptr<LogWriter> writer;
80 auto* asyncOption = get_ptr(options, "async");
83 async = to<bool>(*asyncOption);
84 } catch (const std::exception& ex) {
85 throw std::invalid_argument(to<string>(
86 "expected a boolean value for FileHandlerFactory \"async\" "
91 auto* maxBufferOption = get_ptr(options, "max_buffer_size");
93 auto asyncWriter = make_shared<AsyncFileWriter>(std::move(outputFile));
94 if (maxBufferOption) {
97 maxBufferSize = to<size_t>(*maxBufferOption);
98 } catch (const std::exception& ex) {
99 throw std::invalid_argument(to<string>(
100 "expected an integer value for FileHandlerFactory "
101 "\"max_buffer_size\": ",
104 if (maxBufferSize == 0) {
105 throw std::invalid_argument(to<string>(
106 "expected a positive value for FileHandlerFactory "
107 "\"max_buffer_size\": ",
110 asyncWriter->setMaxBufferSize(maxBufferSize);
112 writer = std::move(asyncWriter);
114 if (maxBufferOption) {
115 throw std::invalid_argument(to<string>(
116 "the \"max_buffer_size\" option is only valid for async file "
119 writer = make_shared<ImmediateFileWriter>(std::move(outputFile));
122 return make_shared<StandardLogHandler>(formatter, writer);