Skip to content

Commit 9c3ac51

Browse files
GregoryComerfacebook-github-bot
authored andcommitted
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 9c3ac51

File tree

5 files changed

+139
-88
lines changed

5 files changed

+139
-88
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/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: 16 additions & 86 deletions
Original file line numberDiff line numberDiff line change
@@ -36,75 +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
10839

10940
namespace executorch::extension {
11041
class TensorHybrid : public facebook::jni::HybridClass<TensorHybrid> {
@@ -436,25 +367,27 @@ class ExecuTorchJni : public facebook::jni::HybridClass<ExecuTorchJni> {
436367

437368
facebook::jni::local_ref<facebook::jni::JArrayClass<jstring>>
438369
readLogBuffer() {
370+
439371
#ifdef __ANDROID__
440-
std::lock_guard<std::mutex> guard(log_buffer_mutex_);
441-
372+
442373
const auto size = log_buffer_.size();
443374
facebook::jni::local_ref<facebook::jni::JArrayClass<jstring>> ret =
444375
facebook::jni::JArrayClass<jstring>::newArray(size);
445376

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-
}
377+
access_log_buffer([&](std::vector<log_entry>& buffer) {
378+
for (auto i = 0u; i < size; i++) {
379+
const auto& entry = buffer[i];
380+
// Format the log entry as "[TIMESTAMP FUNCTION FILE:LINE] LEVEL MESSAGE".
381+
std::stringstream ss;
382+
ss << "[" << entry.timestamp << " " << entry.function << " "
383+
<< entry.filename << ":" << entry.line << "] "
384+
<< static_cast<char>(entry.level) << " " << entry.message;
385+
386+
facebook::jni::local_ref<facebook::jni::JString> jstr_message =
387+
facebook::jni::make_jstring(ss.str().c_str());
388+
(*ret)[i] = jstr_message;
389+
}
390+
});
458391

459392
return ret;
460393
#else
@@ -468,10 +401,7 @@ class ExecuTorchJni : public facebook::jni::HybridClass<ExecuTorchJni> {
468401
makeNativeMethod("forward", ExecuTorchJni::forward),
469402
makeNativeMethod("execute", ExecuTorchJni::execute),
470403
makeNativeMethod("loadMethod", ExecuTorchJni::load_method),
471-
472-
#ifdef __ANDROID__
473404
makeNativeMethod("readLogBuffer", ExecuTorchJni::readLogBuffer),
474-
#endif
475405
});
476406
}
477407
};

extension/android/jni/log.cpp

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
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+
12+
#include <android/log.h>
13+
#include <functional>
14+
#include <mutex>
15+
#include <sstream>
16+
17+
// Number of entries to store in the in-memory log buffer.
18+
const size_t log_buffer_length = 16;
19+
20+
namespace {
21+
std::vector<log_entry> log_buffer_;
22+
std::mutex log_buffer_mutex_;
23+
} // namespace
24+
25+
// For Android, write to logcat
26+
void et_pal_emit_log_message(
27+
et_timestamp_t timestamp,
28+
et_pal_log_level_t level,
29+
const char* filename,
30+
const char* function,
31+
size_t line,
32+
const char* message,
33+
size_t length) {
34+
std::lock_guard<std::mutex> guard(log_buffer_mutex_);
35+
36+
while (log_buffer_.size() >= log_buffer_length) {
37+
log_buffer_.erase(log_buffer_.begin());
38+
}
39+
40+
log_buffer_.emplace_back(
41+
timestamp, level, filename, function, line, message, length);
42+
43+
int android_log_level = ANDROID_LOG_UNKNOWN;
44+
if (level == 'D') {
45+
android_log_level = ANDROID_LOG_DEBUG;
46+
} else if (level == 'I') {
47+
android_log_level = ANDROID_LOG_INFO;
48+
} else if (level == 'E') {
49+
android_log_level = ANDROID_LOG_ERROR;
50+
} else if (level == 'F') {
51+
android_log_level = ANDROID_LOG_FATAL;
52+
}
53+
54+
__android_log_print(android_log_level, "ExecuTorch", "%s", message);
55+
}
56+
57+
namespace executorch::extension {
58+
59+
void access_log_buffer(std::function<void(std::vector<log_entry>&)> accessor) {
60+
std::lock_guard<std::mutex> guard(log_buffer_mutex_);
61+
accessor(log_buffer_);
62+
}
63+
64+
}

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)