Skip to content

Commit

Permalink
Fallback to native StderrLogger
Browse files Browse the repository at this point in the history
  • Loading branch information
nielsenko committed Mar 18, 2024
1 parent b4d8b75 commit bd49967
Show file tree
Hide file tree
Showing 7 changed files with 112 additions and 64 deletions.
92 changes: 73 additions & 19 deletions packages/realm_dart/lib/src/native/realm_bindings.dart
Expand Up @@ -3737,20 +3737,15 @@ class RealmLibrary {
void Function(ffi.Pointer<ffi.Void>, realm_http_request_t,
ffi.Pointer<ffi.Void>)>();

/// Returns `true` if Realm Core logger was initialized.
bool realm_dart_init_core_logger(
int level,
) {
return _realm_dart_init_core_logger(
level,
);
void realm_dart_init_debug_logger() {
return _realm_dart_init_debug_logger();
}

late final _realm_dart_init_core_loggerPtr =
_lookup<ffi.NativeFunction<ffi.Bool Function(ffi.Int32)>>(
'realm_dart_init_core_logger');
late final _realm_dart_init_core_logger =
_realm_dart_init_core_loggerPtr.asFunction<bool Function(int)>();
late final _realm_dart_init_debug_loggerPtr =
_lookup<ffi.NativeFunction<ffi.Void Function()>>(
'realm_dart_init_debug_logger');
late final _realm_dart_init_debug_logger =
_realm_dart_init_debug_loggerPtr.asFunction<void Function()>();

void realm_dart_initializeDartApiDL(
ffi.Pointer<ffi.Void> data,
Expand Down Expand Up @@ -9040,24 +9035,22 @@ class RealmLibrary {
/// Install the default logger
void realm_set_log_callback(
realm_log_func_t arg0,
int arg1,
ffi.Pointer<ffi.Void> userdata,
realm_free_userdata_func_t userdata_free,
) {
return _realm_set_log_callback(
arg0,
arg1,
userdata,
userdata_free,
);
}

late final _realm_set_log_callbackPtr = _lookup<
ffi.NativeFunction<
ffi.Void Function(realm_log_func_t, ffi.Int32, ffi.Pointer<ffi.Void>,
ffi.Void Function(realm_log_func_t, ffi.Pointer<ffi.Void>,
realm_free_userdata_func_t)>>('realm_set_log_callback');
late final _realm_set_log_callback = _realm_set_log_callbackPtr.asFunction<
void Function(realm_log_func_t, int, ffi.Pointer<ffi.Void>,
void Function(realm_log_func_t, ffi.Pointer<ffi.Void>,
realm_free_userdata_func_t)>();

void realm_set_log_level(
Expand Down Expand Up @@ -9390,6 +9383,26 @@ class RealmLibrary {
_realm_sync_client_config_set_fast_reconnect_limitPtr.asFunction<
void Function(ffi.Pointer<realm_sync_client_config_t>, int)>();

void realm_sync_client_config_set_max_resumption_delay_interval(
ffi.Pointer<realm_sync_client_config_t> arg0,
int arg1,
) {
return _realm_sync_client_config_set_max_resumption_delay_interval(
arg0,
arg1,
);
}

late final _realm_sync_client_config_set_max_resumption_delay_intervalPtr =
_lookup<
ffi.NativeFunction<
ffi.Void Function(
ffi.Pointer<realm_sync_client_config_t>, ffi.Uint64)>>(
'realm_sync_client_config_set_max_resumption_delay_interval');
late final _realm_sync_client_config_set_max_resumption_delay_interval =
_realm_sync_client_config_set_max_resumption_delay_intervalPtr.asFunction<
void Function(ffi.Pointer<realm_sync_client_config_t>, int)>();

void realm_sync_client_config_set_metadata_encryption_key(
ffi.Pointer<realm_sync_client_config_t> arg0,
ffi.Pointer<ffi.Uint8> arg1,
Expand Down Expand Up @@ -9502,6 +9515,47 @@ class RealmLibrary {
_realm_sync_client_config_set_reconnect_modePtr.asFunction<
void Function(ffi.Pointer<realm_sync_client_config_t>, int)>();

void realm_sync_client_config_set_resumption_delay_backoff_multiplier(
ffi.Pointer<realm_sync_client_config_t> arg0,
int arg1,
) {
return _realm_sync_client_config_set_resumption_delay_backoff_multiplier(
arg0,
arg1,
);
}

late final _realm_sync_client_config_set_resumption_delay_backoff_multiplierPtr =
_lookup<
ffi.NativeFunction<
ffi.Void Function(
ffi.Pointer<realm_sync_client_config_t>, ffi.Int)>>(
'realm_sync_client_config_set_resumption_delay_backoff_multiplier');
late final _realm_sync_client_config_set_resumption_delay_backoff_multiplier =
_realm_sync_client_config_set_resumption_delay_backoff_multiplierPtr
.asFunction<
void Function(ffi.Pointer<realm_sync_client_config_t>, int)>();

void realm_sync_client_config_set_resumption_delay_interval(
ffi.Pointer<realm_sync_client_config_t> arg0,
int arg1,
) {
return _realm_sync_client_config_set_resumption_delay_interval(
arg0,
arg1,
);
}

late final _realm_sync_client_config_set_resumption_delay_intervalPtr =
_lookup<
ffi.NativeFunction<
ffi.Void Function(
ffi.Pointer<realm_sync_client_config_t>, ffi.Uint64)>>(
'realm_sync_client_config_set_resumption_delay_interval');
late final _realm_sync_client_config_set_resumption_delay_interval =
_realm_sync_client_config_set_resumption_delay_intervalPtr.asFunction<
void Function(ffi.Pointer<realm_sync_client_config_t>, int)>();

void realm_sync_client_config_set_sync_socket(
ffi.Pointer<realm_sync_client_config_t> arg0,
ffi.Pointer<realm_sync_socket_t> arg1,
Expand Down Expand Up @@ -11707,9 +11761,9 @@ class _SymbolAddresses {
ffi.Void Function(ffi.Pointer<ffi.Void>, realm_http_request_t,
ffi.Pointer<ffi.Void>)>> get realm_dart_http_request_callback =>
_library._realm_dart_http_request_callbackPtr;
ffi.Pointer<ffi.NativeFunction<ffi.Bool Function(ffi.Int32)>>
get realm_dart_init_core_logger =>
_library._realm_dart_init_core_loggerPtr;
ffi.Pointer<ffi.NativeFunction<ffi.Void Function()>>
get realm_dart_init_debug_logger =>
_library._realm_dart_init_debug_loggerPtr;
ffi.Pointer<ffi.NativeFunction<ffi.Void Function(ffi.Pointer<ffi.Void>)>>
get realm_dart_initializeDartApiDL =>
_library._realm_dart_initializeDartApiDLPtr;
Expand Down
8 changes: 1 addition & 7 deletions packages/realm_dart/lib/src/native/realm_core.dart
Expand Up @@ -14,7 +14,6 @@ import 'package:cancellation_token/cancellation_token.dart';
import 'package:crypto/crypto.dart';
// Hide StringUtf8Pointer.toNativeUtf8 and StringUtf16Pointer since these allows silently allocating memory. Use toUtf8Ptr instead
import 'package:ffi/ffi.dart' hide StringUtf8Pointer, StringUtf16Pointer;
import 'package:logging/logging.dart';
import 'package:path/path.dart' as path;
import 'package:pubspec_parse/pubspec_parse.dart';
import 'package:realm_common/realm_common.dart' as common show Decimal128;
Expand Down Expand Up @@ -101,13 +100,8 @@ class _RealmCore {

// This prevents reentrance if `realmCore` global variable is accessed during _RealmCore construction
realmCore = this;
_initDefaultLogger();
}

void _initDefaultLogger() {
if (_realmLib.realm_dart_init_core_logger(RealmLogLevel.info.index)) {
loggerAttach(); // TODO: Should we do this, or should we let the user attach the logger?
}
_realmLib.realm_dart_init_debug_logger();
}

void loggerAttach() {
Expand Down
2 changes: 1 addition & 1 deletion packages/realm_dart/src/realm-core
54 changes: 29 additions & 25 deletions packages/realm_dart/src/realm_dart_logger.cpp
Expand Up @@ -16,32 +16,18 @@
//
////////////////////////////////////////////////////////////////////////////////

#include <sstream>
#include <set>
#include <algorithm>
#include <map>
#include <mutex>
#include <set>
#include <sstream>
#include <thread>
#include <map>
#include <algorithm>
#include <realm/object-store/c_api/util.hpp>

#include "realm_dart_logger.h"

using namespace realm::util;

std::mutex dart_logger_mutex;
bool is_core_logger_callback_set = false;
std::set<Dart_Port> dart_send_ports;

RLM_API void realm_dart_detach_logger(Dart_Port port) {
std::lock_guard<std::mutex> lock(dart_logger_mutex);
dart_send_ports.erase(port);
}

RLM_API void realm_dart_attach_logger(Dart_Port port) {
std::lock_guard<std::mutex> lock(dart_logger_mutex);
dart_send_ports.insert(port);
}

bool send_message_to_scheduler(Dart_Port port, const char* category, realm_log_level_e level, const char* message) {
Dart_CObject c_category;
c_category.type = Dart_CObject_kString;
Expand All @@ -64,6 +50,20 @@ bool send_message_to_scheduler(Dart_Port port, const char* category, realm_log_l
return Dart_PostCObject_DL(port, &c_request);
}

std::mutex dart_logger_mutex;
std::set<Dart_Port> dart_send_ports;
std::shared_ptr<StderrLogger> default_debug_logger;
bool default_debug_logger_initialized = false;

RLM_API void realm_dart_init_debug_logger() {
if (default_debug_logger_initialized) {
return;
}
default_debug_logger = std::make_shared<StderrLogger>();
Logger::set_default_logger(default_debug_logger);
default_debug_logger_initialized = true;
}

void realm_dart_logger_callback(realm_userdata_t userData, const char* category, realm_log_level_e level, const char* message) {
std::lock_guard<std::mutex> lock(dart_logger_mutex);
for (auto itr = dart_send_ports.begin(); itr != dart_send_ports.end(); ++itr) {
Expand All @@ -72,16 +72,20 @@ void realm_dart_logger_callback(realm_userdata_t userData, const char* category,
}
}

RLM_API bool realm_dart_init_core_logger(realm_log_level_e level) {
RLM_API void realm_dart_attach_logger(Dart_Port port) {
std::lock_guard<std::mutex> lock(dart_logger_mutex);
if (is_core_logger_callback_set) {
return false;
if (dart_send_ports.empty()) {
realm_set_log_callback(realm_dart_logger_callback, nullptr, nullptr);
}
dart_send_ports.insert(port);
}

realm_set_log_callback(realm_dart_logger_callback, level, nullptr, nullptr);
is_core_logger_callback_set = true;

return is_core_logger_callback_set;
RLM_API void realm_dart_detach_logger(Dart_Port port) {
std::lock_guard<std::mutex> lock(dart_logger_mutex);
dart_send_ports.erase(port);
if (dart_send_ports.empty()) {
Logger::set_default_logger(default_debug_logger);
}
}

RLM_API void realm_dart_log(realm_log_level_e level, const char* category, const char* message) {
Expand Down
5 changes: 1 addition & 4 deletions packages/realm_dart/src/realm_dart_logger.h
Expand Up @@ -22,10 +22,7 @@
#include <realm.h>
#include <dart_api_dl.h>

/**
* Returns `true` if Realm Core logger was initialized.
*/
RLM_API bool realm_dart_init_core_logger(realm_log_level_e level);
RLM_API void realm_dart_init_debug_logger();

RLM_API void realm_dart_attach_logger(Dart_Port port);

Expand Down
2 changes: 0 additions & 2 deletions packages/realm_dart/src/realm_dart_scheduler.cpp
Expand Up @@ -41,8 +41,6 @@ struct SchedulerData {
//This can be invoked on any thread
void realm_dart_scheduler_free_userData(void* userData) {
SchedulerData* schedulerData = static_cast<SchedulerData*>(userData);
realm_dart_detach_logger(schedulerData->port);
//delete the scheduler
delete schedulerData;
}

Expand Down
13 changes: 7 additions & 6 deletions packages/realm_dart/test/realm_logger_test.dart
@@ -1,8 +1,8 @@
// Copyright 2023 MongoDB, Inc.
// SPDX-License-Identifier: Apache-2.0

import 'dart:async';
import 'dart:isolate';
import 'dart:math';
import 'package:logging/logging.dart';
import 'package:realm_dart/src/logging.dart';
import 'package:test/test.dart' hide test, throws;
Expand Down Expand Up @@ -51,7 +51,7 @@ void main() {

test('Trace in subisolate seen in parent', () {
Realm.logger.setLogLevel(RealmLogLevel.all);
expectLater(Realm.logger.onRecord, emits(isA<RealmLogRecord>().having((r) => r.message, '', 'Hey')));
expectLater(Realm.logger.onRecord, emits(isA<RealmLogRecord>().having((r) => r.message, 'message', 'Hey')));
Isolate.run(() {
Realm.logger.log(RealmLogLevel.trace, 'Hey');
});
Expand All @@ -62,7 +62,7 @@ void main() {
final trace = Isolate.run(() async {
return (await Realm.logger.onRecord.first).message;
});
await Future<void>.delayed(const Duration(seconds: 1)); // yield
await Future<void>.delayed(const Duration(milliseconds: 1)); // yield
expectLater(trace, completion('Hey'));
Realm.logger.log(RealmLogLevel.trace, 'Hey');
});
Expand All @@ -73,7 +73,7 @@ void main() {
logger.level = Level.ALL;
Realm.logger.setLogLevel(RealmLogLevel.error);

expectLater(logger.onRecord, emits(isA<LogRecord>().having((r) => r.level, '==', Level.SEVERE).having((r) => r.message, '==', 'error')));
expectLater(logger.onRecord, emits(isA<LogRecord>().having((r) => r.level, 'level', Level.SEVERE).having((r) => r.message, 'message', 'error')));

Realm.logger.log(RealmLogLevel.error, 'error', category: RealmLogCategory.realm.sdk);
});
Expand All @@ -84,8 +84,9 @@ void main() {
Logger.root.level = Level.ALL;
Realm.logger.setLogLevel(RealmLogLevel.error);

expectLater(Logger('Realm').onRecord, emits(isA<LogRecord>().having((r) => r.level, '==', Level.SEVERE).having((r) => r.message, '==', 'error')));
expectLater(Logger('Realm.SDK').onRecord, emits(isA<LogRecord>().having((r) => r.level, '==', Level.SEVERE).having((r) => r.message, '==', 'error')));
expectLater(Logger('Realm').onRecord, emits(isA<LogRecord>().having((r) => r.level, 'level', Level.SEVERE).having((r) => r.message, 'message', 'error')));
expectLater(
Logger('Realm.SDK').onRecord, emits(isA<LogRecord>().having((r) => r.level, 'level', Level.SEVERE).having((r) => r.message, 'message', 'error')));

Realm.logger.log(RealmLogLevel.error, 'error', category: RealmLogCategory.realm.sdk);
});
Expand Down

0 comments on commit bd49967

Please sign in to comment.