Auf dieser Seite wird das erweiterte Konzept von Sitzungen in Spanner beschrieben. einschließlich Best Practices für Sitzungen beim Erstellen einer Clientbibliothek, über die REST API, die RPC API oder die Google-Clientbibliotheken.
Sitzungen – Übersicht
Eine Sitzung stellt einen Kommunikationskanal mit der Spanner-Datenbank dar Service. Eine Sitzung wird zum Ausführen von Transaktionen zum Lesen, Schreiben oder Ändern verwendet Daten in einer Spanner-Datenbank. Jede Sitzung gilt für eine einzige Datenbank.
Sitzungen können jeweils eine oder mehrere Transaktionen ausführen. Wann? Ausführen mehrerer Transaktionen wird diese Sitzung als Multiplex-Sitzung bezeichnet.
Eigenständige Lese-, Schreib- und Abfragevorgänge verwenden intern eine Transaktion.
Leistungsvorteile eines Sitzungspools
Das Erstellen einer Sitzung ist teuer. Um Leistungskosten jedes Mal zu vermeiden, wenn ein Datenbankvorgang ausgeführt wird, sollten Clients einen Sitzungspool beibehalten, bei dem es sich um einen Pool verfügbaren Sitzungen, die einsatzbereit sind. Der Pool sollte vorhandene Sitzungen speichern und bei Anforderung den entsprechenden Sitzungstyp zurückgeben sowie die Bereinigung durchführen. nicht verwendeter Sitzungen. Ein Beispiel für die Implementierung eines Sitzungspools finden Sie in der für eine der Spanner-Clientbibliotheken wie den Go-Clientbibliothek oder Java-Clientbibliothek
Sitzungen sollen langlebig sein. Datenbankvorgang muss der Client die Sitzung zur Wiederverwendung an den Pool zurückgeben.
Übersicht über gRPC-Kanäle
gRPC-Kanäle werden vom Spanner-Client für die Kommunikation verwendet. Ein gRPC -Kanal entspricht in etwa einer TCP-Verbindung. Ein gRPC-Kanal kann bis zu 100 gleichzeitige Anfragen verarbeiten. Das bedeutet, dass eine Anwendung mindestens so viele gRPC-Kanäle wie die Anzahl der gleichzeitigen Anfragen, die die Anwendung ausführen, geteilt durch 100.
Der Spanner-Client erstellt einen Pool von gRPC-Kanälen, wenn Sie und erstellen.
Best Practices für die Verwendung von Google-Clientbibliotheken
Im Folgenden werden Best Practices für die Verwendung des Google-Clients Bibliotheken für Spanner.
Anzahl der Sitzungen und gRPC-Kanäle in den Pools konfigurieren
Die Clientbibliotheken haben eine Standardanzahl von Sitzungen im Sitzungspool und eine Standardanzahl von gRPC-Kanälen im Kanalpool. Beide Standardeinstellungen sind ausreichend in den meisten Fällen. Im Folgenden finden Sie die Standardmindest- und -maximalanzahl von Sitzungen sowie die Standardanzahl von gRPC-Kanälen für jede Programmiersprache.
C++
MinSessions: 100
MaxSessions: 400
NumChannels: 4
C#
MinSessions: 100
MaxSessions: 400
NumChannels: 4
Go
MinSessions: 100
MaxSessions: 400
NumChannels: 4
Java
MinSessions: 100
MaxSessions: 400
NumChannels: 4
Node.js
Der Node.js-Client unterstützt nicht mehrere gRPC-Kanäle. Daher ist es wird empfohlen, mehrere Clients zu erstellen, anstatt die Größe der mehr als 100 Sitzungen für einen einzelnen Client.
MinSessions: 25
MaxSessions: 100
PHP
Der PHP-Client unterstützt keine konfigurierbare Anzahl von gRPC-Kanälen.
MinSessions: 1
MaxSessions: 500
Python
Python unterstützt vier verschiedene Sitzungspooltypen. mit dem Sie Sitzungen verwalten können.
Ruby
Der Ruby-Client unterstützt nicht mehrere gRPC-Kanäle. Daher ist es wird empfohlen, mehrere Clients zu erstellen, anstatt die Größe der mehr als 100 Sitzungen für einen einzelnen Client.
MinSessions: 10
MaxSessions: 100
Die Anzahl der Sitzungen, die Ihre Anwendung verwendet, entspricht der Anzahl der gleichzeitige Transaktionen, die Ihre Anwendung ausführt. Sie sollten die Standardeinstellungen des Sitzungspools nur dann, wenn Sie eine einzelne Anwendungsinstanz erwarten mehr gleichzeitige Transaktionen ausführen, als der Standardsitzungspool verarbeiten kann.
Für Anwendungen mit hoher Nebenläufigkeit wird Folgendes empfohlen:
- Setzen Sie
MinSessions
auf die erwartete Anzahl gleichzeitiger Transaktionen, die ein einzelnen Client auszuführen. - Setzen Sie
MaxSessions
auf die maximale Anzahl gleichzeitiger Transaktionen, die ein ausführen kann. - Legen Sie
MinSessions=MaxSessions
fest, wenn sich die erwartete Nebenläufigkeit nicht ändert viel Zeit vergeht. Dadurch wird verhindert, dass der Sitzungspool das Hoch- oder Herunterskalieren. Das Hoch- oder Herunterskalieren des Sitzungspools verbraucht außerdem Ressourcen. - Setzen Sie
NumChannels
aufMaxSessions / 100
. Ein gRPC-Kanal kann bis zu 100 Anfragen gleichzeitig. Erhöhen Sie diesen Wert, wenn Sie einen hohen Ausschlag bemerken. Latenz (P95/P99-Latenz), da dies ein Hinweis auf gRPC Kanalüberlastung.
Wenn Sie die Anzahl der aktiven Sitzungen erhöhen, werden zusätzliche Ressourcen auf der Spanner-Datenbankdienst und in der Clientbibliothek. Das Erhöhen der die über den tatsächlichen Bedarf der Anwendung hinausgeht, könnte die Zahl der Sitzungen Leistung Ihres Systems.
Sitzungspool erhöhen, anstatt die Anzahl der Clients zu erhöhen
Die Größe des Sitzungspools für eine Anwendung bestimmt, wie viele gleichzeitige Transaktionen, die eine einzelne Anwendungsinstanz ausführen kann. Die Einheit erhöhen Poolgröße über die maximale Nebenläufigkeit hinaus, die eine einzelne Anwendungsinstanz Alias wird nicht empfohlen. Wenn die Anwendung eine Reihe von Anfragen empfängt der die Anzahl der Sitzungen im Pool übersteigt, werden die Anfragen in die Warteschlange gestellt. während eine Sitzung verfügbar ist.
Folgende Ressourcen werden von der Clientbibliothek verbraucht:
- Jeder gRPC-Kanal verwendet eine TCP-Verbindung.
- Für jeden gRPC-Aufruf ist ein Thread erforderlich. Die maximale Anzahl von die von der Clientbibliothek verwendet wird, entspricht der maximalen Anzahl gleichzeitig auszuführende Abfragen. Diese Threads werden zusätzlich zu allen Threads ausgeführt, die die Anwendung für ihre eigene Geschäftslogik verwendet.
Größe des Sitzungspools über die maximale Anzahl von Threads hinaus erhöhen die eine einzelne Anwendungsinstanz verarbeiten kann, wird nicht empfohlen. Stattdessen Anzahl der Anwendungsinstanzen erhöhen.
Anteil der Schreibsitzungen verwalten
Bei einigen Clientbibliotheken reserviert Spanner einen Teil der Sitzungen für Lese-Schreib-Transaktionen. Dies wird als Anteil der Schreibsitzungen bezeichnet. Wenn Ihre App
alle Lesesitzungen verbraucht sind, dann verwendet Spanner
auch für schreibgeschützte Transaktionen. Für Lese-/Schreibvorgänge ist spanner.databases.beginOrRollbackReadWriteTransaction
erforderlich. Wenn sich der Nutzer im
spanner.databaseReader
IAM-Rolle haben, schlägt der Aufruf fehl.
und Spanner gibt folgende Fehlermeldung zurück:
generic::permission_denied: Resource %resource% is missing IAM permission:
spanner.databases.beginOrRollbackReadWriteTransaction
Bei Clientbibliotheken, die einen Anteil an Schreibsitzungen haben, können Sie diesen festlegen.
C++
Alle C ++-Sitzungen sind identisch. Es gibt weder schreibgeschützte noch nicht schreibgeschützte Sitzungen.
C#
Der standardmäßige Anteil an Schreibsitzungen bei C# beträgt 0,2. Sie können die
Bruch mit dem Feld "WriteSessionsFraction" von
SessionPoolOptions
Go
Alle Go-Sitzungen sind gleich. Es gibt weder schreibgeschützte noch nicht schreibgeschützte Sitzungen.
Java
Alle Java-Sitzungen sind gleich. Es gibt weder schreibgeschützte noch nicht schreibgeschützte Sitzungen.
Node.js
Alle Node.js-Sitzungen sind gleich. Es gibt weder schreibgeschützte noch nicht schreibgeschützte Sitzungen.
PHP
Alle PHP-Sitzungen sind gleich. Es gibt keine schreibgeschützten bzw. nicht schreibgeschützten Sitzungen.
Python
Python unterstützt vier verschiedene Sitzungspooltypen, die Sie zum Verwalten von schreibgeschützten und nicht schreibgeschützten Sitzungen verwenden können.
Ruby
Der Standardanteil der Schreibsitzungen bei Ruby ist 0,3. Sie können ihn mit der client initialize-Methode ändern.
Best Practices beim Erstellen einer Clientbibliothek oder bei Verwendung von REST/RPC
Im Folgenden werden Best Practices für die Implementierung von Sitzungen bei einem Kunden beschrieben. Bibliothek für Spanner oder zur Verwendung von Sitzungen mit der REST oder RPC
Diese Best Practices gelten nur, wenn Sie eine Clientbibliothek entwickeln oder wenn Sie REST/RPC-APIs verwenden. Wenn Sie eine der Google-Clientbibliotheken für Spanner verwenden, lesen Sie den Abschnitt Best Practices für die Verwendung von Google-Clientbibliotheken.
Sitzungspool erstellen und Größe anpassen
Legen Sie zum Bestimmen einer optimalen Größe des Sitzungspools für einen Clientprozess den Parameter die Untergrenze für die Anzahl der erwarteten gleichzeitigen Transaktionen und legen Sie den oberen an eine anfängliche Testnummer wie 100 gebunden ist. Wenn die obere Grenze nicht ausreicht, setzen Sie sie herauf. Wenn Sie die Anzahl der aktiven Sitzungen erhöhen, werden zusätzliche Ressourcen verwendet Im Spanner-Datenbankdienst, sodass nicht verwendete Sitzungen nicht bereinigt werden können die Leistung beeinträchtigen kann. Für Nutzer, die mit der RPC API arbeiten, empfehlen wir, nicht mehr als 100 Sitzungen pro gRPC-Kanal zu haben.
Gelöschte Sitzungen
Es gibt drei Möglichkeiten, eine Sitzung zu löschen:
- Ein Client kann eine Sitzung löschen.
- Der Spanner-Datenbankdienst kann eine Sitzung löschen, wenn die Sitzung länger als eine Stunde inaktiv.
- Der Spanner-Datenbankdienst kann eine Sitzung löschen, wenn die Sitzung älter als 28 Tage sind.
Beim Versuch, eine gelöschte Sitzung zu verwenden, wird NOT_FOUND
zurückgegeben. Wenn Sie auf eine
Erstellen und verwenden Sie eine neue Sitzung, fügen Sie die neue Sitzung dem Pool hinzu und
um die gelöschte Sitzung aus dem Pool zu entfernen.
Inaktive Sitzung offen halten
Der Spanner-Datenbankdienst behält sich das Recht vor, eine nicht verwendete
Sitzung. Wenn Sie eine inaktive Sitzung unbedingt offen halten müssen, wenn z. B. eine signifikante Erhöhung der Datenbanknutzung in naher Zukunft erwartet wird, können Sie verhindern, dass die Sitzung gelöscht wird. Führen Sie einen kostengünstigen Vorgang wie das Ausführen der SQL-Abfrage SELECT 1
durch, um die Sitzung aktiv zu halten. Wenn Sie eine
inaktive Sitzung, die nicht zur kurzfristigen Nutzung benötigt wird, lassen Sie Spanner
und erstellen Sie bei Bedarf
eine neue Sitzung.
Ein Szenario, in dem Sitzungen offen gehalten werden, ist der Umgang mit regulärer Spitzennachfrage der Datenbank. Wenn eine starke Datenbanknutzung täglich von 9:00 Uhr bis 18:00 Uhr stattfindet, sollten Sie während dieser Zeit einige inaktive Sitzungen offen halten, da diese wahrscheinlich zu Spitzenzeiten erforderlich sind. Nach 18:00 Uhr können Sie Spanner löschen lassen inaktive Sitzungen. Erstellen Sie jeden Tag vor 9:00 Uhr einige neue Sitzungen, damit sie für die erwartete Nachfrage bereitstehen.
Ein anderes Szenario wäre, wenn Sie eine Anwendung haben, die Spanner verwendet, den Verbindungs-Overhead dabei vermeiden. Sie können eine Gruppe von Sitzungen offen halten, um den Verbindungsaufwand zu vermeiden.
Sitzungsdetails vom Clientbibliotheksbenutzer ausblenden
Wenn Sie eine Clientbibliothek erstellen, geben Sie dem Client keine Sitzungen Nutzer der Bibliothek. Stellen Sie die Möglichkeit für den Client bereit, Datenbankaufrufe ohne den Aufwand der Erstellung und Verwaltung von Sitzungen durchzuführen. Ein Beispiel für eine Clientbibliothek, in der die Sitzungsdetails für den Nutzer der Clientbibliothek ausgeblendet sind, finden Sie in der Spanner-Clientbibliothek für Java.
Fehler bei Schreibtransaktionen bearbeiten, die nicht idempotent sind
Schreibtransaktionen ohne Wiederholungsschutz können Mutationen mehr als einmal anwenden.
Wenn eine Mutation nicht idempotent ist, kann eine Mutation, die mehrmals angewendet wird, zu einem Fehler führen. Beispiel: Eine Einfügung (Insert) kann den Fehler ALREADY_EXISTS
verursachen, obwohl die Zeile vor dem Schreibversuch nicht vorhanden war. Dies kann passieren, wenn der Back-End-Server die Mutation festgeschrieben hat, den Erfolg jedoch nicht dem Client mitteilen konnte. In diesem Fall könnte die Mutation wiederholt werden, was aber zu dem Fehler ALREADY_EXISTS
führen würde.
Im Folgenden sind einige Möglichkeiten aufgelistet, wie Sie mit diesem Szenario bei der Bereitstellung Ihrer eigenen Clientbibliothek oder bei der Verwendung der REST API verfahren können:
- Strukturieren Sie Ihre Schreibvorgänge so, dass sie idempotent sind.
- Verwenden Sie Schreibvorgänge mit Wiederholungsschutz.
- Implementieren Sie eine Methode mit der Logik "upsert", d. h. einfügen, wenn neu, oder aktualisieren, wenn bereits vorhanden.
- Bearbeiten Sie den Fehler für den Client.
Für stabile Verbindungen sorgen
Für eine optimale Leistung sollte die Verbindung, die Sie zum Hosten einer Sitzung verwenden, stabil sein. Wenn sich die Verbindung, die eine Sitzung hostet, ändert, die aktive Transaktion in der Sitzung abbrechen und zusätzliche Belastung Ihrer Datenbank, während die Sitzungsmetadaten aktualisiert werden. Wenn sich einige Verbindungen gelegentlich ändern, ist das kein Problem, aber Sie sollten Situationen vermeiden, in denen sich eine große Anzahl von Verbindungen gleichzeitig ändert. Bei Verwendung eines Proxys zwischen dem Client und Spanner sollten Sie die Verbindungsstabilität aufrechterhalten für jede Sitzung.
Aktive Sitzungen überwachen
Mit dem Befehl ListSessions
können Sie aktive Sitzungen in Ihrer Datenbank überwachen
über die Befehlszeile, mit der REST API oder mit der RPC API.
ListSessions
die aktiven Sitzungen für eine bestimmte Datenbank. Dies ist sinnvoll, wenn Sie die Ursache für ein Sitzungsleck finden möchten. Ein Sitzungsleck ist ein Vorfall, bei dem Sitzungen erstellt, aber nicht zur Wiederverwendung an einen Sitzungspool zurückgegeben werden.
Mit ListSessions
können Sie Metadaten zu Ihren aktiven Sitzungen ansehen, darunter:
wann eine Sitzung erstellt und wann eine Sitzung zuletzt verwendet wurde. Die Analyse dieser Daten wird Ihnen bei der Fehlersuche die richtige Richtung weisen. Wenn die meisten
aktiven Sitzungen haben in letzter Zeit keinen approximate_last_use_time
, dies könnte
deuten darauf hin, dass Sitzungen von Ihrer Anwendung nicht ordnungsgemäß wiederverwendet werden. Weitere Informationen finden Sie in der
Weitere Informationen zum Feld approximate_last_use_time
finden Sie in der RPC API-Referenz.
Weitere Informationen finden Sie in der REST API-Referenz, der RPC API-Referenz oder der gcloud-Referenz.
Referenz zum Befehlszeilentool finden Sie weitere Informationen zur Verwendung von ListSessions
.
Automatische Bereinigung von Sitzungslecks
Wenn Sie alle Sitzungen in Ihrem Sitzungspool verwenden, wartet, bis eine Sitzung an den Pool zurückgegeben wird. Wann Sitzungen erstellt werden aber nicht zur Wiederverwendung an den Sitzungspool zurückgegeben wird, spricht man von einem Sitzungsleck. Bei einem Sitzungsleck bleiben Transaktionen, die auf eine offene Sitzung warten, unbegrenzt hängen und blockieren die Anwendung. Sitzungslecks werden oft durch problematische Transaktionen verursacht, die extrem lange ausgeführt werden und nicht verbindlich sind.
Sie können Ihren Sitzungspool so einrichten, dass diese Probleme automatisch behoben werden. inaktive Transaktionen. Wenn Sie für Ihre Clientbibliothek die automatische inaktiven Übergang beheben können, werden problematische Transaktionen identifiziert, kann ein Sitzungsleck verursachen, sie aus dem Sitzungspool entfernen und ersetzt sie durch eine neue Sitzung.
Logging kann auch dabei helfen, diese problematischen Transaktionen zu identifizieren. Wenn Logging aktiviert ist, werden Warnmeldungen standardmäßig freigegeben, wenn mehr als 95% Ihres Sitzungspools werden verwendet. Wenn Ihre Sitzungsnutzung mehr als 95 % beträgt, erhöhen Sie entweder die maximal zulässige Anzahl an Sitzungen oder es gibt ein Sitzungsleck. Warnlogs enthalten Stacks Transaktionen, die länger als erwartet laufen und die Ursache einer hohen Auslastung des Sitzungspools. Warnlogs werden je nach Konfiguration des Logexporteurs gesendet.
Clientbibliothek aktivieren, um inaktive Transaktionen automatisch zu beheben
Sie können die Clientbibliothek für das Senden von Warnprotokollen aktivieren oder inaktive Transaktionen auflösen oder die Clientbibliothek so aktivieren, dass nur Warnungen angezeigt werden Logs.
Java
Verwenden Sie setWarnAndCloseIfInactiveTransactions
, um Warnlogs zu erhalten und inaktive Transaktionen zu entfernen.
final SessionPoolOptions sessionPoolOptions = SessionPoolOptions.newBuilder().setWarnAndCloseIfInactiveTransactions().build()
final Spanner spanner =
SpannerOptions.newBuilder()
.setSessionPoolOption(sessionPoolOptions)
.build()
.getService();
final DatabaseClient client = spanner.getDatabaseClient(databaseId);
Wenn Sie nur Warnlogs erhalten möchten, verwenden Sie
setWarnIfInactiveTransactions
final SessionPoolOptions sessionPoolOptions = SessionPoolOptions.newBuilder().setWarnIfInactiveTransactions().build()
final Spanner spanner =
SpannerOptions.newBuilder()
.setSessionPoolOption(sessionPoolOptions)
.build()
.getService();
final DatabaseClient client = spanner.getDatabaseClient(databaseId);
Go
Um Warnlogs zu erhalten und inaktive Transaktionen zu entfernen, verwenden Sie
SessionPoolConfig
mit InactiveTransactionRemovalOptions
.
client, err := spanner.NewClientWithConfig(
ctx, database, spanner.ClientConfig{SessionPoolConfig: spanner.SessionPoolConfig{
InactiveTransactionRemovalOptions: spanner.InactiveTransactionRemovalOptions{
ActionOnInactiveTransaction: spanner.WarnAndClose,
}
}},
)
if err != nil {
return err
}
defer client.Close()
Wenn Sie nur Warnlogs erhalten möchten, verwenden Sie customLogger
.
customLogger := log.New(os.Stdout, "spanner-client: ", log.Lshortfile)
// Create a logger instance using the golang log package
cfg := spanner.ClientConfig{
Logger: customLogger,
}
client, err := spanner.NewClientWithConfig(ctx, db, cfg)
Multiplex-Sitzungen
Mit Multiplex-Sitzungen können Sie eine unbegrenzte Anzahl gleichzeitiger Anfragen erstellen auf einmal. Multiplex-Sitzungen bieten folgende Vorteile:
- Geringere Anforderungen an die Backend-Ressourcen. So werden beispielsweise Sitzungswartungsaktivitäten vermieden, die mit der Wartung der Sitzungsinhaberschaft und der Garbage Collection verbunden sind.
- Langlebige Sitzung, die bei Inaktivität keine Keep-Alive-Anfragen erfordert.
- Übliche Clientbibliotheken können eine multiplexierte Sitzung für jeden Client verwenden. Die Die Anzahl der regulären Sitzungen ist bei Kunden, die Multiplex nutzen, geringer Sitzungen für einige Vorgänge im Vergleich zu Clients, die nur reguläre Sitzungen.
- Es ist keine Affinität zu nur einem gRPC-Kanal erforderlich. Clients können Anfragen senden mehrere Kanäle für dieselbe Multiplex-Sitzung nutzen.
Bei Multiplex-Sitzungen wird Folgendes unterstützt:
- Die Java- und Go-Clientbibliotheken".
- die von den Java- und Go-Clientbibliotheken abhängig sind, wie PGAdapter, JDBC, Hibernate, database/sql-Treiber und GORM.
- Spanner APIs für schreibgeschützte Transaktionen
Sie verwenden OpenTelemetry-Messwerte, um zu sehen, wie der Traffic aufgeteilt wird.
dem vorhandenen Sitzungspool
und der Multiplex-Sitzung. OpenTelemetry hat
einen Messwertfilter, is_multiplexed
, der Multiplex-Sitzungen anzeigt, wenn auf
true
.
Multiplex-Sitzungen sind für JDBC und den PG-Adapter standardmäßig aktiviert. Für Java und Go ist sie standardmäßig deaktiviert. Sie verwenden die Java-Clientbibliothek oder die Go-Clientbibliothek, um mehrere Sitzungen zu ermöglichen. Informationen zum Aktivieren einer Multiplex-Sitzung mit Java oder Go finden Sie unter Aktivieren Sie Multiplex-Sitzungen.
Multiplex-Sitzungen aktivieren
Um Multiplex-Sitzungen mit dem Java- oder Go-Client zu aktivieren, legen Sie
GOOGLE_CLOUD_SPANNER_MULTIPLEXED_SESSIONS
in true
.
export GOOGLE_CLOUD_SPANNER_MULTIPLEXED_SESSIONS=TRUE
Zugriffe für reguläre und Multiplex-Sitzungen ansehen
OpenTelemetry bietet den Filter is_multiplexed
, mit dem der Traffic für mehrere Sitzungen angezeigt wird. Wenn Sie diesen Filter auf true to view multiplexed sessions
and
false` festlegen, werden nur reguläre Sitzungen angezeigt.
- Richten Sie Opentelemetry für Spanner mithilfe der Verfahren in der Spanner OpenTelemetrie Hinweis .
Rufen Sie den Metrics Explorer auf.
Filtern Sie im Drop-down-Menü Messwert nach
generic
.Klicken Sie auf Allgemeine Aufgabe und gehen Sie zu Spanner. Spanner/num_acquired_sessions:
Wählen Sie im Feld Filter eine der folgenden Optionen aus:
a.
is_multiplexed = false
, um reguläre Sessions zu sehen. b.is_multiplexed = true
, um Multiplex-Sitzungen anzusehen.Die folgende Abbildung zeigt die Option Filter mit Multiplex-Sitzungen. ausgewählt.
Weitere Informationen zur Verwendung von OpenTelemetry mit Spanner finden Sie unter Mit OpenTelemetry die Spanner-Beobachtbarkeit demokratisieren und Latenz in einer Spanner-Komponente mit OpenTelemetry untersuchen