Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -6,23 +6,33 @@
import androidx.annotation.NonNull;
import androidx.annotation.StringRes;

import org.Mengine.Base.MengineAnalytics;
import org.Mengine.Base.MengineApplication;
import org.Mengine.Base.MengineListenerApplication;
import org.Mengine.Base.MengineListenerEngine;
import org.Mengine.Base.MengineListenerLogger;
import org.Mengine.Base.MengineListenerTransparencyConsent;
import org.Mengine.Base.MengineListenerUser;
import org.Mengine.Base.MengineLog;
import org.Mengine.Base.MengineParamLoggerException;
import org.Mengine.Base.MengineParamLoggerMessage;
import org.Mengine.Base.MengineService;
import org.Mengine.Base.MengineServiceInvalidInitializeException;
import org.Mengine.Base.MengineParamTransparencyConsent;
import org.Mengine.Base.MengineUtils;

import java.util.Map;

import io.sentry.JsonSerializable;
import io.sentry.Sentry;
import io.sentry.SentryAttribute;
import io.sentry.SentryAttributes;
import io.sentry.SentryLogLevel;
import io.sentry.android.core.SentryAndroid;
import io.sentry.logger.SentryLogParameters;
import io.sentry.protocol.User;

public class MengineSentryPlugin extends MengineService implements MengineListenerApplication, MengineListenerEngine, MengineListenerTransparencyConsent, MengineListenerUser {
public class MengineSentryPlugin extends MengineService implements MengineListenerApplication, MengineListenerEngine, MengineListenerTransparencyConsent, MengineListenerLogger, MengineListenerUser {
public static final String SERVICE_NAME = "Sentry";
public static final boolean SERVICE_EMBEDDING = true;

Expand Down Expand Up @@ -162,6 +172,70 @@ public void onAppState(@NonNull MengineApplication application, String name, Obj
this.setCustomKey("." + name, value);
}

static private SentryLogLevel getSentryLogLevel(@NonNull MengineParamLoggerMessage message) {
switch (message.MESSAGE_LEVEL) {
case MengineLog.LM_DEBUG:
return SentryLogLevel.DEBUG;
case MengineLog.LM_INFO:
return SentryLogLevel.INFO;
case MengineLog.LM_MESSAGE:
case MengineLog.LM_MESSAGE_RELEASE:
return SentryLogLevel.INFO;
case MengineLog.LM_WARNING:
return SentryLogLevel.WARN;
case MengineLog.LM_FATAL:
return SentryLogLevel.FATAL;
}

return SentryLogLevel.TRACE;
}

@Override
public void onMengineLog(@NonNull MengineApplication application, @NonNull MengineParamLoggerMessage message) {
if (BuildConfig.DEBUG == false) {
if (message.MESSAGE_LEVEL != MengineLog.LM_WARNING && message.MESSAGE_LEVEL != MengineLog.LM_ERROR && message.MESSAGE_LEVEL != MengineLog.LM_FATAL) {
return;
}
}

SentryLogLevel level = MengineSentryPlugin.getSentryLogLevel(message);

SentryAttributes attributes = SentryAttributes.of(null);
attributes.add(SentryAttribute.stringAttribute("log.category", message.MESSAGE_CATEGORY.toString()));
attributes.add(SentryAttribute.stringAttribute("log.thread", message.MESSAGE_THREAD));

if (message.MESSAGE_FILE != null) {
attributes.add(SentryAttribute.stringAttribute("log.file", message.MESSAGE_FILE));
attributes.add(SentryAttribute.integerAttribute("log.line", message.MESSAGE_LINE));
}

if (message.MESSAGE_FUNCTION != null) {
attributes.add(SentryAttribute.stringAttribute("log.function", message.MESSAGE_FUNCTION));
}

Sentry.logger().log(level, SentryLogParameters.create(attributes), message.MESSAGE_DATA);
}

@Override
public void onMengineException(@NonNull MengineApplication application, @NonNull MengineParamLoggerException exception) {
Sentry.withScope(scope -> {
scope.setExtra("log.category", exception.EXCEPTION_CATEGORY.toString());

for (Map.Entry<String, Object> entry : exception.EXCEPTION_ATTRIBUTES.entrySet()) {
String key = entry.getKey();
Object value = entry.getValue();

if (value == null) {
scope.setExtra(key, "null");
} else {
scope.setExtra(key, String.valueOf(value));
}
}

this.recordException(exception.EXCEPTION_THROWABLE);
});
}

public void setCustomKey(String key, Object value) {
if (value == null) {
Sentry.setExtra(key, "null");
Expand All @@ -175,8 +249,6 @@ public void recordException(Throwable throwable) {
, throwable.getMessage()
);

throwable.printStackTrace(System.err);

Sentry.captureException(throwable);
}

Expand Down
25 changes: 25 additions & 0 deletions src/Plugins/AppleSentryPlugin/AppleSentryLogger.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
#pragma once

#include "Kernel/LoggerBase.h"

namespace Mengine
{
//////////////////////////////////////////////////////////////////////////
class AppleSentryLogger
: public LoggerBase
{
public:
AppleSentryLogger();
~AppleSentryLogger() override;

protected:
bool _initializeLogger() override;
void _finalizeLogger() override;

protected:
void _log( const LoggerRecordInterfacePtr & _record ) override;
};
//////////////////////////////////////////////////////////////////////////
typedef IntrusivePtr<AppleSentryLogger, LoggerInterface> AppleSentryLoggerPtr;
//////////////////////////////////////////////////////////////////////////
}
98 changes: 98 additions & 0 deletions src/Plugins/AppleSentryPlugin/AppleSentryLogger.mm
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
#include "AppleSentryLogger.h"

#include "Interface/LoggerRecordInterface.h"
#include "Kernel/LoggerMessage.h"

#import <Sentry/Sentry.h>

namespace Mengine
{
//////////////////////////////////////////////////////////////////////////
AppleSentryLogger::AppleSentryLogger()
{
}
//////////////////////////////////////////////////////////////////////////
AppleSentryLogger::~AppleSentryLogger()
{
}
//////////////////////////////////////////////////////////////////////////
bool AppleSentryLogger::_initializeLogger()
{
return true;
}
//////////////////////////////////////////////////////////////////////////
void AppleSentryLogger::_finalizeLogger()
{
//Empty
}
//////////////////////////////////////////////////////////////////////////
static SentryLevel s_getSentryLevel( ELoggerLevel _level )
{
switch( _level )
{
case LM_FATAL:
return kSentryLevelFatal;
case LM_ERROR:
return kSentryLevelError;
case LM_WARNING:
return kSentryLevelWarning;
case LM_INFO:
case LM_MESSAGE:
case LM_MESSAGE_RELEASE:
return kSentryLevelInfo;
case LM_DEBUG:
case LM_VERBOSE:
return kSentryLevelDebug;
default:
break;
}

return kSentryLevelInfo;
}
//////////////////////////////////////////////////////////////////////////
void AppleSentryLogger::_log( const LoggerRecordInterfacePtr & _record )
{
LoggerMessage message;
_record->getMessage( &message );

NSString * nsMessage = [NSString stringWithUTF8String:message.data];
NSString * nsCategory = [NSString stringWithUTF8String:message.category];
NSString * nsThread = [NSString stringWithUTF8String:message.thread.c_str()];

NSString * nsFile = nil;
if( message.file != nullptr && message.file[0] != '\0' )
{
nsFile = [NSString stringWithUTF8String:message.file];
}

NSString * nsFunction = nil;
if( message.function != nullptr && message.function[0] != '\0' )
{
nsFunction = [NSString stringWithUTF8String:message.function];
}

SentryLevel level = s_getSentryLevel( message.level );

[SentrySDK captureMessage:nsMessage withScope:^(SentryScope * _Nonnull scope) {
scope.level = level;
[scope setExtraValue:nsCategory forKey:@"log.category"];
[scope setExtraValue:nsThread forKey:@"log.thread"];

if( nsFile != nil )
{
[scope setExtraValue:nsFile forKey:@"log.file"];

if( message.line != 0 )
{
[scope setExtraValue:@(message.line) forKey:@"log.line"];
}
}

if( nsFunction != nil )
{
[scope setExtraValue:nsFunction forKey:@"log.function"];
}
}];
}
//////////////////////////////////////////////////////////////////////////
}
6 changes: 5 additions & 1 deletion src/Plugins/AppleSentryPlugin/AppleSentryService.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
#include "Kernel/ServiceBase.h"
#include "Kernel/AssertionLevel.h"
#include "Kernel/ErrorLevel.h"
#include "Interface/LoggerInterface.h"

namespace Mengine
{
Expand All @@ -23,6 +24,9 @@ namespace Mengine
void notifyCreateApplication_();
void notifyAssertion_( const Char * _category, EAssertionLevel _level, const Char * _test, const Char * _file, int32_t _line, const Char * _message );
void notifyError_( const Char * _category, EErrorLevel _level, const Char * _file, int32_t _line, const Char * _message );
void notifyEngineStop_();
void notifyEngineStop_();

protected:
LoggerInterfacePtr m_logger;
};
}
32 changes: 30 additions & 2 deletions src/Plugins/AppleSentryPlugin/AppleSentryService.mm
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@
#include "Kernel/NotificationHelper.h"
#include "Kernel/ConfigHelper.h"
#include "Kernel/TimestampHelper.h"
#include "Kernel/FactorableUnique.h"
#include "AppleSentryLogger.h"

#include "Config/StdString.h"
#include "Config/StdIO.h"
Expand All @@ -45,7 +47,25 @@
NOTIFICATION_ADDOBSERVERMETHOD_THIS( NOTIFICATOR_ASSERTION, &AppleSentryService::notifyAssertion_, MENGINE_DOCUMENT_FACTORABLE );
NOTIFICATION_ADDOBSERVERMETHOD_THIS( NOTIFICATOR_ERROR, &AppleSentryService::notifyError_, MENGINE_DOCUMENT_FACTORABLE );
NOTIFICATION_ADDOBSERVERMETHOD_THIS( NOTIFICATOR_ENGINE_STOP, &AppleSentryService::notifyEngineStop_, MENGINE_DOCUMENT_FACTORABLE );


AppleSentryLoggerPtr loggerSentry = Helper::makeFactorableUnique<AppleSentryLogger>( MENGINE_DOCUMENT_FACTORABLE );

bool debugMode = Helper::isDebugMode();

if( debugMode == false )
{
loggerSentry->setVerboseLevel( LM_WARNING );
}

uint32_t loggerFilter = MAKE_LOGGER_FILTER( LFILTER_PROTECTED );
loggerSentry->setVerboseFilter( loggerFilter );

if( LOGGER_SERVICE()
->registerLogger( loggerSentry ) == true )
{
m_logger = loggerSentry;
}

return true;
}
//////////////////////////////////////////////////////////////////////////
Expand All @@ -55,7 +75,15 @@
NOTIFICATION_REMOVEOBSERVER_THIS( NOTIFICATOR_ASSERTION );
NOTIFICATION_REMOVEOBSERVER_THIS( NOTIFICATOR_ERROR );
NOTIFICATION_REMOVEOBSERVER_THIS( NOTIFICATOR_ENGINE_STOP );


if( m_logger != nullptr )
{
LOGGER_SERVICE()
->unregisterLogger( m_logger );

m_logger = nullptr;
}

[SentrySDK close];
}
//////////////////////////////////////////////////////////////////////////
Expand Down
4 changes: 3 additions & 1 deletion src/Plugins/AppleSentryPlugin/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,11 @@ src

AppleSentryPlugin.h
AppleSentryPlugin.mm

AppleSentryService.h
AppleSentryService.mm
AppleSentryLogger.h
AppleSentryLogger.mm
)

if(MENGINE_TARGET_IOS)
Expand Down
6 changes: 4 additions & 2 deletions src/Plugins/Win32SentryPlugin/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,11 @@ src
Win32SentryPlugin.h
Win32SentryPlugin.def
Win32SentryPlugin.cpp

Win32SentryService.h
Win32SentryService.cpp
Win32SentryLogger.h
Win32SentryLogger.cpp
)

add_definitions(-DSENTRY_BUILD_STATIC)
Expand All @@ -35,4 +37,4 @@ TARGET_LINK_LIBRARIES(${PROJECT_NAME} ${THIRDPARTY_LIB_DIR}/${MENGINE_LIB_PREFIX
TARGET_LINK_LIBRARIES(${PROJECT_NAME} Winhttp.lib)
TARGET_LINK_LIBRARIES(${PROJECT_NAME} Rpcrt4.lib)
TARGET_LINK_LIBRARIES(${PROJECT_NAME} Dbghelp.lib)
TARGET_LINK_LIBRARIES(${PROJECT_NAME} Version.lib)
TARGET_LINK_LIBRARIES(${PROJECT_NAME} Version.lib)
Loading