1/* Copyright 2017 The TensorFlow Authors. All Rights Reserved.
2
3Licensed under the Apache License, Version 2.0 (the "License");
4you may not use this file except in compliance with the License.
5You may obtain a copy of the License at
6
7    http://www.apache.org/licenses/LICENSE-2.0
8
9Unless required by applicable law or agreed to in writing, software
10distributed under the License is distributed on an "AS IS" BASIS,
11WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12See the License for the specific language governing permissions and
13limitations under the License.
14==============================================================================*/
15
16#include "tensorflow/examples/android/jni/object_tracking/logging.h"
17
18#ifdef STANDALONE_DEMO_LIB
19
20#include <android/log.h>
21#include <stdlib.h>
22#include <time.h>
23#include <iostream>
24#include <sstream>
25
26LogMessage::LogMessage(const char* fname, int line, int severity)
27    : fname_(fname), line_(line), severity_(severity) {}
28
29void LogMessage::GenerateLogMessage() {
30  int android_log_level;
31  switch (severity_) {
32    case INFO:
33      android_log_level = ANDROID_LOG_INFO;
34      break;
35    case WARNING:
36      android_log_level = ANDROID_LOG_WARN;
37      break;
38    case ERROR:
39      android_log_level = ANDROID_LOG_ERROR;
40      break;
41    case FATAL:
42      android_log_level = ANDROID_LOG_FATAL;
43      break;
44    default:
45      if (severity_ < INFO) {
46        android_log_level = ANDROID_LOG_VERBOSE;
47      } else {
48        android_log_level = ANDROID_LOG_ERROR;
49      }
50      break;
51  }
52
53  std::stringstream ss;
54  const char* const partial_name = strrchr(fname_, '/');
55  ss << (partial_name != nullptr ? partial_name + 1 : fname_) << ":" << line_
56     << " " << str();
57  __android_log_write(android_log_level, "native", ss.str().c_str());
58
59  // Also log to stderr (for standalone Android apps).
60  std::cerr << "native : " << ss.str() << std::endl;
61
62  // Android logging at level FATAL does not terminate execution, so abort()
63  // is still required to stop the program.
64  if (severity_ == FATAL) {
65    abort();
66  }
67}
68
69namespace {
70
71// Parse log level (int64) from environment variable (char*)
72int64_t LogLevelStrToInt(const char* tf_env_var_val) {
73  if (tf_env_var_val == nullptr) {
74    return 0;
75  }
76
77  // Ideally we would use env_var / safe_strto64, but it is
78  // hard to use here without pulling in a lot of dependencies,
79  // so we use std:istringstream instead
80  std::string min_log_level(tf_env_var_val);
81  std::istringstream ss(min_log_level);
82  int64_t level;
83  if (!(ss >> level)) {
84    // Invalid vlog level setting, set level to default (0)
85    level = 0;
86  }
87
88  return level;
89}
90
91int64_t MinLogLevelFromEnv() {
92  const char* tf_env_var_val = getenv("TF_CPP_MIN_LOG_LEVEL");
93  return LogLevelStrToInt(tf_env_var_val);
94}
95
96int64_t MinVLogLevelFromEnv() {
97  const char* tf_env_var_val = getenv("TF_CPP_MIN_VLOG_LEVEL");
98  return LogLevelStrToInt(tf_env_var_val);
99}
100
101}  // namespace
102
103LogMessage::~LogMessage() {
104  // Read the min log level once during the first call to logging.
105  static int64_t min_log_level = MinLogLevelFromEnv();
106  if (TF_PREDICT_TRUE(severity_ >= min_log_level)) GenerateLogMessage();
107}
108
109int64_t LogMessage::MinVLogLevel() {
110  static const int64_t min_vlog_level = MinVLogLevelFromEnv();
111  return min_vlog_level;
112}
113
114LogMessageFatal::LogMessageFatal(const char* file, int line)
115    : LogMessage(file, line, ANDROID_LOG_FATAL) {}
116LogMessageFatal::~LogMessageFatal() {
117  // abort() ensures we don't return (we promised we would not via
118  // ATTRIBUTE_NORETURN).
119  GenerateLogMessage();
120  abort();
121}
122
123void LogString(const char* fname, int line, int severity,
124               const std::string& message) {
125  LogMessage(fname, line, severity) << message;
126}
127
128void LogPrintF(const int severity, const char* format, ...) {
129  char message[1024];
130  va_list argptr;
131  va_start(argptr, format);
132  vsnprintf(message, 1024, format, argptr);
133  va_end(argptr);
134  __android_log_write(severity, "native", message);
135
136  // Also log to stderr (for standalone Android apps).
137  std::cerr << "native : " << message << std::endl;
138}
139
140#endif
141