Skip to content

Commit ac27907

Browse files
committed
Add Android standalone log target (#6590)
Summary: Add a standalone Android log target to enable ExecuTorch logging to logcat when not using JNI bindings. Reviewed By: kirklandsign Differential Revision: D65268257
1 parent 17ad8d3 commit ac27907

File tree

6 files changed

+139
-90
lines changed

6 files changed

+139
-90
lines changed

extension/android/BUCK

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
load("@fbsource//tools/build_defs/android:fb_android_library.bzl", "fb_android_library")
2+
load("@fbsource//tools/build_defs:fb_xplat_cxx_library.bzl", "fb_xplat_cxx_library")
23

34
oncall("executorch")
45

@@ -39,3 +40,17 @@ fb_android_library(
3940
"//fbandroid/libraries/soloader/java/com/facebook/soloader/nativeloader:nativeloader",
4041
],
4142
)
43+
44+
fb_xplat_cxx_library(
45+
name = "log_provider",
46+
srcs = ["jni/log.cpp"],
47+
compiler_flags = [
48+
"-frtti",
49+
"-fexceptions",
50+
"-Wno-unused-variable",
51+
],
52+
deps = [
53+
"//xplat/executorch/runtime/platform:platform",
54+
],
55+
visibility = ["PUBLIC"],
56+
)

extension/android/CMakeLists.txt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ set(executorch_DIR ${CMAKE_CURRENT_BINARY_DIR}/../../lib/cmake/ExecuTorch)
6464
find_package(executorch CONFIG REQUIRED)
6565
target_link_options_shared_lib(executorch)
6666

67-
add_library(executorch_jni SHARED jni/jni_layer.cpp)
67+
add_library(executorch_jni SHARED jni/jni_layer.cpp jni/log.cpp)
6868

6969
set(link_libraries)
7070
list(
@@ -146,7 +146,7 @@ if(EXECUTORCH_JNI_CUSTOM_LIBRARY)
146146
endif()
147147

148148
if(EXECUTORCH_BUILD_LLAMA_JNI)
149-
target_sources(executorch_jni PRIVATE jni/jni_layer_llama.cpp)
149+
target_sources(executorch_jni PRIVATE jni/jni_layer_llama.cpp log.cpp)
150150
list(APPEND link_libraries llama_runner llava_runner)
151151
target_compile_definitions(executorch_jni PUBLIC EXECUTORCH_BUILD_LLAMA_JNI=1)
152152
add_subdirectory(

extension/android/jni/BUCK

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ executorch_generated_lib(
2525

2626
fb_android_cxx_library(
2727
name = "executorch_jni",
28-
srcs = ["jni_layer.cpp"],
28+
srcs = ["jni_layer.cpp", "log.cpp"],
2929
headers = ["jni_layer_constants.h"],
3030
allow_jni_merging = False,
3131
compiler_flags = [
@@ -49,7 +49,7 @@ fb_android_cxx_library(
4949

5050
fb_android_cxx_library(
5151
name = "executorch_jni_full",
52-
srcs = ["jni_layer.cpp"],
52+
srcs = ["jni_layer.cpp", "log.cpp"],
5353
headers = ["jni_layer_constants.h"],
5454
allow_jni_merging = False,
5555
compiler_flags = [

extension/android/jni/jni_layer.cpp

Lines changed: 15 additions & 86 deletions
Original file line numberDiff line numberDiff line change
@@ -36,76 +36,6 @@
3636
using namespace executorch::extension;
3737
using namespace torch::executor;
3838

39-
#ifdef __ANDROID__
40-
#include <android/log.h>
41-
#include <mutex>
42-
#include <sstream>
43-
44-
// Number of entries to store in the in-memory log buffer.
45-
const size_t log_buffer_length = 16;
46-
47-
struct log_entry {
48-
et_timestamp_t timestamp;
49-
et_pal_log_level_t level;
50-
std::string filename;
51-
std::string function;
52-
size_t line;
53-
std::string message;
54-
55-
log_entry(
56-
et_timestamp_t timestamp,
57-
et_pal_log_level_t level,
58-
const char* filename,
59-
const char* function,
60-
size_t line,
61-
const char* message,
62-
size_t length)
63-
: timestamp(timestamp),
64-
level(level),
65-
filename(filename),
66-
function(function),
67-
line(line),
68-
message(message, length) {}
69-
};
70-
71-
namespace {
72-
std::vector<log_entry> log_buffer_;
73-
std::mutex log_buffer_mutex_;
74-
} // namespace
75-
76-
// For Android, write to logcat
77-
void et_pal_emit_log_message(
78-
et_timestamp_t timestamp,
79-
et_pal_log_level_t level,
80-
const char* filename,
81-
const char* function,
82-
size_t line,
83-
const char* message,
84-
size_t length) {
85-
std::lock_guard<std::mutex> guard(log_buffer_mutex_);
86-
87-
while (log_buffer_.size() >= log_buffer_length) {
88-
log_buffer_.erase(log_buffer_.begin());
89-
}
90-
91-
log_buffer_.emplace_back(
92-
timestamp, level, filename, function, line, message, length);
93-
94-
int android_log_level = ANDROID_LOG_UNKNOWN;
95-
if (level == 'D') {
96-
android_log_level = ANDROID_LOG_DEBUG;
97-
} else if (level == 'I') {
98-
android_log_level = ANDROID_LOG_INFO;
99-
} else if (level == 'E') {
100-
android_log_level = ANDROID_LOG_ERROR;
101-
} else if (level == 'F') {
102-
android_log_level = ANDROID_LOG_FATAL;
103-
}
104-
105-
__android_log_print(android_log_level, "ExecuTorch", "%s", message);
106-
}
107-
#endif
108-
10939
namespace executorch::extension {
11040
class TensorHybrid : public facebook::jni::HybridClass<TensorHybrid> {
11141
public:
@@ -437,24 +367,26 @@ class ExecuTorchJni : public facebook::jni::HybridClass<ExecuTorchJni> {
437367
facebook::jni::local_ref<facebook::jni::JArrayClass<jstring>>
438368
readLogBuffer() {
439369
#ifdef __ANDROID__
440-
std::lock_guard<std::mutex> guard(log_buffer_mutex_);
441370

442371
const auto size = log_buffer_.size();
443372
facebook::jni::local_ref<facebook::jni::JArrayClass<jstring>> ret =
444373
facebook::jni::JArrayClass<jstring>::newArray(size);
445374

446-
for (auto i = 0u; i < size; i++) {
447-
const auto& entry = log_buffer_[i];
448-
// Format the log entry as "[TIMESTAMP FUNCTION FILE:LINE] LEVEL MESSAGE".
449-
std::stringstream ss;
450-
ss << "[" << entry.timestamp << " " << entry.function << " "
451-
<< entry.filename << ":" << entry.line << "] "
452-
<< static_cast<char>(entry.level) << " " << entry.message;
453-
454-
facebook::jni::local_ref<facebook::jni::JString> jstr_message =
455-
facebook::jni::make_jstring(ss.str().c_str());
456-
(*ret)[i] = jstr_message;
457-
}
375+
access_log_buffer([&](std::vector<log_entry>& buffer) {
376+
for (auto i = 0u; i < size; i++) {
377+
const auto& entry = buffer[i];
378+
// Format the log entry as "[TIMESTAMP FUNCTION FILE:LINE] LEVEL
379+
// MESSAGE".
380+
std::stringstream ss;
381+
ss << "[" << entry.timestamp << " " << entry.function << " "
382+
<< entry.filename << ":" << entry.line << "] "
383+
<< static_cast<char>(entry.level) << " " << entry.message;
384+
385+
facebook::jni::local_ref<facebook::jni::JString> jstr_message =
386+
facebook::jni::make_jstring(ss.str().c_str());
387+
(*ret)[i] = jstr_message;
388+
}
389+
});
458390

459391
return ret;
460392
#else
@@ -468,10 +400,7 @@ class ExecuTorchJni : public facebook::jni::HybridClass<ExecuTorchJni> {
468400
makeNativeMethod("forward", ExecuTorchJni::forward),
469401
makeNativeMethod("execute", ExecuTorchJni::execute),
470402
makeNativeMethod("loadMethod", ExecuTorchJni::load_method),
471-
472-
#ifdef __ANDROID__
473403
makeNativeMethod("readLogBuffer", ExecuTorchJni::readLogBuffer),
474-
#endif
475404
});
476405
}
477406
};

extension/android/jni/log.cpp

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
/*
2+
* Copyright (c) Meta Platforms, Inc. and affiliates.
3+
* All rights reserved.
4+
*
5+
* This source code is licensed under the BSD-style license found in the
6+
* LICENSE file in the root directory of this source tree.
7+
*/
8+
9+
#include <executorch/extension/android/jni/log.h>
10+
11+
#include <android/log.h>
12+
#include <functional>
13+
#include <mutex>
14+
#include <sstream>
15+
16+
// Number of entries to store in the in-memory log buffer.
17+
const size_t log_buffer_length = 16;
18+
19+
namespace {
20+
std::vector<log_entry> log_buffer_;
21+
std::mutex log_buffer_mutex_;
22+
} // namespace
23+
24+
// For Android, write to logcat
25+
void et_pal_emit_log_message(
26+
et_timestamp_t timestamp,
27+
et_pal_log_level_t level,
28+
const char* filename,
29+
const char* function,
30+
size_t line,
31+
const char* message,
32+
size_t length) {
33+
std::lock_guard<std::mutex> guard(log_buffer_mutex_);
34+
35+
while (log_buffer_.size() >= log_buffer_length) {
36+
log_buffer_.erase(log_buffer_.begin());
37+
}
38+
39+
log_buffer_.emplace_back(
40+
timestamp, level, filename, function, line, message, length);
41+
42+
int android_log_level = ANDROID_LOG_UNKNOWN;
43+
if (level == 'D') {
44+
android_log_level = ANDROID_LOG_DEBUG;
45+
} else if (level == 'I') {
46+
android_log_level = ANDROID_LOG_INFO;
47+
} else if (level == 'E') {
48+
android_log_level = ANDROID_LOG_ERROR;
49+
} else if (level == 'F') {
50+
android_log_level = ANDROID_LOG_FATAL;
51+
}
52+
53+
__android_log_print(android_log_level, "ExecuTorch", "%s", message);
54+
}
55+
56+
namespace executorch::extension {
57+
58+
void access_log_buffer(std::function<void(std::vector<log_entry>&)> accessor) {
59+
std::lock_guard<std::mutex> guard(log_buffer_mutex_);
60+
accessor(log_buffer_);
61+
}
62+
63+
} // namespace executorch::extension

extension/android/jni/log.h

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
/*
2+
* Copyright (c) Meta Platforms, Inc. and affiliates.
3+
* All rights reserved.
4+
*
5+
* This source code is licensed under the BSD-style license found in the
6+
* LICENSE file in the root directory of this source tree.
7+
*/
8+
9+
#include <functional>
10+
#include <vector>
11+
12+
#include <executorch/runtime/platform/log.h>
13+
#include <executorch/runtime/platform/platform.h>
14+
#include <executorch/runtime/platform/runtime.h>
15+
16+
namespace executorch::extension {
17+
struct log_entry {
18+
et_timestamp_t timestamp;
19+
et_pal_log_level_t level;
20+
std::string filename;
21+
std::string function;
22+
size_t line;
23+
std::string message;
24+
25+
log_entry(
26+
et_timestamp_t timestamp,
27+
et_pal_log_level_t level,
28+
const char* filename,
29+
const char* function,
30+
size_t line,
31+
const char* message,
32+
size_t length)
33+
: timestamp(timestamp),
34+
level(level),
35+
filename(filename),
36+
function(function),
37+
line(line),
38+
message(message, length) {}
39+
};
40+
41+
void access_log_buffer(std::function<void(std::vector<log_entry>&)> accessor);
42+
} // namespace executorch::extension

0 commit comments

Comments
 (0)