TensorFlow Serving C++ API Documentation
net_logging.cc
1 /* Copyright 2018 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 #include "tensorflow_serving/util/net_http/internal/net_logging.h"
17 
18 #include <stddef.h>
19 
20 #include <cstdarg>
21 #include <cstdio>
22 #include <cstdlib>
23 #include <cstring>
24 
25 #include "absl/base/attributes.h"
26 #include "absl/base/config.h"
27 #include "absl/base/log_severity.h"
28 
29 #if defined(__linux__) || defined(__APPLE__) || defined(__FreeBSD__) || \
30  defined(__Fuchsia__) || defined(__native_client__) || \
31  defined(__EMSCRIPTEN__)
32 #include <unistd.h>
33 
34 #define NET_HAVE_POSIX_WRITE 1
35 #define NET_LOW_LEVEL_WRITE_SUPPORTED 1
36 #else
37 #undef NET_HAVE_POSIX_WRITE
38 #endif
39 
40 #if (defined(__linux__) || defined(__FreeBSD__)) && !defined(__ANDROID__)
41 #include <sys/syscall.h>
42 #define NET_HAVE_SYSCALL_WRITE 1
43 #define NET_LOW_LEVEL_WRITE_SUPPORTED 1
44 #else
45 #undef NET_HAVE_SYSCALL_WRITE
46 #endif
47 
48 #ifdef _WIN32
49 #include <io.h>
50 
51 #define NET_HAVE_RAW_IO 1
52 #define NET_LOW_LEVEL_WRITE_SUPPORTED 1
53 #else
54 #undef NET_HAVE_RAW_IO
55 #endif
56 
57 #ifdef NET_LOW_LEVEL_WRITE_SUPPORTED
58 static const char kTruncated[] = " ... (message truncated)\n";
59 
60 inline static bool VADoNetLog(char** buf, int* size, const char* format,
61  va_list ap) ABSL_PRINTF_ATTRIBUTE(3, 0);
62 inline static bool VADoNetLog(char** buf, int* size, const char* format,
63  va_list ap) {
64  int n = vsnprintf(*buf, *size, format, ap);
65  bool result = true;
66  if (n < 0 || n > *size) {
67  result = false;
68  if (static_cast<size_t>(*size) > sizeof(kTruncated)) {
69  n = *size - sizeof(kTruncated); // room for truncation message
70  } else {
71  n = 0; // no room for truncation message
72  }
73  }
74  *size -= n;
75  *buf += n;
76  return result;
77 }
78 #endif // NET_LOW_LEVEL_WRITE_SUPPORTED
79 
80 static constexpr int kLogBufSize = 10000; // absl defaults to 3000
81 
82 namespace {
83 
84 bool DoNetLog(char** buf, int* size, const char* format, ...)
85  ABSL_PRINTF_ATTRIBUTE(3, 4);
86 bool DoNetLog(char** buf, int* size, const char* format, ...) {
87  va_list ap;
88  va_start(ap, format);
89  int n = vsnprintf(*buf, *size, format, ap);
90  va_end(ap);
91  if (n < 0 || n > *size) return false;
92  *size -= n;
93  *buf += n;
94  return true;
95 }
96 
97 void NetLogVA(absl::LogSeverity severity, const char* file, int line,
98  const char* format, va_list ap) ABSL_PRINTF_ATTRIBUTE(4, 0);
99 void NetLogVA(absl::LogSeverity severity, const char* file, int line,
100  const char* format, va_list ap) {
101  char buffer[kLogBufSize];
102  char* buf = buffer;
103  int size = sizeof(buffer);
104 #ifdef NET_LOW_LEVEL_WRITE_SUPPORTED
105  bool enabled = true;
106 #else
107  bool enabled = false;
108 #endif
109 
110 #ifdef ABSL_MIN_LOG_LEVEL
111  if (severity < static_cast<absl::LogSeverity>(ABSL_MIN_LOG_LEVEL) &&
112  severity < absl::LogSeverity::kFatal) {
113  enabled = false;
114  }
115 #endif
116 
117  if (enabled) {
118  DoNetLog(&buf, &size, "[%s : %d] NET_LOG: ", file, line);
119  }
120 
121 #ifdef NET_LOW_LEVEL_WRITE_SUPPORTED
122  if (enabled) {
123  bool no_chop = VADoNetLog(&buf, &size, format, ap);
124  if (no_chop) {
125  DoNetLog(&buf, &size, "\n");
126  } else {
127  DoNetLog(&buf, &size, "%s", kTruncated);
128  }
129  tensorflow::serving::net_http::SafeWriteToStderr(buffer, strlen(buffer));
130  }
131 #else
132  static_cast<void>(format);
133  static_cast<void>(ap);
134 #endif
135 
136  if (severity == absl::LogSeverity::kFatal) {
137  abort();
138  }
139 }
140 
141 } // namespace
142 
143 namespace tensorflow {
144 namespace serving {
145 namespace net_http {
146 
147 void SafeWriteToStderr(const char* s, size_t len) {
148 #if defined(NET_HAVE_SYSCALL_WRITE)
149  syscall(SYS_write, STDERR_FILENO, s, len);
150 #elif defined(NET_HAVE_POSIX_WRITE)
151  write(STDERR_FILENO, s, len);
152 #elif defined(NET_HAVE_RAW_IO)
153  _write(/* stderr */ 2, s, len);
154 #else
155  (void)s;
156  (void)len;
157 #endif
158 }
159 
160 void NetLog(absl::LogSeverity severity, const char* file, int line,
161  const char* format, ...) ABSL_PRINTF_ATTRIBUTE(4, 5);
162 void NetLog(absl::LogSeverity severity, const char* file, int line,
163  const char* format, ...) {
164  va_list ap;
165  va_start(ap, format);
166  NetLogVA(severity, file, line, format, ap);
167  va_end(ap);
168 }
169 
170 } // namespace net_http
171 } // namespace serving
172 } // namespace tensorflow