Analyse des performances d'exécution IRIS ^PERFMON à l'aide du SDK natif Java
Documentation technique — Système de surveillance Quarkus IRIS
1. Le but et la portée
Ce module assure l'intégration entre les applications Java basées sur Quarkus et les capacités natives de surveillance des performances d'InterSystems IRIS.
Il permet aux développeurs d'annoter les méthodes avec @PerfmonReport, ce qui déclenche automatiquement les routines ^PERFMON d'IRIS lors de l'exécution des méthodes, et génère des rapports de performances sans intervention manuelle.
2. Composants du système
2.1 Annotation: @PerfmonReport
- Définie comme un CDI InterceptorBinding.
- Peut être appliquée à des méthodes ou à des classes.
- Indique au framework d'encapsuler l'exécution de la méthode avec la logique de surveillance IRIS.
2.2 Intercepteur: PerfmonReportInterceptor
Interception des appels vers les méthodes annotées.
Flux d'exécution:
- Enregistrement de l'événement de début (
LOG.infof("INIT: …")) - Appel à
monitorSystem.startPerfmon() - Poursuite avec
context.proceed() - Dans le bloc
finally:- Appel à
monitorSystem.generateReportPerfmon(...) - Appel à
monitorSystem.stopPerfmon() - Enregistrement de l'événement de fin avec le temps d'exécution
- Appel à
- Enregistrement de l'événement de début (
Ansi, la surveillance est toujours terminée, même si une exception est levée.
2.3 Bean DAO: MonitorSystem
Un bean CDI annoté avec
@ApplicationScoped.Contient une seule instance
d'IRISinitialisée au démarrage.Configuration injectée via
@ConfigProperty(URL JDBC, utilisateur, mot de passe).Utilization de
DriverManager.getConnection(...)pour obtenir un lienIRISConnectionbrut.Contient les méthodes suivantes:
startPerfmon()generateReportPerfmon(String reportName)stopPerfmon()
Chaque méthode appelle les méthodes ObjectScript appropriées dans
iris.src.dc.AdapterPerfmonProcviairis.classMethodVoid(...).
2.4 Adaptateur ObjectScript: iris.src.dc.AdapterPerfmonProc
Définition des routines qui encapsulent la logique
^PERFMONlogic:Class iris.src.dc.AdapterPerfmonProc Extends %RegisteredObject { ClassMethod start() As %Status { Set namespace = $NAMESPACE zn "%SYS" set status = $$Stop^PERFMON() set status = $$Start^PERFMON() zn namespace return status } ClassMethod generateReport(nameReport As %String = "report.txt") As %Status { Set namespace = $NAMESPACE zn "%SYS" Set tempDirectory = ##class(%SYS.System).TempDirectory() set status = $$Report^PERFMON("R","R","P", tempDirectory_"/"_nameReport) zn namespace return status } ClassMethod stop() As %Status { Set namespace = $NAMESPACE zn "%SYS" Set status = $$Stop^PERFMON() zn namespace return status } }Il fonctionne dans l'espace de noms
%SYSpour accéder aux routines^PERFMONpuis revient à l'espace de noms d'origine.
3. Flux d'exécution
Une requête entre dans l'application Quarkus.
L'intercepteur CDI détecte l'annotation
@PerfmonReportet intercepte l'appel de méthode.monitorSystem.startPerfmon()est invoqué, ce qui déclenche la surveillance^PERFMONd'IRIS.La méthode métier s'exécute de manière normale (accès aux données, transformations, logique, etc.).
Une fois que la méthode renvoie ou génère une exception, l'intercepteur s'assure des éléments suivants:
monitorSystem.generateReportPerfmon(...)est appelé pour créer un rapport de performances.txt.monitorSystem.stopPerfmon()est exécuté pour arrêter la session de surveillance.- Le temps d'exécution total côté Java est consigné à l'aide de
Logger.infof(...).
Le fichier de rapport généré est stocké dans le répertoire temporaire IRIS, typiquement le répertoire:
/usr/irissys/mgr/Temp/- Le fichier est nommé selon le modèle suivant:
<ClassName><MethodName><timestamp>.txt
- Le fichier est nommé selon le modèle suivant:
4. Défis techniques et leurs solutions
| Défis | Solution |
|---|---|
ClassCastException lors de l'utilisation de connexions JDBC mises en pool | Utilisation de DriverManager.getConnection(...) pour obtenir une connexion native IRISConnection au lieu d'une connexion mise en pool ConnectionWrapper. |
| Surcharge due à l'ouverture répétée de connexions | Maintien d'une instance IRIS unique dans un bean @ApplicationScoped, initialisée via @PostConstruct. |
Assurance du fait que ^PERFMON est toujours arrêté, même en cas d'exception | Utilisationu bloc d try-finally dans l'intercepteur pour appeler stopPerfmon() et generateReportPerfmon(). |
| Portabilité de la configuration | Injection des paramètres de connexion (jdbc.url, username, password) avec @ConfigProperty et application.properties. |
| Gestion des sessions de surveillance simultanées | Évitez d'annoter les points de terminaison à haute simultanéité. Les versions futures pourraient implémenter l'isolation au niveau de la session. |
5. Cas d'utilisation et avantages
- Possibilité de visualisation en temps réel de l'activité d'exécution IRIS à partir du code Java.
- Simplification de l'analyse des performances et de l'optimisation des requêtes pour les développeurs.
- Utile pour le benchmarking, le profilage et les tests de régression du système.
- Peut-être utilisé comme suivi d'audit des performances léger pour les opérations critiques.
6. Exemple pratique d'utilisation
Le code source complet et la configuration de déploiement sont disponibles aux adresses suivantes:
- Open Exchange: https://openexchange.intersystems.com/package/quarkus-iris-monitor-system
- Référentiel GitHub: https://github.com/Davi-Massaru/quarkus-iris-monitor-system
6.1 Aperçu
L'application exécute un serveur Quarkus connecté à une instance InterSystems IRIS configurée avec l'espace de noms FHIRSERVER.
La couche ORM est implémentée à l'aide de Hibernate ORM avec PanacheRepository, ce qui permet un mappage direct entre les entités Java et les classes de base de données IRIS.
Au démarrage de l'application (via docker-compose up), les éléments suivants s'affichent:
- Le conteneur IRIS, qui héberge le modèle de données FHIR et les routines ObjectScript (y compris
AdapterPerfmonProc); - Le conteneur Quarkus, qui expose les points de terminaison REST et se connecte à IRIS via le pilote JDBC natif.
6.2 Point de terminaison REST
Une ressource REST expose un point de terminaison simple pour récupérer les informations du patient:
@Path("/patient")
public class PatientResource {
@Inject
PatientService patientService;
@GET
@Path("/info")
@Produces(MediaType.APPLICATION_JSON)
public PatientInfoDTO searchPatientInfo(@QueryParam("key") String key) {
return patientService.patientGetInfo(key);
}
}
Ce point de terminaison accepte un paramètre de requête (clé) qui identifie la ressource patient dans le référentiel de données FHIR.
### 6.3 Couche de service avec @PerfmonReport
La classe PatientService contient la logique métier permettant de récupérer et de composer les informations sur les patients. Cette classe est annotée avec @PerfmonReport, ce qui signifie que chaque requête adressée à /patient/info déclenche la surveillance des performances IRIS:
@ApplicationScoped
public class PatientService {
@Inject
PatientRepository patientRepository;
@PerfmonReport
public PatientInfoDTO patientGetInfo(String patientKey) {
Optional<Patient> patientOpt = patientRepository.find("key", patientKey).firstResultOptional();
Patient patient = patientOpt.orElseThrow(() -> new IllegalArgumentException("Patient not found"));
PatientInfoDTO dto = new PatientInfoDTO();
dto.setKey(patient.key);
dto.setName(patient.name);
dto.setAddress(patient.address);
dto.setBirthDate(patient.birthDate != null ? patient.birthDate.toString() : null);
dto.setGender(patient.gender);
dto.setMedications(patientRepository.findMedicationTextByPatient(patientKey));
dto.setConditions(patientRepository.findConditionsByPatient(patientKey));
dto.setAllergies(patientRepository.findAllergyByPatient(patientKey));
return dto;
}
}
6.4 Flux d'exécution
Une requête est envoyée à l'adresse suivante: GET /patient/info?key=Patient/4
Quarkus achemine la requête vers PatientResource.searchPatientInfo().
L'intercepteur CDI détecte l'annotation @PerfmonReport dans PatientService.patientGetInfo().
Avant d'exécuter la logique de service:
L'intercepteur invoque
MonitorSystem.startPerfmon(), qui appelle la classe IRIS iris.src.dc.AdapterPerfmonProc.start().La méthode exécute la logique métier en interrogeant les données des patients à l'aide des mappages Hibernate
PanacheRepository.
Lorsque la méthode est terminée:
MonitorSystem.generateReportPerfmon()est appelé pour créer un rapport de performances.MonitorSystem.stopPerfmon()arrête le moniteur de performances IRIS.
Un rapport .txt est généré dans: usr/irissys/mgr/Temp/
Exemple de nom de fichier: PatientService_patientGetInfo_20251005_161906.txt
6.5 Résultat
Le rapport généré contient des statistiques détaillées sur l'exécution d'IRIS, par exemple:
Routine Activity by Routine
Started: 10/11/2025 05:07:30PM Collected: 10/11/2025 05:07:31PM
Routine Name RtnLines % Lines RtnLoads RtnFetch Line/Load Directory
----------------------------------- --------- --------- --------- --------- --------- ---------
Other 0.0 0.0 0.0 0.0 0
PERFMON 44.0 0.0 0.0 0.0 0 /usr/irissys/mgr/
%occLibrary 3415047.0 34.1 48278.0 0.0 70.7 /usr/irissys/mgr/irislib/
iris.src.dc.AdapterPerfmonProc.1 7.0 0.0 2.0 0.0 3.5 /usr/irissys/mgr/FHIRSERVER/
%occName 5079994.0 50.7 0.0 0.0 0 /usr/irissys/mgr/irislib/
%apiDDL2 1078497.0 10.8 63358.0 0.0 17.0 /usr/irissys/mgr/irislib/
%SQL.FeatureGetter.1 446710.0 4.5 66939.0 0.0 6.7 /usr/irissys/mgr/irislib/
%SYS.WorkQueueMgr 365.0 0.0 1.0 0.0 365.0 /usr/irissys/mgr/
%CSP.Daemon.1 16.0 0.0 1.0 0.0 16.0 /usr/irissys/mgr/irislib/
%SYS.TokenAuth.1 14.0 0.0 5.0 0.0 2.8 /usr/irissys/mgr/
%Library.PosixTime.1 2.0 0.0 0.0 0.0 0 /usr/irissys/mgr/irislib/
%SYS.sqlcq.uEXTg3QR7a7I7Osf9e8Bz... 52.0 0.0 1.0 0.0 52.0 /usr/irissys/mgr/
%SYS.SQLSRV 16.0 0.0 0.0 0.0 0 /usr/irissys/mgr/
%apiOBJ 756.0 0.0 0.0 0.0 0 /usr/irissys/mgr/irislib/
FT.Collector.1 0.0 0.0 0.0 0.0 0 /usr/irissys/mgr/
SYS.Monitor.FeatureTrackerSensor.1 0.0 0.0 0.0 0.0 0 /usr/irissys/mgr/
%SYS.Monitor.Control.1 0.0 0.0 0.0 0.0 0 /usr/irissys/mgr/
%SYS.DBSRV.1 252.0 0.0 4.0 0.0 63.0 /usr/irissys/mgr/
%sqlcq.FHIRSERVER.cls12.1 19.0 0.0 0.0 0.0 0 /usr/irissys/mgr/irislocaldata/
%sqlcq.FHIRSERVER.cls13.1 74.0 0.0 0.0 0.0 0 /usr/irissys/mgr/irislocaldata/
%sqlcq.FHIRSERVER.cls14.1 74.0 0.0 0.0 0.0 0 /usr/irissys/mgr/irislocaldata/
%sqlcq.FHIRSERVER.cls15.1 52.0 0.0 0.0 0.0 0 /usr/irissys/mgr/irislocaldata/
%SYS.System.1 1.0 0.0 0.0 0.0 0 /usr/irissys/mgr/
Ces données fournissent des visions précises des routines exécutées au sein d'IRIS pendant cet appel REST, notamment la compilation SQL, l'exécution et l'accès aux données FHIR.
Vision précise: Les routines
%sqlcq.FHIRSERVER.*capturent toutes les requêtes de cache SQL exécutées par Quarkus au sein de la méthode. La surveillance de ces routines permet aux développeurs d'analyser l'exécution des requêtes, de comprendre le comportement du code et d'identifier les goulots d'étranglement de performance potentiels. Ils constituent donc un outil puissant pour le développement et le débogage des opérations liées à FHIR.

6.6 Récapitulatif
Cet exemple explique comment un service Quarkus standard peut exploiter les outils de surveillance natifs IRIS de manière transparente à l'aide de l'annotation @PerfmonReport. Il combine:
Intercepteurs CDI (Quarkus)
Hibernate PanacheRepositories (ORM)
Routines ObjectScript natives IRIS (^PERFMON)
Il en résulte un mécanisme de profilage des performances entièrement automatisé et reproductible qui peut être appliqué à n'importe quelle méthode de service dans l'application.