mirror of
https://github.com/keymanapp/keyman.git
synced 2026-09-23 08:07:40 +00:00
Merge branch 'stable-18.0' into maint/cherrypick/builder-autocomplete-inc-sh
This commit is contained in:
commit
5909086bf7
7 changed files with 143 additions and 9 deletions
|
|
@ -4,15 +4,19 @@
|
|||
|
||||
package com.keyman.engine.util;
|
||||
|
||||
import static com.keyman.engine.KMManager.KMKey_LexicalModelID;
|
||||
|
||||
import android.util.Log;
|
||||
import android.widget.Toast;
|
||||
|
||||
import com.keyman.engine.BaseActivity;
|
||||
import com.keyman.engine.BuildConfig;
|
||||
import com.keyman.engine.KMManager;
|
||||
import com.keyman.engine.util.DependencyUtil;
|
||||
import com.keyman.engine.data.Keyboard;
|
||||
import com.keyman.engine.util.DependencyUtil.LibraryType;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import io.sentry.Breadcrumb;
|
||||
import io.sentry.Sentry;
|
||||
import io.sentry.SentryLevel;
|
||||
|
|
@ -20,19 +24,67 @@ import io.sentry.SentryLevel;
|
|||
public final class KMLog {
|
||||
private static final String TAG = "KMLog";
|
||||
|
||||
private static final String KEYBOARD_TAG = "keyboardId";
|
||||
private static final String KEYBOARD_COUNT_TAG = "installedKeyboardCount";
|
||||
private static final String MODEL_TAG = "modelId";
|
||||
private static final String LANGCODE_TAG = "languageCode";
|
||||
|
||||
// Some of the methods used to generate debug logging information can, themselves,
|
||||
// trigger errors that can also trigger the same logging. We must not get
|
||||
// caught in an infinite loop / stack-overflow; this field helps us avoid states
|
||||
// that would otherwise cause error-looping, etc.
|
||||
private static boolean isLogging = false;
|
||||
|
||||
private static void tagDebugInfo() {
|
||||
String kbdId = "";
|
||||
String lngCode = "";
|
||||
String modelId = "";
|
||||
int kbdCount = 0;
|
||||
// Do not risk raising a new error while tagging info for another error.
|
||||
try {
|
||||
// Both take a context parameter... but don't actually need or use it!
|
||||
Keyboard kbd = KMManager.getCurrentKeyboardInfo(null);
|
||||
kbdCount = KMManager.getKeyboardsList(null).size();
|
||||
if (kbd != null) {
|
||||
kbdId = kbd.getKeyboardID();
|
||||
lngCode = kbd.getLanguageCode();
|
||||
Map<String, String> modelMap = KMManager.getAssociatedLexicalModel(kbd.getLanguageID());
|
||||
if (modelMap != null) {
|
||||
modelId = modelMap.get(KMKey_LexicalModelID);
|
||||
if (modelId == null) {
|
||||
modelId = "";
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
String msg = ex.getMessage() == null ? "" : ex.getMessage();
|
||||
Sentry.setExtra("debugLoggingError", msg);
|
||||
}
|
||||
Sentry.setExtra(KEYBOARD_TAG, kbdId);
|
||||
Sentry.setExtra(KEYBOARD_COUNT_TAG, "" + kbdCount);
|
||||
Sentry.setExtra(LANGCODE_TAG, lngCode);
|
||||
Sentry.setExtra(MODEL_TAG, modelId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Utility to log info and send to Sentry
|
||||
* @param tag String of the caller
|
||||
* @param msg String of the info message
|
||||
*/
|
||||
public static void LogInfo(String tag, String msg) {
|
||||
if(isLogging) {
|
||||
return;
|
||||
}
|
||||
isLogging = true;
|
||||
if (msg != null && !msg.isEmpty()) {
|
||||
Log.i(tag, msg);
|
||||
|
||||
if (DependencyUtil.libraryExists(LibraryType.SENTRY) && Sentry.isEnabled()) {
|
||||
tagDebugInfo();
|
||||
Sentry.captureMessage(msg, SentryLevel.INFO);
|
||||
}
|
||||
}
|
||||
isLogging = false;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -46,9 +98,15 @@ public final class KMLog {
|
|||
return;
|
||||
}
|
||||
|
||||
if(isLogging) {
|
||||
return;
|
||||
}
|
||||
isLogging = true;
|
||||
|
||||
Log.i(tag, msg);
|
||||
|
||||
if (!DependencyUtil.libraryExists(LibraryType.SENTRY) || !Sentry.isEnabled()) {
|
||||
isLogging = false;
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -74,7 +132,9 @@ public final class KMLog {
|
|||
crumb.setData("stacktrace", trace);
|
||||
}
|
||||
}
|
||||
tagDebugInfo();
|
||||
Sentry.addBreadcrumb(crumb);
|
||||
isLogging = false;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -83,6 +143,10 @@ public final class KMLog {
|
|||
* @param msg String of the error message
|
||||
*/
|
||||
public static void LogError(String tag, String msg) {
|
||||
if(isLogging) {
|
||||
return;
|
||||
}
|
||||
isLogging = true;
|
||||
if (msg != null && !msg.isEmpty()) {
|
||||
Log.e(tag, msg);
|
||||
|
||||
|
|
@ -91,9 +155,11 @@ public final class KMLog {
|
|||
}
|
||||
|
||||
if (DependencyUtil.libraryExists(LibraryType.SENTRY) && Sentry.isEnabled()) {
|
||||
tagDebugInfo();
|
||||
Sentry.captureMessage(msg, SentryLevel.ERROR);
|
||||
}
|
||||
}
|
||||
isLogging = false;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -103,6 +169,10 @@ public final class KMLog {
|
|||
* @param e Throwable exception
|
||||
*/
|
||||
public static void LogException(String tag, String msg, Throwable e) {
|
||||
if(isLogging) {
|
||||
return;
|
||||
}
|
||||
isLogging = true;
|
||||
String errorMsg = "";
|
||||
if (msg != null && !msg.isEmpty()) {
|
||||
errorMsg = msg + "\n" + e;
|
||||
|
|
@ -116,9 +186,11 @@ public final class KMLog {
|
|||
}
|
||||
|
||||
if (DependencyUtil.libraryExists(LibraryType.SENTRY) && Sentry.isEnabled()) {
|
||||
tagDebugInfo();
|
||||
Sentry.addBreadcrumb(errorMsg);
|
||||
Sentry.captureException(e);
|
||||
}
|
||||
isLogging = false;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -131,7 +203,12 @@ public final class KMLog {
|
|||
*/
|
||||
public static void LogExceptionWithData(String tag, String msg,
|
||||
String objName, Object obj, Throwable e) {
|
||||
if(isLogging) {
|
||||
return;
|
||||
}
|
||||
isLogging = true;
|
||||
if (obj != null && DependencyUtil.libraryExists(LibraryType.SENTRY) && Sentry.isEnabled()) {
|
||||
tagDebugInfo();
|
||||
String objStr = null;
|
||||
try {
|
||||
objStr = obj.toString();
|
||||
|
|
@ -141,6 +218,10 @@ public final class KMLog {
|
|||
}
|
||||
// Report the original exception
|
||||
LogException(tag, msg, e);
|
||||
// And remove the exception-specific tagged data, lest it also be
|
||||
// tracked on subsequent errors not associated with the current call.
|
||||
Sentry.removeExtra(objName);
|
||||
}
|
||||
isLogging = false;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -16,10 +16,20 @@ import os.log
|
|||
*/
|
||||
public class SentryManager {
|
||||
private static var _started: Bool = false
|
||||
|
||||
// Set once Manager.shared is fully initialized and safe to reference.
|
||||
private static var engineHasInitialized: Bool = false
|
||||
|
||||
public static var hasStarted: Bool {
|
||||
return _started
|
||||
}
|
||||
|
||||
/**
|
||||
This method should be called once Manager.shared is fully initialized and safe to reference - a precondition needed to enable engine-state logging, such as current keyboard, etc when errors occur.
|
||||
*/
|
||||
public static func setEngineInitialized() {
|
||||
engineHasInitialized = true
|
||||
}
|
||||
|
||||
public static func start(sendingEnabled: Bool = true) {
|
||||
// First things first: enable Sentry for crash reporting.
|
||||
|
|
@ -89,6 +99,31 @@ public class SentryManager {
|
|||
return SentryManager.enabled
|
||||
#endif
|
||||
}
|
||||
|
||||
private static func setDebugInfo() {
|
||||
// We cannot directly use Manager.shared while it's initializing,
|
||||
// and there are logging lines during that process that can lead here!
|
||||
guard engineHasInitialized else {
|
||||
return
|
||||
}
|
||||
|
||||
let kbd = Manager.shared.currentKeyboard
|
||||
let modelId = Manager.shared.currentLexicalModelID?.id ?? ""
|
||||
let kbdId = kbd?.id ?? ""
|
||||
let langCode = kbd?.lgCode ?? ""
|
||||
let kbdCnt = "\(Storage.active.userDefaults.userKeyboards?.count ?? 0)"
|
||||
|
||||
let engineState: [String: String] = [
|
||||
"installedKeyboardCount": kbdCnt,
|
||||
"keyboardId" : kbdId,
|
||||
"languageCode" : langCode,
|
||||
"modelId" : modelId,
|
||||
]
|
||||
|
||||
SentrySDK.configureScope { scope in
|
||||
scope.setContext(value: engineState, key: "engineState")
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Captures a Sentry event and safely bypass the Sentry component if not activated by the app.
|
||||
|
|
@ -96,6 +131,7 @@ public class SentryManager {
|
|||
public static func capture(_ event: Sentry.Event) {
|
||||
// Guarded in case a library consumer decides against initializing Sentry.
|
||||
if _started {
|
||||
setDebugInfo()
|
||||
SentrySDK.capture(event: event)
|
||||
}
|
||||
}
|
||||
|
|
@ -131,6 +167,7 @@ public class SentryManager {
|
|||
public static func breadcrumb(crumb: Sentry.Breadcrumb) {
|
||||
// Guarded in case a library consumer decides against initializing Sentry.
|
||||
if _started {
|
||||
setDebugInfo()
|
||||
SentrySDK.addBreadcrumb(crumb)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -249,8 +249,9 @@ public class Manager: NSObject, UIGestureRecognizerDelegate {
|
|||
NotificationCenter.default.addObserver(self, selector: #selector(self.keyboardWillHide), //
|
||||
name: UIResponder.keyboardWillHideNotification, object: nil)
|
||||
|
||||
// We used to preload the old KeymanWebViewController, but now that it's embedded within the
|
||||
// InputViewController, that's not exactly viable.
|
||||
// Note that the engine has initialized and that Manager.shared
|
||||
// is accessible for advanced logging info once this method ends.
|
||||
SentryManager.setEngineInitialized()
|
||||
}
|
||||
|
||||
// MARK: - Keyboard Notifications
|
||||
|
|
|
|||
|
|
@ -3,5 +3,5 @@
|
|||
|
||||
[D-BUS Service]
|
||||
Name=com.keyman.SystemService1
|
||||
Exec=/usr/libexec/systemd-keyman.service
|
||||
Exec=@LIBEXECDIR@/systemd-keyman.service
|
||||
User=root
|
||||
|
|
|
|||
|
|
@ -1,11 +1,26 @@
|
|||
# This file will be appended to meson.build by build.sh
|
||||
cfg = configuration_data()
|
||||
cfg.set('LIBEXECDIR', get_option('prefix') / get_option('libexecdir'))
|
||||
|
||||
install_data('com.keyman.SystemService1.conf', install_dir: get_option('datadir') / 'dbus-1/system.d/')
|
||||
|
||||
if systemd.name() == 'libsystemd'
|
||||
install_data('com.keyman.SystemService1.service.systemd', install_dir: get_option('datadir') / 'dbus-1/system-services/', rename: ['com.keyman.SystemService1.service'])
|
||||
else
|
||||
# libelogind or basu
|
||||
install_data('com.keyman.SystemService1.service.basu', install_dir: get_option('datadir') / 'dbus-1/system-services/')
|
||||
configure_file(
|
||||
configuration: cfg,
|
||||
input: 'com.keyman.SystemService1.service.basu',
|
||||
output: 'com.keyman.SystemService1.service',
|
||||
install: true,
|
||||
install_dir: get_option('datadir') / 'dbus-1/system-services/'
|
||||
)
|
||||
endif
|
||||
|
||||
install_data('systemd-keyman.service', install_dir: get_option('prefix') / 'lib/systemd/system/')
|
||||
configure_file(
|
||||
configuration: cfg,
|
||||
input: 'systemd-keyman.service.in',
|
||||
output: 'systemd-keyman.service',
|
||||
install: true,
|
||||
install_dir: get_option('prefix') / 'lib/systemd/system/'
|
||||
)
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ Description=Keyman System Service
|
|||
[Service]
|
||||
Type=dbus
|
||||
BusName=com.keyman.SystemService1
|
||||
ExecStart=/usr/libexec/keyman-system-service
|
||||
ExecStart=@LIBEXECDIR@/keyman-system-service
|
||||
Restart=on-failure
|
||||
|
||||
# Filesystem lockdown
|
||||
|
|
@ -7,9 +7,9 @@
|
|||
<key>teamID</key>
|
||||
<string>D7TR486TEH</string>
|
||||
<key>signingCertificate</key>
|
||||
<string>227D454DE9320031D7E9C3E02FEB7463B9A33776</string>
|
||||
<string>D7B7973A30C90C1A04666667F24B4D5C7E913923</string>
|
||||
<key>installerSigningCertificate</key>
|
||||
<string>227D454DE9320031D7E9C3E02FEB7463B9A33776</string>
|
||||
<string>D7B7973A30C90C1A04666667F24B4D5C7E913923</string>
|
||||
<key>provisioningProfiles</key>
|
||||
<dict>
|
||||
<key>com.firstvoices.keyboards</key>
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue