Flutter Engine
The Flutter Engine
Loading...
Searching...
No Matches
log.cc
Go to the documentation of this file.
1// Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file
2// for details. All rights reserved. Use of this source code is governed by a
3// BSD-style license that can be found in the LICENSE file.
4
5#include "vm/log.h"
6
7#include "vm/dart.h"
8#include "vm/flags.h"
9#include "vm/isolate.h"
10#include "vm/thread.h"
11
12namespace dart {
13
14DEFINE_FLAG(bool, force_log_flush, false, "Always flush log messages.");
15
16// The following flag is useful when debugging on Android, since
17// adb logcat truncates messages that are "too long" (and always
18// flushing would result in too many short messages).
20 int,
21 force_log_flush_at_size,
22 0,
23 "Flush log messages when buffer exceeds given size (disabled when 0).");
24
26 isolate_log_filter,
27 nullptr,
28 "Log isolates whose name include the filter. "
29 "Default: service isolate log messages are suppressed "
30 "(specify 'vm-service' to log them).");
31
33 redirect_isolate_log_to,
34 nullptr,
35 "Log isolate messages into the given file.");
36
37namespace {
38class LogFile {
39 public:
40 static const LogFile& Instance() {
41 static LogFile log_file;
42 return log_file;
43 }
44
45 static void Print(const char* data) {
46 Dart::file_write_callback()(data, strlen(data), Instance().handle_);
47 }
48
49 private:
50 LogFile()
51 : handle_(Dart::file_open_callback()(FLAG_redirect_isolate_log_to,
52 /*write=*/true)) {}
53
54 ~LogFile() { Dart::file_close_callback()(handle_); }
55
56 void* handle_;
57};
58} // namespace
59
60Log::Log(LogPrinter printer) : printer_(printer), manual_flush_(0), buffer_(0) {
61 if (printer_ == nullptr) {
62 if (FLAG_redirect_isolate_log_to == nullptr) {
63 printer_ = [](const char* data) { OS::PrintErr("%s", data); };
64 } else {
65 printer_ = &LogFile::Print;
66 }
67 }
68}
69
71 // Did someone enable manual flushing and then forgot to Flush?
72 ASSERT(cursor() == 0);
73}
74
76 Thread* thread = Thread::Current();
77 if (thread == nullptr) {
78 OSThread* os_thread = OSThread::Current();
79 ASSERT(os_thread != nullptr);
80 return os_thread->log();
81 }
82 IsolateGroup* isolate_group = thread->isolate_group();
83 if ((isolate_group != nullptr) &&
84 Log::ShouldLogForIsolateGroup(isolate_group)) {
85 OSThread* os_thread = thread->os_thread();
86 ASSERT(os_thread != nullptr);
87 return os_thread->log();
88 } else {
89 return Log::NoOpLog();
90 }
91}
92
93void Log::Print(const char* format, ...) {
94 if (this == NoOpLog()) {
95 return;
96 }
97
98 va_list args;
99 va_start(args, format);
101 va_end(args);
102}
103
104void Log::VPrint(const char* format, va_list args) {
105 if (this == NoOpLog()) {
106 return;
107 }
108
109 // Measure.
110 va_list measure_args;
111 va_copy(measure_args, args);
112 intptr_t len = Utils::VSNPrint(nullptr, 0, format, measure_args);
113 va_end(measure_args);
114
115 // Print.
116 char* buffer = reinterpret_cast<char*>(malloc(len + 1));
117 va_list print_args;
118 va_copy(print_args, args);
119 Utils::VSNPrint(buffer, (len + 1), format, print_args);
120 va_end(print_args);
121
122 // Append.
123 // NOTE: does not append the '\0' character.
124 for (intptr_t i = 0; i < len; i++) {
125 buffer_.Add(buffer[i]);
126 }
127 free(buffer);
128
129 if (ShouldFlush()) {
130 Flush();
131 }
132}
133
134void Log::Flush(const intptr_t cursor) {
135 if (this == NoOpLog()) {
136 return;
137 }
138 if (buffer_.is_empty()) {
139 return;
140 }
141 if (buffer_.length() <= cursor) {
142 return;
143 }
144 TerminateString();
145 const char* str = &buffer_[cursor];
146 ASSERT(str != nullptr);
147 printer_(str);
148 buffer_.TruncateTo(cursor);
149}
150
152 if (this == NoOpLog()) {
153 return;
154 }
155 buffer_.TruncateTo(0);
156}
157
158intptr_t Log::cursor() const {
159 return buffer_.length();
160}
161
162bool Log::ShouldLogForIsolateGroup(const IsolateGroup* isolate_group) {
163 if (FLAG_isolate_log_filter == nullptr) {
164 // By default, do not log for the service or kernel isolates.
165 if (isolate_group == Dart::vm_isolate_group()) {
166 return true;
167 }
168 if (IsolateGroup::IsSystemIsolateGroup(isolate_group)) {
169 return false;
170 }
171 return true;
172 }
173 const char* name = isolate_group->source()->name;
174 ASSERT(name != nullptr);
175 if (strstr(name, FLAG_isolate_log_filter) == nullptr) {
176 // Filter does not match, do not log for this isolate.
177 return false;
178 }
179 return true;
180}
181
182Log Log::noop_log_;
184 return &noop_log_;
185}
186
187void Log::TerminateString() {
188 if (this == NoOpLog()) {
189 return;
190 }
191 buffer_.Add('\0');
192}
193
194void Log::EnableManualFlush() {
195 if (this == NoOpLog()) {
196 return;
197 }
198 manual_flush_++;
199}
200
201void Log::DisableManualFlush(const intptr_t cursor) {
202 if (this == NoOpLog()) {
203 return;
204 }
205
206 manual_flush_--;
207 ASSERT(manual_flush_ >= 0);
208 if (manual_flush_ == 0) {
209 Flush(cursor);
210 }
211}
212
213bool Log::ShouldFlush() const {
214#ifdef DART_TARGET_OS_ANDROID
215 // Android truncates on 1023 characters, flush more eagerly.
216 // Flush on newlines, because otherwise Android inserts newlines everywhere.
217 if (*(buffer_.end() - 1) == '\n') {
218 return true;
219 }
220#endif // DART_TARGET_OS_ANDROID
221 return ((manual_flush_ == 0) || FLAG_force_log_flush ||
222 ((FLAG_force_log_flush_at_size > 0) &&
223 (cursor() > FLAG_force_log_flush_at_size)));
224}
225
226void LogBlock::Initialize() {
227 log_->EnableManualFlush();
228}
229
231 log_->DisableManualFlush(cursor_);
232}
233
234} // namespace dart
void TruncateTo(intptr_t length)
void Add(const T &value)
intptr_t length() const
static Dart_FileWriteCallback file_write_callback()
Definition dart.h:125
static IsolateGroup * vm_isolate_group()
Definition dart.h:69
static Dart_FileCloseCallback file_close_callback()
Definition dart.h:128
static bool IsSystemIsolateGroup(const IsolateGroup *group)
Definition isolate.cc:3559
IsolateGroupSource * source() const
Definition isolate.h:285
void Clear()
Definition log.cc:151
void Print(const char *format,...) PRINTF_ATTRIBUTE(2
Definition log.cc:93
static Log * NoOpLog()
Definition log.cc:183
intptr_t cursor() const
Definition log.cc:158
~Log()
Definition log.cc:70
static Log * Current()
Definition log.cc:75
Log(LogPrinter printer=nullptr)
Definition log.cc:60
void Flush(const intptr_t cursor=0)
Definition log.cc:134
void void VPrint(const char *format, va_list args)
Definition log.cc:104
Log * log() const
Definition os_thread.h:126
static OSThread * Current()
Definition os_thread.h:175
static void static void PrintErr(const char *format,...) PRINTF_ATTRIBUTE(1
OSThread * os_thread() const
static Thread * Current()
Definition thread.h:361
IsolateGroup * isolate_group() const
Definition thread.h:540
static int static int VSNPrint(char *str, size_t size, const char *format, va_list args)
#define ASSERT(E)
G_BEGIN_DECLS G_MODULE_EXPORT FlValue * args
static const uint8_t buffer[]
uint32_t uint32_t * format
const char * charp
Definition flags.h:12
#define DEFINE_FLAG(type, name, default_value, comment)
Definition flags.h:16
void Log(const char *format,...) SK_PRINTF_LIKE(1
const char *const name
void * malloc(size_t size)
Definition allocation.cc:19
static int8_t data[kExtLength]
void(* LogPrinter)(const char *data)
Definition log.h:25
fuchsia::ui::composition::ParentViewportWatcherHandle handle_