Sentry: Unterschied zwischen den Versionen

Aus Helper
Zur Navigation springen Zur Suche springen
(Die Seite wurde neu angelegt: „<!-- MediaWiki source for page: Sentry --> <!-- Upload required files before publishing: sentry-issue.png, sentry-stack.png, sentry-tags.png, sentry-projects.png, demo-window.svg, demo-dsn.svg --> __TOC__ == Überblick == OSentry ist ein REST-API-Konnektor von Omnis Studio zu Sentry. Der Konnektor sendet Fehler, Messages, Logs und Laufzeitkontext aus Omnis-Anwendungen an Sentry, damit Probleme in produktiven Systemen sichtbar, gruppierbar und analysierb…“)
 
Keine Bearbeitungszusammenfassung
Zeile 1: Zeile 1:
<!-- MediaWiki source for page: Sentry -->
<!-- MediaWiki source for page: Sentry -->
<!-- Upload required files before publishing: sentry-issue.png, sentry-stack.png, sentry-tags.png, sentry-projects.png, demo-window.svg, demo-dsn.svg -->
<!-- Upload required files before publishing: Sentry-issue.png, Sentry-stack.png, Sentry-tags.png, Sentry-projects.png, Demo-window.svg, Demo-dsn.svg -->
__TOC__
__TOC__


Zeile 45: Zeile 45:
* Lokales Speichern von Reports bei Übertragungsfehlern
* Lokales Speichern von Reports bei Übertragungsfehlern


=== Screenshots ===
=== Weiterführende Links ===


[[Datei:sentry-issue.png|thumb|Sentry Issue-Übersicht]]
* [https://sentry.io/welcome/ Sentry Website]
* [https://sentry.io/signup/ Sentry Account erstellen]
* [https://develop.sentry.dev/self-hosted/ Sentry self-hosted]


[[Datei:sentry-stack.png|thumb|Sentry Stacktrace mit Omnis-Kontext]]
=== Screenshots ===


[[Datei:sentry-tags.png|thumb|Sentry Tags und User-Kontext]]
[[Datei:Sentry-issue.png|900px|Sentry Issue-Übersicht]]


== Installation ==
== Installation ==
Zeile 74: Zeile 76:


Die DSN wird beim Initialisieren verwendet. <code>OSentry</code> zerlegt sie intern in Public Key, Host und Project ID.
Die DSN wird beim Initialisieren verwendet. <code>OSentry</code> zerlegt sie intern in Public Key, Host und Project ID.
[[Datei:Sentry-projects.png|900px|Sentry Projektübersicht]]


=== Klassen kopieren ===
=== Klassen kopieren ===
Zeile 94: Zeile 98:
|}
|}


<code>tSentry</code> sollte als global erreichbarer Singleton der Anwendung verwendet werden. In Omnis ist dafür eine Task Variable sinnvoll, weil sie von Fenstern, Objektklassen und zentralen Error-Handlern aus konsistent erreichbar ist. Dadurch gibt es genau eine aktive Sentry-Konfiguration mit einer DSN, einem Status, optionalen Proxy-Daten und gemeinsamen Wrapper-Methoden in <code>OSentryHL</code>.
<div style="border-left:4px solid #3366cc; padding:8px 12px; margin:12px 0; background:#f8f9fa;">'''Empfehlung:''' <code>tSentry</code> sollte als global erreichbarer Singleton der Anwendung verwendet werden. In Omnis ist dafür eine Task Variable sinnvoll, weil sie von Fenstern, Objektklassen und zentralen Error-Handlern aus konsistent erreichbar ist. Dadurch gibt es genau eine aktive Sentry-Konfiguration mit einer DSN, einem Status, optionalen Proxy-Daten und gemeinsamen Wrapper-Methoden in <code>OSentryHL</code>.</div>


Im [[#Demo Library|Demo-Projekt]] ist diese Variable in <code>Startup_Task</code> definiert.
Im [[#Demo Library|Demo-Projekt]] ist diese Variable in <code>Startup_Task</code> definiert.
Zeile 102: Zeile 106:
Initialisiere <code>tSentry</code> beim Start deiner Anwendung mit der DSN deines Sentry-Projekts:
Initialisiere <code>tSentry</code> beim Start deiner Anwendung mit der DSN deines Sentry-Projekts:


<syntaxhighlight lang="text">
<pre>
Do tSentry.$init('<DSN>')
Do tSentry.$init('<DSN>')
</syntaxhighlight>
</pre>


Die [[#Demo Library|Demo-Library]] ruft im Startup Task ebenfalls die Initialisierung auf. Quelle: <code>Startup_Task.$construct</code>.
Die [[#Demo Library|Demo-Library]] ruft im Startup Task ebenfalls die Initialisierung auf. Quelle: <code>Startup_Task.$construct</code>.


<syntaxhighlight lang="text">
<pre>
#Init Sentry on lbs startup
#Init Sentry on lbs startup
Do tSentry.$init()
Do tSentry.$init()
</syntaxhighlight>
</pre>


In einer produktiven Anwendung sollte die DSN explizit oder aus einer Konfiguration übergeben werden:
In einer produktiven Anwendung sollte die DSN explizit oder aus einer Konfiguration übergeben werden:


<syntaxhighlight lang="text">
<pre>
Do tSentry.$init('https://PUBLIC_KEY@sentry.io/PROJECT_ID')
Do tSentry.$init('https://PUBLIC_KEY@sentry.io/PROJECT_ID')
</syntaxhighlight>
</pre>


Für produktive Systeme ist es sinnvoll, die DSN nicht fest im Code zu hinterlegen. Speichere sie besser in einer Datenbank, einer Konfigurationstabelle oder einem Config File. Dadurch kann die DSN pro Kunde, Umgebung oder Installation geändert werden, ohne die Library neu auszuliefern.
<div style="border-left:4px solid #3366cc; padding:8px 12px; margin:12px 0; background:#f8f9fa;">'''Empfehlung:''' Speichere die DSN in einer Datenbank, einer Konfigurationstabelle oder einem Config File. So kann sie pro Kunde, Umgebung oder Installation geändert werden, ohne die Library neu auszuliefern.</div>


=== Testcall ===
=== Testcall ===
Zeile 125: Zeile 129:
Nach der Initialisierung kann ein erstes Testevent gesendet werden:
Nach der Initialisierung kann ein erstes Testevent gesendet werden:


<syntaxhighlight lang="text">
<pre>
Do tSentry.$captureMessage('Hello World!')
Do tSentry.$captureMessage('Hello World!')
</syntaxhighlight>
</pre>


Wenn alles korrekt eingerichtet ist, erscheint das Event im Sentry-Projekt.
Wenn alles korrekt eingerichtet ist, erscheint das Event im Sentry-Projekt.
Zeile 135: Zeile 139:
Falls die Anwendung in einem geschützten Netzwerk läuft, kann ein Proxy gesetzt werden. Die Methode befindet sich im Low-Level-Objekt <code>OSentry</code>.
Falls die Anwendung in einem geschützten Netzwerk läuft, kann ein Proxy gesetzt werden. Die Methode befindet sich im Low-Level-Objekt <code>OSentry</code>.


<syntaxhighlight lang="text">
<pre>
Do tSentry.iOSentry.$setProxy('proxy.example.local','8080')
Do tSentry.iOSentry.$setProxy('proxy.example.local','8080')
</syntaxhighlight>
</pre>


Die interne Implementierung setzt den Proxy vor dem HTTP-Request:
Die interne Implementierung setzt den Proxy vor dem HTTP-Request:


<syntaxhighlight lang="text">
<pre>
#Configure proxy; needed when sending data out of secured networks
#Configure proxy; needed when sending data out of secured networks
If not(isclear(iProxyHost))&not(isclear(iProxyPort))
If not(isclear(iProxyHost))&not(isclear(iProxyPort))
HTTPSetProxyServer (iProxyHost,iProxyPort)
HTTPSetProxyServer (iProxyHost,iProxyPort)
End If
End If
</syntaxhighlight>
</pre>


=== Sentry aktivieren oder deaktivieren ===
=== Sentry aktivieren oder deaktivieren ===


OSentry kann zentral ein- oder ausgeschaltet werden. Es ist empfohlen, Sentry in der Entwicklungs-Version standardmäßig zu deaktivieren oder eine separate Entwicklungs-DSN zu verwenden. So landen lokale Tests, Debug-Fehler und absichtlich ausgelöste Exceptions nicht im produktiven Sentry-Projekt.
OSentry kann zentral ein- oder ausgeschaltet werden.
 
<div style="border-left:4px solid #3366cc; padding:8px 12px; margin:12px 0; background:#f8f9fa;">'''Empfehlung:''' Deaktiviere Sentry in der Entwicklungs-Version standardmäßig oder verwende eine separate Entwicklungs-DSN. So landen lokale Tests, Debug-Fehler und absichtlich ausgelöste Exceptions nicht im produktiven Sentry-Projekt.</div>


<syntaxhighlight lang="text">
<pre>
Do tSentry.$setStatus(1)    ## aktiv
Do tSentry.$setStatus(1)    ## aktiv
Do tSentry.$setStatus(0)    ## inaktiv
Do tSentry.$setStatus(0)    ## inaktiv
</syntaxhighlight>
</pre>


Im Low-Level-Objekt <code>OSentry</code> wird vor dem Senden geprüft:
Im Low-Level-Objekt <code>OSentry</code> wird vor dem Senden geprüft:


<syntaxhighlight lang="text">
<pre>
#Check if Sentry is enabled
#Check if Sentry is enabled
If iStatus=0|isclear(iStatus)
If iStatus=0|isclear(iStatus)
Quit method 0
Quit method 0
End If
End If
</syntaxhighlight>
</pre>


== Quickstart ==
== Quickstart ==
Zeile 170: Zeile 176:
Diese Seite zeigt die minimale Integration in eine bestehende Omnis-Anwendung.
Diese Seite zeigt die minimale Integration in eine bestehende Omnis-Anwendung.


=== 1. Klassen übernehmen ===
=== Klassen übernehmen ===


Kopiere <code>OSentry</code> und <code>OSentryHL</code> in deine Library.
Kopiere <code>OSentry</code> und <code>OSentryHL</code> in deine Library.


=== 2. Task Variable erstellen ===
=== Task Variable erstellen ===


In der Startup Task:
In der Startup Task:
Zeile 184: Zeile 190:
|}
|}


=== 3. Sentry initialisieren ===
=== Sentry initialisieren ===


<syntaxhighlight lang="text">
<pre>
Do tSentry.$init('https://PUBLIC_KEY@sentry.io/PROJECT_ID')
Do tSentry.$init('https://PUBLIC_KEY@sentry.io/PROJECT_ID')
</syntaxhighlight>
</pre>


<code>OSentryHL.$init</code> delegiert an das Low-Level-Objekt <code>OSentry</code>:
<code>OSentryHL.$init</code> delegiert an das Low-Level-Objekt <code>OSentry</code>:


<syntaxhighlight lang="text">
<pre>
#Init of the main sentry object
#Init of the main sentry object
Do iOSentry.$init(pDSN)
Do iOSentry.$init(pDSN)
Quit method
Quit method
</syntaxhighlight>
</pre>


=== 4. Message senden ===
=== Message senden ===


<syntaxhighlight lang="text">
<pre>
Do tSentry.$captureMessage('Hello Euromnis! This is a test message...')
Do tSentry.$captureMessage('Hello Euromnis! This is a test message...')
</syntaxhighlight>
</pre>


Die [[#Demo Library|Demo-Library]] verwendet genau diesen Aufruf im Button <code>Trigger a message</code>. Quelle: <code>FSY_Demo.message.$event</code>.
Die [[#Demo Library|Demo-Library]] verwendet genau diesen Aufruf im Button <code>Trigger a message</code>. Quelle: <code>FSY_Demo.message.$event</code>.


<syntaxhighlight lang="text">
<pre>
On evClick ## Event Parameters - pRow( Itemreference )
On evClick ## Event Parameters - pRow( Itemreference )
Do tSentry.$captureMessage('Hello Euromnis! This is a test message...')
Do tSentry.$captureMessage('Hello Euromnis! This is a test message...')
Do $cinst.$showmessage('Sentry Event successfully triggered!','Info')
Do $cinst.$showmessage('Sentry Event successfully triggered!','Info')
Quit method
Quit method
</syntaxhighlight>
</pre>


=== 5. Exception senden ===
=== Exception senden ===


<syntaxhighlight lang="text">
<pre>
Do tSentry.$captureException('A generic Exception occured',1234,'Generic Exception','error')
Do tSentry.$captureException('A generic Exception occured',1234,'Generic Exception','error')
</syntaxhighlight>
</pre>


=== 6. In Sentry prüfen ===
=== In Sentry prüfen ===


In Sentry sollte anschließend ein neues Event sichtbar sein. Je nach Event-Typ enthält es:
In Sentry sollte anschließend ein neues Event sichtbar sein. Je nach Event-Typ enthält es:
Zeile 239: Zeile 245:
Eine einfache Information wird mit <code>$captureMessage</code> gesendet:
Eine einfache Information wird mit <code>$captureMessage</code> gesendet:


<syntaxhighlight lang="text">
<pre>
Do tSentry.$captureMessage('Hello World!')
Do tSentry.$captureMessage('Hello World!')
</syntaxhighlight>
</pre>


Implementierung in <code>OSentryHL</code>:
Implementierung in <code>OSentryHL</code>:


<syntaxhighlight lang="text">
<pre>
# Captures an Info Message
# Captures an Info Message
Do iOSentry.$captureException(pMessage,3,,'info',kFalse,,kFalse) Returns code
Do iOSentry.$captureException(pMessage,3,,'info',kFalse,,kFalse) Returns code
Quit method
Quit method
</syntaxhighlight>
</pre>


Verhalten:
Verhalten:
Zeile 262: Zeile 268:
Ein Log-Event wird mit <code>$captureLog</code> gesendet:
Ein Log-Event wird mit <code>$captureLog</code> gesendet:


<syntaxhighlight lang="text">
<pre>
Do tSentry.$captureLog('Uh oh this is a Log because something went wrong')
Do tSentry.$captureLog('Uh oh this is a Log because something went wrong')
</syntaxhighlight>
</pre>


Implementierung in <code>OSentryHL</code>:
Implementierung in <code>OSentryHL</code>:


<syntaxhighlight lang="text">
<pre>
# Captures a Log Sentry Report
# Captures a Log Sentry Report
Do iOSentry.$captureException(pErrorText,1,'Log','warning',1,0,1) Returns code
Do iOSentry.$captureException(pErrorText,1,'Log','warning',1,0,1) Returns code


Quit method
Quit method
</syntaxhighlight>
</pre>


Verhalten:
Verhalten:
Zeile 286: Zeile 292:
Eine generische Exception wird mit <code>$captureException</code> gesendet:
Eine generische Exception wird mit <code>$captureException</code> gesendet:


<syntaxhighlight lang="text">
<pre>
Do tSentry.$captureException('A generic Exception occured',1234,'Generic Exception','error')
Do tSentry.$captureException('A generic Exception occured',1234,'Generic Exception','error')
</syntaxhighlight>
</pre>


Implementierung in <code>OSentryHL</code>:
Implementierung in <code>OSentryHL</code>:


<syntaxhighlight lang="text">
<pre>
# Method to capture a generic Exception
# Method to capture a generic Exception
#Add any custom tags / extras
#Add any custom tags / extras
Zeile 300: Zeile 306:


Quit method
Quit method
</syntaxhighlight>
</pre>


Parameter:
Parameter:
Zeile 328: Zeile 334:
SQL-Fehler können mit <code>$captureSQLException</code> gemeldet werden.
SQL-Fehler können mit <code>$captureSQLException</code> gemeldet werden.


<syntaxhighlight lang="text">
<pre>
Do tSentry.$captureSQLException('SQL statement failed',stat)
Do tSentry.$captureSQLException('SQL statement failed',stat)
</syntaxhighlight>
</pre>


Implementierung in <code>OSentryHL</code>:
Implementierung in <code>OSentryHL</code>:


<syntaxhighlight lang="text">
<pre>
# Method to capture an SQL Exception
# Method to capture an SQL Exception
Do $cinst.$addTag('Database',tOSLSession.$hostname)
Do $cinst.$addTag('Database',tOSLSession.$hostname)
Zeile 343: Zeile 349:
Do iOSentry.$captureException(pErrorText,1,'SQL-Exception','error')
Do iOSentry.$captureException(pErrorText,1,'SQL-Exception','error')
Quit method
Quit method
</syntaxhighlight>
</pre>


Verhalten:
Verhalten:
Zeile 356: Zeile 362:
Veraltete Codepfade können gezielt gemeldet werden:
Veraltete Codepfade können gezielt gemeldet werden:


<syntaxhighlight lang="text">
<pre>
Do tSentry.$captureDeprecatedCall()
Do tSentry.$captureDeprecatedCall()
</syntaxhighlight>
</pre>


Implementierung in <code>OSentryHL</code>:
Implementierung in <code>OSentryHL</code>:


<syntaxhighlight lang="text">
<pre>
# Report a deprecated call of a piece of code to sentry
# Report a deprecated call of a piece of code to sentry
Do iOSentry.$captureException('Deprecated Call',3,'Deprecated Call','warning',1,1,1) Returns code
Do iOSentry.$captureException('Deprecated Call',3,'Deprecated Call','warning',1,1,1) Returns code


Quit method
Quit method
</syntaxhighlight>
</pre>


Dieser Wrapper eignet sich, um zu erkennen, ob alter Code in produktiven Systemen noch ausgeführt wird.
Dieser Wrapper eignet sich, um zu erkennen, ob alter Code in produktiven Systemen noch ausgeführt wird.
Zeile 375: Zeile 381:
Für Sonderfälle gibt es <code>$captureAnything</code>:
Für Sonderfälle gibt es <code>$captureAnything</code>:


<syntaxhighlight lang="text">
<pre>
Do tSentry.$captureAnything('Text',1001,'Custom Type','error',kTrue,kTrue,kTrue)
Do tSentry.$captureAnything('Text',1001,'Custom Type','error',kTrue,kTrue,kTrue)
</syntaxhighlight>
</pre>


Implementierung in <code>OSentryHL</code>:
Implementierung in <code>OSentryHL</code>:


<syntaxhighlight lang="text">
<pre>
# Capture a generic Sentry Report (max configurability)
# Capture a generic Sentry Report (max configurability)
Do iOSentry.$captureException(pErrorText,pErrorCode,pExcType,pLevel,pStacktraveInterface,pExceptionInterface,pUserInterface) Returns code
Do iOSentry.$captureException(pErrorText,pErrorCode,pExcType,pLevel,pStacktraveInterface,pExceptionInterface,pUserInterface) Returns code


Quit method
Quit method
</syntaxhighlight>
</pre>


Diese Methode bietet maximale Flexibilität. Für wiederkehrende Exception-Typen sollte aber eine eigene Methode in <code>OSentryHL</code> angelegt werden. Siehe [[#Eigene Exceptions standardisieren|04 Eigene Exceptions standardisieren]].
Diese Methode bietet maximale Flexibilität. Für wiederkehrende Exception-Typen sollte aber eine eigene Methode in <code>OSentryHL</code> angelegt werden. Siehe [[#Eigene Exceptions standardisieren|04 Eigene Exceptions standardisieren]].
Zeile 411: Zeile 417:
Bestehende Beispiele aus <code>OSentryHL</code>:
Bestehende Beispiele aus <code>OSentryHL</code>:


<syntaxhighlight lang="text">
<pre>
# Report a deprecated call of a piece of code to sentry
# Report a deprecated call of a piece of code to sentry
Do iOSentry.$captureException('Deprecated Call',3,'Deprecated Call','warning',1,1,1) Returns code
Do iOSentry.$captureException('Deprecated Call',3,'Deprecated Call','warning',1,1,1) Returns code


Quit method
Quit method
</syntaxhighlight>
</pre>


<syntaxhighlight lang="text">
<pre>
# Method to capture an SQL Exception
# Method to capture an SQL Exception
Do $cinst.$addTag('Database',tOSLSession.$hostname)
Do $cinst.$addTag('Database',tOSLSession.$hostname)
Zeile 427: Zeile 433:
Do iOSentry.$captureException(pErrorText,1,'SQL-Exception','error')
Do iOSentry.$captureException(pErrorText,1,'SQL-Exception','error')
Quit method
Quit method
</syntaxhighlight>
</pre>


=== Empfohlenes Muster ===
=== Empfohlenes Muster ===
Zeile 435: Zeile 441:
Beispiel:
Beispiel:


<syntaxhighlight lang="text">
<pre>
# Captures a validation exception
# Captures a validation exception
Do $cinst.$addTag('Module',pModule)
Do $cinst.$addTag('Module',pModule)
Zeile 444: Zeile 450:


Quit method code
Quit method code
</syntaxhighlight>
</pre>


Mögliche Parameter der neuen Methode:
Mögliche Parameter der neuen Methode:
Zeile 462: Zeile 468:
Der Applikationscode bleibt dadurch einfach:
Der Applikationscode bleibt dadurch einfach:


<syntaxhighlight lang="text">
<pre>
Do tSentry.$captureValidationException('Invalid customer number','Customer','cu_number',cu_number)
Do tSentry.$captureValidationException('Invalid customer number','Customer','cu_number',cu_number)
</syntaxhighlight>
</pre>


=== Beispiel: Business Rule Exception ===
=== Beispiel: Business Rule Exception ===
Zeile 470: Zeile 476:
Neue Methode in <code>OSentryHL</code>:
Neue Methode in <code>OSentryHL</code>:


<syntaxhighlight lang="text">
<pre>
# Captures a business rule violation
# Captures a business rule violation
Do $cinst.$addTag('Module',pModule)
Do $cinst.$addTag('Module',pModule)
Zeile 479: Zeile 485:


Quit method code
Quit method code
</syntaxhighlight>
</pre>


Aufruf in der Anwendung:
Aufruf in der Anwendung:


<syntaxhighlight lang="text">
<pre>
Do tSentry.$captureBusinessRuleViolation('Invoice cannot be posted','Invoice','PostingAllowed','Invoice is missing customer')
Do tSentry.$captureBusinessRuleViolation('Invoice cannot be posted','Invoice','PostingAllowed','Invoice is missing customer')
</syntaxhighlight>
</pre>


=== Beispiel: Integration Exception ===
=== Beispiel: Integration Exception ===
Zeile 491: Zeile 497:
Neue Methode in <code>OSentryHL</code>:
Neue Methode in <code>OSentryHL</code>:


<syntaxhighlight lang="text">
<pre>
# Captures an integration exception
# Captures an integration exception
Do $cinst.$addTag('Integration',pSystem)
Do $cinst.$addTag('Integration',pSystem)
Zeile 501: Zeile 507:


Quit method code
Quit method code
</syntaxhighlight>
</pre>


Aufruf in der Anwendung:
Aufruf in der Anwendung:


<syntaxhighlight lang="text">
<pre>
Do tSentry.$captureIntegrationException('External API request failed','ERP','/api/customer',jsonPayload,responseText)
Do tSentry.$captureIntegrationException('External API request failed','ERP','/api/customer',jsonPayload,responseText)
</syntaxhighlight>
</pre>


=== Namenskonventionen ===
=== Namenskonventionen ===
Zeile 549: Zeile 555:
Nicht jeder Einzelfall braucht eine eigene Methode. Für einmalige technische Tests oder sehr spezielle Fälle reicht:
Nicht jeder Einzelfall braucht eine eigene Methode. Für einmalige technische Tests oder sehr spezielle Fälle reicht:


<syntaxhighlight lang="text">
<pre>
Do tSentry.$captureException('A generic Exception occured',1234,'Generic Exception','error')
Do tSentry.$captureException('A generic Exception occured',1234,'Generic Exception','error')
</syntaxhighlight>
</pre>


Sobald ein Exception-Typ aber mehrfach vorkommt oder fachlich relevant ist, sollte er als eigene Methode in <code>OSentryHL</code> definiert werden.
Sobald ein Exception-Typ aber mehrfach vorkommt oder fachlich relevant ist, sollte er als eigene Methode in <code>OSentryHL</code> definiert werden.
Zeile 558: Zeile 564:


Tags, Extras und User-Kontext reichern Sentry-Events mit zusätzlichen Informationen an. Diese Informationen helfen beim Filtern, Gruppieren und Analysieren.
Tags, Extras und User-Kontext reichern Sentry-Events mit zusätzlichen Informationen an. Diese Informationen helfen beim Filtern, Gruppieren und Analysieren.
[[Datei:Sentry-tags.png|900px|Sentry Tags und User-Kontext]]


=== Tags ===
=== Tags ===
Zeile 574: Zeile 582:
Methode in <code>OSentryHL</code>:
Methode in <code>OSentryHL</code>:


<syntaxhighlight lang="text">
<pre>
# Add a Tag to the next Sentry Report
# Add a Tag to the next Sentry Report
Do iOSentry.$addTag(pName,pValue)
Do iOSentry.$addTag(pName,pValue)
Quit method
Quit method
</syntaxhighlight>
</pre>


Methode in <code>OSentry</code>:
Methode in <code>OSentry</code>:


<syntaxhighlight lang="text">
<pre>
#Adds a tag to the next request processed
#Adds a tag to the next request processed
Do iTagList.$add(pName,pValue)
Do iTagList.$add(pName,pValue)
Quit method
Quit method
</syntaxhighlight>
</pre>


Beispiel:
Beispiel:


<syntaxhighlight lang="text">
<pre>
Do tSentry.$addTag('Module','Invoice')
Do tSentry.$addTag('Module','Invoice')
Do tSentry.$addTag('Customer','10001')
Do tSentry.$addTag('Customer','10001')
Do tSentry.$captureException('Invoice posting failed',3001,'Business-Rule-Violation','warning')
Do tSentry.$captureException('Invoice posting failed',3001,'Business-Rule-Violation','warning')
</syntaxhighlight>
</pre>


=== Extras ===
=== Extras ===
Zeile 611: Zeile 619:
Methode in <code>OSentryHL</code>:
Methode in <code>OSentryHL</code>:


<syntaxhighlight lang="text">
<pre>
# Add an Extra to the next Sentry Report
# Add an Extra to the next Sentry Report
Do iOSentry.$addExtra(pName,pValue)
Do iOSentry.$addExtra(pName,pValue)
Quit method
Quit method
</syntaxhighlight>
</pre>


Methode in <code>OSentry</code>:
Methode in <code>OSentry</code>:


<syntaxhighlight lang="text">
<pre>
#Adds extra information to the next request being processed
#Adds extra information to the next request being processed
Do iExtraList.$add(pName,pValue)
Do iExtraList.$add(pName,pValue)
Quit method
Quit method
</syntaxhighlight>
</pre>


Beispiel aus der SQL Exception:
Beispiel aus der SQL Exception:


<syntaxhighlight lang="text">
<pre>
Do $cinst.$addExtra('SQL-Text',pStat.$sqltext)
Do $cinst.$addExtra('SQL-Text',pStat.$sqltext)
Do $cinst.$addExtra('SQL-Error',pStat.$nativeerrortext)
Do $cinst.$addExtra('SQL-Error',pStat.$nativeerrortext)
</syntaxhighlight>
</pre>


=== Automatische Tags ===
=== Automatische Tags ===
Zeile 638: Zeile 646:
<code>OSentry.$generateJson</code> fügt mehrere Tags automatisch hinzu:
<code>OSentry.$generateJson</code> fügt mehrere Tags automatisch hinzu:


<syntaxhighlight lang="text">
<pre>
# Add static tags
# Add static tags
Do iTagList.$add('Omnisversion',sys(1))
Do iTagList.$add('Omnisversion',sys(1))
Zeile 645: Zeile 653:
Do iTagList.$add('OS Version',con(systemversionRow.major,'.',systemversionRow.minor,'.',systemversionRow.build))
Do iTagList.$add('OS Version',con(systemversionRow.major,'.',systemversionRow.minor,'.',systemversionRow.build))
Do iTagList.$add('error_code',pErrorCode)
Do iTagList.$add('error_code',pErrorCode)
</syntaxhighlight>
</pre>


Automatisch gesendete Tags:
Automatisch gesendete Tags:
Zeile 663: Zeile 671:
Beispiel für eine eigene Exception: Der Wrapper muss nicht erneut <code>Omnisversion</code> oder <code>OS Version</code> setzen. Er ergänzt nur das, was für diesen Exception-Typ zusätzlich hilfreich ist.
Beispiel für eine eigene Exception: Der Wrapper muss nicht erneut <code>Omnisversion</code> oder <code>OS Version</code> setzen. Er ergänzt nur das, was für diesen Exception-Typ zusätzlich hilfreich ist.


<syntaxhighlight lang="text">
<pre>
Do $cinst.$addTag('Module',pModule)
Do $cinst.$addTag('Module',pModule)
Do $cinst.$addTag('Business Rule',pRuleName)
Do $cinst.$addTag('Business Rule',pRuleName)
Do iOSentry.$captureException(pErrorText,3001,'Business-Rule-Violation','warning',1,1,1) Returns code
Do iOSentry.$captureException(pErrorText,3001,'Business-Rule-Violation','warning',1,1,1) Returns code
</syntaxhighlight>
</pre>


=== Automatische Extras ===
=== Automatische Extras ===
Zeile 675: Zeile 683:
<code>OSentry.$generateJson</code> fügt offene Fenster, offene Reports und die aktuelle Printfile hinzu:
<code>OSentry.$generateJson</code> fügt offene Fenster, offene Reports und die aktuelle Printfile hinzu:


<syntaxhighlight lang="text">
<pre>
# Static extra 1: All open windows
# Static extra 1: All open windows
Do $root.$iwindows.$makelist($ref.$name) Returns nameList
Do $root.$iwindows.$makelist($ref.$name) Returns nameList
Zeile 692: Zeile 700:
Do iExtraList.$add('Open Reports',reports)
Do iExtraList.$add('Open Reports',reports)
Do iExtraList.$add('Current Printfile',$root.$prefs.$printfile)
Do iExtraList.$add('Current Printfile',$root.$prefs.$printfile)
</syntaxhighlight>
</pre>


Automatisch gesendete Extras:
Automatisch gesendete Extras:
Zeile 708: Zeile 716:
Beispiel für zusätzliche Extras in einem eigenen Wrapper:
Beispiel für zusätzliche Extras in einem eigenen Wrapper:


<syntaxhighlight lang="text">
<pre>
Do $cinst.$addExtra('Payload',pPayload)
Do $cinst.$addExtra('Payload',pPayload)
Do $cinst.$addExtra('Response',pResponse)
Do $cinst.$addExtra('Response',pResponse)
Do iOSentry.$captureException(pErrorText,4001,'Integration-Exception','error',1,1,1) Returns code
Do iOSentry.$captureException(pErrorText,4001,'Integration-Exception','error',1,1,1) Returns code
</syntaxhighlight>
</pre>


=== User-Kontext ===
=== User-Kontext ===
Zeile 734: Zeile 742:
<code>OSentry</code> kann User-Daten an das Event anhängen:
<code>OSentry</code> kann User-Daten an das Event anhängen:


<syntaxhighlight lang="text">
<pre>
#Sets userinformation for the next request being processed
#Sets userinformation for the next request being processed
Calculate iUserID as pID
Calculate iUserID as pID
Zeile 740: Zeile 748:
Calculate iUserEmail as pEmail
Calculate iUserEmail as pEmail
Quit method
Quit method
</syntaxhighlight>
</pre>


Das User Interface wird so generiert:
Das User Interface wird so generiert:


<syntaxhighlight lang="text">
<pre>
# Create user data row
# Create user data row
Do UserdataRow.$define(id,email,username)
Do UserdataRow.$define(id,email,username)
Zeile 758: Zeile 766:


Quit method jsonString
Quit method jsonString
</syntaxhighlight>
</pre>


Die aktuelle Demo-Methode in <code>OSentryHL</code> verwendet feste Testdaten. Quelle: <code>OSentryHL.$setUser</code>.
Die aktuelle Demo-Methode in <code>OSentryHL</code> verwendet feste Testdaten. Quelle: <code>OSentryHL.$setUser</code>.


<syntaxhighlight lang="text">
<pre>
# Set the User which should be linked to the Sentry Issue
# Set the User which should be linked to the Sentry Issue
Do iOSentry.$setUserData(23,'Euromnis Test User','euromnis@test.com')
Do iOSentry.$setUserData(23,'Euromnis Test User','euromnis@test.com')
Quit method
Quit method
</syntaxhighlight>
</pre>


Für produktive Nutzung sollte diese Methode angepasst und parametrisiert werden:
Für produktive Nutzung sollte diese Methode angepasst und parametrisiert werden:


<syntaxhighlight lang="text">
<pre>
Do iOSentry.$setUserData(pUserID,pUserName,pUserEmail)
Do iOSentry.$setUserData(pUserID,pUserName,pUserEmail)
Quit method
Quit method
</syntaxhighlight>
</pre>


Empfohlen ist, den User nach Login oder beim Wechsel des aktiven Benutzers zentral zu setzen. Bei anonymen oder sensiblen Installationen kann statt Name und E-Mail auch nur eine interne ID oder ein pseudonymisierter Wert verwendet werden.
Empfohlen ist, den User nach Login oder beim Wechsel des aktiven Benutzers zentral zu setzen. Bei anonymen oder sensiblen Installationen kann statt Name und E-Mail auch nur eine interne ID oder ein pseudonymisierter Wert verwendet werden.
Zeile 779: Zeile 787:
=== Datenschutz ===
=== Datenschutz ===


Prüfe vor produktiver Nutzung, welche Daten an Sentry gesendet werden. Besonders kritisch sind:
<div style="border-left:4px solid #72777d; padding:8px 12px; margin:12px 0; background:#f8f9fa;">'''Datenschutz:''' Prüfe vor produktiver Nutzung, welche Daten an Sentry gesendet werden. Besonders kritisch sind personenbezogene Daten, SQL-Statements, Zugangsdaten, Tokens und interne Pfade.</div>
 
Besonders kritisch sind:


* personenbezogene Daten
* personenbezogene Daten
Zeile 794: Zeile 804:
<code>OSentry</code> erzeugt einen Omnis-spezifischen Stacktrace und übergibt ihn an Sentry. Dadurch sieht man in Sentry nicht nur eine Fehlermeldung, sondern auch Klassen, Methoden, Zeilen und Variablenkontext. Ergänzende Informationen zu [[#Tags, Extras und User-Kontext|Tags, Extras und User-Kontext]] stehen auf der separaten Kontext-Seite.
<code>OSentry</code> erzeugt einen Omnis-spezifischen Stacktrace und übergibt ihn an Sentry. Dadurch sieht man in Sentry nicht nur eine Fehlermeldung, sondern auch Klassen, Methoden, Zeilen und Variablenkontext. Ergänzende Informationen zu [[#Tags, Extras und User-Kontext|Tags, Extras und User-Kontext]] stehen auf der separaten Kontext-Seite.


[[Datei:sentry-stack.png|thumb|Sentry Stacktrace mit Omnis-Kontext]]
[[Datei:Sentry-stack.png|900px|Sentry Stacktrace mit Omnis-Kontext]]


=== Stack lesen ===
=== Stack lesen ===
Zeile 800: Zeile 810:
<code>OSentry.$generateStacktraceInterface</code> verwendet <code>sys(192)</code>, um den aktuellen Omnis-Stack zu lesen:
<code>OSentry.$generateStacktraceInterface</code> verwendet <code>sys(192)</code>, um den aktuellen Omnis-Stack zu lesen:


<syntaxhighlight lang="text">
<pre>
# Clean up the Stacklist (remove OSentry classes from the stack)
# Clean up the Stacklist (remove OSentry classes from the stack)
Do sys(192) Returns sys192List
Do sys(192) Returns sys192List
Zeile 810: Zeile 820:
End For
End For
Do sys192List.$remove(kListDeleteSelected)
Do sys192List.$remove(kListDeleteSelected)
</syntaxhighlight>
</pre>


Interne Frames von <code>OSentry</code> und <code>OSentryHL</code> werden entfernt, damit in Sentry die fachlich relevanten Stellen sichtbar bleiben.
Interne Frames von <code>OSentry</code> und <code>OSentryHL</code> werden entfernt, damit in Sentry die fachlich relevanten Stellen sichtbar bleiben.
Zeile 818: Zeile 828:
Bestimmte interne SQL-Fehlerframes werden ebenfalls entfernt:
Bestimmte interne SQL-Fehlerframes werden ebenfalls entfernt:


<syntaxhighlight lang="text">
<pre>
# Remove some other classes which we do not want to display
# Remove some other classes which we do not want to display
If sys192List.1.method='$sqlerror'
If sys192List.1.method='$sqlerror'
Zeile 825: Zeile 835:
Do sys192List.$remove(1)
Do sys192List.$remove(1)
End If
End If
</syntaxhighlight>
</pre>


=== Frames erzeugen ===
=== Frames erzeugen ===
Zeile 831: Zeile 841:
Für jeden Stack-Eintrag werden Funktion, Zeilennummer und Kontextzeile erzeugt:
Für jeden Stack-Eintrag werden Funktion, Zeilennummer und Kontextzeile erzeugt:


<syntaxhighlight lang="text">
<pre>
#Loop through every item on the omnis stack
#Loop through every item on the omnis stack
For sys192List.$line from 1 to sys192List.$linecount step 1
For sys192List.$line from 1 to sys192List.$linecount step 1
Zeile 849: Zeile 859:
Do contentList.$add(contentRow)
Do contentList.$add(contentRow)
End For
End For
</syntaxhighlight>
</pre>


=== Variablen aufnehmen ===
=== Variablen aufnehmen ===
Zeile 855: Zeile 865:
Pro Stackframe werden Instance Variablen und Parameter gesammelt:
Pro Stackframe werden Instance Variablen und Parameter gesammelt:


<syntaxhighlight lang="text">
<pre>
# Get all iVars
# Get all iVars
Do varList.$define(name,value)
Do varList.$define(name,value)
Zeile 870: Zeile 880:
End If
End If
End For
End For
</syntaxhighlight>
</pre>


=== Pre- und Post-Context ===
=== Pre- und Post-Context ===
Zeile 876: Zeile 886:
OSentry fügt Methodenzeilen vor und nach der aktuellen Zeile hinzu:
OSentry fügt Methodenzeilen vor und nach der aktuellen Zeile hinzu:


<syntaxhighlight lang="text">
<pre>
# Pre Context (all method lines before the error occured)
# Pre Context (all method lines before the error occured)
Set reference method to sys192List.methoditem
Set reference method to sys192List.methoditem
Zeile 889: Zeile 899:
Do postcontextList.$add(method.$methodlines.[i].$text)
Do postcontextList.$add(method.$methodlines.[i].$text)
End For
End For
</syntaxhighlight>
</pre>


=== Variablentypen ===
=== Variablentypen ===
Zeile 897: Zeile 907:
Basisvariablen:
Basisvariablen:


<syntaxhighlight lang="text">
<pre>
If varType='char'|varType='boolean'|varType='integer'|varType='number'|varType='date'
If varType='char'|varType='boolean'|varType='integer'|varType='number'|varType='date'
Calculate varContent as pItemRef.$[pVarType].[varName]
Calculate varContent as pItemRef.$[pVarType].[varName]
Do varList.$add(varName,varContent)
Do varList.$add(varName,varContent)
</syntaxhighlight>
</pre>


Rows:
Rows:


<syntaxhighlight lang="text">
<pre>
Else If varType='row'
Else If varType='row'
Calculate varRow as pItemRef.$[pVarType].[varName]
Calculate varRow as pItemRef.$[pVarType].[varName]
Zeile 915: Zeile 925:
End For
End For
Do varList.$add(varName,varContent)
Do varList.$add(varName,varContent)
</syntaxhighlight>
</pre>


Lists:
Lists:


<syntaxhighlight lang="text">
<pre>
Else If varType='list'
Else If varType='list'
Calculate varListType as pItemRef.$[pVarType].[varName]
Calculate varListType as pItemRef.$[pVarType].[varName]
Zeile 935: Zeile 945:
End If
End If
End If
End If
</syntaxhighlight>
</pre>


=== Hinweise ===
=== Hinweise ===
Zeile 969: Zeile 979:
Applikationscode sollte <code>OSentryHL</code> verwenden:
Applikationscode sollte <code>OSentryHL</code> verwenden:


<syntaxhighlight lang="text">
<pre>
Do tSentry.$captureException('A generic Exception occured',1234,'Generic Exception','error')
Do tSentry.$captureException('A generic Exception occured',1234,'Generic Exception','error')
</syntaxhighlight>
</pre>


<code>OSentryHL</code> delegiert anschließend an <code>OSentry</code>:
<code>OSentryHL</code> delegiert anschließend an <code>OSentry</code>:


<syntaxhighlight lang="text">
<pre>
Do iOSentry.$captureException(pErrorText,pErrorCode,pExcType,pLevel) Returns code
Do iOSentry.$captureException(pErrorText,pErrorCode,pExcType,pLevel) Returns code
</syntaxhighlight>
</pre>


=== Ablauf eines Events ===
=== Ablauf eines Events ===
Zeile 996: Zeile 1.006:
<code>OSentry.$init</code> zerlegt die DSN:
<code>OSentry.$init</code> zerlegt die DSN:


<syntaxhighlight lang="text">
<pre>
# Parse the DSN into Public Key, Host and Project ID
# Parse the DSN into Public Key, Host and Project ID
If len(pDSN)>5
If len(pDSN)>5
Zeile 1.016: Zeile 1.026:


Quit method
Quit method
</syntaxhighlight>
</pre>


=== JSON-Erzeugung ===
=== JSON-Erzeugung ===
Zeile 1.038: Zeile 1.048:
Auszug:
Auszug:


<syntaxhighlight lang="text">
<pre>
# Add all required fields (those are required from the API)
# Add all required fields (those are required from the API)
Do JSON.$addmember('','event_id',$cinst.$generateUUID()) ## auto generated UUID 4
Do JSON.$addmember('','event_id',$cinst.$generateUUID()) ## auto generated UUID 4
Zeile 1.050: Zeile 1.060:
Do JSON.$addmember('','level',pLevel)
Do JSON.$addmember('','level',pLevel)
Do JSON.$addmember('','tags','')
Do JSON.$addmember('','tags','')
</syntaxhighlight>
</pre>


=== HTTP-Kommunikation ===
=== HTTP-Kommunikation ===
Zeile 1.056: Zeile 1.066:
<code>OSentry.$captureException</code> sendet den erzeugten JSON-Payload an Sentry:
<code>OSentry.$captureException</code> sendet den erzeugten JSON-Payload an Sentry:


<syntaxhighlight lang="text">
<pre>
#Generate HTTP Auth header
#Generate HTTP Auth header
Begin text block
Begin text block
Zeile 1.074: Zeile 1.084:
Do HdrList.$add('Content-Length',binlength(json))
Do HdrList.$add('Content-Length',binlength(json))
Do HdrList.$add('X-Sentry-Auth',auth)
Do HdrList.$add('X-Sentry-Auth',auth)
</syntaxhighlight>
</pre>


Anschließend wird der Request über <code>HTTPPost</code>, <code>HTTPSend</code> und <code>HTTPRead</code> ausgeführt.
Anschließend wird der Request über <code>HTTPPost</code>, <code>HTTPSend</code> und <code>HTTPRead</code> ausgeführt.
Zeile 1.082: Zeile 1.092:
Wenn der Socket nicht geöffnet werden kann:
Wenn der Socket nicht geöffnet werden kann:


<syntaxhighlight lang="text">
<pre>
HTTPPost (Host,Url,,HdrList,443,kTrue,kTrue) Returns Socket
HTTPPost (Host,Url,,HdrList,443,kTrue,kTrue) Returns Socket
If Socket<0
If Socket<0
Zeile 1.091: Zeile 1.101:
Quit method -1
Quit method -1
End If
End If
</syntaxhighlight>
</pre>


Wenn das Senden fehlschlägt:
Wenn das Senden fehlschlägt:


<syntaxhighlight lang="text">
<pre>
HTTPSend (Socket,json) Returns byteCount
HTTPSend (Socket,json) Returns byteCount
If byteCount<0
If byteCount<0
Zeile 1.104: Zeile 1.114:
Quit method -2
Quit method -2
End If
End If
</syntaxhighlight>
</pre>


Wenn die Antwort nicht erfolgreich ist:
Wenn die Antwort nicht erfolgreich ist:


<syntaxhighlight lang="text">
<pre>
HTTPRead (Socket,Buffer) Returns byteCount
HTTPRead (Socket,Buffer) Returns byteCount
If byteCount<0|not(pos('200 OK',Buffer))
If byteCount<0|not(pos('200 OK',Buffer))
Zeile 1.117: Zeile 1.127:
Quit method -3
Quit method -3
End If
End If
</syntaxhighlight>
</pre>


=== Lokales Speichern ===
=== Lokales Speichern ===
Zeile 1.123: Zeile 1.133:
Bei Fehlern wird der JSON Report lokal im Omnis-Installationsordner gespeichert:
Bei Fehlern wird der JSON Report lokal im Omnis-Installationsordner gespeichert:


<syntaxhighlight lang="text">
<pre>
#Writes the json and the http buffer to a file in the omnis installation folder
#Writes the json and the http buffer to a file in the omnis installation folder
Calculate path as sys(115)
Calculate path as sys(115)
Zeile 1.135: Zeile 1.145:


Quit method
Quit method
</syntaxhighlight>
</pre>


=== Cleanup ===
=== Cleanup ===
Zeile 1.141: Zeile 1.151:
Nach erfolgreichem Senden werden [[#Tags, Extras und User-Kontext|Tags und Extras]] gelöscht:
Nach erfolgreichem Senden werden [[#Tags, Extras und User-Kontext|Tags und Extras]] gelöscht:


<syntaxhighlight lang="text">
<pre>
#Clears all extras and tags => to be used after a sentry request has successfully been sent
#Clears all extras and tags => to be used after a sentry request has successfully been sent
Do iTagList.$clear()
Do iTagList.$clear()
Do iExtraList.$clear()
Do iExtraList.$clear()
Quit method
Quit method
</syntaxhighlight>
</pre>


== Demo Library ==
== Demo Library ==
Zeile 1.176: Zeile 1.186:
<code>Startup_Task.$construct</code> initialisiert Sentry, baut eine SQLite Session auf und öffnet das Demo-Fenster. Quelle: <code>Startup_Task.$construct</code>.
<code>Startup_Task.$construct</code> initialisiert Sentry, baut eine SQLite Session auf und öffnet das Demo-Fenster. Quelle: <code>Startup_Task.$construct</code>.


<syntaxhighlight lang="text">
<pre>
#Init Sentry on lbs startup
#Init Sentry on lbs startup
Do tSentry.$init()
Do tSentry.$init()
Zeile 1.191: Zeile 1.201:


Quit method
Quit method
</syntaxhighlight>
</pre>


=== Demo-Fenster ===
=== Demo-Fenster ===
Zeile 1.217: Zeile 1.227:
|}
|}


[[Datei:demo-window.svg|thumb|Demo-Fenster der OSentry Library]]
[[Datei:Demo-window.svg|850px|Demo-Fenster der OSentry Library]]


=== DSN setzen ===
=== DSN setzen ===
Zeile 1.223: Zeile 1.233:
Die DSN wird im Feld <code>iDSN</code> erfasst. Der Button <code>Set DSN</code> ruft anschließend <code>tSentry.$init(iDSN)</code> auf. Nach dem Setzen werden Public Key, Host und Project ID aus der DSN gelesen und in den darunterliegenden Feldern angezeigt.
Die DSN wird im Feld <code>iDSN</code> erfasst. Der Button <code>Set DSN</code> ruft anschließend <code>tSentry.$init(iDSN)</code> auf. Nach dem Setzen werden Public Key, Host und Project ID aus der DSN gelesen und in den darunterliegenden Feldern angezeigt.


[[Datei:demo-dsn.svg|thumb|DSN-Konfiguration im Demo-Fenster]]
[[Datei:Demo-dsn.svg|850px|DSN-Konfiguration im Demo-Fenster]]


Der Button <code>Set DSN</code> initialisiert Sentry mit der eingegebenen DSN. Quelle: <code>FSY_Demo.setDSN.$event</code>.
Der Button <code>Set DSN</code> initialisiert Sentry mit der eingegebenen DSN. Quelle: <code>FSY_Demo.setDSN.$event</code>.


<syntaxhighlight lang="text">
<pre>
On evClick ## Event Parameters - pRow( Itemreference )
On evClick ## Event Parameters - pRow( Itemreference )
Do tSentry.$init(iDSN)
Do tSentry.$init(iDSN)
Zeile 1.236: Zeile 1.246:
Do $cinst.$redraw()
Do $cinst.$redraw()
Quit method
Quit method
</syntaxhighlight>
</pre>


=== DB Status anzeigen ===
=== DB Status anzeigen ===
Zeile 1.242: Zeile 1.252:
<code>FSY_Demo.$displayDBState</code> zeigt, ob die SQLite Session verbunden ist. Quelle: <code>FSY_Demo.$displayDBState</code>.
<code>FSY_Demo.$displayDBState</code> zeigt, ob die SQLite Session verbunden ist. Quelle: <code>FSY_Demo.$displayDBState</code>.


<syntaxhighlight lang="text">
<pre>
Do tOSLSession.$state Returns dbState
Do tOSLSession.$state Returns dbState
If dbState='kSessionStateLoggedOff'
If dbState='kSessionStateLoggedOff'
Zeile 1.254: Zeile 1.264:
Do $cinst.$redraw()
Do $cinst.$redraw()
Quit method
Quit method
</syntaxhighlight>
</pre>


=== Demo-Datenbank erstellen ===
=== Demo-Datenbank erstellen ===
Zeile 1.260: Zeile 1.270:
Der Button <code>Create Database</code> ruft <code>ODatabaseHandler.$DBFirstInit</code> auf. Quelle: <code>FSY_Demo.createDB.$event</code>.
Der Button <code>Create Database</code> ruft <code>ODatabaseHandler.$DBFirstInit</code> auf. Quelle: <code>FSY_Demo.createDB.$event</code>.


<syntaxhighlight lang="text">
<pre>
On evClick ## Event Parameters - pRow( Itemreference )
On evClick ## Event Parameters - pRow( Itemreference )
#Setup the DB
#Setup the DB
Zeile 1.273: Zeile 1.283:
Quit method
Quit method
</syntaxhighlight>
</pre>


Die Datenbank wird im Arbeitsverzeichnis der Library angelegt. Quelle: <code>ODatabaseHandler.$getWorkingDir</code>.
Die Datenbank wird im Arbeitsverzeichnis der Library angelegt. Quelle: <code>ODatabaseHandler.$getWorkingDir</code>.


<syntaxhighlight lang="text">
<pre>
Quit method con(FileOps.$parentdir($clib.$pathname),pathsep())
Quit method con(FileOps.$parentdir($clib.$pathname),pathsep())
</syntaxhighlight>
</pre>


Die Demo-DB enthält unter anderem:
Die Demo-DB enthält unter anderem:
Zeile 1.291: Zeile 1.301:
Button <code>Trigger a message</code>. Quelle: <code>FSY_Demo.message.$event</code>.
Button <code>Trigger a message</code>. Quelle: <code>FSY_Demo.message.$event</code>.


<syntaxhighlight lang="text">
<pre>
On evClick ## Event Parameters - pRow( Itemreference )
On evClick ## Event Parameters - pRow( Itemreference )
Do tSentry.$captureMessage('Hello Euromnis! This is a test message...')
Do tSentry.$captureMessage('Hello Euromnis! This is a test message...')
Do $cinst.$showmessage('Sentry Event successfully triggered!','Info')
Do $cinst.$showmessage('Sentry Event successfully triggered!','Info')
Quit method
Quit method
</syntaxhighlight>
</pre>


=== Log auslösen ===
=== Log auslösen ===
Zeile 1.302: Zeile 1.312:
Button <code>Trigger a log</code>. Quelle: <code>FSY_Demo.log.$event</code>.
Button <code>Trigger a log</code>. Quelle: <code>FSY_Demo.log.$event</code>.


<syntaxhighlight lang="text">
<pre>
On evClick ## Event Parameters - pRow( Itemreference )
On evClick ## Event Parameters - pRow( Itemreference )
Do tSentry.$captureLog('Uh oh this is a Log because something went wrong')
Do tSentry.$captureLog('Uh oh this is a Log because something went wrong')
Do $cinst.$showmessage('Sentry Event successfully triggered!','Info')
Do $cinst.$showmessage('Sentry Event successfully triggered!','Info')
Quit method
Quit method
</syntaxhighlight>
</pre>


=== Exception auslösen ===
=== Exception auslösen ===
Zeile 1.313: Zeile 1.323:
Button <code>Trigger an exception</code> bereitet eine Row und eine List vor und ruft anschließend <code>ODummy.$dummyMethod</code> auf. Quelle: <code>FSY_Demo.exception.$event</code>.
Button <code>Trigger an exception</code> bereitet eine Row und eine List vor und ruft anschließend <code>ODummy.$dummyMethod</code> auf. Quelle: <code>FSY_Demo.exception.$event</code>.


<syntaxhighlight lang="text">
<pre>
On evClick ## Event Parameters - pRow( Itemreference )
On evClick ## Event Parameters - pRow( Itemreference )
Do iDummyRow.$define(id,name)
Do iDummyRow.$define(id,name)
Zeile 1.334: Zeile 1.344:
Quit method
Quit method
</syntaxhighlight>
</pre>


<code>ODummy.$dummyMethod</code> sendet die Exception. Quelle: <code>ODummy.$dummyMethod</code>.
<code>ODummy.$dummyMethod</code> sendet die Exception. Quelle: <code>ODummy.$dummyMethod</code>.


<syntaxhighlight lang="text">
<pre>
#In here is some logic
#In here is some logic
#This logic would produce an error
#This logic would produce an error
Zeile 1.346: Zeile 1.356:


Quit method 0
Quit method 0
</syntaxhighlight>
</pre>


=== Deprecated Call auslösen ===
=== Deprecated Call auslösen ===
Zeile 1.352: Zeile 1.362:
Button <code>Trigger a deprecated call</code>. Quelle: <code>FSY_Demo.deprecatedCall.$event</code>.
Button <code>Trigger a deprecated call</code>. Quelle: <code>FSY_Demo.deprecatedCall.$event</code>.


<syntaxhighlight lang="text">
<pre>
On evClick ## Event Parameters - pRow( Itemreference )
On evClick ## Event Parameters - pRow( Itemreference )
Do tSentry.$captureDeprecatedCall()
Do tSentry.$captureDeprecatedCall()
Do $cinst.$showmessage('Sentry Event successfully triggered!','Info')
Do $cinst.$showmessage('Sentry Event successfully triggered!','Info')
Quit method
Quit method
</syntaxhighlight>
</pre>


=== SQL Exception Button ===
=== SQL Exception Button ===
Zeile 1.363: Zeile 1.373:
Der Button <code>Trigger an SQLException</code> ist im Export vorhanden, enthält aber noch keinen fertigen Demo-Code. Quelle: <code>FSY_Demo.sqlException.$event</code>.
Der Button <code>Trigger an SQLException</code> ist im Export vorhanden, enthält aber noch keinen fertigen Demo-Code. Quelle: <code>FSY_Demo.sqlException.$event</code>.


<syntaxhighlight lang="text">
<pre>
On evClick ## Event Parameters - pRow( Itemreference )
On evClick ## Event Parameters - pRow( Itemreference )
#Code need's to be written
#Code need's to be written
</syntaxhighlight>
</pre>


Für die Dokumentation der SQL-Erfassung siehe [[#Events erfassen|03 Events erfassen]].
Für die Dokumentation der SQL-Erfassung siehe [[#Events erfassen|03 Events erfassen]].
Zeile 1.378: Zeile 1.388:
<code>OSentryHL</code> ist die empfohlene Klasse für Applikationscode.
<code>OSentryHL</code> ist die empfohlene Klasse für Applikationscode.


==== <code>$init(pDSN)</code> ====
'''<code>$init(pDSN)</code>'''


Initialisiert das interne <code>OSentry</code>-Objekt.
Initialisiert das interne <code>OSentry</code>-Objekt.


<syntaxhighlight lang="text">
<pre>
#Init of the main sentry object
#Init of the main sentry object
Do iOSentry.$init(pDSN)
Do iOSentry.$init(pDSN)
Quit method
Quit method
</syntaxhighlight>
</pre>


==== <code>$captureMessage(pMessage)</code> ====
'''<code>$captureMessage(pMessage)</code>'''


Sendet eine einfache Info-Message.
Sendet eine einfache Info-Message.


<syntaxhighlight lang="text">
<pre>
# Captures an Info Message
# Captures an Info Message
Do iOSentry.$captureException(pMessage,3,,'info',kFalse,,kFalse) Returns code
Do iOSentry.$captureException(pMessage,3,,'info',kFalse,,kFalse) Returns code
Quit method
Quit method
</syntaxhighlight>
</pre>


==== <code>$captureException(pErrorText,pErrorCode,pExcType,pLevel)</code> ====
'''<code>$captureException(pErrorText,pErrorCode,pExcType,pLevel)</code>'''


Sendet eine generische Exception.
Sendet eine generische Exception.


<syntaxhighlight lang="text">
<pre>
# Method to capture a generic Exception
# Method to capture a generic Exception
#Add any custom tags / extras
#Add any custom tags / extras
Zeile 1.410: Zeile 1.420:


Quit method
Quit method
</syntaxhighlight>
</pre>


==== <code>$captureAnything(pErrorText,pErrorCode,pExcType,pLevel,pStacktraveInterface,pExceptionInterface,pUserInterface)</code> ====
'''<code>$captureAnything(pErrorText,pErrorCode,pExcType,pLevel,pStacktraveInterface,pExceptionInterface,pUserInterface)</code>'''


Sendet ein frei konfigurierbares Event.
Sendet ein frei konfigurierbares Event.


<syntaxhighlight lang="text">
<pre>
# Capture a generic Sentry Report (max configurability)
# Capture a generic Sentry Report (max configurability)
Do iOSentry.$captureException(pErrorText,pErrorCode,pExcType,pLevel,pStacktraveInterface,pExceptionInterface,pUserInterface) Returns code
Do iOSentry.$captureException(pErrorText,pErrorCode,pExcType,pLevel,pStacktraveInterface,pExceptionInterface,pUserInterface) Returns code


Quit method
Quit method
</syntaxhighlight>
</pre>


Hinweis: Der Parameter ist im Export als <code>pStacktraveInterface</code> geschrieben.
Hinweis: Der Parameter ist im Export als <code>pStacktraveInterface</code> geschrieben.


==== <code>$captureLog(pErrorText)</code> ====
'''<code>$captureLog(pErrorText)</code>'''


Sendet ein Log-Event.
Sendet ein Log-Event.


<syntaxhighlight lang="text">
<pre>
# Captures a Log Sentry Report
# Captures a Log Sentry Report
Do iOSentry.$captureException(pErrorText,1,'Log','warning',1,0,1) Returns code
Do iOSentry.$captureException(pErrorText,1,'Log','warning',1,0,1) Returns code


Quit method
Quit method
</syntaxhighlight>
</pre>


==== <code>$captureDeprecatedCall()</code> ====
'''<code>$captureDeprecatedCall()</code>'''


Meldet die Ausführung eines veralteten Codepfads.
Meldet die Ausführung eines veralteten Codepfads.


<syntaxhighlight lang="text">
<pre>
# Report a deprecated call of a piece of code to sentry
# Report a deprecated call of a piece of code to sentry
Do iOSentry.$captureException('Deprecated Call',3,'Deprecated Call','warning',1,1,1) Returns code
Do iOSentry.$captureException('Deprecated Call',3,'Deprecated Call','warning',1,1,1) Returns code


Quit method
Quit method
</syntaxhighlight>
</pre>


==== <code>$captureSQLException(pErrorText,pStat)</code> ====
'''<code>$captureSQLException(pErrorText,pStat)</code>'''


Meldet einen SQL-Fehler mit SQL-Text und nativer Datenbankfehlermeldung.
Meldet einen SQL-Fehler mit SQL-Text und nativer Datenbankfehlermeldung.


<syntaxhighlight lang="text">
<pre>
# Method to capture an SQL Exception
# Method to capture an SQL Exception
Do $cinst.$addTag('Database',tOSLSession.$hostname)
Do $cinst.$addTag('Database',tOSLSession.$hostname)
Zeile 1.460: Zeile 1.470:
Do iOSentry.$captureException(pErrorText,1,'SQL-Exception','error')
Do iOSentry.$captureException(pErrorText,1,'SQL-Exception','error')
Quit method
Quit method
</syntaxhighlight>
</pre>


==== <code>$addTag(pName,pValue)</code> ====
'''<code>$addTag(pName,pValue)</code>'''


Fügt einen Tag für das nächste Event hinzu.
Fügt einen Tag für das nächste Event hinzu.


<syntaxhighlight lang="text">
<pre>
# Add a Tag to the next Sentry Report
# Add a Tag to the next Sentry Report
Do iOSentry.$addTag(pName,pValue)
Do iOSentry.$addTag(pName,pValue)
Quit method
Quit method
</syntaxhighlight>
</pre>


==== <code>$addExtra(pName,pValue)</code> ====
'''<code>$addExtra(pName,pValue)</code>'''


Fügt ein Extra für das nächste Event hinzu.
Fügt ein Extra für das nächste Event hinzu.


<syntaxhighlight lang="text">
<pre>
# Add an Extra to the next Sentry Report
# Add an Extra to the next Sentry Report
Do iOSentry.$addExtra(pName,pValue)
Do iOSentry.$addExtra(pName,pValue)
Quit method
Quit method
</syntaxhighlight>
</pre>


==== <code>$setStatus(pStatus)</code> ====
'''<code>$setStatus(pStatus)</code>'''


Aktiviert oder deaktiviert Sentry.
Aktiviert oder deaktiviert Sentry.


<syntaxhighlight lang="text">
<pre>
#Toggels Sentry on or off
#Toggels Sentry on or off
Do iOSentry.$setStatus(pStatus)
Do iOSentry.$setStatus(pStatus)
Quit method
Quit method
</syntaxhighlight>
</pre>


==== <code>$setUser()</code> ====
'''<code>$setUser()</code>'''


Setzt im Export feste [[#Demo Library|Demo]]-Userdaten.
Setzt im Export feste [[#Demo Library|Demo]]-Userdaten.


<syntaxhighlight lang="text">
<pre>
# Set the User which should be linked to the Sentry Issue
# Set the User which should be linked to the Sentry Issue
Do iOSentry.$setUserData(23,'Euromnis Test User','euromnis@test.com')
Do iOSentry.$setUserData(23,'Euromnis Test User','euromnis@test.com')
Quit method
Quit method
</syntaxhighlight>
</pre>


Für produktive Nutzung sollte diese Methode parametrisiert werden.
Für produktive Nutzung sollte diese Methode parametrisiert werden.
Zeile 1.508: Zeile 1.518:
<code>OSentry</code> ist die Low-Level-Klasse für Payload-Erzeugung und Versand.
<code>OSentry</code> ist die Low-Level-Klasse für Payload-Erzeugung und Versand.


==== <code>$init(pDSN)</code> ====
'''<code>$init(pDSN)</code>'''


Parst die DSN in Protokoll, Public Key, Host und Project ID.
Parst die DSN in Protokoll, Public Key, Host und Project ID.


==== <code>$captureException(pErrorText,pErrorCode,pExcType,pLevel,pStacktraceInterface,pUserInterface,pExceptionInterface)</code> ====
'''<code>$captureException(pErrorText,pErrorCode,pExcType,pLevel,pStacktraceInterface,pUserInterface,pExceptionInterface)</code>'''


Erzeugt JSON, sendet es an Sentry und behandelt Fehlerfälle.
Erzeugt JSON, sendet es an Sentry und behandelt Fehlerfälle.
Zeile 1.536: Zeile 1.546:
|}
|}


==== <code>$generateJson(...)</code> ====
'''<code>$generateJson(...)</code>'''


Erzeugt den Sentry JSON Payload als Binary.
Erzeugt den Sentry JSON Payload als Binary.


==== <code>$generateStacktraceInterface(pCulprit)</code> ====
'''<code>$generateStacktraceInterface(pCulprit)</code>'''


Erzeugt den Omnis-[[#Stacktrace und Kontext|Stacktrace]] inklusive Variablen und Kontextzeilen.
Erzeugt den Omnis-[[#Stacktrace und Kontext|Stacktrace]] inklusive Variablen und Kontextzeilen.


==== <code>$generateExceptionInterface(pType,pValue)</code> ====
'''<code>$generateExceptionInterface(pType,pValue)</code>'''


Erzeugt das Sentry Exception Interface.
Erzeugt das Sentry Exception Interface.


<syntaxhighlight lang="text">
<pre>
# Generate Row to store in the JSON
# Generate Row to store in the JSON
Do exceptionRow.$define(type,value,stacktrace)
Do exceptionRow.$define(type,value,stacktrace)
Zeile 1.554: Zeile 1.564:
Calculate exceptionRow.value as pValue
Calculate exceptionRow.value as pValue
Calculate exceptionRow.stacktrace as 'sentry.interfaces.stacktrace' ## Tells the exception interface that a stacktrace is passed aswell
Calculate exceptionRow.stacktrace as 'sentry.interfaces.stacktrace' ## Tells the exception interface that a stacktrace is passed aswell
</syntaxhighlight>
</pre>


==== <code>$generateUserInterface()</code> ====
'''<code>$generateUserInterface()</code>'''


Erzeugt den [[#Tags, Extras und User-Kontext|User-Kontext]].
Erzeugt den [[#Tags, Extras und User-Kontext|User-Kontext]].


==== <code>$addTag(pName,pValue)</code> ====
'''<code>$addTag(pName,pValue)</code>'''


Fügt einen Tag zur internen Tag-Liste hinzu.
Fügt einen Tag zur internen Tag-Liste hinzu.


==== <code>$addExtra(pName,pValue)</code> ====
'''<code>$addExtra(pName,pValue)</code>'''


Fügt ein Extra zur internen Extra-Liste hinzu.
Fügt ein Extra zur internen Extra-Liste hinzu.


==== <code>$clearList()</code> ====
'''<code>$clearList()</code>'''


Leert [[#Tags, Extras und User-Kontext|Tags und Extras]] nach einem Request.
Leert [[#Tags, Extras und User-Kontext|Tags und Extras]] nach einem Request.


==== <code>$setUserData(pID,pName,pEmail)</code> ====
'''<code>$setUserData(pID,pName,pEmail)</code>'''


Setzt Userdaten für den nächsten Request.
Setzt Userdaten für den nächsten Request.


==== <code>$setProxy(pProxyHost,pProxyPort)</code> ====
'''<code>$setProxy(pProxyHost,pProxyPort)</code>'''


Setzt Proxy-Informationen.
Setzt Proxy-Informationen.


==== <code>$setStatus(pStatus)</code> ====
'''<code>$setStatus(pStatus)</code>'''


Setzt den Sentry-Status.
Setzt den Sentry-Status.


<syntaxhighlight lang="text">
<pre>
#Toggels Sentry Reports on or off
#Toggels Sentry Reports on or off
Calculate iStatus as pStatus
Calculate iStatus as pStatus
Quit method
Quit method
</syntaxhighlight>
</pre>


==== <code>$writeJSON(pJSON,pBuffer)</code> ====
'''<code>$writeJSON(pJSON,pBuffer)</code>'''


Schreibt fehlgeschlagene Reports lokal in eine Datei.
Schreibt fehlgeschlagene Reports lokal in eine Datei.


==== <code>$getUnixTimestamp()</code> ====
'''<code>$getUnixTimestamp()</code>'''


Gibt den aktuellen UNIX Timestamp zurück.
Gibt den aktuellen UNIX Timestamp zurück.


==== <code>$generateUUID()</code> ====
'''<code>$generateUUID()</code>'''


Erzeugt eine UUID für die Sentry Event ID.
Erzeugt eine UUID für die Sentry Event ID.


<syntaxhighlight lang="text">
<pre>
#Genereates a UUID for the issue id
#Genereates a UUID for the issue id
Quit method OW3.$makeuuid(kFalse)
Quit method OW3.$makeuuid(kFalse)
</syntaxhighlight>
</pre>


== Troubleshooting ==
== Troubleshooting ==
Zeile 1.613: Zeile 1.623:
Prüfe zuerst, ob Sentry aktiv ist:
Prüfe zuerst, ob Sentry aktiv ist:


<syntaxhighlight lang="text">
<pre>
Do tSentry.$setStatus(1)
Do tSentry.$setStatus(1)
</syntaxhighlight>
</pre>


<code>OSentry.$captureException</code> beendet sich sofort, wenn der Status <code>0</code> oder leer ist:
<code>OSentry.$captureException</code> beendet sich sofort, wenn der Status <code>0</code> oder leer ist:


<syntaxhighlight lang="text">
<pre>
#Check if Sentry is enabled
#Check if Sentry is enabled
If iStatus=0|isclear(iStatus)
If iStatus=0|isclear(iStatus)
Quit method 0
Quit method 0
End If
End If
</syntaxhighlight>
</pre>


=== Die DSN ist falsch ===
=== Die DSN ist falsch ===
Zeile 1.640: Zeile 1.650:
Wenn die Anwendung keinen direkten Zugriff auf Sentry hat, setze einen Proxy:
Wenn die Anwendung keinen direkten Zugriff auf Sentry hat, setze einen Proxy:


<syntaxhighlight lang="text">
<pre>
Do tSentry.iOSentry.$setProxy('proxy.example.local','8080')
Do tSentry.iOSentry.$setProxy('proxy.example.local','8080')
</syntaxhighlight>
</pre>


Intern wird der Proxy vor dem HTTP Request gesetzt:
Intern wird der Proxy vor dem HTTP Request gesetzt:


<syntaxhighlight lang="text">
<pre>
If not(isclear(iProxyHost))&not(isclear(iProxyPort))
If not(isclear(iProxyHost))&not(isclear(iProxyPort))
HTTPSetProxyServer (iProxyHost,iProxyPort)
HTTPSetProxyServer (iProxyHost,iProxyPort)
End If
End If
</syntaxhighlight>
</pre>


=== Report wird lokal gespeichert ===
=== Report wird lokal gespeichert ===
Zeile 1.656: Zeile 1.666:
Wenn <code>HTTPPost</code>, <code>HTTPSend</code> oder <code>HTTPRead</code> fehlschlägt, speichert OSentry den Report lokal:
Wenn <code>HTTPPost</code>, <code>HTTPSend</code> oder <code>HTTPRead</code> fehlschlägt, speichert OSentry den Report lokal:


<syntaxhighlight lang="text">
<pre>
Calculate path as sys(115)
Calculate path as sys(115)
Calculate filename as con('Sentryreport_',$cinst.$getUnixTimestamp(),'.json')
Calculate filename as con('Sentryreport_',$cinst.$getUnixTimestamp(),'.json')
Do fOP.$createfile(con(path,filename)) Returns err
Do fOP.$createfile(con(path,filename)) Returns err
</syntaxhighlight>
</pre>


Suche im Omnis-Installationsordner nach Dateien mit dem Namen:
Suche im Omnis-Installationsordner nach Dateien mit dem Namen:


<syntaxhighlight lang="text">
<pre>
Sentryreport_<timestamp>.json
Sentryreport_<timestamp>.json
</syntaxhighlight>
</pre>


=== Sentry antwortet nicht mit 200 OK ===
=== Sentry antwortet nicht mit 200 OK ===
Zeile 1.672: Zeile 1.682:
Wenn die HTTP-Antwort kein <code>200 OK</code> enthält, wird der JSON Report ebenfalls lokal gespeichert:
Wenn die HTTP-Antwort kein <code>200 OK</code> enthält, wird der JSON Report ebenfalls lokal gespeichert:


<syntaxhighlight lang="text">
<pre>
HTTPRead (Socket,Buffer) Returns byteCount
HTTPRead (Socket,Buffer) Returns byteCount
If byteCount<0|not(pos('200 OK',Buffer))
If byteCount<0|not(pos('200 OK',Buffer))
Zeile 1.681: Zeile 1.691:
Quit method -3
Quit method -3
End If
End If
</syntaxhighlight>
</pre>


Mögliche Ursachen:
Mögliche Ursachen:
Zeile 1.695: Zeile 1.705:
[[#Tags, Extras und User-Kontext|Tags und Extras]] werden für den nächsten Request gesammelt. Nach erfolgreichem Request werden sie gelöscht:
[[#Tags, Extras und User-Kontext|Tags und Extras]] werden für den nächsten Request gesammelt. Nach erfolgreichem Request werden sie gelöscht:


<syntaxhighlight lang="text">
<pre>
Do iTagList.$clear()
Do iTagList.$clear()
Do iExtraList.$clear()
Do iExtraList.$clear()
</syntaxhighlight>
</pre>


Wenn ein Request fehlschlägt, wird ebenfalls aufgeräumt:
Wenn ein Request fehlschlägt, wird ebenfalls aufgeräumt:


<syntaxhighlight lang="text">
<pre>
Do $cinst.$clearList()
Do $cinst.$clearList()
</syntaxhighlight>
</pre>


Prüfe trotzdem, ob in eigenen Wrapper-Methoden Tags und Extras direkt vor dem passenden Capture-Aufruf gesetzt werden.
Prüfe trotzdem, ob in eigenen Wrapper-Methoden Tags und Extras direkt vor dem passenden Capture-Aufruf gesetzt werden.
Zeile 1.712: Zeile 1.722:
<code>OSentryHL.$setUser</code> verwendet im Export feste Testdaten:
<code>OSentryHL.$setUser</code> verwendet im Export feste Testdaten:


<syntaxhighlight lang="text">
<pre>
Do iOSentry.$setUserData(23,'Euromnis Test User','euromnis@test.com')
Do iOSentry.$setUserData(23,'Euromnis Test User','euromnis@test.com')
</syntaxhighlight>
</pre>


Für produktive Nutzung sollte die Methode parametrisiert werden:
Für produktive Nutzung sollte die Methode parametrisiert werden:


<syntaxhighlight lang="text">
<pre>
Do iOSentry.$setUserData(pUserID,pUserName,pUserEmail)
Do iOSentry.$setUserData(pUserID,pUserName,pUserEmail)
</syntaxhighlight>
</pre>


=== SQL Exception Demo-Button funktioniert nicht ===
=== SQL Exception Demo-Button funktioniert nicht ===
Zeile 1.726: Zeile 1.736:
Der Button <code>Trigger an SQLException</code> ist im Export noch nicht implementiert:
Der Button <code>Trigger an SQLException</code> ist im Export noch nicht implementiert:


<syntaxhighlight lang="text">
<pre>
On evClick ## Event Parameters - pRow( Itemreference )
On evClick ## Event Parameters - pRow( Itemreference )
#Code need's to be written
#Code need's to be written
</syntaxhighlight>
</pre>


Die produktive Methode für SQL-Fehler ist aber vorhanden. Siehe auch [[#Events erfassen|Events erfassen]].
Die produktive Methode für SQL-Fehler ist aber vorhanden. Siehe auch [[#Events erfassen|Events erfassen]].


<syntaxhighlight lang="text">
<pre>
Do tSentry.$captureSQLException('SQL statement failed',stat)
Do tSentry.$captureSQLException('SQL statement failed',stat)
</syntaxhighlight>
</pre>


=== Zu viele Events ===
=== Zu viele Events ===

Version vom 12. Juni 2026, 16:05 Uhr

Überblick

OSentry ist ein REST-API-Konnektor von Omnis Studio zu Sentry. Der Konnektor sendet Fehler, Messages, Logs und Laufzeitkontext aus Omnis-Anwendungen an Sentry, damit Probleme in produktiven Systemen sichtbar, gruppierbar und analysierbar werden.

Diese Dokumentation beschreibt die Installation, die Nutzung in bestehenden Omnis-Anwendungen, die Definition eigener standardisierter Exception-Typen, die interne Struktur und die Demo-Library.

Inhalt

Kernidee

OSentry besteht aus zwei produktiv relevanten Klassen:

  • OSentryHL: High-Level-Adapter für die Anwendung. Diese Klasse sollte von normalem Applikationscode aufgerufen werden.
  • OSentry: Low-Level-Adapter für DSN-Parsing, JSON-Erzeugung, Stacktrace-Aufbereitung und HTTP-Kommunikation mit Sentry.

Die Anwendung arbeitet im Normalfall mit OSentryHL. Dadurch bleiben Sentry-spezifische Details zentral gekapselt und neue standardisierte Exception-Typen können als eigene Methoden in OSentryHL definiert werden.

Hauptfeatures

  • Direkte Anbindung von Omnis Studio an Sentry über REST API und DSN
  • Erfassen von Exceptions, Messages, Logs und SQL-Fehlern
  • Unterstützung der Sentry-Level fatal, error, warning, info und debug
  • Automatische Omnis-Kontextinformationen
  • Omnis-Stacktrace mit Klassen, Methoden, Zeilen und Variablen
  • Tags für Filterung und Gruppierung
  • Extras für zusätzliche Diagnoseinformationen
  • Optionaler User-Kontext
  • Proxy-Unterstützung
  • Aktivieren und Deaktivieren der Sentry-Übertragung
  • Lokales Speichern von Reports bei Übertragungsfehlern

Weiterführende Links

Screenshots

Sentry Issue-Übersicht

Installation

Diese Seite beschreibt, wie OSentry in eine bestehende Omnis-Anwendung integriert wird.

Voraussetzungen

  • Omnis Studio Anwendung
  • Sentry Account oder self-hosted Sentry Installation
  • Ein Sentry-Projekt mit SDK-Typ Other
  • Die DSN des Sentry-Projekts
  • Netzwerkzugriff auf Sentry

Die exportierte Demo-Library wurde mit Omnis 11.1 erstellt.

Sentry-Projekt erstellen

  1. In Sentry ein neues Projekt erstellen.
  2. Als SDK Other auswählen.
  3. Die DSN des Projekts kopieren.

Die DSN wird beim Initialisieren verwendet. OSentry zerlegt sie intern in Public Key, Host und Project ID.

Sentry Projektübersicht

Klassen kopieren

Kopiere die folgenden Klassen in deine bestehende Omnis-Library:

  • OSentry
  • OSentryHL

Die Demo-spezifischen Klassen sind für die produktive Integration nicht erforderlich. Damit sind die übrigen Klassen der Demo-Library gemeint, zum Beispiel FSY_Demo, ODummy, ODatabaseHandler und OSLSession. Diese Klassen dienen nur dazu, die Demo-Library mit Fenster, SQLite-Testdaten und Beispielaufrufen auszuführen.

Task Variable anlegen

Lege in deiner Startup Task eine Task Variable an:

Name Typ
tSentry OSentryHL
Empfehlung: tSentry sollte als global erreichbarer Singleton der Anwendung verwendet werden. In Omnis ist dafür eine Task Variable sinnvoll, weil sie von Fenstern, Objektklassen und zentralen Error-Handlern aus konsistent erreichbar ist. Dadurch gibt es genau eine aktive Sentry-Konfiguration mit einer DSN, einem Status, optionalen Proxy-Daten und gemeinsamen Wrapper-Methoden in OSentryHL.

Im Demo-Projekt ist diese Variable in Startup_Task definiert.

Initialisierung im Startup Task

Initialisiere tSentry beim Start deiner Anwendung mit der DSN deines Sentry-Projekts:

Do tSentry.$init('<DSN>')

Die Demo-Library ruft im Startup Task ebenfalls die Initialisierung auf. Quelle: Startup_Task.$construct.

#Init Sentry on lbs startup
Do tSentry.$init()

In einer produktiven Anwendung sollte die DSN explizit oder aus einer Konfiguration übergeben werden:

Do tSentry.$init('https://PUBLIC_KEY@sentry.io/PROJECT_ID')
Empfehlung: Speichere die DSN in einer Datenbank, einer Konfigurationstabelle oder einem Config File. So kann sie pro Kunde, Umgebung oder Installation geändert werden, ohne die Library neu auszuliefern.

Testcall

Nach der Initialisierung kann ein erstes Testevent gesendet werden:

Do tSentry.$captureMessage('Hello World!')

Wenn alles korrekt eingerichtet ist, erscheint das Event im Sentry-Projekt.

Proxy konfigurieren

Falls die Anwendung in einem geschützten Netzwerk läuft, kann ein Proxy gesetzt werden. Die Methode befindet sich im Low-Level-Objekt OSentry.

Do tSentry.iOSentry.$setProxy('proxy.example.local','8080')

Die interne Implementierung setzt den Proxy vor dem HTTP-Request:

#Configure proxy; needed when sending data out of secured networks
If not(isclear(iProxyHost))&not(isclear(iProxyPort))
	HTTPSetProxyServer (iProxyHost,iProxyPort)
End If

Sentry aktivieren oder deaktivieren

OSentry kann zentral ein- oder ausgeschaltet werden.

Empfehlung: Deaktiviere Sentry in der Entwicklungs-Version standardmäßig oder verwende eine separate Entwicklungs-DSN. So landen lokale Tests, Debug-Fehler und absichtlich ausgelöste Exceptions nicht im produktiven Sentry-Projekt.
Do tSentry.$setStatus(1)     ## aktiv
Do tSentry.$setStatus(0)     ## inaktiv

Im Low-Level-Objekt OSentry wird vor dem Senden geprüft:

#Check if Sentry is enabled
If iStatus=0|isclear(iStatus)
	Quit method 0
End If

Quickstart

Diese Seite zeigt die minimale Integration in eine bestehende Omnis-Anwendung.

Klassen übernehmen

Kopiere OSentry und OSentryHL in deine Library.

Task Variable erstellen

In der Startup Task:

Name Typ
tSentry OSentryHL

Sentry initialisieren

Do tSentry.$init('https://PUBLIC_KEY@sentry.io/PROJECT_ID')

OSentryHL.$init delegiert an das Low-Level-Objekt OSentry:

#Init of the main sentry object
Do iOSentry.$init(pDSN)
Quit method

Message senden

Do tSentry.$captureMessage('Hello Euromnis! This is a test message...')

Die Demo-Library verwendet genau diesen Aufruf im Button Trigger a message. Quelle: FSY_Demo.message.$event.

On evClick ## Event Parameters - pRow( Itemreference )
	Do tSentry.$captureMessage('Hello Euromnis! This is a test message...')
	Do $cinst.$showmessage('Sentry Event successfully triggered!','Info')
	Quit method

Exception senden

Do tSentry.$captureException('A generic Exception occured',1234,'Generic Exception','error')

In Sentry prüfen

In Sentry sollte anschließend ein neues Event sichtbar sein. Je nach Event-Typ enthält es:

Events erfassen

OSentryHL ist die empfohlene Einstiegsschicht für Applikationscode. Die Klasse bietet sprechende Methoden für typische Event-Arten und ruft intern OSentry.$captureException auf.

Message

Eine einfache Information wird mit $captureMessage gesendet:

Do tSentry.$captureMessage('Hello World!')

Implementierung in OSentryHL:

# Captures an Info Message
Do iOSentry.$captureException(pMessage,3,,'info',kFalse,,kFalse) Returns code
Quit method

Verhalten:

Log

Ein Log-Event wird mit $captureLog gesendet:

Do tSentry.$captureLog('Uh oh this is a Log because something went wrong')

Implementierung in OSentryHL:

# Captures a Log Sentry Report
Do iOSentry.$captureException(pErrorText,1,'Log','warning',1,0,1) Returns code

Quit method

Verhalten:

Generische Exception

Eine generische Exception wird mit $captureException gesendet:

Do tSentry.$captureException('A generic Exception occured',1234,'Generic Exception','error')

Implementierung in OSentryHL:

# Method to capture a generic Exception
#Add any custom tags / extras
Do $cinst.$addTag('Custom Test Tag','Euromnis')

Do iOSentry.$captureException(pErrorText,pErrorCode,pExcType,pLevel) Returns code

Quit method

Parameter:

Parameter Bedeutung
pErrorText Text, der in Sentry als Message sichtbar ist
pErrorCode Fehlercode oder fachlicher Code
pExcType Exception-Typ für Benennung und Gruppierung
pLevel Sentry-Level

Gültige Levels:

  • fatal
  • error
  • warning
  • info
  • debug

SQL Exception

SQL-Fehler können mit $captureSQLException gemeldet werden.

Do tSentry.$captureSQLException('SQL statement failed',stat)

Implementierung in OSentryHL:

# Method to capture an SQL Exception
Do $cinst.$addTag('Database',tOSLSession.$hostname)

Do $cinst.$addExtra('SQL-Text',pStat.$sqltext)
Do $cinst.$addExtra('SQL-Error',pStat.$nativeerrortext)

Do iOSentry.$captureException(pErrorText,1,'SQL-Exception','error')
Quit method

Verhalten:

  • Fügt die Datenbank als Tag hinzu
  • Fügt SQL-Text als Extra hinzu
  • Fügt native Datenbankfehlermeldung als Extra hinzu
  • Sendet das Event als SQL-Exception mit Level error

Deprecated Call

Veraltete Codepfade können gezielt gemeldet werden:

Do tSentry.$captureDeprecatedCall()

Implementierung in OSentryHL:

# Report a deprecated call of a piece of code to sentry
Do iOSentry.$captureException('Deprecated Call',3,'Deprecated Call','warning',1,1,1) Returns code

Quit method

Dieser Wrapper eignet sich, um zu erkennen, ob alter Code in produktiven Systemen noch ausgeführt wird.

Frei konfigurierbares Event

Für Sonderfälle gibt es $captureAnything:

Do tSentry.$captureAnything('Text',1001,'Custom Type','error',kTrue,kTrue,kTrue)

Implementierung in OSentryHL:

# Capture a generic Sentry Report (max configurability)
Do iOSentry.$captureException(pErrorText,pErrorCode,pExcType,pLevel,pStacktraveInterface,pExceptionInterface,pUserInterface) Returns code

Quit method

Diese Methode bietet maximale Flexibilität. Für wiederkehrende Exception-Typen sollte aber eine eigene Methode in OSentryHL angelegt werden. Siehe 04 Eigene Exceptions standardisieren.

Eigene Exceptions standardisieren

Wenn ein Exception-Typ mehrfach in der Anwendung vorkommt, sollte er nicht überall manuell mit $captureException aufgebaut werden. Besser ist eine eigene Methode in OSentryHL.

Dadurch entsteht eine zentrale, wiederverwendbare Definition für:

Die automatisch gesetzten Tags und Extras aus OSentry.$generateJson müssen in solchen Wrappern nicht erneut ergänzt werden. Eigene Exception-Methoden setzen nur zusätzliche Werte, die für diesen standardisierten Exception-Typ relevant sind.

Warum über OSentryHL?

OSentryHL ist die Abstraktionsschicht für Applikationscode. Sie kapselt die Details von OSentry und sorgt dafür, dass Aufrufe in der Anwendung kurz und konsistent bleiben.

Bestehende Beispiele aus OSentryHL:

# Report a deprecated call of a piece of code to sentry
Do iOSentry.$captureException('Deprecated Call',3,'Deprecated Call','warning',1,1,1) Returns code

Quit method
# Method to capture an SQL Exception
Do $cinst.$addTag('Database',tOSLSession.$hostname)

Do $cinst.$addExtra('SQL-Text',pStat.$sqltext)
Do $cinst.$addExtra('SQL-Error',pStat.$nativeerrortext)

Do iOSentry.$captureException(pErrorText,1,'SQL-Exception','error')
Quit method

Empfohlenes Muster

Für jeden standardisierten Exception-Typ wird eine eigene Methode in OSentryHL erstellt.

Beispiel:

# Captures a validation exception
Do $cinst.$addTag('Module',pModule)
Do $cinst.$addExtra('Field',pField)
Do $cinst.$addExtra('Invalid Value',pValue)

Do iOSentry.$captureException(pErrorText,2001,'Validation-Exception','warning',1,1,1) Returns code

Quit method code

Mögliche Parameter der neuen Methode:

Parameter Beispiel Zweck
pErrorText 'Invalid customer number' Sentry Message
pModule 'Customer' Filterbarer Tag
pField 'cu_number' Diagnoseinformation
pValue 'ABC' Diagnoseinformation

Der Applikationscode bleibt dadurch einfach:

Do tSentry.$captureValidationException('Invalid customer number','Customer','cu_number',cu_number)

Beispiel: Business Rule Exception

Neue Methode in OSentryHL:

# Captures a business rule violation
Do $cinst.$addTag('Module',pModule)
Do $cinst.$addTag('Business Rule',pRuleName)
Do $cinst.$addExtra('Details',pDetails)

Do iOSentry.$captureException(pErrorText,3001,'Business-Rule-Violation','warning',1,1,1) Returns code

Quit method code

Aufruf in der Anwendung:

Do tSentry.$captureBusinessRuleViolation('Invoice cannot be posted','Invoice','PostingAllowed','Invoice is missing customer')

Beispiel: Integration Exception

Neue Methode in OSentryHL:

# Captures an integration exception
Do $cinst.$addTag('Integration',pSystem)
Do $cinst.$addTag('Endpoint',pEndpoint)
Do $cinst.$addExtra('Payload',pPayload)
Do $cinst.$addExtra('Response',pResponse)

Do iOSentry.$captureException(pErrorText,4001,'Integration-Exception','error',1,1,1) Returns code

Quit method code

Aufruf in der Anwendung:

Do tSentry.$captureIntegrationException('External API request failed','ERP','/api/customer',jsonPayload,responseText)

Namenskonventionen

Empfehlung für neue Methoden:

  • Methodenname beginnt mit $capture
  • Der fachliche Typ steht im Methodennamen
  • Der Sentry Exception Type ist stabil und ändert sich nicht laufend
  • Tags sind kurz und filterbar
  • Extras dürfen länger sein und Diagnoseinformationen enthalten

Beispiele:

  • $captureValidationException
  • $captureBusinessRuleViolation
  • $captureIntegrationException
  • $capturePermissionViolation
  • $captureConfigurationError

Error Codes

Verwende feste Fehlercodes für standardisierte Exception-Typen. Dadurch können Events in Sentry besser gefiltert und wiedererkannt werden.

Beispiel:

Code Exception Type
2001 Validation-Exception
3001 Business-Rule-Violation
4001 Integration-Exception
5001 Configuration-Error

Wann nicht standardisieren?

Nicht jeder Einzelfall braucht eine eigene Methode. Für einmalige technische Tests oder sehr spezielle Fälle reicht:

Do tSentry.$captureException('A generic Exception occured',1234,'Generic Exception','error')

Sobald ein Exception-Typ aber mehrfach vorkommt oder fachlich relevant ist, sollte er als eigene Methode in OSentryHL definiert werden.

Tags, Extras und User-Kontext

Tags, Extras und User-Kontext reichern Sentry-Events mit zusätzlichen Informationen an. Diese Informationen helfen beim Filtern, Gruppieren und Analysieren.

Sentry Tags und User-Kontext

Tags

Tags sind kurze, filterbare Werte.

Beispiele:

  • Datenbank
  • Kunde
  • Modul
  • Umgebung
  • Error Code
  • Omnis-Version

Methode in OSentryHL:

# Add a Tag to the next Sentry Report
Do iOSentry.$addTag(pName,pValue)
Quit method

Methode in OSentry:

#Adds a tag to the next request processed
Do iTagList.$add(pName,pValue)
Quit method

Beispiel:

Do tSentry.$addTag('Module','Invoice')
Do tSentry.$addTag('Customer','10001')
Do tSentry.$captureException('Invoice posting failed',3001,'Business-Rule-Violation','warning')

Extras

Extras sind Detailinformationen, die nicht primär zum Filtern gedacht sind.

Beispiele:

  • SQL-Text
  • Native Datenbankfehlermeldung
  • Payload
  • Response Body
  • interne IDs
  • zusätzliche Debug-Informationen

Methode in OSentryHL:

# Add an Extra to the next Sentry Report
Do iOSentry.$addExtra(pName,pValue)
Quit method

Methode in OSentry:

#Adds extra information to the next request being processed
Do iExtraList.$add(pName,pValue)
Quit method

Beispiel aus der SQL Exception:

Do $cinst.$addExtra('SQL-Text',pStat.$sqltext)
Do $cinst.$addExtra('SQL-Error',pStat.$nativeerrortext)

Automatische Tags

Die folgenden Tags werden bei jedem Event automatisch von OSentry.$generateJson ergänzt. Sie müssen bei eigenen Exceptions nicht erneut gesetzt werden. Eigene Wrapper-Methoden in OSentryHL sollten nur zusätzliche, fachlich oder technisch relevante Tags hinzufügen.

OSentry.$generateJson fügt mehrere Tags automatisch hinzu:

# Add static tags
Do iTagList.$add('Omnisversion',sys(1))
Calculate systemversionRow as systemversion()
Do iTagList.$add('Plattform',con(sys(8),pick(systemversionRow.server,'',' SRV')))
Do iTagList.$add('OS Version',con(systemversionRow.major,'.',systemversionRow.minor,'.',systemversionRow.build))
Do iTagList.$add('error_code',pErrorCode)

Automatisch gesendete Tags:

Tag Herkunft Zweck
Omnisversion sys(1) Zeigt, mit welcher Omnis-Version das Event erzeugt wurde
Plattform sys(8) und Server-Flag aus systemversion() Unterscheidet Plattform und Server Runtime
OS Version systemversionRow.major/minor/build Zeigt die Betriebssystemversion
error_code Parameter pErrorCode Verbindet das Event mit dem übergebenen Fehlercode

Beispiel für eine eigene Exception: Der Wrapper muss nicht erneut Omnisversion oder OS Version setzen. Er ergänzt nur das, was für diesen Exception-Typ zusätzlich hilfreich ist.

Do $cinst.$addTag('Module',pModule)
Do $cinst.$addTag('Business Rule',pRuleName)
Do iOSentry.$captureException(pErrorText,3001,'Business-Rule-Violation','warning',1,1,1) Returns code

Automatische Extras

Auch die folgenden Extras werden bei jedem Event automatisch ergänzt. Bei eigenen Exceptions müssen nur zusätzliche Extras gesetzt werden, zum Beispiel ein SQL-Statement, ein Payload oder fachliche Zusatzdaten.

OSentry.$generateJson fügt offene Fenster, offene Reports und die aktuelle Printfile hinzu:

# Static extra 1: All open windows
Do $root.$iwindows.$makelist($ref.$name) Returns nameList
For i from 1 to nameList.$linecount step 1
	Calculate windows as con(windows,', ',nameList.[i].1)
End For
Calculate windows as right(windows,len(windows)-2)
Do iExtraList.$add('Open Windows',windows)

# Static extra 2: All open reports
Do $root.$ireports.$makelist($ref.$name) Returns nameList
For i from 1 to nameList.$linecount step 1
	Calculate reports as con(reports,', ',nameList.[i].1)
End For
Calculate reports as right(reports,len(reports)-2)
Do iExtraList.$add('Open Reports',reports)
Do iExtraList.$add('Current Printfile',$root.$prefs.$printfile)

Automatisch gesendete Extras:

Extra Herkunft Zweck
Open Windows $root.$iwindows.$makelist($ref.$name) Zeigt, welche Fenster im Moment des Events offen waren
Open Reports $root.$ireports.$makelist($ref.$name) Zeigt, welche Reports im Moment des Events offen waren
Current Printfile $root.$prefs.$printfile Zeigt die aktuell gesetzte Printfile

Beispiel für zusätzliche Extras in einem eigenen Wrapper:

Do $cinst.$addExtra('Payload',pPayload)
Do $cinst.$addExtra('Response',pResponse)
Do iOSentry.$captureException(pErrorText,4001,'Integration-Exception','error',1,1,1) Returns code

User-Kontext

Der User-Kontext ordnet ein Event einem betroffenen Benutzer zu. In Sentry erscheint dadurch ein eigener User-Bereich, und Events können nach Benutzer gefiltert oder gruppiert werden. Das ist besonders hilfreich, wenn ein Fehler nur bei einzelnen Kunden, Arbeitsplätzen oder Benutzerkonten auftritt.

OSentry unterstützt drei User-Felder:

Feld Bedeutung
id stabile interne Benutzer-ID oder Kundennummer
username lesbarer Benutzername
email E-Mail-Adresse, falls sie übertragen werden darf

Der User-Kontext wird nur in das Event geschrieben, wenn das User Interface beim Capture-Aufruf aktiviert ist. Die Standardmethode OSentry.$captureException hat pUserInterface standardmäßig auf kTrue. Einzelne High-Level-Methoden können das bewusst deaktivieren, zum Beispiel $captureMessage.

OSentry kann User-Daten an das Event anhängen:

#Sets userinformation for the next request being processed
Calculate iUserID as pID
Calculate iUserName as pName
Calculate iUserEmail as pEmail
Quit method

Das User Interface wird so generiert:

# Create user data row
Do UserdataRow.$define(id,email,username)

Calculate UserdataRow.id as iUserID
Calculate UserdataRow.email as iUserEmail
Calculate UserdataRow.username as iUserName

Do JSON.$addmember('','user','')
Do JSON.$setobject('user',UserdataRow)

Calculate jsonString as OJSON.$formatjson(JSON.$getjson())

Quit method jsonString

Die aktuelle Demo-Methode in OSentryHL verwendet feste Testdaten. Quelle: OSentryHL.$setUser.

# Set the User which should be linked to the Sentry Issue
Do iOSentry.$setUserData(23,'Euromnis Test User','euromnis@test.com')
Quit method

Für produktive Nutzung sollte diese Methode angepasst und parametrisiert werden:

Do iOSentry.$setUserData(pUserID,pUserName,pUserEmail)
Quit method

Empfohlen ist, den User nach Login oder beim Wechsel des aktiven Benutzers zentral zu setzen. Bei anonymen oder sensiblen Installationen kann statt Name und E-Mail auch nur eine interne ID oder ein pseudonymisierter Wert verwendet werden.

Datenschutz

Datenschutz: Prüfe vor produktiver Nutzung, welche Daten an Sentry gesendet werden. Besonders kritisch sind personenbezogene Daten, SQL-Statements, Zugangsdaten, Tokens und interne Pfade.

Besonders kritisch sind:

  • personenbezogene Daten
  • Kundendaten
  • SQL-Statements mit Werten
  • Zugangsdaten
  • Tokens
  • interne Pfade

Tags und Extras sollten so gestaltet werden, dass sie für die Fehleranalyse hilfreich sind, aber keine unnötigen sensiblen Daten übertragen.

Stacktrace und Kontext

OSentry erzeugt einen Omnis-spezifischen Stacktrace und übergibt ihn an Sentry. Dadurch sieht man in Sentry nicht nur eine Fehlermeldung, sondern auch Klassen, Methoden, Zeilen und Variablenkontext. Ergänzende Informationen zu Tags, Extras und User-Kontext stehen auf der separaten Kontext-Seite.

Sentry Stacktrace mit Omnis-Kontext

Stack lesen

OSentry.$generateStacktraceInterface verwendet sys(192), um den aktuellen Omnis-Stack zu lesen:

# Clean up the Stacklist (remove OSentry classes from the stack)
Do sys(192) Returns sys192List
For sys192List.$line from 1 to sys192List.$linecount step 1
	Set reference class to sys192List.classitem
	If pos('OSentry',class.$name)>0|pos('OSentryHL',class.$name)>0
		Do sys192List.[sys192List.$line].$selected.$assign(kTrue)
	End If
End For
Do sys192List.$remove(kListDeleteSelected)

Interne Frames von OSentry und OSentryHL werden entfernt, damit in Sentry die fachlich relevanten Stellen sichtbar bleiben.

SQL-Error Frames entfernen

Bestimmte interne SQL-Fehlerframes werden ebenfalls entfernt:

# Remove some other classes which we do not want to display
If sys192List.1.method='$sqlerror'
	Do sys192List.$remove(1)
Else If sys192List.1.method='$statementerror'
	Do sys192List.$remove(1)
End If

Frames erzeugen

Für jeden Stack-Eintrag werden Funktion, Zeilennummer und Kontextzeile erzeugt:

#Loop through every item on the omnis stack
For sys192List.$line from 1 to sys192List.$linecount step 1
	Set reference class to sys192List.classitem
	Calculate className as class.$name
	
	# Create the content row
	Do contentRow.$define(vars,function,pre_context,context_line,lineno,filename,post_context)
	Calculate contentRow.lineno as sys192List.line
	Calculate contentRow.filename as testFileName
	Calculate contentRow.context_line as sys192List.linetext
	If isclear(sys192List.object)
		Calculate contentRow.function as con(className,'.',sys192List.method) ## If it's a class method
	Else
		Calculate contentRow.function as con(className,'.',sys192List.object,'.',sys192List.method) ## If it's a method of an object of a class (e.g. Headedlist)
	End If
	Do contentList.$add(contentRow)
End For

Variablen aufnehmen

Pro Stackframe werden Instance Variablen und Parameter gesammelt:

# Get all iVars
Do varList.$define(name,value)
Set reference class to sys192List.inst
Do $cinst.$getVars('ivars',class) Returns varList

# Get all params
Calculate paramList as sys192List.params
For paramList.$line from 1 to paramList.$linecount step 1
	If not(paramList.value='(Not empty)')
		Do varList.$add(paramList.name,paramList.value)
	Else
		Do varList.$add(paramList.name,'(Not empty)')
	End If
End For

Pre- und Post-Context

OSentry fügt Methodenzeilen vor und nach der aktuellen Zeile hinzu:

# Pre Context (all method lines before the error occured)
Set reference method to sys192List.methoditem
Do precontextList.$define(line)
For i from 1 to sys192List.line-1 step 1
	Do precontextList.$add(method.$methodlines.[i].$text)
End For

# Post Context (all method lines after the error occured
Do postcontextList.$define(line)
For i from sys192List.line+1 to method.$methodlines.$count step 1
	Do postcontextList.$add(method.$methodlines.[i].$text)
End For

Variablentypen

OSentry.$getVars unterstützt Basisvariablen, Rows und Lists.

Basisvariablen:

If varType='char'|varType='boolean'|varType='integer'|varType='number'|varType='date'
	Calculate varContent as pItemRef.$[pVarType].[varName]
	Do varList.$add(varName,varContent)

Rows:

Else If varType='row'
	Calculate varRow as pItemRef.$[pVarType].[varName]
	If varRow.$colcount=0
		Do varList.$add(varName,'(Empty)')
	Else
		For Z2 from 1 to varRow.$colcount step 1
			Calculate varContent as con(varContent,varRow.$cols.[Z2].$name,': ',varRow.[Z2],', ')
		End For
		Do varList.$add(varName,varContent)

Lists:

Else If varType='list'
	Calculate varListType as pItemRef.$[pVarType].[varName]
	Calculate varContent as con('Colcount: ',varListType.$colcount,', ','Linecount: ',varListType.$linecount,', ','Current Line: ',varListType.$line)
	If varListType.$linecount=0&varListType.$line=0&varListType.$colcount=0
		Do varList.$add(varName,'(Empty)')
		Calculate varContent as ''
	Else
		For Z3 from 1 to varListType.$colcount step 1
			Calculate colName as varListType.$cols.[Z3].$name
			Calculate varContent as con(varContent,'  ',colName,': ',varListType.[colName])
		End For
		Do varList.$add(varName,varContent)
		Calculate varContent as ''
	End If
End If

Hinweise

Stacktrace und Variablenkontext sind sehr hilfreich, können aber sensible Daten enthalten. Vor produktiver Nutzung sollte geprüft werden, ob bestimmte Variablen anonymisiert oder ausgeschlossen werden müssen.

Interne Architektur

Diese Seite beschreibt die produktiv relevanten Klassen OSentryHL und OSentry.

Klassenübersicht

Klasse Rolle
OSentryHL High-Level-Adapter für Applikationscode
OSentry Low-Level-Adapter für JSON, Stacktrace und HTTP
Startup_Task Demo-Startup und Beispiel für Initialisierung
FSY_Demo Demo-Fenster
ODummy Demo-Code für Stacktrace-Beispiel
ODatabaseHandler Demo-DB Initialisierung
OSLSession SQLite Session für Demo

Empfohlener Aufrufweg

Applikationscode sollte OSentryHL verwenden:

Do tSentry.$captureException('A generic Exception occured',1234,'Generic Exception','error')

OSentryHL delegiert anschließend an OSentry:

Do iOSentry.$captureException(pErrorText,pErrorCode,pExcType,pLevel) Returns code

Ablauf eines Events

  1. Applikationscode ruft Methode in OSentryHL auf.
  2. OSentryHL fügt bei Bedarf Tags und Extras hinzu.
  3. OSentryHL ruft iOSentry.$captureException(...) auf.
  4. OSentry prüft, ob Sentry aktiv ist.
  5. OSentry erzeugt JSON.
  6. Stacktrace, Exception Interface und User Interface werden optional ergänzt.
  7. HTTP Header und Sentry Auth Header werden erstellt.
  8. JSON wird per HTTPS an Sentry gesendet.
  9. Bei Erfolg werden Tags und Extras geleert.
  10. Bei Fehler wird der JSON Report lokal gespeichert.

DSN Parsing

OSentry.$init zerlegt die DSN:

# Parse the DSN into Public Key, Host and Project ID
If len(pDSN)>5
	Calculate iDSN as pDSN
	Calculate part1 as strtok('iDSN','@')
	Calculate iProtocol as strtok('part1','/')
	Calculate iProtocol as left(iProtocol,len(iProtocol)-1)
	Do strtok('part1','/')
	Calculate iPubKey as strtok('part1',':')
	
	Calculate iHost as strtok('iDSN','/')
	Calculate iProID as iDSN
	
	#Save the values for the next startup
	Calculate $cclass.$ivardefs.iPubKey.$objinitval as con('"',iPubKey,'"')
	Calculate $cclass.$ivardefs.iHost.$objinitval as con('"',iHost,'"')
	Calculate $cclass.$ivardefs.iProID.$objinitval as con('"',iProID,'"')
End If

Quit method

JSON-Erzeugung

OSentry.$generateJson ist die zentrale Methode für den Payload. Sie setzt unter anderem:

  • event_id
  • logger
  • platform
  • culprit
  • timestamp
  • sdk
  • message
  • level
  • tags
  • extra
  • optional user
  • optional exception
  • optional stacktrace

Auszug:

# Add all required fields (those are required from the API)
Do JSON.$addmember('','event_id',$cinst.$generateUUID()) ## auto generated UUID 4
Do JSON.$addmember('','logger',logger)
Do JSON.$addmember('','platform',platform)
Do JSON.$addmember('','culprit',culprit)
#Do JSON.$addmember('','release',release)
Do JSON.$addmember('','timestamp',timestamp)
Do JSON.$addmember('','sdk','')
Do JSON.$addmember('','message',pErrorText)
Do JSON.$addmember('','level',pLevel)
Do JSON.$addmember('','tags','')

HTTP-Kommunikation

OSentry.$captureException sendet den erzeugten JSON-Payload an Sentry:

#Generate HTTP Auth header
Begin text block
Text:Sentry sentry_version=7,
Text:sentry_timestamp=[$cinst.$getUnixTimestamp()],
Text:sentry_key=[iPubKey],
Text:sentry_client=omnis/1.0
End text block
Get text block auth

#Generate header list
Calculate Host as 'sentry.io'
Calculate Url as con('/api/',iProID,'/store/')
Do HdrList.$define(wert,name)
Do HdrList.$add('User-Agent','omnis/1.0')
Do HdrList.$add('Content-Type','application/json')
Do HdrList.$add('Content-Length',binlength(json))
Do HdrList.$add('X-Sentry-Auth',auth)

Anschließend wird der Request über HTTPPost, HTTPSend und HTTPRead ausgeführt.

Fehlerbehandlung beim Senden

Wenn der Socket nicht geöffnet werden kann:

HTTPPost (Host,Url,,HdrList,443,kTrue,kTrue) Returns Socket
If Socket<0
	#Error when opening connection -> save json as a file
	Do $cinst.$writeJSON(iJSON,con('Error ',Socket,' when performing HTTPPost'))
	Do $cinst.$clearList()
	HTTPClose (Socket)
	Quit method -1
End If

Wenn das Senden fehlschlägt:

HTTPSend (Socket,json) Returns byteCount
If byteCount<0
	# Error while sending data -> save json as a file
	Do $cinst.$writeJSON(iJSON,con('Erorr ',byteCount,' when performing HTTPSend'))
	Do $cinst.$clearList()
	HTTPClose (Socket)
	Quit method -2
End If

Wenn die Antwort nicht erfolgreich ist:

HTTPRead (Socket,Buffer) Returns byteCount
If byteCount<0|not(pos('200 OK',Buffer))
	# JSON may be corrupted or contains errors -> save json and the buffer as a file
	Do $cinst.$writeJSON(iJSON,Buffer)
	Do $cinst.$clearList()
	HTTPClose (Socket)
	Quit method -3
End If

Lokales Speichern

Bei Fehlern wird der JSON Report lokal im Omnis-Installationsordner gespeichert:

#Writes the json and the http buffer to a file in the omnis installation folder
Calculate path as sys(115)
Calculate filename as con('Sentryreport_',$cinst.$getUnixTimestamp(),'.json')
Do fOP.$createfile(con(path,filename)) Returns err
Do fOP.$writecharacter(kUniTypeUTF8,pJSON) Returns err
If not(isclear(pBuffer))
	Do fOP.$writecharacter(kUniTypeUTF8,con(kCr,pBuffer),kTrue) Returns err
End If
Do fOP.$closefile()

Quit method

Cleanup

Nach erfolgreichem Senden werden Tags und Extras gelöscht:

#Clears all extras and tags => to be used after a sentry request has successfully been sent
Do iTagList.$clear()
Do iExtraList.$clear()
Quit method

Demo Library

Die Demo-Library zeigt, wie OSentry initialisiert wird und wie verschiedene Event-Typen aus einer Omnis-Oberfläche heraus an Sentry gesendet werden.

Bestandteile

Klasse Zweck
Startup_Task Initialisiert Sentry, SQLite und öffnet das Demo-Fenster
FSY_Demo Demo-Fenster
ODummy Erzeugt Demo-Stack für Exception
ODatabaseHandler Erstellt SQLite-Demo-Datenbank
OSLSession SQLite Session
OSentry Low-Level-Sentry-Adapter
OSentryHL High-Level-Sentry-Adapter

Startup

Startup_Task.$construct initialisiert Sentry, baut eine SQLite Session auf und öffnet das Demo-Fenster. Quelle: Startup_Task.$construct.

#Init Sentry on lbs startup
Do tSentry.$init()

#SQLite Session init
Do $objects.OSLSession.$newref() Returns tOSLSession
#Calculate tOSLSession.$opencreate as kTrue
Calculate workingDir as tODatabaseHandler.$getWorkingDir()
Do con(workingDir,'Sentry_Test.db') Returns dbLocation
Do tOSLSession.$logon(dbLocation,'','','slsession') Returns #F

#Open Test Window
Do $windows.FSY_Demo.$openonce('*')

Quit method

Demo-Fenster

FSY_Demo enthält folgende Bereiche:

  • DSN Configuration
  • DB Status
  • Actions

Wichtige Felder:

Feld Datenanbindung
DSN iDSN
Host tSentry.iOSentry.iHost
Public Key tSentry.iOSentry.iPubKey
Project ID tSentry.iOSentry.iProID
DB Status iCurrentDBStatus

Demo-Fenster der OSentry Library

DSN setzen

Die DSN wird im Feld iDSN erfasst. Der Button Set DSN ruft anschließend tSentry.$init(iDSN) auf. Nach dem Setzen werden Public Key, Host und Project ID aus der DSN gelesen und in den darunterliegenden Feldern angezeigt.

DSN-Konfiguration im Demo-Fenster

Der Button Set DSN initialisiert Sentry mit der eingegebenen DSN. Quelle: FSY_Demo.setDSN.$event.

On evClick ## Event Parameters - pRow( Itemreference )
	Do tSentry.$init(iDSN)
	Calculate $cclass.$ivardefs.iDSN.$objinitval as con(kSq,iDSN,kSq)
	
	Do $cinst.$showmessage('DSN set and Sentry initialized!','Info')
	
	Do $cinst.$redraw()
	Quit method

DB Status anzeigen

FSY_Demo.$displayDBState zeigt, ob die SQLite Session verbunden ist. Quelle: FSY_Demo.$displayDBState.

Do tOSLSession.$state Returns dbState
If dbState='kSessionStateLoggedOff'
	Calculate iCurrentDBStatus as 'Logged Off'
Else If dbState='kSessionStateLoggedOn'
	Calculate iCurrentDBStatus as 'Logged On'
Else
	Calculate iCurrentDBStatus as 'Unkown DB State'
End If

Do $cinst.$redraw()
Quit method

Demo-Datenbank erstellen

Der Button Create Database ruft ODatabaseHandler.$DBFirstInit auf. Quelle: FSY_Demo.createDB.$event.

On evClick ## Event Parameters - pRow( Itemreference )
	#Setup the DB
	Do tODatabaseHandler.$DBFirstInit() Returns err
	If err=0
		Do $cinst.$showmessage('DB successfully created!','Info')
	Else
		Do $cinst.$showmessage('Error while creating the DB. Make sure that the DB does not already exist.','Info')
	End If
	
	Do $cinst.$displayDBState()
	
	Quit method

Die Datenbank wird im Arbeitsverzeichnis der Library angelegt. Quelle: ODatabaseHandler.$getWorkingDir.

Quit method con(FileOps.$parentdir($clib.$pathname),pathsep())

Die Demo-DB enthält unter anderem:

  • dperson
  • drelease
  • dvcs

Message auslösen

Button Trigger a message. Quelle: FSY_Demo.message.$event.

On evClick ## Event Parameters - pRow( Itemreference )
	Do tSentry.$captureMessage('Hello Euromnis! This is a test message...')
	Do $cinst.$showmessage('Sentry Event successfully triggered!','Info')
	Quit method

Log auslösen

Button Trigger a log. Quelle: FSY_Demo.log.$event.

On evClick ## Event Parameters - pRow( Itemreference )
	Do tSentry.$captureLog('Uh oh this is a Log because something went wrong')
	Do $cinst.$showmessage('Sentry Event successfully triggered!','Info')
	Quit method

Exception auslösen

Button Trigger an exception bereitet eine Row und eine List vor und ruft anschließend ODummy.$dummyMethod auf. Quelle: FSY_Demo.exception.$event.

On evClick ## Event Parameters - pRow( Itemreference )
	Do iDummyRow.$define(id,name)
	Calculate iDummyRow.id as 22
	Calculate iDummyRow.name as 'Tom'
	
	Do iDummyList.$define(id,weekday)
	Do iDummyList.$add(1,'Monday')
	Do iDummyList.$add(2,'Tuesday')
	Do iDummyList.$add(3,'Wednesday')
	Do iDummyList.$add(4,'Thursday')
	Do iDummyList.$add(5,'Friday')
	Do iDummyList.$add(6,'Saturday')
	Do iDummyList.$add(7,'Sunday')
	
	Calculate iDummyList.$line as 5
	
	Do iODummy.$dummyMethod('Important Value')
	Do $cinst.$showmessage('Sentry Event successfully triggered!','Info')
	
	Quit method

ODummy.$dummyMethod sendet die Exception. Quelle: ODummy.$dummyMethod.

#In here is some logic
#This logic would produce an error
#We send all this information to Sentry

Do tSentry.$captureException('A generic Exception occured',1234,'Generic Exception','error')

Quit method 0

Deprecated Call auslösen

Button Trigger a deprecated call. Quelle: FSY_Demo.deprecatedCall.$event.

On evClick ## Event Parameters - pRow( Itemreference )
	Do tSentry.$captureDeprecatedCall()
	Do $cinst.$showmessage('Sentry Event successfully triggered!','Info')
	Quit method

SQL Exception Button

Der Button Trigger an SQLException ist im Export vorhanden, enthält aber noch keinen fertigen Demo-Code. Quelle: FSY_Demo.sqlException.$event.

On evClick ## Event Parameters - pRow( Itemreference )
	#Code need's to be written

Für die Dokumentation der SQL-Erfassung siehe 03 Events erfassen.

API Reference

Diese Seite dokumentiert die produktiv relevanten Methoden von OSentryHL und OSentry.

OSentryHL

OSentryHL ist die empfohlene Klasse für Applikationscode.

$init(pDSN)

Initialisiert das interne OSentry-Objekt.

#Init of the main sentry object
Do iOSentry.$init(pDSN)
Quit method

$captureMessage(pMessage)

Sendet eine einfache Info-Message.

# Captures an Info Message
Do iOSentry.$captureException(pMessage,3,,'info',kFalse,,kFalse) Returns code
Quit method

$captureException(pErrorText,pErrorCode,pExcType,pLevel)

Sendet eine generische Exception.

# Method to capture a generic Exception
#Add any custom tags / extras
Do $cinst.$addTag('Custom Test Tag','Euromnis')

Do iOSentry.$captureException(pErrorText,pErrorCode,pExcType,pLevel) Returns code

Quit method

$captureAnything(pErrorText,pErrorCode,pExcType,pLevel,pStacktraveInterface,pExceptionInterface,pUserInterface)

Sendet ein frei konfigurierbares Event.

# Capture a generic Sentry Report (max configurability)
Do iOSentry.$captureException(pErrorText,pErrorCode,pExcType,pLevel,pStacktraveInterface,pExceptionInterface,pUserInterface) Returns code

Quit method

Hinweis: Der Parameter ist im Export als pStacktraveInterface geschrieben.

$captureLog(pErrorText)

Sendet ein Log-Event.

# Captures a Log Sentry Report
Do iOSentry.$captureException(pErrorText,1,'Log','warning',1,0,1) Returns code

Quit method

$captureDeprecatedCall()

Meldet die Ausführung eines veralteten Codepfads.

# Report a deprecated call of a piece of code to sentry
Do iOSentry.$captureException('Deprecated Call',3,'Deprecated Call','warning',1,1,1) Returns code

Quit method

$captureSQLException(pErrorText,pStat)

Meldet einen SQL-Fehler mit SQL-Text und nativer Datenbankfehlermeldung.

# Method to capture an SQL Exception
Do $cinst.$addTag('Database',tOSLSession.$hostname)

Do $cinst.$addExtra('SQL-Text',pStat.$sqltext)
Do $cinst.$addExtra('SQL-Error',pStat.$nativeerrortext)

Do iOSentry.$captureException(pErrorText,1,'SQL-Exception','error')
Quit method

$addTag(pName,pValue)

Fügt einen Tag für das nächste Event hinzu.

# Add a Tag to the next Sentry Report
Do iOSentry.$addTag(pName,pValue)
Quit method

$addExtra(pName,pValue)

Fügt ein Extra für das nächste Event hinzu.

# Add an Extra to the next Sentry Report
Do iOSentry.$addExtra(pName,pValue)
Quit method

$setStatus(pStatus)

Aktiviert oder deaktiviert Sentry.

#Toggels Sentry on or off
Do iOSentry.$setStatus(pStatus)
Quit method

$setUser()

Setzt im Export feste Demo-Userdaten.

# Set the User which should be linked to the Sentry Issue
Do iOSentry.$setUserData(23,'Euromnis Test User','euromnis@test.com')
Quit method

Für produktive Nutzung sollte diese Methode parametrisiert werden.

OSentry

OSentry ist die Low-Level-Klasse für Payload-Erzeugung und Versand.

$init(pDSN)

Parst die DSN in Protokoll, Public Key, Host und Project ID.

$captureException(pErrorText,pErrorCode,pExcType,pLevel,pStacktraceInterface,pUserInterface,pExceptionInterface)

Erzeugt JSON, sendet es an Sentry und behandelt Fehlerfälle.

Parameter:

Parameter Default Bedeutung
pErrorText Message
pErrorCode Fehlercode
pExcType Exception-Typ
pLevel fatal, error, warning, info, debug
pStacktraceInterface kTrue Stacktrace senden
pUserInterface kTrue User-Kontext senden
pExceptionInterface kTrue Exception Interface senden

$generateJson(...)

Erzeugt den Sentry JSON Payload als Binary.

$generateStacktraceInterface(pCulprit)

Erzeugt den Omnis-Stacktrace inklusive Variablen und Kontextzeilen.

$generateExceptionInterface(pType,pValue)

Erzeugt das Sentry Exception Interface.

# Generate Row to store in the JSON
Do exceptionRow.$define(type,value,stacktrace)
Calculate exceptionRow.type as pType
Calculate exceptionRow.value as pValue
Calculate exceptionRow.stacktrace as 'sentry.interfaces.stacktrace' ## Tells the exception interface that a stacktrace is passed aswell

$generateUserInterface()

Erzeugt den User-Kontext.

$addTag(pName,pValue)

Fügt einen Tag zur internen Tag-Liste hinzu.

$addExtra(pName,pValue)

Fügt ein Extra zur internen Extra-Liste hinzu.

$clearList()

Leert Tags und Extras nach einem Request.

$setUserData(pID,pName,pEmail)

Setzt Userdaten für den nächsten Request.

$setProxy(pProxyHost,pProxyPort)

Setzt Proxy-Informationen.

$setStatus(pStatus)

Setzt den Sentry-Status.

#Toggels Sentry Reports on or off
Calculate iStatus as pStatus
Quit method

$writeJSON(pJSON,pBuffer)

Schreibt fehlgeschlagene Reports lokal in eine Datei.

$getUnixTimestamp()

Gibt den aktuellen UNIX Timestamp zurück.

$generateUUID()

Erzeugt eine UUID für die Sentry Event ID.

#Genereates a UUID for the issue id
Quit method OW3.$makeuuid(kFalse)

Troubleshooting

Es erscheinen keine Events in Sentry

Prüfe zuerst, ob Sentry aktiv ist:

Do tSentry.$setStatus(1)

OSentry.$captureException beendet sich sofort, wenn der Status 0 oder leer ist:

#Check if Sentry is enabled
If iStatus=0|isclear(iStatus)
	Quit method 0
End If

Die DSN ist falsch

Prüfe, ob die DSN korrekt aus Sentry kopiert wurde. OSentry.$init erwartet eine DSN, aus der Public Key, Host und Project ID gelesen werden können.

Nach dem Setzen der DSN sollten in der Demo-Library folgende Felder gefüllt sein:

  • Host
  • Public Key
  • Project ID

Netzwerk oder Proxy blockiert den Request

Wenn die Anwendung keinen direkten Zugriff auf Sentry hat, setze einen Proxy:

Do tSentry.iOSentry.$setProxy('proxy.example.local','8080')

Intern wird der Proxy vor dem HTTP Request gesetzt:

If not(isclear(iProxyHost))&not(isclear(iProxyPort))
	HTTPSetProxyServer (iProxyHost,iProxyPort)
End If

Report wird lokal gespeichert

Wenn HTTPPost, HTTPSend oder HTTPRead fehlschlägt, speichert OSentry den Report lokal:

Calculate path as sys(115)
Calculate filename as con('Sentryreport_',$cinst.$getUnixTimestamp(),'.json')
Do fOP.$createfile(con(path,filename)) Returns err

Suche im Omnis-Installationsordner nach Dateien mit dem Namen:

Sentryreport_<timestamp>.json

Sentry antwortet nicht mit 200 OK

Wenn die HTTP-Antwort kein 200 OK enthält, wird der JSON Report ebenfalls lokal gespeichert:

HTTPRead (Socket,Buffer) Returns byteCount
If byteCount<0|not(pos('200 OK',Buffer))
	# JSON may be corrupted or contains errors -> save json and the buffer as a file
	Do $cinst.$writeJSON(iJSON,Buffer)
	Do $cinst.$clearList()
	HTTPClose (Socket)
	Quit method -3
End If

Mögliche Ursachen:

  • falsche Project ID
  • falscher Public Key
  • ungültige DSN
  • JSON Payload wird von Sentry abgelehnt
  • Netzwerk-Gateway verändert den Request

Tags oder Extras erscheinen beim falschen Event

Tags und Extras werden für den nächsten Request gesammelt. Nach erfolgreichem Request werden sie gelöscht:

Do iTagList.$clear()
Do iExtraList.$clear()

Wenn ein Request fehlschlägt, wird ebenfalls aufgeräumt:

Do $cinst.$clearList()

Prüfe trotzdem, ob in eigenen Wrapper-Methoden Tags und Extras direkt vor dem passenden Capture-Aufruf gesetzt werden.

User-Kontext zeigt Demo-Daten

OSentryHL.$setUser verwendet im Export feste Testdaten:

Do iOSentry.$setUserData(23,'Euromnis Test User','euromnis@test.com')

Für produktive Nutzung sollte die Methode parametrisiert werden:

Do iOSentry.$setUserData(pUserID,pUserName,pUserEmail)

SQL Exception Demo-Button funktioniert nicht

Der Button Trigger an SQLException ist im Export noch nicht implementiert:

On evClick ## Event Parameters - pRow( Itemreference )
	#Code need's to be written

Die produktive Methode für SQL-Fehler ist aber vorhanden. Siehe auch Events erfassen.

Do tSentry.$captureSQLException('SQL statement failed',stat)

Zu viele Events

Sentry kann sehr schnell viele Events sammeln. Verwende für produktive Systeme:

  • klare Wrapper-Methoden in OSentryHL
  • sinnvolle Levels
  • gezielte Tags
  • keine Events in sehr häufigen Schleifen
  • keine rein informativen Debug-Events ohne Nutzen

Sensible Daten

Stacktrace, Parameter, Instance Variablen, SQL-Text und Extras können sensible Daten enthalten. Prüfe vor produktiver Nutzung:

  • Welche Variablen werden übertragen?
  • Enthalten SQL-Statements personenbezogene Daten?
  • Werden Tokens oder Passwörter in Extras geschrieben?
  • Sollen bestimmte Werte maskiert werden?