1// Copyright 2013 The Flutter Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include <algorithm>
6#include <cstring>
7#include <iostream>
8
9#include "flutter/fml/build_config.h"
10#include "flutter/fml/log_settings.h"
11#include "flutter/fml/logging.h"
12
13#if defined(FML_OS_ANDROID)
14#include <android/log.h>
15#elif defined(FML_OS_IOS)
16#include <syslog.h>
17#elif defined(OS_FUCHSIA)
18#include <lib/syslog/global.h>
19#endif
20
21namespace fml {
22
23namespace {
24
25#if !defined(OS_FUCHSIA)
26const char* const kLogSeverityNames[LOG_NUM_SEVERITIES] = {"INFO", "WARNING",
27 "ERROR", "FATAL"};
28
29const char* GetNameForLogSeverity(LogSeverity severity) {
30 if (severity >= LOG_INFO && severity < LOG_NUM_SEVERITIES) {
31 return kLogSeverityNames[severity];
32 }
33 return "UNKNOWN";
34}
35
36const char* StripDots(const char* path) {
37 while (strncmp(s1: path, s2: "../", n: 3) == 0) {
38 path += 3;
39 }
40 return path;
41}
42
43const char* StripPath(const char* path) {
44 auto* p = strrchr(s: path, c: '/');
45 if (p) {
46 return p + 1;
47 }
48 return path;
49}
50#endif
51
52} // namespace
53
54LogMessage::LogMessage(LogSeverity severity,
55 const char* file,
56 int line,
57 const char* condition)
58 : severity_(severity), file_(file), line_(line) {
59#if !defined(OS_FUCHSIA)
60 stream_ << "[";
61 if (severity >= LOG_INFO) {
62 stream_ << GetNameForLogSeverity(severity);
63 } else {
64 stream_ << "VERBOSE" << -severity;
65 }
66 stream_ << ":" << (severity > LOG_INFO ? StripDots(path: file_) : StripPath(path: file_))
67 << "(" << line_ << ")] ";
68#endif
69
70 if (condition) {
71 stream_ << "Check failed: " << condition << ". ";
72 }
73}
74
75// static
76thread_local std::ostringstream* LogMessage::capture_next_log_stream_ = nullptr;
77
78namespace testing {
79
80LogCapture::LogCapture() {
81 fml::LogMessage::CaptureNextLog(stream: &stream_);
82}
83
84LogCapture::~LogCapture() {
85 fml::LogMessage::CaptureNextLog(stream: nullptr);
86}
87
88std::string LogCapture::str() const {
89 return stream_.str();
90}
91
92} // namespace testing
93
94// static
95void LogMessage::CaptureNextLog(std::ostringstream* stream) {
96 LogMessage::capture_next_log_stream_ = stream;
97}
98
99LogMessage::~LogMessage() {
100#if !defined(OS_FUCHSIA)
101 stream_ << std::endl;
102#endif
103
104 if (capture_next_log_stream_) {
105 *capture_next_log_stream_ << stream_.str();
106 capture_next_log_stream_ = nullptr;
107 } else {
108#if defined(FML_OS_ANDROID)
109 android_LogPriority priority =
110 (severity_ < 0) ? ANDROID_LOG_VERBOSE : ANDROID_LOG_UNKNOWN;
111 switch (severity_) {
112 case LOG_INFO:
113 priority = ANDROID_LOG_INFO;
114 break;
115 case LOG_WARNING:
116 priority = ANDROID_LOG_WARN;
117 break;
118 case LOG_ERROR:
119 priority = ANDROID_LOG_ERROR;
120 break;
121 case LOG_FATAL:
122 priority = ANDROID_LOG_FATAL;
123 break;
124 }
125 __android_log_write(priority, "flutter", stream_.str().c_str());
126#elif defined(FML_OS_IOS)
127 syslog(LOG_ALERT, "%s", stream_.str().c_str());
128#elif defined(OS_FUCHSIA)
129 fx_log_severity_t fx_severity;
130 switch (severity_) {
131 case LOG_INFO:
132 fx_severity = FX_LOG_INFO;
133 break;
134 case LOG_WARNING:
135 fx_severity = FX_LOG_WARNING;
136 break;
137 case LOG_ERROR:
138 fx_severity = FX_LOG_ERROR;
139 break;
140 case LOG_FATAL:
141 fx_severity = FX_LOG_FATAL;
142 break;
143 default:
144 if (severity_ < 0) {
145 fx_severity = fx_log_severity_from_verbosity(-severity_);
146 } else {
147 // Unknown severity. Use INFO.
148 fx_severity = FX_LOG_INFO;
149 }
150 }
151 fx_logger_log_with_source(fx_log_get_logger(), fx_severity, nullptr, file_,
152 line_, stream_.str().c_str());
153#else
154 // Don't use std::cerr here, because it may not be initialized properly yet.
155 fprintf(stderr, format: "%s", stream_.str().c_str());
156 fflush(stderr);
157#endif
158 }
159
160 if (severity_ >= LOG_FATAL) {
161 KillProcess();
162 }
163}
164
165int GetVlogVerbosity() {
166 return std::max(a: -1, b: LOG_INFO - GetMinLogLevel());
167}
168
169bool ShouldCreateLogMessage(LogSeverity severity) {
170 return severity >= GetMinLogLevel();
171}
172
173void KillProcess() {
174 abort();
175}
176
177} // namespace fml
178

source code of flutter_engine/flutter/fml/logging.cc