TensorFlow Serving C++ API Documentation
server_request_logger.h
1 /* Copyright 2016 Google Inc. All Rights Reserved.
2 
3 Licensed under the Apache License, Version 2.0 (the "License");
4 you may not use this file except in compliance with the License.
5 You may obtain a copy of the License at
6 
7  http://www.apache.org/licenses/LICENSE-2.0
8 
9 Unless required by applicable law or agreed to in writing, software
10 distributed under the License is distributed on an "AS IS" BASIS,
11 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 See the License for the specific language governing permissions and
13 limitations under the License.
14 ==============================================================================*/
15 
16 #ifndef TENSORFLOW_SERVING_CORE_SERVER_REQUEST_LOGGER_H_
17 #define TENSORFLOW_SERVING_CORE_SERVER_REQUEST_LOGGER_H_
18 
19 #include <functional>
20 #include <map>
21 #include <memory>
22 #include <string>
23 #include <unordered_map>
24 #include <vector>
25 
26 #include "google/protobuf/message.h"
27 #include "tensorflow/core/lib/core/status.h"
28 #include "tensorflow_serving/apis/logging.pb.h"
29 #include "tensorflow_serving/config/logging_config.pb.h"
30 #include "tensorflow_serving/core/request_logger.h"
31 #include "tensorflow_serving/util/fast_read_dynamic_ptr.h"
32 
33 namespace tensorflow {
34 namespace serving {
35 
36 // Logs a sample of requests hitting all the models in the server.
37 //
38 // Constructed based on the logging config for the server, which contains the
39 // sampling config.
41  public:
42  using LoggerCreator = std::function<Status(
43  const LoggingConfig& logging_config, std::shared_ptr<RequestLogger>*)>;
44  // Creates the ServerRequestLogger based on a custom request_logger_creator
45  // method.
46  //
47  // You can create an empty ServerRequestLogger with an empty
48  // request_logger_creator.
49  static Status Create(
50  LoggerCreator request_logger_creator,
51  std::unique_ptr<ServerRequestLogger>* server_request_logger);
52 
53  virtual ~ServerRequestLogger() = default;
54 
55  // Updates the logger with the new 'logging_config_map'.
56  //
57  // If the ServerRequestLogger was created using an empty
58  // request_logger_creator, this will return an error if a non-empty
59  // logging_config_map is passed in.
60  virtual Status Update(
61  const std::map<string, std::vector<LoggingConfig>>& logging_config_map);
62 
63  // Similar to RequestLogger::Log().
64  //
65  // If request is logged/written to multiple sinks, we return error from
66  // the first failed write (and continue attempting to write to all).
67  virtual Status Log(const google::protobuf::Message& request,
68  const google::protobuf::Message& response,
69  const LogMetadata& log_metadata);
70 
71  // Starts logging a stream. Returns a StreamLogger created through
72  // `create_stream_logger_fn`. Returns NULL if the stream should not be logged.
73  //
74  // Even if the stream is logged/written to multiple sinks, we return a single
75  // stream logger but register multiple callbacks, one for each sink.
76  template <typename Request, typename Response>
77  using CreateStreamLoggerFn =
78  std::function<std::unique_ptr<StreamLogger<Request, Response>>()>;
79  template <typename Request, typename Response>
80  std::unique_ptr<StreamLogger<Request, Response>> StartLoggingStream(
81  const LogMetadata& log_metadata,
82  CreateStreamLoggerFn<Request, Response> create_stream_logger_fn);
83 
84  protected:
85  explicit ServerRequestLogger(LoggerCreator request_logger_creator);
86 
87  private:
88  using StringToRequestLoggersMap =
89  std::unordered_map<string, std::vector<std::shared_ptr<RequestLogger>>>;
90  using StringToUniqueRequestLoggerMap =
91  std::unordered_map<string, std::shared_ptr<RequestLogger>>;
92 
93  // Find a logger for config in either config_to_logger_map_ or
94  // new_config_to_logger_map. If the logger was found in
95  // config_to_logger_map_ move it to new_config_to_logger_map and erase the
96  // entry from config_to_logger_map_. If such a logger does not exist,
97  // create a new logger and insert it into new_config_to_logger_map. Return the
98  // logger in result.
99  Status FindOrCreateLogger(
100  const LoggingConfig& config,
101  StringToUniqueRequestLoggerMap* new_config_to_logger_map,
102  std::shared_ptr<RequestLogger>* result);
103 
104  // Invokes `fn` with all loggers for the corresponding model.
105  void InvokeLoggerForModel(
106  const LogMetadata& log_metadata,
107  std::function<void(const std::shared_ptr<RequestLogger>&)> fn);
108 
109  // Mutex to ensure concurrent calls to Update() are serialized.
110  mutable mutex update_mu_;
111  // A map from serialized model logging config to its corresponding
112  // RequestLogger. If two models have the same logging config, they
113  // will share the RequestLogger.
114  // This is only used during calls to Update().
115  StringToUniqueRequestLoggerMap config_to_logger_map_;
116 
117  // A map from model_name to its corresponding RequestLoggers.
118  // The RequestLoggers are owned by config_to_logger_map_.
119  FastReadDynamicPtr<StringToRequestLoggersMap> model_to_loggers_map_;
120 
121  LoggerCreator request_logger_creator_;
122 };
123 
124 /***************************Implementation Details***************************/
125 template <typename Request, typename Response>
126 std::unique_ptr<StreamLogger<Request, Response>>
127 ServerRequestLogger::StartLoggingStream(
128  const LogMetadata& log_metadata,
129  CreateStreamLoggerFn<Request, Response> create_stream_logger_fn) {
130  StreamLogger<Request, Response>* stream_logger = nullptr;
131  InvokeLoggerForModel(
132  log_metadata, [create_stream_logger_fn, &stream_logger, &log_metadata](
133  const std::shared_ptr<RequestLogger>& request_logger) {
134  RequestLogger::GetStreamLoggerFn<Request, Response> create_logger =
135  [&create_stream_logger_fn, &stream_logger]() {
136  stream_logger = create_stream_logger_fn().release();
137  return stream_logger;
138  };
139  RequestLogger::GetStreamLoggerFn<Request, Response> get_logger =
140  [stream_logger]() { return stream_logger; };
141  request_logger->MaybeStartLoggingStream(
142  log_metadata, stream_logger == nullptr ? std::move(create_logger)
143  : std::move(get_logger));
144  // If the stream logger has been created, reuse it.
145  });
146  return absl::WrapUnique(stream_logger);
147 }
148 
149 } // namespace serving
150 } // namespace tensorflow
151 
152 #endif // TENSORFLOW_SERVING_CORE_SERVER_REQUEST_LOGGER_H_