#Health Connect

0 Abonnés · 44 Publications

InterSystems HealthShare Health Connect est un moteur d'intégration des soins de santé offrant une prise en charge des transactions à haut volume, une gestion des processus et une surveillance pour soutenir les applications critiques. Un moteur de données multi-modèles très performant est au cœur de Health Connect. Il traite parfaitement et à grande vitesse de multiples formes de données. Health Connect s'adapte facilement, qu'il s'agisse de servir de petites cliniques ou de gérer les volumes de transactions provenant des systèmes de prestation de soins de santé les plus importants et les plus complexes au monde. Les capacités incluent: - Interopérabilité par conception - Mise en miroir avec récupération rapide en cas de basculement - Contrôle de code source pour les schémas HL7 - Édition intuitive du schéma HL7 par glisser-déposer - Un modèle de sécurité flexible et adaptable et beaucoup d'autres choses

Article Sylvain Guilbaud · Oct 29, 2025 14m read

Aperçu

Cette interface Web est conçue pour faciliter la gestion des tables de recherche de données (Data Lookup Tables) via une page Web conviviale. Elle est particulièrement utile lorsque les valeurs de votre table de recherche sont volumineuses, dynamiques et changeantes. Les utilisateurs finaux peuvent gérer efficacement les données de la table de recherche en fonction de leurs besoins grâce à un accès contrôlé à cette interface Web (autorisations de lecture, d'écriture et de suppression limitées à cette page).

Les données gérées via cette interface peuvent être utilisées de manière transparente pour les règles HealthConnect ou les transformations de données, ce qui élimine le besoin d'une surveillance et d'une gestion manuelles constantes des tables de recherche et permet ainsi un gain de temps considérable.

Remarque:
Si la table de recherche de données classique ne répond pas à vos besoins en matière de mappage, vous pouvez créer une table personnalisée et adapter cette interface Web ainsi que sa classe de support avec un minimum de modifications. Un exemple de code de classe est disponible sur demande.

Conditions préalables

Avant d'utiliser l'interface Web, veillez à avoir créé une table de recherche de données vide dans HealthConnect:

  1. Accédez à Interoperability → Configure → Data Lookup Tables.
  2. Cliquez sur New pour ouvrir la fenêtre contextuelle "Create New Lookup Table" (Créer une nouvelle table de recherche).
  3. Saisissez le nom souhaité pour votre table de recherche et cliquez sur OK.
  4. Cliquez sur Save pour finaliser la création de la table.
  5. Vérifiez la création de la table de recherche en cliquant sur Open dans la même fenêtre. Votre nouvelle table devrait apparaître dans la liste.

Dans cette documentation, la table de recherche de données utilisée à titre d'exemple est intitulée:
"Exemple de table de recherche de données"

Mode d'emploi

Le processus de configuration est simple:

  1. Obtention du code:Téléchargez le code fourni à partir du référentiel GitHub ou copiez-le à partir du lien communautaire.
  2. Création d'une page CSP:Créez une nouvelle page CSP dans votre environnement HealthConnect et insérez tout le code du fichier DataLookupWebApp.
  3. Création d'une classe:Copiez et insérez le code de classe fourni dans la documentation ou dans le référentiel.

Configuration

Avant la compilation et l'exécution:

  1. Indiquez le nom de votre table de recherche de données sur la page Web en remplaçant l'espace réservé indiqués par le cadre rouge dans la capture d'écran ci-dessous par le nom réel de votre table de recherche.

  1. Vérifiez si le nom de la classe dans le code correspond au nom de votre classe personnalisée.

  1. Attribuez un nom à votre table de recherche dans la classe, comme indiqué par myDtName = 'votre table de recherche'. Consultez la capture d'écran ci-dessus.
  1. Compilez la classe et la page CSP pour finaliser la configuration.

Mise à l'essai de l'application

Ajout d'enregistrements

  • Saisissez la clé et la paire clé-valeur correspondante dans les champs du formulaire.
  • Cliquez sur Add Record pour insérer les données dans la table de recherche.

Capture d'écran 1: Ajout d'enregistrements (122 – Radiographie de la colonne vertébrale)

Mise à jour de l'enregistrement

  • Sélectionnez un enregistrement existant et modifiez la paire clé-valeur si nécessaire.

  • Cliquez sur Update pour enregistrer les modifications. Exemple : Modification de  122 "Radiographie de la colonne vertébrale" en "Radiographie abdominale".

Suppression de l'enregistrement

  • Sélectionnez un enregistrement à supprimer (144 – IRM)

  • Cliquez sur le bouton Delete pour supprimer l'enregistrement de la table de recherche. Exemple : Suppression de "144 - IRM".

Vérification de la table de recherche de données dans HealthConnect

Accédez à Interoperability → Configure → Data Lookup Tables à Open

Recherche de l'enregistrement

Code / Ressources

  • La version complète du code source est également disponible pour téléchargement et consultation sur GitHub.

https://github.com/pandeySR/Reusable-Web-Interface-for-Data-Lookup-Table

<!DOCTYPE html>
<!--
This web application is designed and developed to insert, update, and delete records (key–value pairs) in the Data Lookup Table through a web interface.
Author: Sanjib Pandey
Date: 16/10/2025
-->
<html lang="en">
<head>
  <meta charset="UTF-8" />
  <meta name="viewport" content="width=device-width, initial-scale=1" />
  <meta name="author" content="Sanjib Pandey" />
  <title>YOUR TITLE : Data Lookup Table - Data Record </title>
  <!-- Bootstrap CSS CDN, jQuery, Datatable -->
  <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet" />
  <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css">
  <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.bundle.min.js"></script> 
  <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.4.1/css/bootstrap.min.css"> 
  <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.4.1/js/bootstrap.min.js"></script>
  <link rel="stylesheet" href="https://cdn.datatables.net/1.13.5/css/dataTables.bootstrap5.min.css" />
  <script src="https://code.jquery.com/jquery-3.7.0.min.js"></script>
  <script src="https://cdn.datatables.net/1.13.5/js/jquery.dataTables.min.js"></script>
  <script src="https://cdn.datatables.net/1.13.5/js/dataTables.bootstrap5.min.js"></script>
  <style>
    h2 {
      text-align: center;
      color: #fff;
      background-color: #00b300;
      padding: 15px 10px;
      border-radius: 5px;
      margin-bottom: 5px;
      margin-top: 0px;
    }
    html, body {
      height: 100%;
      margin: 0;
    }
    body {
      display: flex;
      min-height: 100vh;
      background-color: #f8f9fa;
      padding-top: 10px;
      flex-direction: column;
      align-items: center;
    }
    .container {
      max-width: 1100px;
      background: white;
      padding: 20px;
      border-radius: 8px;
      box-shadow: 0015px rgba(0,0,0,0.2);
      margin-top: 5px;
      width: 100%;
    }
 
    .table-scroll-vertical
    {
 	 max-height: 450px;
 	 overflow-y: auto;
  	 border: 1px solid #dee2e6;
  	 border-radius: 5px;
  	 margin-top: 0; 
	}
	
	.small-italic 
	{
  	 font-size: 0.85em; 
  	 font-style: italic; 
  	 color: #C0C0C0; 
	}
	
	.dataTables_filter label 
	{
  	 font-weight: bold;
  	 color: #333;
  	 color: red;
  	 float: left;
	}

	.dataTables_filter input
	{
  	 border: 2px solid #993399;
  	 border-radius: 5px;
  	 padding: 6px 10px;
  	 outline: none;
   	 width: 250px;
	}
	
	.page-footer
	{
  	 text-align: center;
  	 padding: 10px 5px;
  	 font-size: 0.95rem;
 	 color: #809fff;
 	 background-color: #f8f9fa;
  	 border-top: 1px solid #993399;
  	 margin-top: 5px;
	}
  </style>
  <style>
  @keyframes blink
  {
    50%
    {
      opacity: 0;
    }
  }
</style>
</head>
<body>
<div class="container">
<div style="overflow: hidden;">
  <div style="float: left; font-size: smaller; font-weight: bold;color:#b3ffff;animation: blink 1s infinite;">
    Environment : DEV
  </div>
  <h2 style="text-align: center; margin: 0;">
    Your Organization Name or Company Name<br>
    <span style="font-size: smaller; color: yellow;text-align: center;">Data Lookup Table</span>
  </h2>
</div> 
 <form id="recordForm"class="form-horizontal" action="" method="POST">
 	<div class="form-group">
        <!--for any other information if you want> -->
       </div>
      <div class="row mb-3">
        <label for="key"class="col-sm-3 col-form-label fw-bold">Key :</label>
        <div class="col-sm-9">
          <input type="text"class="form-control" id="key" name="key" placeholder="Enter the Key data !" required />
        </div>
      </div>
      <div class="row mb-3">
        <label for="kvalue"class="col-sm-3 col-form-label fw-bold">Key Pair Value</label>
        <div class="col-sm-9">
          <input type="text"class="form-control" id="kvalue" name="kvalue" placeholder="Enter the key paris value !" required />
        </div>
      </div>
	<div class="d-flex justify-content-between align-items-center mt-4 flex-wrap">
		<p class="mb-2 mb-md-0 text-primary">
    		<i>Click the edit icon to modify a record, then press "Update" to save. To delete, press the "Delete" button.</i> 
  		</p> 
  		
	<div class="d-flex flex-wrap justify-content-end">
		<button class="btn btn-success me-2" id="Add" type="submit" name="Add">
			<i class="fa fa-plus me-1" style="font-size:18px; color:white;"></i> Add Record
		</button>
	
		<button class="btn btn-primary me-2" type="submit" name="Update">
			<i class="fa fa-edit me-1" style="font-size:18px;"></i> Update
    	</button>

		<button class="btn btn-danger me-2" id="Delete" type="submit" name="Delete">
			<i class="fa fa-remove me-1" style="font-size:18px;"></i> Delete
		</button>
		
		<button class="btn btn-info" id="Cancel" type="submit" name="Cancel">
  			<i class="glyphicon glyphicon-refresh" style="font-size:18px;"></i> Cancel
		</button>
  	   </div> 
    </div>
    <div></div>
	</form>
<script language=SQL name="query">
  SELECT KeyName, DataValue FROM Ens_Util.LookupTable WHERE TableName='Data Lookup Table Example'
</script>

<script language=cache runat=server>
 S myKeyName=$Get(%request.Data("key",1))
 S myKeyValue=$Get(%request.Data("kvalue",1))
 S myDtName="Data Lookup Table Example"
 I ($Data(%request.Data("Add",1)))
 {
	I ((myKeyName '="") && (myKeyValue '="") && (myDtName '=""))
	{	
		I ##Class(SANJIB.DataLookup.Methods).ChkLookupKeyValue(myDtName,myKeyName)="F"
		{
			D##Class(SANJIB.DataLookup.Methods).InsertLookUpValues(myDtName,myKeyName,myKeyValue)
		}
		else
		{	W"The key has already been inserted.."&html<<divstyle=color:red>#(myKeyName)#</div>> }
		
	}
 }
 I ($Data(%request.Data("Update",1)))
 {
	I ((myKeyName '="") && (myKeyValue '="") && (myDtName '=""))
	{
		D##Class(SANJIB.DataLookup.Methods).UpdateLookUpValues(myDtName,myKeyName,myKeyValue)
	}
 }
 I ($Data(%request.Data("Delete",1)))
 {
	 I ((myKeyName '="") && (myKeyValue '="") && (myDtName '=""))
	 {
		D##Class(SANJIB.DataLookup.Methods).DeleteLookUpValues(myDtName,myKeyName)		
	 }
 }	
</script>
 <div class="table-responsive table-scroll-vertical"> 
    <table class="table table-bordered border-primary table table-hover mt-2" id="dataTable" style="min-width: 1000px;">
      <thead class="table-warning">
        <tr>
          <th>Key Data</th>
          <th>Key Pair Value</th>
          <th style="text-align:center;">Actions</th> 
        </tr>
      </thead>
      <tbody id="tableRecordset">
 		</tr>
 		<csp:while counter=myQueryRow condition=query.Next()>
 			<tr class='#($S(myQueryRow#2:"LightRow",1:"LightRow"))#'>
  				<csp:while counter=myQueryColumn condition="(myQueryColumn<query.GetColumnCount())">
      				<td style="background-color:#e6ffff">#(query.GetData(myQueryColumn))#</td>
  						</csp:while>
 							<td style="text-align:center;">
          						<button class="btn btn-sm btn-danger me-2 edit-delete-btn" data-id="#(query.GetData(0))#">
    								<i class="fa fa-edit"></i>
    								<i class="fa fa-trash"></i>
  								</button>
        					</td> 
 						</tr>
 				</csp:while>
      		</tbody>
       </table>
    </div>
  </div>
  
<script language=javascript>
  document.addEventListener('DOMContentLoaded', () => 
  {
    const editButtons = document.querySelectorAll('.edit-delete-btn');
    editButtons.forEach(button =>
    {
      button.addEventListener('click', () => 
      {
        const row = button.closest('tr');
        document.getElementById("Add").disabled=true
        const kID=row.cells[0].textContent.trim();
        const pairVal = row.cells[1].textContent.trim();
        document.getElementById('key').value = kID;
        document.getElementById('kvalue').value = pairVal;
        document.getElementById('key').focus();
      });
    });
  });
</script>
 <script language=javascript>
    document.getElementById('Cancel').addEventListener('click', () => 
    {
    	event.preventDefault();
    	document.getElementById('recordForm').reset();
    });
</script>

<script language=javascript>
  $(document).ready(function()
  {
    $('#dataTable').DataTable(
    {
      "order": [[0, "asc"]],
      "paging": true,
      "lengthChange": false,
      "searching": true,
      "info": true,
      "autoWidth": false
    });
  		$('#dataTable_filter input').css('font-size', '12px').attr('placeholder', 'Type to search..?');
  });
</script>

</body> 

<script language="javascript">
  document.addEventListener('DOMContentLoaded', () =>
  {
  	const updateBtn = document.querySelector('button[name="Update"]');
  	const deleteBtn = document.querySelector('button[name="Delete"]');
  	const addBtn = document.getElementById('Add');
  	const cancelBtn = document.getElementById('Cancel');
  	updateBtn.style.display = 'none';
  	deleteBtn.style.display = 'none';
  	addBtn.style.visibility = 'visible';  
  	addBtn.disabled = false;
  document.querySelectorAll('.edit-delete-btn').forEach(editBtn =>
  {
    editBtn.addEventListener('click', () =>
    {
      updateBtn.style.display = 'inline-block';
      deleteBtn.style.display = 'inline-block';
      addBtn.style.display = 'none';
      addBtn.style.visibility = 'visible'; 
      addBtn.disabled = true;
    });
  });
  updateBtn.addEventListener('click', (e) =>
  {
    updateBtn.style.display = 'none';
    deleteBtn.style.display = 'none';
    addBtn.style.display = 'inline-block';
    addBtn.style.visibility = 'visible';
    addBtn.disabled = false;
  });
  deleteBtn.addEventListener('click', (e) =>
  {
    updateBtn.style.display = 'none';
    deleteBtn.style.display = 'none';
    addBtn.style.display = 'inline-block';
    addBtn.style.visibility = 'visible';
    addBtn.disabled = false;
  });
  cancelBtn.addEventListener('click', (e) =>
  {
    e.preventDefault();  
    document.getElementById('recordForm').reset();
    updateBtn.style.display = 'none';
    deleteBtn.style.display = 'none';
    addBtn.style.display = 'inline-block';
    addBtn.style.visibility = 'visible';  
    addBtn.disabled = false;              
  });
});
</script>

<footer class="page-footer">
  <a href="https://sanjibpandey.wixsite.com/pandey/" target="_blank" rel="noopener noreferrer" style="color: #6c757d; text-decoration: none;"> https://sanjibpandey.wixsite.com/pandey/</a>
</footer>
</html>

 

/// Cette classe est conçue et créée pour insérer, mettre à jour et supprimer des enregistrements (clé & valeur)/// dans la table de recherche de données à partir d'une application Web. /// Ensuite, cela peut être utilisé dans des règles ou des transformations de données à l'aide de la fonction de recherche./// Auteur : Sanjib Pandey/// Date : 16/10/2025Class SANJIB.DataLookup.Methods Extends%Persistent
{

/// Avec cette méthode, on ajoute une valeur à la table de recherche. Les paramètres obligatoires sont:/// dtTableName : Le nom de votre table de recherche de données/// keyData     : La clé/// keyValue    : La valeur ( la valeur de paire de clés)	ClassMethod InsertLookUpValues(dtTable As%String = "", keyData As%String = "", keyValue As%String = "") As%Status
{
	S tSC = $$$OKTry
	{
		I (dtTable '="") && (keyData '="") && (keyValue '="")
		{
			S mySQLStatement = "INSERT into Ens_Util.LookupTable (KeyName,DataValue,TableName) values ('"_keyData_"','"_keyValue_"','"_dtTable_"')"S myRecordSet = ##class(%SQL.Statement).%ExecDirect(,mySQLStatement)
			S tSC={"InserRecorded":(myRecordSet)}
		}
	}
	Catch (Exception)
	{
		Throw Exception	
	}
	Q tSC
}

/// Cette méthode vérifie si la valeur existe déjà dans la table de recherche de données.ClassMethod ChkLookupKeyValue(dtTable As%String, keyData As%String) As%Status
{
	S tSC = $$$OKTry
	{
		I (dtTable '="") && (keyData '="")
		{
			S mySQLStatement="SELECT KeyName FROM Ens_Util.LookupTable WHERE TableName='"_dtTable_"' and KeyName='"_keyData_"'"S myRecordSet = ##class(%SQL.Statement).%ExecDirect(,mySQLStatement)
			D myRecordSet.%Next()
			I (myRecordSet.%SQLCODE=0)
			{ 
				S tSC= "T"
			}
			else
			{
				S tSC="F"
			}
		}
		else
		{
			S tSC= "Invalid Parameters - missing table name or key !"
		}
	}
	Catch (Exception)
	{
		Throw Exception	
	}
	Q tSC
}

/// Cette méthode met à jour uniquement la valeur clé dans la table de recherche de données.ClassMethod UpdateLookUpValues(dtTable As%String = "", keyData As%String = "", keyValue As%String = "") As%Status
{
	S tSC = $$$OKTry
	{
		I (dtTable '="") && (keyData '="") && (keyValue '="")
		{
			S mySQLStatement = "UPDATE Ens_Util.LookupTable SET DataValue='"_keyValue_"' WHERE TableName='"_dtTable_"' AND KeyName='"_keyData_"'"S myRecordSet = ##class(%SQL.Statement).%ExecDirect(,mySQLStatement)
			S tSC={"Updated Record":(myRecordSet)}
		}
	}
	Catch (Exception)
	{
		Throw Exception	
	}
	Q tSC
}

/// Cette méthode est utilisée pour supprimer un enregistrement de la table de recherche de données.ClassMethod DeleteLookUpValues(dtTable As%String, keyData As%String) As%Status
{
	S tSC = $$$OKTry
	{
		I (dtTable '="") && (keyData '="") 
		{
			S mySQLStatement = "DELETE FROM Ens_Util.LookupTable WHERE  TableName='"_dtTable_"' And KeyName='"_keyData_"'"S myRecordSet = ##class(%SQL.Statement).%ExecDirect(,mySQLStatement)
			S tSC={"Deleted Record":(myRecordSet)}
		}
	}
	Catch (Exception)
	{
		Throw Exception	
	}
	Q tSC
}

Storage Default
{
<Data name="MethodsDefaultData">
<Value name="1">
<Value>%%CLASSNAME</Value>
</Value>
</Data>
<DataLocation>^SANJIB.DataLookup.MethodsD</DataLocation>
<DefaultData>MethodsDefaultData</DefaultData>
<IdLocation>^SANJIB.DataLookup.MethodsD</IdLocation>
<IndexLocation>^SANJIB.DataLookup.MethodsI</IndexLocation>
<StreamLocation>^SANJIB.DataLookup.MethodsS</StreamLocation>
<Type>%Storage.Persistent</Type>
}

}

Conclusion

Cette interface Web réutilisable et cette classe offrent un moyen simple mais efficace pour la gestion des tables de recherche de données dans HealthConnect, en améliorant l'efficacité et la flexibilité. Grâce à l'accès contrôlé dont bénéficient les utilisateurs finaux, cette interface réduit les frais administratifs traditionnellement associés à la maintenance des tables de recherche.

0
0 17
InterSystems officiel Adeline Icard · Oct 27, 2025

Cette version met l'accent sur la fiabilité des mises à niveau, l'extension de la sécurité et l'amélioration du support pour plusieurs services cloud InterSystems. Avec cette version, toutes les offres majeures, notamment FHIR Server, InterSystems Data Fabric Studio (IDS), IDS avec Supply Chain et IRIS Managed Services, prennent désormais en charge la sécurité avancée, offrant ainsi une sécurité unifiée et renforcée.

Nouvelles fonctionnalités et améliorations

0
0 16
InterSystems officiel Adeline Icard · Oct 24, 2025

Les versions de maintenance 2025.1.2 et 2024.1.5 de la plateforme de données InterSystems IRIS, d'InterSystems IRIS for Health et d'HealthShare Health Connect sont désormais disponibles en disponibilité générale (GA). Ces versions incluent les correctifs pour plusieurs alertes et avis publiés récemment, notamment :

0
0 15
Article Iryna Mykhailova · Oct 21, 2025 2m read

Bonjour,

Je voulais partager avec vous une méthode pratique qui m'a été utile lors de mes développements sur Health Connect Cloud avec VS Code et GitBash. Lors de ces développements, si des modifications sont effectuées directement sur le serveur, comme des règles de routage ou des déploiements de composants, elles ne sont pas automatiquement incluses dans le contrôle de code source. Vous devez donc exporter les modifications depuis le serveur vers vos fichiers locaux et les envoyer vers votre dépôt distant. Je suis sûr qu'il existe des méthodes plus simples pour gérer ce problème, que je suis en train de tester, mais pour une solution rapide, j'ai pensé qu'il serait utile d'utiliser une méthode de pré-validation qui déclenche un rappel dans GitBash – voir ci-dessous.

0
0 16
Article Iryna Mykhailova · Août 28, 2025 12m read

Nous présentons ici le processus d'utilisation de la célèbre solution Jaeger pour tracer les applications InterSystems IRIS. Jaeger est un produit open source permettant de suivre et d'identifier des problèmes, en particulier dans les environnements distribués et de microservices. Ce backend de traçage, apparu chez Uber en 2015, a été inspiré par Dapper de Google et OpenZipkin de Twitter. Il a ensuite rejoint la Fondation Cloud Native Computing (CNCF) en tant que projet en incubation en 2017, avant d'obtenir le statut gradué en 2019. Ce guide vous montrera comment utiliser la solution Jaeger conteneurisée intégrée à IRIS.

Caractéristiques du Jaeger

  1. Surveillance des flux de transactions exécutés par une ou plusieurs applications et composants (services) dans des environnements conventionnels ou distribués:
  2. Identification précise des goulots d'étranglement dans les flux métier, y compris ceux qui sont distribués:
  3. Étude et optimisation des dépendances entre services, composants, classes et méthodes:
  4. Identification des indicateurs de performance pour découvrir les possibilités d'amélioration:

Composants Jaeger



Extrait de la documentation Jaeger: https://www.jaegertracing.io/docs/1.23/architecture/

  1. Client: Solutions, applications ou technologies (telles que IRIS) qui envoient des données de surveillance à Jaeger.
  2. Agent: Démon réseau qui surveille les segments envoyés via UDP, les regroupe et les transmet au collecteur. Il est conçu pour être déployé sur tous les hôtes en tant que composant d'infrastructure, en abstraisant le routage et la découverte des collecteurs depuis le client.
  3. Collecteur: Récepteur des traces provenant des agents Jaeger, qui les traite via un pipeline de traitement , lequel valide les traces, les indexe, effectue les transformations nécessaires, puis les stocke.
  4. Agent d'ingestion (facultatif): Si une file d'attente de messages telle qu'Apache Kafka tamponne les données entre le collecteur et le stockage, l'agent d'ingestion Jaeger lit les données dans Kafka et les écrit dans le stockage.
  5. Requête: Service qui récupère les traces du stockage et héberge une interface utilisateur pour les afficher.
  6. Interface utilisateur: L'interface Web Jaeger pour analyser et tracer les flux de transactions.

Aperçu d'Open Telemetry (OTel)

Étant donné qu'OpenTelemetry est la technologie exploitée par IRIS pour envoyer des données de traçage à Jaeger, il est important de comprendre son fonctionnement.
OpenTelemetry (alias OTel) est un framework d'observabilité open source et fournisseur neutre permettant d'instrumenter, de générer, de collecter et d'exporter des données de télémétrie telles que des traces, des métriques et des logs. Dans cet article, nous nous concentrerons sur la fonctionnalité traces.
L'unité fondamentale de données dans OpenTelemetry est le “signal”. L'objectif d'OpenTelemetry est de collecter, traiter et exporter ces signaux, qui sont des sorties système décrivant l'activité sous-jacente du système d'exploitation et des applications s'exécutant sur une plateforme. Un signal peut être quelque chose que vous souhaitez mesurer à un moment précis (par exemple, la température, l'utilisation de la mémoire) ou un événement qui traverse les composants de votre système distribué que vous souhaitez tracer. Vous pouvez regrouper différents signaux afin d'observer le fonctionnement interne d'une même technologie sous plusieurs angles (source: https://opentelemetry.io/docs/concepts/signals/). Cet article explique la manière d'émettre des signaux associés à des traces (le cheminement d'une requête dans votre application) depuis IRIS vers les collecteurs OTel.
OpenTelemetry est un excellent choix pour surveiller et tracer votre environnement IRIS et votre code source, car il est pris en charge par plus de 40 fournisseurs d'observabilité. Il est également intégré à de nombreuses bibliothèques, services et applications, et adopté par de nombreux utilisateurs finaux (source: https://opentelemetry.io/docs/).

  • Les microservices développés en Java, .NET, Python, NodeJS, InterSystems ObjectScript et des dizaines d'autres langages peuvent envoyer des données de télémétrie à un collecteur OTel à l'aide des points de terminaison et des ports distants (dans notre exemple, nous utiliserons un port HTTP).
  • Les composants de l'infrastructure peuvent également envoyer des données, notamment des données sur les performances, l'utilisation des ressources (processeur, mémoire, etc.) et d'autres informations pertinentes pour la surveillance de ces composants. Pour InterSystems IRIS, les données sont collectées par Prometheus à partir du point de terminaison /monitor et peuvent être transférées vers un collecteur OTel.
  • Les API et les outils de base de données peuvent également envoyer des données de télémétrie. Certains produits de base de données sont capables de le faire automatiquement (instrumentalisation).
  • Le collecteur OTel reçoit les données OTel et les stocke dans une base de données compatible et/ou les transmet à des outils de surveillance (par exemple, Jaeger).


Comment InterSystems IRIS envoie des données de surveillance à Jaeger

À partir de la version 2025, InterSystems a lancé la prise en charge d'OpenTelemetry (OTel) dans son API de surveillance. Cette nouvelle fonctionnalité inclut l'émission de données de télémétrie pour le traçage, la journalisation et les métriques d'environnement. Cet article traite de l'envoi de données de traçage à Jaeger via OTel. Vous trouverez plus de détails ici: https://docs.intersystems.com/irislatest/csp/docbook/DocBook.UI.Page.cls?KEY=AOTEL&ADJUST=1.
Bien que certains langages de programmation et certaines technologies prennent en charge la transmission automatique des données OTel (instrumentation automatique), pour IRIS, vous devez écrire des instructions de code spécifiques pour activer cette fonctionnalité. Téléchargez le code source de l'application exemple à partir de https://openexchange.intersystems.com/package/iris-telemetry-sample, ouvrez votre IDE et suivez les étapes ci-dessous:

1. Accédez à la classe dc.Sample.REST.TelemetryUtil. La méthode SetTracerProvider initialise un fournisseur de traceurs, ce qui vous permet de définir le nom et la version du service surveillé:

/// Définition du fournisseur de traceursClassMethod SetTracerProvider(ServiceName As%String, Version As%String) As%Status
{
    Set sc = $$$OKset attributes("service.name") = ServiceName
    set attributes("service.version") = Version
    Set tracerProv = ##class(%Trace.TracerProvider).%New(.attributes)
    Set sc = ##class(%Trace.Provider).SetTracerProvider(tracerProv)
    Quit sc
}

2. L'étape suivante consiste à récupérer l'instance du fournisseur de traceurs créée:
 

/// Obtention du fournisseur de traceursClassMethod GetTracerProvider() As%Trace.Provider
{
    Return##class(%Trace.Provider).GetTracerProvider()
}

3. Cet exemple va surveiller l'API PersonREST sur le point de terminaison /persons/all. Accédez à la classe dc.Sample.PersonREST (méthode de classe GetAllPersons):

/// Récupération de tous les enregistrements de dc.Sample.PersonClassMethod GetAllPersons() As%Status
{
<span class="hljs-keyword">#dim</span> tSC <span class="hljs-keyword">As</span> <span class="hljs-built_in">%Status</span> = <span class="hljs-built_in">$$$OK</span>
<span class="hljs-keyword">do</span> <span class="hljs-keyword">##class</span>(dc.Sample.REST.TelemetryUtil).SetTracerProvider(<span class="hljs-string">"Get.All.Persons"</span>, <span class="hljs-string">"1.0"</span>)
<span class="hljs-keyword">set</span> tracerProv = <span class="hljs-keyword">##class</span>(dc.Sample.REST.TelemetryUtil).GetTracerProvider()
<span class="hljs-keyword">set</span> tracer = tracerProv.GetTracer(<span class="hljs-string">"Get.All.Persons"</span>, <span class="hljs-string">"1.0"</span>)

4. Le fournisseur de traceurs vient de créer un service de surveillance appelé Get.All.Persons (version 1.0) et a obtenu l'instance de traceurs avec GetTracer.
5. L'exemple doit créer un racine Span comme suit:
 

set rootAttr("GetAllPersons") = 1set rootSpan = tracer.StartSpan("GetAllPersons", , "Server", .rootAttr)
    set rootScope = tracer.SetActiveSpan(rootSpan)

6. Les spans sont des éléments du flux de traçage. Chaque span doit être mappé à un élément du code source que vous souhaitez analyser.
7. SetActiveSpan est obligatoire pour définir le span actuel à surveiller.
8. À présent, l'exemple crée plusieurs spans descendants mappés à des éléments importants du flux:
 

set childSpan1 = tracer.StartSpan("Query.All.Persons")
    set child1Scope = tracer.SetActiveSpan(childSpan1)
    Try {
        Set rset = ##class(dc.Sample.Person).ExtentFunc()
        do childSpan1.SetStatus("Ok")
    } Catch Ex {
        do childSpan1.SetStatus("Error")
    }
    do childSpan1.End()
    kill childSpan1

9. Ce premier span des descendant surveille la requête pour toutes les personnes dans la base de données. Pour créer un span descendant, l'exemple utilise StartSpan avec un titre suggéré (Query.All.Persons). Le span actif doit ensuite être défini sur le span descendant actuel, ce que l'exemple réalise à l'aide de SetActiveSpan avec la référence childSpan1.
10. L'exemple exécute le code source métier (Set rset = ##class(dc.Sample.Person).ExtentFunc()). Si l'opération réussit, il définit le statut sur "Ok" ; sinon, il le définit sur "Error."
11. L'exemple termine la surveillance de ce morceau de code à l'aide de la méthode End et en supprimant la référence childSpan1.
12. Vous pouvez répéter cette procédure pour tous les autres segments de code que vous souhaitez examiner:

Pour surveiller la détection d'une personne par son ID (obtenir les détails de la personne):

set childSpan2 = tracer.StartSpan("Get.PersonByID")
set child2Scope = tracer.SetActiveSpan(childSpan2)
Set person = ##class(dc.Sample.Person).%OpenId(rset.ID)

       Pour observer le calcul de l'âge (classe dc.Sample.Person, méthode CalculateAge):
 

set tracerProv = ##class(dc.Sample.REST.TelemetryUtil).GetTracerProvider()
set tracer = tracerProv.GetTracer("Get.All.Persons", "1.0")
set childSpan1 = tracer.StartSpan("CalculateAge")
set child1Scope = tracer.SetActiveSpan(childSpan1)

Pour vérifier la définition du signe du zodiaque (classe dc.Sample.Person, méthode CalculateZodiacSign):
 

set tracerProv = ##class(dc.Sample.REST.TelemetryUtil).GetTracerProvider()
set tracer = tracerProv.GetTracer("Get.All.Persons", "1.0")
set childSpan1 = tracer.StartSpan("GetZodiacSign")
set child1Scope = tracer.SetActiveSpan(childSpan1)

 
Configuration des conteneurs IRIS et Jaeger

1. Créez le conteneur collecteur OTel (dans docker-composer.yml):
 

# --- 2. Collecteur OpenTelemetry ---  otel-collector:    image:otel/opentelemetry-collector-contrib:latest    command:["--config=/etc/otel-collector-config.yml"]    volumes:      -./otel-collector-config.yml:/etc/otel-collector-config.yml    ports:      -"4317:4317"# OTLP gRPC       -"4318:4318"# OTLP HTTP      -"9464:9464"# Métriques    depends_on:      -iris      -jaeger

2. Ajustez le fichier de configuration du collecteur OTel:

receivers:  otlp:    protocols:      grpc:        endpoint:"0.0.0.0:4317"      http:        endpoint:"0.0.0.0:4318"exporters:  otlp:    endpoint:jaeger:4317# Le nom du service « jaeger » de docker-compose pour le collecteur gRPC    tls:      insecure:true  prometheus:    endpoint:"0.0.0.0:9464"  debug:{}processors:  batch:# Processeur pour regrouper des traces en lots    send_batch_size:100    timeout:10sconnectors:  spanmetrics:# Connecteur SpanMetricsservice:  pipelines:    traces:      receivers:[otlp]      processors:[batch]# Les traces sont traitées pour générer des métriques      exporters:[otlp,spanmetrics]    metrics:      receivers:[otlp,spanmetrics]      exporters:[prometheus]    logs:      receivers:[otlp]      exporters:[debug]

3. Le collecteur OTel recevra les données de surveillance à l'adresse suivante:

http:        endpoint:"0.0.0.0:4318"

4. Le collecteur OTel enverra les exportateurs (Exporters) à Jaeger comme indiqué ci-dessous:

exporters:
  otlp:
    endpoint: jaeger:4317 # O nome do serviço 'jaeger' do docker-compose para o Collector gRPC
    tls:
      insecure: true

5. Le service OTel créera un pipeline pour recevoir et envoyer les données de surveillance:
 

service:  pipelines:    traces:      receivers:[otlp]      processors:[batch]      exporters:[otlp]

6. Dans le fichier docker-compose.yml, l'exemple va créer un conteneur IRIS, en définissant OTEL_EXPORTER_OTLP_ENDPOINT avec l'adresse du collecteur OTel:

iris:    build:      context:.      dockerfile:Dockerfile    restart:always    ports:      -51773:1972      -52773:52773      -53773    volumes:      -./:/home/irisowner/dev    environment:    -ISC_DATA_DIRECTORY=/home/irisowner/dev/durable    -OTEL_EXPORTER_OTLP_ENDPOINT=http://otel-collector:4318

 
7. Enfin, un conteneur Jaeger est créé pour recevoir les données du collecteur OTel et fournir une interface utilisateur permettant aux utilisateurs de surveiller et de tracer les données IRIS OTel:

jaeger:    image:jaegertracing/all-in-one:latest    ports:      -"16686:16686"# Jaeger UI      -"14269:14269"# Jaeger Metrics      -"14250:14250"# Jaeger Collector gRPC     environment:      -COLLECTOR_OTLP_ENABLED=true

 
Il existe des options de port supplémentaires pour Jaeger qui vous permettent de traiter plusieurs types de collecteurs. Vous trouverez ci-dessous la liste des ports exposés disponibles:

  • 6831/udp: Accepte les spans jaeger.thrift (Thrift compact)
  • 6832/udp: Accepte les spans jaeger.thrift (Thrift binaire)
  • 5778: Configuration Jaeger
  • 16686: Interface utilisateur Jaeger
  • 4317: Récepteur gRPC du protocole OpenTelemetry (OTLP)
  • 4318: Récepteur HTTP du protocole OpenTelemetry (OTLP)
  • 14250: Acceptation des spans model.proto via gRPC
  • 14268: Acceptation directe des spans jaeger.thrift via HTTP
  • 14269: Vérification de l'intégrité de Jaeger
  • 9411: Compatibilité Zipkin

Exécution de l'exemple

1. Copiez le code source de l'exemple: 

$ git clone https://github.com/yurimarx/iris-telemetry-sample.git

2. Ouvrez le terminal dans ce répertoire et exécutez le code ci-dessous:

$ docker-compose up -d --build

3. Créez quelques données de test simulées. Pour ce faire, ouvrez le terminal IRIS ou le terminal web sur /localhost:52773/terminal/ and call the following:

USER>do##class(dc.Sample.Person).AddTestData(10)

4. Ouvrez http://localhost:52773/swagger-ui/index.html et exécutez le point de terminaison /persons/all.

 

Analyse et traçage du code IRIS sur Jaeger

1. Accédez à Jaeger ici http://localhost:16686/search.

2. Sélectionnez Get.All.Persons dans le champ "Service", puis cliquez sur "Find Traces" (Rechercher les traces).


3. Cliquez sur la trace détectée pour afficher ses détails.


4. Observez la chronologie de la trace sélectionnée.


5. Dans le coin supérieur droit, sélectionnez "Trace Graph" :


6. Analysez les dépendances:


7. Cette analyse des dépendances est essentielle pour identifier les problèmes dans les systèmes/services distants au sein de votre environnement, en particulier si différents services distribués utilisent le même nom de service.
8. Maintenant, sélectionnez “Framegraph”:


9. Observez tous les composants du flux de transactions surveillé dans une table graphique:


10. Grâce à toutes ces ressources Jaeger, vous pouvez résoudre efficacement les problèmes de performances et identifier la source des erreurs.

 

Pour en savoir plus

Pour approfondir vos connaissances sur le traçage distribué, consultez les ressources externes suivantes:

  • Maîtrise du traçage distribué (Mastering Distributed Tracing) (2019) par Yuri Shkuro : article de blog rédigé par le créateur de Jaeger, qui explique l'histoire et les choix architecturaux à l'origine de Jaeger. Ce livre traite en détail de la conception et du fonctionnement de Jaeger, ainsi que du traçage distribué en général.
  • Suivez Jaeger pour un tour en HotROD: un tutoriel étape par étape qui montre comment utiliser Jaeger pour résoudre les problèmes de performances des applications.
  • Présentation de Jaeger : un (ancien) webinaire présentant Jaeger et ses capacités.
  • Tutoriel détaillé sur Jaeger: https://betterstack.com/community/guides/observability/jaeger-guide/ 
  • Évolution du traçage distribué au sein d'Uber.
  • Émettre des données de télémétrie vers un outil de surveillance compatible avec OpenTelemetry par la documentation InterSystems.
  • Observabilité moderne avec InterSystems IRIS & et OpenTelemetry: Une vidéo de démonstration sur la manière de travailler avec OpenTelemetry et IRIS: https://www.youtube.com/watch?v=NxA4nBe31nA
  • OpenTelemetry sur GitHub : Une collection d'API, de SDK et d'outils pour instrumenter, générer, collecter et exporter des données de télémétrie (métriques, journaux et traces) afin d'aider à analyser les performances et le comportement de logiciels: https://github.com/open-telemetry.
0
0 21
InterSystems officiel Adeline Icard · Août 19, 2025

Version 2025.1.0.1.24372U.f00326d.

Aperçu

Cette version offre une prise en charge Azure étendue pour InterSystems Data Fabric Studio, une flexibilité d’abonnement améliorée, des mises à jour majeures des modules et de multiples améliorations de la mise en réseau, de la sécurité et de la réactivité des API.

Nouvelles fonctionnalités et améliorations

0
0 25
InterSystems officiel Adeline Icard · Juil 25, 2025

Les versions de maintenance 2025.1.1 de la plateforme de données InterSystems IRIS, d'InterSystems IRIS for Health et de HealthShare Health Connect sont désormais disponibles en disponibilité générale (GA). N'hésitez pas à partager vos commentaires via la Communauté des développeurs afin que nous puissions développer ensemble un produit plus performant.

Documentation

Vous trouverez les listes détaillées des modifications et les listes de contrôle des mises à niveau sur les pages suivantes :

0
0 23
InterSystems officiel Adeline Icard · Juil 24, 2025

InterSystems annonce la disponibilité générale d'InterSystems IRIS 2025.2

InterSystems a le plaisir d'annoncer la disponibilité générale (GA) de la version 2025.2 de la plateforme de données InterSystems IRIS. Il s'agit d'une version en livraison continue (CD). Veuillez noter que les versions GA d'InterSystems IRIS for Health et HealthShare Health Connect 2025.2 sont actuellement suspendues en raison de limitations de mise en miroir introduites par les mises à jour de sécurité (détails ci-dessous).

Points forts de la version

0
0 27
Article Guillaume Rongier · Juil 2, 2025 4m read

Bonjour chers ingénieurs interface et développeurs d'applications,     

Saviez-vous que Python peut être utilisé dans des productions ou des intégrations?

L'interface utilisateur de configuration de production est low-code, mais dans de nombreux projets, vous pouvez arriver au point où il est nécessaire d'écrire du code. Comme nous l'avons vu dans le cours Architecture d'intégration, les Business Process comportent de nombreux emplacements où insérer du code, notamment l'éditeur BPL (pour les Business Process BPL) et l'éditeur DTL (pour les transformations de données).

😯 À partir d'InterSystems IRIS 2025.1, Python et InterSystems ObjectScript sont tous deux pris en charge dans les éditeurs BPL et DTL. 😄 Vous pouvez choisir entre ces langues selon vos préférences personnelles, et pas selon des besoins techniques. 😍

Rédaction du code Python dans l'éditeur BPL

Python est pris en charge dans l'éditeur BPL depuis InterSystems IRIS 2024.1. Examinons un Business Process BPL:

Business Process BPL comprend les activités suivantes (dans l'ordre) : activité Début, activité Affectation, activité Code avec un logo Python, activité If avec un logo Python, activité Transformation du côté vrai de l'activité If, et activité Fin.

Dans l'activité <code>, GetWinningBid, remarquez l'icône Python. En ouvrant cette activité <code>, on peut voir que le champ intitulé Code contient des instructions Python! Ces instructions utilisent la bibliothèque intégrée iris pour ouvrir un objet d'un ID donné.

Une activité Code provenant d'un éditeur BPL. Le langage est défini sur Python. Le code indique # Utilisation du corps de la requête pour ouvrir l'objet Bid avec l'ID donné. New line. bidID = request.id. New line. context.winningBid = iris.cls("AuctionServer.Bid")._OpenId(bidID).

Vous pouvez définir le langage pour l'ensemble du BPL (Python ou ObjectScript) via le paramètre Language dans l'onglet General u BPL, puis utiliser le menu déroulant Language Override (Remplacement du language) dans un champ de code donné pour remplacer la valeur par défaut du BPL.

L'activité <code> n'est pas la seule activité qui analyse le code dans un Business Process BPL. L'activité <code> analyse les instructions de code complètes, mais autres champs des activités BPL acceptent également des expressions de code. Vous pouvez les reconnaître grâce au menu déroulant Language Override (Remplacement du langage), où vous pouvez remplacer la valeur par défaut de BPL. 

Par exemple, l'activité <if>, qui crée un flux logique conditionnel, a un champ appelé Condition qui accepte des expressions de code. Il a un champ correspondant appelé Condition Language Override (Remplacement du langage de condition). Dans cet exemple, ce champ est défini sur Python.

Lorsque Python n'était pas encore pris en charge dans ces domaines, les ingénieurs d'interface devaient savoir comment écrire des expressions logiques dans ObjectScript. Par exemple, vous deviez savoir que || signifie Or, et && signifie And. Vous pouvez désormais utiliser Python, dont la syntaxe pour les expressions logiques est plus proche du langage naturel.

Dans l'éditeur BPL, s'il vous faut importer des paquetages Python, vous pouvez le faire sous les instructions Python From/Import dans l'onglet General.

Rédaction du code Python dans l'éditeur DTL 

Python est également pris en charge dans les champs de code de l'éditeur DTL depuis InterSystems IRIS 2025.1. Les utilisations courantes du code personnalisé dans DTL sont le formatage de chaînes et les calculs.

Une transformation de données DTL convertissant un objet source, AuctionServer.Bid, into a target object, AuctionServer.Order

Si vous devez importer des paquetages Python dans l'éditeur DTL, recherchez l'onglet Paramètres Transformation et utilisez le champ d' instruction Python From / Import. Le langage par défaut pour les expressions de code peut également être défini dans l'onglet d'instructions Transformation .

Dans l'onglet Paramètres de transformation du DTL, le langage est défini sur Python et le champ des instructions Python From / Import contient la mention from numpy import random.

Pour trouver les champs d'analyse de code des actions DTL, il suffit de rechercher tout champ associé à une liste déroulante Language Override. Par exemple, dans l'action <code> du DTL, vous pouvez écrire des instructions de code complètes. Les actions telles que Set, If, Trace et autres prennent en charge les expressions de code, qui peuvent être écrites en Python ou en ObjectScript.

Une activité de code issue d'une transformation de données DTL, avec le langage défini sur Python. Le contenu du champ de code indique bidders = [bid.User for bid in source.Lot.Bids()]. New line. bidders = set(bidders). New line. target.NumOutbid = (len(bidders) - 1).

Flux de travail axés sur le code

Si vous maîtrisez le processus d'édition de productions via un code, vous pouvez modifier les fichiers BPL et DTL via leurs fichiers de configuration. Cette méthode n'est pas aussi simple que les interfaces de l'éditeur, mais elle est très intuitive pour les programmeurs expérimentés.

Vous pouvez également utiliser Python pour écrire des méthodes dans des fonctions utilitaires personnalisées et des composants personnalisés, tels que des opérations commerciales et des services commerciaux (à l'exception des méthodes de rappel callback methods, comme défini dans la documentation).

Récapitulatif 

  • L'éditeur DTL et l'éditeur BPL prennent désormais en charge le code et les expressions Python. 
  • Si nécessaire, indiquez les paquetages que vous souhaitez importer via les paramètres généraux de BPL ou DTL. 
  • Vous pouvez définir un langage par défaut pour chaque DTL/BPL et remplacer des champs spécifiques si nécessaire.

Rejoignez la conversation!

  • Avez-vous déjà utilisé Python pour créer des intégrations personnalisées? 
  • Quelles questions avez-vous au sujet de la prise en charge de Python dans les intégrations?
  • Ajoutez vos commentaires ci-dessous!
0
0 28
InterSystems officiel Adeline Icard · Juin 27, 2025

Référence : Build 2025.1.0.1.24372U.25e14d55

Cette version apporte des améliorations significatives à la sécurité, aux capacités d'analyse et à l'expérience utilisateur, ainsi que des améliorations opérationnelles majeures visant à réduire les temps d'arrêt et à améliorer la fiabilité.

Nouvelles fonctionnalités et améliorations

0
0 21
InterSystems officiel Adeline Icard · Juin 10, 2025

InterSystems a publié de nouvelles mises à jour afin de corriger un défaut affectant les versions antérieures les plus récentes (2025.1.0, 2024.1.4, 2023.1.6 et 2022.1.7), pour les gammes de produits prises en charge suivantes :

  • InterSystems IRIS
  • InterSystems IRIS for Health
  • HealthShare Health Connect

Ce problème pouvait entraîner des erreurs <PROTECT> inattendues ou des anomalies d'accès lors de l'utilisation de fonctionnalités telles que :

0
0 33
InterSystems officiel Adeline Icard · Mai 22, 2025

Nous publions une version intermédiaire pour InterSystems IRIS, IRIS for Health et Health Connect 2025.1 (version 2025.1.0.225.1) afin de résoudre un problème d'interopérabilité critique affectant les utilisateurs utilisant des hôtes métier compatibles SDS.

Quel est le problème ?

0
0 21
Article Sylvain Guilbaud · Avr 25, 2025 22m read

TLS, qu'est-ce que c'est ?

La TLS (Transport Layer Security ou "Sécurité de la couche de transport"), qui succède à SSL (Secure Sockets Layer ou "Couche de sockets sécurisée"), fournit de la sécurité (c'est-à-dire le chiffrement et l'authentification) sur une connexion TCP/IP. Si vous avez déjà remarqué le "s" sur les URLs "https" vous avez reconnu une connexion HTTP "sécurisée" par SSL/TLS. Dans le passé, seules les pages de connexion/autorisation sur le web utilisaient TLS, mais dans l'environnement hostile d'Internet d'aujourd'hui, les meilleures pratiques indiquent que nous devrions sécuriser toutes les connexions avec TLS.

Pourquoi utiliser TLS?

Alors, pourquoi mettre en œuvre TLS pour les connexions HL7 ? Alors que les violations de données, les rançongiciels et les vulnérabilités sont de plus en plus fréquents, chaque mesure que vous prenez pour renforcer la sécurité de ces précieuses sources de données devient plus cruciale. La TLS est une méthode éprouvée et bien comprise pour protéger les données en transit.

TLS fournit deux fonctionnalités principales qui nous sont bénéfiques : 1) le chiffrement et 2) l'authentification.

Chiffrement

Le chiffrement transforme les données en cours de transfert de sorte que seules les deux parties engagées dans la communication peuvent lire/comprendre les informations échangées. Dans la plupart des cas, seules les applications impliquées dans la connexion TLS peuvent interpréter les données transférées. Cela signifie que les acteurs malveillants opérant sur les serveurs ou réseaux de communication ne pourront pas lire les données, même s'ils parviennent à capturer les paquets TCP bruts à l'aide d'un renifleur de paquets (wiretap, wireshark, tcpdump, etc.).

Without TLS

Authentification

L'authentification garantit que chaque partie communique avec la partie prévue et non avec un imposteur. En s'appuyant sur l'échange de certificats (et la vérification de la preuve de propriété associée qui s'est produite lors d'un handshake TLS), lorsque vous utilisez TLS, vous pouvez être sûr que vous échangez des données avec une partie de confiance. Plusieurs attaques consistent à tromper un serveur pour qu'il communique avec un acteur malveillant en redirigeant le trafic vers le mauvais serveur (par exemple, l'emploi de DNS et d'ARP poisoning) Lorsque TLS est impliqué, les imposteurs doivent non seulement rediriger le trafic, mais aussi voler les certificats et les clés appartenant à la partie de confiance.

L'authentification protège non seulement contre les attaques intentionnelles de pirates informatiques ou de acteurs malveillants, mais aussi contre les erreurs de configuration accidentelles qui pourraient envoyer des données vers le ou les mauvais systèmes. Par exemple, si vous attribuez accidentellement l'adresse IP d'une connexion HL7 à un serveur qui n'utilise pas le certificat attendu, la vérification de la négociation TLS échouera avant l'envoi de données vers ce mauvais serveur.

Vérification d'hôte

Lors de la vérification, les clients ont la possibilité d'effectuer une vérification d'hôte. Cette vérification compare l'adresse IP ou le nom d'hôte utilisé dans la connexion avec les adresses IP et les noms d'hôte intégrés dans le certificat. Si cette vérification est activée et que l'adresse IP/l'hôte de la connexion ne correspond pas à une adresse IP/un hôte figurant dans le certificat, le handshake TLS échouera. Vous trouverez les adresses IP et les noms d'hôte dans les champs X.509 « Subject » et « Subject Alternative Name » présentés ci-dessous.

Preuve de la propriété d'un certificat avec une clé privée

Pour prouver la propriété des certificats échangés avec TLS, vous devez également avoir accès à la clé privée liée à la clé publique intégrée au certificat. Nous ne discuterons pas de la cryptographie employée pour la preuve de propriété avec une clé privée, mais vous devez savoir que l'accès à la clé privée de votre certificat est nécessaire pendant le handshake TLS.

TLS mutuel

Pour la plupart des connexions https établies par votre navigateur web, seul le certificat d'authenticité du serveur web est vérifié. Normalement, les serveurs web n'authentifient pas le client avec des certificats. Au lieu de cela, la plupart des serveurs web s'appuient sur l'authentification du client au niveau de l'application (formulaires de connexion, cookies, mots de passe, etc.).

Avec HL7, il est préférable que les deux côtés de la connexion soient authentifiés. Lorsque les deux côtés sont authentifiés, on parle de «TLS mutuel». Avec le TLS mutuel, le serveur et le client échangent leurs certificats et l'autre côté vérifie les certificats fournis avant de poursuivre la connexion et l'échange de données.

X.509 Certificats

X.509 Champs du certificat

Pour fournir le cryptage et l'authentification, les informations sur la clé publique et l'identité de chaque partie sont échangées dans des certificats [X.509] (https://en.wikipedia.org/wiki/X.509). Vous trouverez ci-dessous certains champs courants d'un certificat X.509 qui nous intéresseront:

  • Serial Number: numéro unique à un CA qui identifie ce certificat spécifique
  • Subject Public Key Info: clé publique du propriétaire
  • Subject: nom distinctif (DN) du serveur/service représenté par ce certificat
    • Ce champ peut être vide si des "Subject Alternative Names" (noms alternatifs du sujet) sont fournis.
  • Issuer: nom distinctif (DN) du CA qui a émis/signé ce certifica
  • Validity Not Before: date de mise en vigueur de ce certificat
  • Validity Not After: date d'expiration de ce certificat
  • Basic Constraints: indique s'il s'agit d'un CA ou non
  • Key Usage: l'utilisation prévue de la clé publique fournie par ce certificat
    • Valeurs d'exemple: digitalSignature, contentCommitment, keyEncipherment, dataEncipherment, keyAgreement, keyCertSign, cRLSign, encipherOnly, decipherOnly
  • Extended Key Usage: utilisations supplémentaires prévues de la clé publique fournie par ce certificat
    • Valeurs d'exemple: serverAuth, clientAuth, codeSigning, emailProtection, timeStamping, OCSPSigning, ipsecIKE, msCodeInd, msCodeCom, msCTLSign, msEFS
    • Pour les connexions TLS mutuelles, les deux modes d'utilisation serverAuth et clientAuth sont nécessaires.
  • Subject Key Identifier: identifie la clé publique du sujet fournie par ce certificat
  • Authority Key Identifier: identifie la clé publique du fournisseur utilisée pour vérifier ce certificat
  • Subject Alternative Name: contient un ou plusieurs noms alternatifs pour ce sujet
    • Les noms DNS et les adresses IP sont des noms alternatifs fréquemment fournis dans ce champ.
    • Subject Alternative Name est parfois abrégé en SAN.
    • Le nom DNS ou l'adresse IP utilisés dans la connexion doivent figurer dans cette liste ou dans le Common Name du Subject pour que la vérification de l'hôte soit réussie.

Noms distingués

Les champs Subject (Sujet) et Issuer (Émetteur) d'un certificat X.509 sont définis comme des Distinguished Names (DN, Noms Distingués). Les noms distingués sont constitués de plusieurs attributs, chaque attribut ayant le format <attr>=<value>. Voici une liste non exhaustive des attributs courants que l'on trouve dans les champs Subject et Issuer

AbréviationNomExempleRemarques
CNNom communCN=server1.domain.comLe nom de domaine complet (FQDN) d'un serveur/service
CPaysC=USCode pays à deux caractères
STÉtat (ou province)ST=MassachusettsNom complet de l'état/province
LLocalitéL=CambridgeVille, région, etc.
OOrganisationO=Best CorporationNom de l'organisation
OUUnité opérationnelleOU=FinanceDépartment, division, etc.

Selon les exemples du tableau ci-dessus, le DN complet pour cet exemple serait C=US, ST=Massachusetts, L=Cambridge, O=Best Corporation, OU=Finance, CN=server1.domain.com

Notez que le Common Name (nom commun) trouvé dans le Subject (sujet) est utilisé lors de la vérification de l'hôte et correspond normalement au nom de domaine complet (FQDN) du serveur ou du service associé au certificat. Les Subject Alternative Names (noms alternatifs du sujet) du certificat peuvent également être utilisés lors de la vérification de l'hôte.

Expiration du certificat

Les champs Validity Not Before (Validité avant la date) et Validity Not After (Validité après la date) du certificat fournissent une plage de dates entre lesquelles le certificat est valide

Normalement, les certificats feuille ont une validité d'un ou deux ans (bien que les sites Web soient encouragés à réduire leurs délais d'expiration à des périodes beaucoup plus courtes). Les autorités de certification ont généralement un délai d'expiration de plusieurs années.

L'expiration des certificats est une fonctionnalité TLS nécessaire mais peu pratique. Avant d'ajouter TLS à vos connexions HL7, assurez-vous d'avoir un plan pour remplacer les certificats avant leur expiration. Une fois qu'un certificat expire, vous ne pourrez plus établir de connexion TLS à l'aide de celui-ci.

Formats de certificat X.509

Les champs de ces certificats X.509 (ainsi que d'autres) sont structurés suivant le format ASN.1 et généralement enregistrés dans l'un des formats de fichier suivants :

Exemple d'encodage PEM d'un certificat X.509:

-----BEGIN CERTIFICATE-----
MIIEVTCCAz2gAwIBAgIQMm4hDSrdNjwKZtu3NtAA9DANBgkqhkiG9w0BAQsFADA7
MQswCQYDVQQGEwJVUzEeMBwGA1UEChMVR29vZ2xlIFRydXN0IFNlcnZpY2VzMQww
CgYDVQQDEwNXUjIwHhcNMjUwMTIwMDgzNzU0WhcNMjUwNDE0MDgzNzUzWjAZMRcw
FQYDVQQDEw53d3cuZ29vZ2xlLmNvbTBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IA
BDx/pIz8HwLWsWg16BG6YqeIYBGof9fn6z6QwQ2v6skSaJ9+0UaduP4J3K61Vn2v
US108M0Uo1R1PGkTvVlo+C+jggJAMIICPDAOBgNVHQ8BAf8EBAMCB4AwEwYDVR0l
BAwwCgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADAdBgNVHQ4EFgQU3rId2EvtObeF
NL+Beadr56BlVZYwHwYDVR0jBBgwFoAU3hse7XkV1D43JMMhu+w0OW1CsjAwWAYI
KwYBBQUHAQEETDBKMCEGCCsGAQUFBzABhhVodHRwOi8vby5wa2kuZ29vZy93cjIw
JQYIKwYBBQUHMAKGGWh0dHA6Ly9pLnBraS5nb29nL3dyMi5jcnQwGQYDVR0RBBIw
EIIOd3d3Lmdvb2dsZS5jb20wEwYDVR0gBAwwCjAIBgZngQwBAgEwNgYDVR0fBC8w
LTAroCmgJ4YlaHR0cDovL2MucGtpLmdvb2cvd3IyLzlVVmJOMHc1RTZZLmNybDCC
AQMGCisGAQQB1nkCBAIEgfQEgfEA7wB2AE51oydcmhDDOFts1N8/Uusd8OCOG41p
wLH6ZLFimjnfAAABlIMTadcAAAQDAEcwRQIgf6SEH+xVO+nGDd0wHlOyVTbmCwUH
ADj7BJaSQDR1imsCIQDjJjt0NunwXS4IVp8BP0+1sx1BH6vaxgMFOATepoVlCwB1
AObSMWNAd4zBEEEG13G5zsHSQPaWhIb7uocyHf0eN45QAAABlIMTaeUAAAQDAEYw
RAIgBNtbWviWZQGIXLj6AIEoFKYQW4pmwjEfkQfB1txFV20CIHeouBJ1pYp6HY/n
3FqtzC34hFbgdMhhzosXRC8+9qfGMA0GCSqGSIb3DQEBCwUAA4IBAQCHB09Uz2gM
A/gRNfsyUYvFJ9J2lHCaUg/FT0OncW1WYqfnYjCxTlS6agVUPV7oIsLal52ZfYZU
lNZPu3r012S9C/gIAfdmnnpJEG7QmbDQZyjF7L59nEoJ80c/D3Rdk9iH45sFIdYK
USAO1VeH6O+kAtFN5/UYxyHJB5sDJ9Cl0Y1t91O1vZ4/PFdMv0HvlTA2nyCsGHu9
9PKS0tM1+uAT6/9abtqCBgojVp6/1jpx3sx3FqMtBSiB8QhsIiMa3X0Pu4t0HZ5j
YcAkxtIVpNJ8h50L/52PySJhW4gKm77xNCnAhAYCdX0sx76eKBxB4NqMdCR945HW
tDUHX+LWiuJX
-----END CERTIFICATE-----

Comme vous pouvez le voir, l'encodage PEM ajoute -----BEGIN CERTIFICATE----- et -----END CERTIFICATE----- aux données ASN.1 du certificat encodées en base64.

Établir la confiance avec les autorités de certification

Sur l'Internet ouvert, il serait impossible pour votre navigateur Web de connaître et de faire confiance au certificat de chaque site Web. Il y en a tout simplement trop! Pour contourner ce problème, votre navigateur Web délègue la confiance à un ensemble prédéterminé d'autorités de certification (AC). Les autorités de certification sont des entités qui vérifient qu'une personne demandant un certificat pour un site Web ou un domaine est bien propriétaire et responsable du serveur, du domaine ou des activités commerciales associés à la demande de certificat. Une fois que l'autorité de certification a vérifié un propriétaire, elle est en mesure d'émettre le certificat demandé.

Chaque autorité de certification est représentée par un ou plusieurs certificats X.509. Ces certificats CA sont utilisés pour signer tous les certificats émis par la CA. Si vous regardez dans le champ Issuer (Émetteur) d'un certificat X.509, vous trouverez une référence au certificat CA qui a créé et signé ce certificat.

Si un certificat est créé sans autorité de certification, il est appelé certificat auto-signé. Vous savez qu'un certificat est auto-signé si les champs Subject (Sujet) et Issuer (Émetteur) du certificat sont identiques.

En général, la CA crée un certificat root (racine) auto-signé avec une longue fenêtre d'expiration. Ce certificat racine est ensuite utilisé pour générer quelques autorités de certification intermédiaires, qui ont une fenêtre d'expiration légèrement plus courte. La CA racine sera sécurisée et rarement utilisée après la création des CA intermédiaires. Les CA intermédiaires seront utilisées pour émettre et signer les certificats leaf (feuille) au quotidien.

Les CA intermédiaires sont créées au lieu d'utiliser directement la CA racine afin de minimiser l'impact en cas de violation ou de mauvaise gestion d'un certificat. Si une seule CA intermédiaire est compromise, l'entreprise aura toujours les autres CA disponibles pour continuer à fournir le service.

Chaînes de certificats

Un certificat de connexion et tous les certificats CA impliqués dans l'émission et la signature de ce certificat peuvent être organisés en une structure appelée chaîne de certificats. Cette chaîne de certificats (décrite ci-dessous) sera utilisée pour vérifier et approuver le certificat de connexion.

Si vous suivez le certificat feuille d'une connexion jusqu'à la CA émettrice (en utilisant le champ Issuer) puis, à partir de cette CA, jusqu'à son émetteur (et ainsi de suite, jusqu'à ce que vous atteigniez un certificat racine auto-signé), vous aurez parcouru la chaîne de certificats.

Construction d'une chaîne de certificats

Faire confiance à un certificat

Votre navigateur Web et votre système d'exploitation conservent généralement une liste d'autorités de certification approuvées. Lors de la configuration d'une interface HL7 ou d'une autre application, vous dirigerez probablement votre interface vers un fichier CA-bundle contenant une liste de CA approuvées. Ce fichier contiendra généralement une liste d'un ou plusieurs certificats CA encodés au format PEM. Par exemple:

# Probablement, une CA intermédiaire
-----BEGIN CERTIFICATE-----
MIIDQTCCAimgAwIBAgITBmyfz5m/jAo54vB4ikPmljZbyjANBgkqhkiG9w0BAQsF
...
rqXRfboQnoZsG4q5WTP468SQvvG5
-----END CERTIFICATE-----

# Probablement, une CA racine
-----BEGIN CERTIFICATE-----
MIIDqDCCApCgAwIBAgIJAP7c4wEPyUj/MA0GCSqGSIb3DQEBBQUAMDQxCzAJBgNV
...
WyH8EZE0vkHve52Xdf+XlcCWWC/qu0bXu+TZLg==
-----END CERTIFICATE-----

Lorsque votre navigateur Web (ou l'interface HL7) tente d'établir une connexion TLS, il utilise cette liste de certificats CA de confiance pour déterminer s'il fait confiance au certificat échangé lors du handshake TLS.

Le processus commence par le certificat racine et traverse la chaîne de certificats jusqu'au certificat CA suivant. Si le certificat CA n'est pas trouvé dans le magasin de confiance ou le fichier CA-bundle, le certificat racine n'est pas considéré comme fiable et la connexion TLS échoue.

Si le certificat CA ou le fichier CA-bundle est trouvé dans le magasin de confiance, le processus continue en remontant la chaîne de certificats, en vérifiant que chaque CA se trouvant sur le chemin est dans le magasin de confiance. Une fois que le certificat CA racine au sommet de la chaîne est vérifié (ainsi que tous les certificats CA intermédiaires se trouvant sur le chemin), le processus peut approuver le certificat feuille du serveur.

Détermination de la confiance

Le handshake TLS

Pour ajouter TLS à une connexion TCP/IP (comme un flux HL7), le client et le serveur doivent effectuer un handshake TLS après que la connexion TCP/IP a été établie. Ce handshake implique de s'accorder sur les chiffrements/méthodes de chiffrement, de s'accorder sur la version TLS, d'échanger des certificats X.509, de prouver la propriété de ces certificats et de valider que chaque partie fait confiance à l'autre.

Les étapes principales d'un handshake TLS sont les suivantes:

  1. Le client établit une connexion TCP/IP avec le serveur.
  2. Le client lance le handshake TLS.
  3. Le serveur envoie son certificat (et la preuve de sa propriété) au client.
  4. Le client vérifie le certificat du serveur.
  5. En cas de TLS mutuel, le client envoie son certificat (et la preuve de sa propriété) au serveur.
  6. En cas de TLS mutuel, le serveur vérifie le certificat du client.
  7. Le client et le serveur s'échangent des données encryptées.

Handshake TLS

1. Le client établit une connexion TCP/IP avec le serveur.

À l'étape n° 1, le client et le serveur effectuent un handshake TCP à la procédure de base « ternaire » [TCP 3-way handshake] (https://en.wikipedia.org/wiki/Transmission_Control_Protocol#Connection_establishment) pour établir une connexion TCP/IP entre eux. Dans un handshake à la procédure de base ternaire:

  1. Le client envoie un paquet SYN.
  2. Le serveur envoie un paquet SYN-ACK.
  3. Le client envoie un paquet ACK.

Une fois ce handshake terminé, la connexion TCP/IP est établie. L'étape suivante consiste à lancer le handshake TLS.

2. Le client lance le handshake TLS.

Une fois la connexion TCP établie, l'une des parties doit agir en tant que client et lancer le handshake TLS. Généralement, le processus qui a initié la connexion TCP est également responsable du lancement du handshake TLS, mais cela peut être inversé dans de rares cas.

Pour lancer le handshake TLS, le client envoie un message ClientHello au serveur. Ce message contient diverses options utilisées pour négocier les paramètres de sécurité de la connexion avec le serveur.

3. Le serveur envoie son certificat (et la preuve de sa propriété) au client.

Après avoir reçu le message ClientHello du client, le serveur répond à son tour par un message ServerHello. Celui-ci inclut les paramètres de sécurité négociés.

Après le message ServerHello, le serveur envoie également un message Certificate et CertificateVerify au client. Cela permet de partager la chaîne de certificats X.509 avec le client et de fournir la preuve de propriété de la clé privée associée au certificat.

4. Le client vérifie le certificat du serveur.

Une fois que le client a reçu les messages ServerHello, Certificate et CertificateVerify, il vérifie que le certificat est valide et approuvé (en comparant les CAs aux fichiers CA-bundle approuvés, au magasin de certificats du système opérationnel ou au magasin de certificats du navigateur web). Le client effectue également toute vérification de l'hôte (voir ci-dessus) pour s'assurer que l'adresse de connexion correspond aux adresses/IP du certificat.

5. S'il s'agit d'une connexion TLS mutuelle, le client envoie son certificat (et la preuve de propriété) au serveur.

S'il s'agit d'une connexion TLS mutuelle (déterminée par l'envoi d'un message CertificateRequest par le serveur), le client enverra un message Certificate incluant sa chaîne de certificats, puis un message CertificateVerify pour prouver qu'il est le propriétaire de la clé privée associée.

6. S'il s'agit d'une connexion TLS mutuelle, le serveur vérifie le certificat client.

Là encore, s'il s'agit d'une connexion TLS mutuelle, le serveur vérifie que la chaîne de certificats envoyée par le client est valide et approuvée.

7. Le client et le serveur s'échangent des données encryptées.

Si la négociation TLS se déroule sans erreur, le client et le serveur s'échangent des messages Finished (Terminé) pour achever la négociation. Après cela, les données encryptées peuvent être échangées entre le client et le serveur.

Configuration de TLS sur les interfaces HL7

Félicitations d'être arrivé jusqu'ici ! Maintenant que vous savez en quoi consiste TLS, comment procéderiez-vous pour mettre en œuvre le protocole TLS sur vos connexions HL7 ? De manière générale, voici les étapes à suivre pour configurer TLS sur vos connexions HL7.

  1. Choisissez une autorité de certification.
  2. Créez une clé et une demande de signature de certificat.
  3. Obtenez votre certificat auprès de votre CA.
  4. Obtenez la chaîne de certificats pour votre pair.
  5. Créez une configuration SSL pour la connexion.
  6. Ajoutez la configuration SSL à l'interface, faites rebondir l'interface et vérifiez le flux de messages.

1. Choisissez une autorité de certification.

La procédure que vous utiliserez pour obtenir un certificat et une clé pour votre serveur dépendra largement des politiques de sécurité de votre entreprise. Dans la plupart des cas, votre certificat sera signé par l'une des autorités de certification suivantes:

  1. Votre certificat sera signé par une CA interne à l'entreprise.
  • C'est mon option préférée, car votre entreprise dispose déjà de l'infrastructure nécessaire pour gérer les certificats et les CAs. Il vous suffit de travailler avec l'équipe qui possède cette infrastructure pour obtenir votre propre certificat pour vos interfaces HL7.
  1. Votre certificat sera signé par une CA publique.
  • Cette option est intéressante dans le sens où la CA publique dispose également de toute l'infrastructure nécessaire pour maintenir les certificats et les CAs. Cette option est sans doute exagérée pour la plupart des interfaces HL7, car les CA publiques fournissent généralement des certificats pour l'Internet ouvert ; les interfaces HL7 ont tendance à se connecter via un intranet privé, et non via l'Internet public.
  • L'obtention de certificats auprès d'une CA publique peut également entraîner des frai.
  1. Votre certificat sera signé par une CA que vous créerez et maintiendrezvous-même.
  • Cette option peut vous convenir, mais malheureusement, cela signifie que vous supportez la charge de la maintenance et de la sécurisation de votre configuration CA et de votre logiciel.
  • Vous l'utilisez à vos risques et périls!
  • Cette option est la plus complexe. Préparez-vous à une courbe d'apprentissage abrupte.
  • Vous pouvez utiliser des progiciels open source éprouvés pour gérer votre CA et vos certificats. La suite OpenSSL est une excellente option. Les autres options sont EJBCA, step-ca et cfssl.

2. Créez une clé et une demande de signature de certificat.

Après avoir choisi votre CA, l'étape suivante consiste à créer une clé privée et une demande de signature de certificat (CSR) . La manière dont vous générez la clé et la CSR dépendra de la politique de votre entreprise et de la CA choisie. Pour l'instant, nous allons simplement parler des étapes de manière générale.

Lors de la génération d'une clé privée, la clé publique associée est également générée. La clé publique sera intégrée à votre CSR et à votre certificat signé. Ces deux clés seront utilisées pour prouver la propriété de votre certificat signé lors de l'établissement d'une connexion TLS.

ATTENTION! Veillez à enregistrer votre clé privée dans un endroit sûr (de préférence dans un format protégé par un mot de passe). Si vous perdez cette clé, votre certificat ne sera plus utilisable. Si quelqu'un d'autre accède à cette clé, il pourra se faire passer pour votre serveur.

La demande de signature de certificat inclura des informations sur votre serveur, votre entreprise, votre clé publique, la manière d'utiliser le certificat, etc. Elle inclura également la preuve que vous possédez la clé privée associée. Cette CSR sera ensuite fournie à votre CA pour générer et signer votre certificat.

REMARQUE: lors de la création de la CSR, assurez-vous de demander une Extended Key Usage (utilisation étendue de la clé) à la fois pour serverAuth et clientAuth, si vous utilisez le TLS mutuel. La plupart des CA sont habituées à signer des certificats avec uniquement la clé serverAuth. Malheureusement, cela signifie que le certificat ne peut pas être utilisé comme certificat client dans une connexion TLS mutuelle.

3. Obtenez votre certificat auprès de votre CA.

Après avoir créé votre clé et votre CSR, soumettez la CSR à votre autorité de certification. Après avoir effectué plusieurs vérifications, votre CA devrait être en mesure de vous fournir un certificat signé et la chaîne de certificats associée. Ce certificat et cette chaîne doivent être enregistrés au format PEM. Si la CA a fourni votre certificat dans un format différent, vous devrez le convertir à l'aide d'un outil tel qu'OpenSSL.

4. Obtenez la chaîne de certificats pour votre homologue.

Les étapes précédentes étaient axées sur l'obtention d'un certificat pour votre serveur. Vous devriez pouvoir utiliser ce certificat (et la clé associée) avec chaque connexion HL7 vers/depuis ce serveur. Vous devrez également obtenir les chaînes de certificats pour chacun des systèmes/homologues auxquels vous vous connecterez.

Les chaînes de certificats de chaque homologue devront être enregistrées dans un fichier au format PEM. Ce CA-bundle n'aura pas besoin de contenir les certificats feuille ; il doit uniquement contenir les certificats CA intermédiaires et racine.

Veillez à fournir à votre homologue un CA-bundle contenant vos CA intermédiaires et racine. Cela lui permettra de faire confiance à votre certificat lorsque vous établirez une connexion.

5. Créez une configuration SSL pour la connexion.

Dans Health Connect d'InterSystems, il vous faudra créer des configurations SSL client et serveur pour chaque système auquel votre serveur se connectera. Ces configurations SSL dirigeront vers le fichier CA-bundle du système associé et vers les fichiers clé et de certificat de votre serveur.

Les configurations SSL client sont utilisées lors des opérations pour lancer le handshake TLS. Les configurations SSL serveur sont utilisées sur les services pour répondre aux handshakes TLS. Si un système dispose à la fois de services entrants et de services sortants, il faudra configurer à la fois une configuration SSL client et une configuration SSL serveur pour ce système.

Pour créer une configuration SSL client:

  1. Accédez à System Administration > Security > SSL/TLS Configurations (Administration système > Sécurité > Configurations SSL/TLS).
  2. Appuyeze sur Create New Configuration (Créer une nouvelle configuration).
  3. Donnez un Configuration Name (Nom de configuration) et une Description (Description) à votre configuration SSL.
  4. Assurez-vous que votre configuration SSL est Enabled (Activée).
  5. Choisissez Client comme Type.
  6. Choisissez Require (Obligatoire) pour le champ Server certificate verification (Vérification du certificat serveur). Cela effectue une vérification de l'hôte sur la connexion.
  7. Dirigez le champ File (Fichier) contenant le(s) certificat(s) CA de confiance vers le fichier CA-bundle contenant les CA intermédiaires et racines (au format PEM) du système auquel vous vous connectez.
  8. Dirigez le champ File (Fichier) contenant le certificat de ce client vers le fichier contenant le certificat X.509 de votre serveur au format PEM.
  9. Dirigez le champ File (Fichier) contenant la clé privée associée vers le fichier contenant la clé privée de votre certificat.
  10. Le Private key type (type de clé privée) sera très probablement RSA (chiffrement RSA). Cela devrait correspondre au type de votre clé privée.
  11. Si votre clé privée est protégée par un mot de passe (comme cela devrait être le cas), saisissez le mot de passe dans les champs Private key password (mot de passe de la clé privée) et Private key password (confirm) (confirmer le mot de passe de la clé privée).
  12. Vous pouvez probablement laisser les autres champs à leurs valeurs par défaut.

Pour créer une configuration de serveur SSL:

  1. Go to System Administration > Security > SSL/TLS Configurations.
  2. Appuyeze sur Create New Configuration (Créer une nouvelle configuration).
  3. Donnez un Configuration Name (Nom de configuration) et une Description (Description) à votre configuration SSL.
  4. Assurez-vous que votre configuration SSL est Enabled (Activée).
  5. Choisissez Server comme Type.
  6. Choisissez Require (Obligatoire) pour le champ Client certificate verification (Vérification du certificat client). Cela permettra de s'assurer que le TLS mutuel est exécuté.
  7. Dirigez File containing trusted Certificate Authority certificate(s) (Fichier contenant le(s) certificat(s) de l'autorité de certification de confiance) vers le fichier CA-bundle contenant les CA intermédiaires et racines (au format PEM) du système auquel vous vous connectez.
  8. Dirigez File containing this server's certificate (Fichier contenant le certificat de ce serveur) vers le fichier contenant le certificat X.509 de votre serveur au format PEM.
  9. Dirigez File containing associated private key (Fichier contenant la clé privée associée) vers le fichier contenant la clé privée de votre certificat.
  10. Le Private key type (type de clé privée) sera très probablement RSA (chiffrement RSA). Cela devrait correspondre au type de votre clé privée.
  11. Si votre clé privée est protégée par un mot de passe (comme cela devrait être le cas), saisissez le mot de passe dans les champs Private key password (mot de passe de la clé privée) et Private key password (confirm) (confirmer le mot de passe de la clé privée).
  12. Vous pouvez probablement laisser les autres champs à leurs valeurs par défaut.

configuration de configuration SSL

6. Ajoutez la configuration SSL à l'interface, relancez l'interface et vérifiez le flux de messages.

Une fois que vous avez créé les configurations SSL client et serveur, vous êtes prêt à activer TLS sur les interfaces. Pour chaque service ou opération, choisissez la configuration SSL associée dans le menu déroulant Connection Settings > SSL Configuration (Paramètres de connexion > Configuration SSL) qui se trouve dans l'onglet Settings (Paramètres) de l'interface.

Après avoir relancé l'interface, vous verrez la connexion se rétablir. Lorsqu'un nouveau message est transféré, un statut Completed (Terminé) indique que TLS fonctionne. Si TLS ne fonctionne pas, la connexion sera interrompue à chaque tentative de message.

Pour vous aider à déboguer les problèmes avec TLS, il se peut que vous ayez besoin d'utiliser des outils tels que tcpdump, Wireshark ou l'utilitaire s_client d'OpenSSL.

Conclusion

Nous avons fait une analyse très approfondie du sujet SSL/TLS. Il y a tellement d'autres informations qui n'ont pas été incluses dans cet article. J'espère que cet article vous a fourni un aperçu suffisant du fonctionnement de TLS pour que vous puissiez rechercher les détails et obtenir plus d'informations si nécessaire.

Si vous recherchez une ressource approfondie sur TLS, consultez le site Web d'Ivan Ristić, fiestyduck.com et son livre, Bulletproof TLS and PKI. J'ai trouvé que ce livre était une excellente ressource pour en savoir plus sur l'utilisation de TLS.

0
0 48
InterSystems officiel Adeline Icard · Avr 23, 2025

Les versions de maintenance 2024.1.4 et 2023.1.6 de la plateforme de données InterSystems IRIS®, d'InterSystems IRIS® for HealthTMet de HealthShare® Health Connect sont désormais disponibles en disponibilité générale (GA). Ces versions incluent les correctifs pour l'alerte suivante récemment émise : Alerte : Requêtes SQL renvoyant des résultats erronés | InterSystems. N'hésitez pas à partager vos commentaires via la Communauté des développeurs afin que nous puissions développer ensemble un meilleur produit.

Documentation

0
0 52
Article Iryna Mykhailova · Avr 10, 2025 3m read

Le mappeur d'enregistrements complexes peut vous aider à transformer des données de fichiers texte composées de différents types d'enregistrements en messages persistants dans IRIS. Pour comprendre les bases du mappeur d'enregistrements complexes et découvrir un exemple de mise en œuvre en production, visionnez la vidéo des services d'apprentissage.

0
0 32
InterSystems officiel Adeline Icard · Avr 8, 2025

Résumé des alertes

Alert ID Produit et versions concernés Exigences explicites
DP-439207 Plateforme de données InterSystems IRIS® 2024.3 (AIX) Installations AIX utilisant le traitement JSON et les caractères Unicode non-Latin-1
DP-439280 InterSystems IRIS 2024.3 (conteneurs avec IntegratedML) Conteneurs IntegratedML utilisant TensorFlow

Détail des alertes

DP-439207 - Problème d'analyse JSON Unicode AIX

Un bug a été identifié dans InterSystems IRIS 2024.3.0 sur les instances AIX. Il affecte l'analyse des chaînes JSON Unicode. Ce problème survient lorsque la méthode %FromJSON() ou %FromJSONFile() analyse des chaînes contenant des caractères dont la valeur est inférieure à $CHAR(256) suivis de caractères Unicode dont la valeur est supérieure à $CHAR(255). Le processus de conversion transforme incorrectement les premiers caractères en $CHAR(0), ce qui entraîne une corruption silencieuse des données. Ce problème concerne uniquement la version AIX 2024.3 des produits suivants :

  • InterSystems IRIS
  • InterSystems IRIS for Health
  • HealthShare® Health Connect
0
0 24
InterSystems officiel Adeline Icard · Mars 27, 2025

InterSystems annonce la disponibilité générale d'InterSystems IRIS, InterSystems IRIS for Health et HealthShare Health Connect 2025.1.

La version 2025.1 de la plateforme de données InterSystems IRIS®, InterSystems IRIS® for HealthTM et HealthShare® Health Connect est désormais disponible. Il s'agit d'une version en maintenance prolongée.

Points forts de la version

Cette nouvelle version propose plusieurs nouvelles fonctionnalités et améliorations, notamment :

1. Fonctionnalités avancées de recherche vectorielle

0
0 28
Article Sylvain Guilbaud · Fév 26, 2025 7m read

L'utilisation de Embedded Python lors de la création d'une solution basée sur InterSystems peut ajouter des fonctionnalités très puissantes et approfondies à votre boîte à outils.

J'aimerais partager un exemple de cas d'utilisation que j'ai rencontré : l'activation d'un CDC (Change Data Capture) pour une collection mongoDB - la capture de ces modifications, leur digestion via un flux d'interopérabilité et, pour finir, la mise à jour d'un EMR via une API REST.

0
0 39
InterSystems officiel Adeline Icard · Fév 20, 2025

19 février 2025 – Alerte : les requêtes SQL renvoient des résultats erronés

InterSystems a corrigé deux problèmes pouvant entraîner le renvoi de résultats erronés par un petit nombre de requêtes SQL. De plus, InterSystems a corrigé une incohérence dans la gestion des types de données date/heure qui peut entraîner des résultats différents, inattendus, mais corrects, pour les applications existantes qui s'appuient sur le comportement antérieur et incohérent.

DP-436825 : les requêtes SQL avec jointure latérale peuvent renvoyer des résultats erronés

0
0 31
Article Iryna Mykhailova · Fév 19, 2025 3m read

Pour l'un de nos clients, j'ai dû intégrer le point de terminaison AFAS imageconnector /imageconnector/{imageId}?format={format}. Ce point de terminaison renvoie un message json avec l'image comme propriété de chaîne codée en base64, en plus du type MIME de l'image :

/// Objet image
Class Mycustomer.Model.AfasGet.Image Extends (%SerialObject, %XML.Adaptor, %JSON.Adaptor)
{
/// données de fichier (encodées en base64)
Property Filedata As %String(%JSONFIELDNAME = "filedata");

/// MimeType par exemple "image/jpeg"
Property MimeType As %String(%JSONFIELDNAME = "mimetype");
}

Dans la classe Message, nous avons essayé de gérer cela comme :

Property Image As Mycustomer.Model.AfasGet.Image;

/// Réponse AFAS GetImage
/// get /imageconnector/{imageId}?format={format}
Method LoadFromResponse(httpResponse As %Net.HttpResponse, caller As %String = "") As %Status
{
	Set sc = $$$OK

	If $$$LOWER($Piece(httpResponse.ContentType,";",1))="application/json",httpResponse.StatusCode = "200" {
		set ..Image = ##class(Mycustomer.Model.AfasGet.Image).%New()
		set ..status = ..Image.%JSONImport(httpResponse.Data)
	}

	Return sc
}

Tout cela a bien fonctionné jusqu'à ce qu'à un moment donné, la taille des données du fichier devienne supérieure à $$$MaxStringLength (3641144), auquel cas une MAXSTRING exception a été levée.

L'étape logique suivante consistait à modifier le type de la propriété filedata en %Stream.GlobalCharacter :

/// Objet image
Class Mycustomer.Model.AfasGet.Image Extends (%SerialObject, %XML.Adaptor, %JSON.Adaptor)
{
/// Données de fichier (encodées en base64)
Property Filedata As %Stream.GlobalCharacter(%JSONFIELDNAME = "filedata");

/// Type Mime par exemple "image/jpeg"
Property MimeType As %String(%JSONFIELDNAME = "mimetype");
}

Mais cela n'a pas fonctionné, %JSONImport() générait toujours une erreur MAXSTRING.

J'ai ensuite essayé Python, mais comme je ne suis pas un expert en Python, j'ai finalement abandonné cette voie.

Grâce à la réponse de https://community.intersystems.com/user/steven-hobbs sur https://community.intersystems.com/post/maxstring-trying-read-string-json-object#comment-250216, j'ai alors appris qu'il est possible et simple de récupérer les propriétés de la chaîne json dans un flux en utilisant image.%Get("filedata", , "stream")):

Method LoadFromResponse(httpResponse As %Net.HttpResponse, caller As %String = "") As %Status
{
	Set sc = $$$OK

	If $$$LOWER($Piece(httpResponse.ContentType,";",1))="application/json",httpResponse.StatusCode = "200" {
		set ..Image = ##class(Mycustomer.Model.AfasGet.Image).%New()
		set image = {}.%FromJSON(httpResponse.Data)
		set ..Image.MimeType = image.mimetype
		set ..Image.Filedata = ##class(%Stream.GlobalCharacter).%New()
		do ..Image.Filedata.CopyFrom(image.%Get("filedata", , "stream"))
	}

	Return sc
}

Je ne sais toujours pas comment je pourrais instruire la classe %JSON.Adaptor et utiliser la logique intégrée pour mapper vers un flux. Si quelqu'un sait comment faire cela, faites-le moi savoir !

0
0 37
InterSystems officiel Adeline Icard · Fév 4, 2025

Les dernières versions de maintenance étendue d'InterSystems IRIS, InterSystems IRIS for Health et HealthShare Health Connect sont désormais disponibles.

✅ 2024.1.3

La version 2024.1.3 fournit des correctifs de bogues pour toutes les versions 2024.1.x précédentes, y compris le correctif pour l'alerte suivante récemment émise - Alerte : Données non valides introduites dans la base de données et les fichiers journaux avec des....

Vous trouverez les listes de modifications détaillées et les listes de contrôle de mise à niveau sur ces pages :

0
0 29
Article Iryna Mykhailova · Jan 27, 2025 1m read

Dans votre production d'interopérabilité, vous pouvez toujours avoir une Business Operation qui est un client HTTP, qui utilise OAuth 2.0 pour l'authentification, mais vous avez du personnaliser l'opération pour cette méthodologie d'authentification. Depuis la version v2024.3, qui a été récemment publiée, il existe une nouvelle fonctionnalité, fournissant de nouveaux paramètres, pour gérer cela plus facilement.

Dans votre Business Operation qui utilise l'outbound adaptateur HTTP, vous trouverez de nouveaux paramètres, sous le groupe OAuth.

0
0 42
InterSystems officiel Adeline Icard · Jan 21, 2025

InterSystems a corrigé un défaut qui provoque l'introduction d'enregistrements de base de données et de journaux non valides lors de l'utilisation d'une syntaxe $LIST spécifique. La probabilité de rencontrer ce défaut est très faible, mais les impacts opérationnels peuvent être importants.

Produits concernés

0
0 32
Article Sylvain Guilbaud · Jan 2, 2025 10m read

Votre mission

Imaginons que vous êtes un espion international qui consacre sa vie à protéger les habitants de notre planète contre les dangers. La mission suivante vous est confiée:

Cher agent IRIS,

Nous sommes désolés d'interrompre vos vacances aux Bahamas, mais notre agent à Londres vient de nous informer qu'une "bombe à explosion retardée" est prête à exploser dans une zone très peuplée de Los Angeles. Selon nos informateurs, la "bombe à explosion retardée" devrait se déclencher à 15h14 aujourd'hui.

Dépêchez-vous, les citoyens comptent sur vous!

Le problème

Alors que vous vous précipitez et vous préparez à partir pour Los Angeles, vous vous rendez compte qu'il vous manque un renseignement essentiel : cette "bombe à explosion retardée" explosera-t-elle à 15h14 heure des Bahamas ou à 15h14 heure de Los Angeles? ...ou peut-être même à 15h14 heure de Londres.

Vous comprenez bien vite que l'heure fournie (15h14) ne vous donne pas assez de renseignements pour déterminer le moment où vous devez vous rendre à Los Angeles.

L'heure indiquée (15h14) était ambiguë. Vous avez besoin de plus de renseignements pour déterminer une heure exacte.

Quelques solutions

Lorsque vous réfléchissez au problème, vous vous rendez compte qu'il existe des méthodes pour surmonter l'ambiguïté de l'heure indiquée qui vous a été fournie:

  1. Votre informateur aurait pu vous fournir le lieu où l'heure locale était 3:14 PM. Par exemple, Los Angeles, les Bahamas, ou Londres.

  2. Votre informateur aurait pu utiliser un standard telle que l'UTC (temps universel coordonné) pour vous fournir un décalage par rapport à un lieu convenu (tel que Greenwich, Londres).

La fin heureuse

Vous téléphonez à votre informateur et confirmez que l'heure fournie était bien 15h14 heure de Los Angeles. Vous pouvez vous rendre à Los Angeles, désamorcer la "bombe à explosion retardée" avant 15h14, et retourner rapidement aux Bahamas pour y terminer vos vacances.

Le but

Quel est donc le but de cet exercice de réflexion? Je doute qu'aucun d'entre nous soit confronté au problème présenté ci-dessus, mais si vous travaillez avec une application ou un code qui déplace des données d'un lieu à un autre (en particulier si les lieux se trouvent dans des fuseaux horaires différents), vous devez savoir comment gérer les dates-heures et les fuseaux horaires.

Les fuseaux horaires, C'EST DUR!

Eh bien, les fuseaux horaires ne sont pas si mauvais. Ce sont l'heure d'été et les périmètres politiques qui rendent les fuseaux horaires si difficiles à gérer.

Je croyais avoir toujours compris l'idée "générale" des fuseaux horaires: le globe est divisé en tranches verticales par fuseau horaire, où chaque fuseau horaire est en retard d'une heure par rapport au fuseau horaire situé à l'Est.

Les fuseaux horaires sur la carte du monde (simplification)

Bien que cette simplification soit valable pour de nombreux endroits, il existe malheureusement de nombreuses exceptions à cette règle.

Fuseaux horaires du monde (Wikipedia) Référence: Fuseaux horaires du monde (Wikipedia)

Représentation du temps UTC ("l'origine")

Pour simplifier la communication de l'heure spécifique, le monde a décidé d'utiliser l'UTC (le temps universel coordonné). Ce standard fixe "l'origine" à la longitude 0° qui passe par Greenwich, Londres.

Définition du "décalage"

En utilisant le temps universel coordonné (UTC) comme base, tous les autres fuseaux horaires peuvent être définis par rapport à l'UTC. Cette relation est appelée décalage UTC.

Si vous connaissez l'heure locale et le décalage, vous n'avez plus d'heure ambiguë (comme dans notre exemple d'espionnage ci-dessus) ; vous avez une heure définie et spécifique, sans ambiguïté.

Le format type utilisé pour indiquer le décalage UTC est le suivant: ±HHMM[SS[.ffffff]].

  • Le symbole moins - indique un décalage à l'ouest de l'UTC.
  • Le signe plus + indique un décalage à l'est de l'UTC..
  • HH indique les heures (avec un zéro initial)
  • MM indique les minutes (avec un zéro initial)
  • SS indique les secondes (avec un zéro initial)
  • .ffffff indique les fractions de secondes

Par exemple, en Amérique, le fuseau horaire de l'Est (EST) est défini comme -0500 UTC. Cela signifie que toutes les localités situées dans le fuseau horaire EST sont en retard de 5 heures par rapport à l'UTC. Si l'heure est 9:00 PM à UTC, l'heure locale à EST est 4:00 PM.

Dans le fuseau horaire central occidental d'Australie (ACWST), le décalage est défini comme +0845 UTC. Si l'heure est 21h00 à UTC, l'heure locale d'EST est 16h00.

Heure d'été

Revenons aux cartes des fuseaux horaires ci-dessus. Vous y trouverez de nombreux fuseaux horaires qui suivent les frontières politiques des pays et des régions. Cela complique légèrement le calcul des fuseaux horaires, mais c'est assez facile à comprendre.

Malheureusement, il y a un autre élément à prendre en compte lorsque l'on travaille avec des heures et des fuseaux horaires. Regardons Los Angeles.

Cette carte indique que le décalage UTC pour Los Angeles est de -8 en Standard Time. L'heure normale est généralement suivie pendant les mois d'hiver, tandis que l'heure d'été est généralement suivie pendant les mois d'été.

L'heure d'été (en anglais; Daylight Savings Time (DST) avance les horloges d'un fuseau horaire donné (généralement d'une heure pendant les mois d'été). Les régions politiques peuvent choisir de suivre l'heure d'été pour plusieurs raisons (économies d'énergie, meilleure utilisation de la lumière du jour, etc.) La difficulté et la complexité de l'heure d'été résident dans le fait que l'heure d'été n'est pas appliquée de manière uniforme dans le monde entier. Selon votre situation géographique, votre région peut suivre ou non l'heure d'été.

Base de données de fuseaux horaires

La combinaison des frontières politiques et de l'heure d'été augmentant considérablement la complexité de la détermination d'une heure spécifique, une base de données des fuseaux horaires est nécessaire pour faire correspondre correctement les heures locales à des heures spécifiques par rapport à l'UTC. La base de données des fuseaux horaires de l'IANA (Internet Assigned Numbers Authority) est la source commune de renseignements sur les fuseaux horaires utilisée par les systèmes d'exploitation et les langages de programmation.

La base de données comprend les noms et alias de tous les fuseaux horaires, des renseignements sur le décalage, des renseignements sur l'utilisation de l'heure d'été, les abréviations des fuseaux horaires et les plages de données auxquelles les différentes règles s'appliquent.

Des copies et des renseignements concernant la base de données sur les fuseaux horaires sont disponibles sur le site web de l'IANA.

La plupart des systèmes UNIX disposent d'une copie de la base de données qui est mise à jour par le gestionnaire de paquetages du système d'exploitation (généralement installé dans /usr/share/zoneinfo). Certains langages de programmation ont la base de données intégrée. D'autres la rendent disponible par le biais d'une bibliothèque ou peuvent lire la copie de la base de données du système.

Noms et identifiants des fuseaux horaires

La base de données des fuseaux horaires contient un grand nombre de noms et d'alias pour des fuseaux horaires spécifiques. La plupart des saisies incluent un pays (ou un continent) et une grande ville dans le nom. Par exemple:

  • Amérique/New_York
  • Amérique/Los_Angeles
  • Europe/Rome
  • Australie/Melbourne

Conversion et formatage à l'aide d'ObjectScript

Ainsi, voici ce que nous savons:

  • les heures locales (heures ambiguës sans décalage ni emplacement)
  • les décalages UTC (le décalage relatif d'un horodatage ou d'un emplacement par rapport à l'« origine » UTC à Greenwich, Londres)
  • l'heure d'été (une tentative d'aider la civilisation au détriment des décalages de fuseaux horaires)
  • base de données des fuseaux horaires (qui contient des renseignements sur les fuseaux horaires et le respect de l'heure d'été dans de nombreux lieux et régions).

Sachant cela, comment pouvons-nous travailler avec les heures-dates et les fuseaux horaires en ObjectScript?

***Note: Je crois que toutes les affirmations suivantes sont vraies à propos d'ObjectScript, mais n'hésitez pas à me faire savoir si j'ai mal expliqué comment ObjectScript fonctionne avec les fuseaux horaires et les décalages.

Variables et fonctions intégrées

Si vous avez besoin de convertir des horodatages entre différents formats dans le fuseau horaire du processus exécutant IRIS, les fonctionnalités intégrées d'ObjectScript devraient être suffisantes. Voici une brève liste des variables/fonctions relatives au temps dans ObjectScript:

  • $ZTIMESTAMP / $ZTS

    • Format interne d'IRIS en tant que valeur UTC (décalage +0000).
    • Format: ddddd,sssss.fffffff
  • $NOW(tzmins)

    • Heure locale du système actuel avec le décalage de tzmins donné par rapport à UTC.
    • Heure d'été n'est pas prise en compte.
    • Par défaut, tzmins est basé sur la variable $ZTIMEZONE.
    • Format: ddddd,sssss.fffffff
  • $HOROLOG

    • Heure locale actuelle du système (basée sur $ZTIMEZONE), avec prise en compte de l'heure d'été.
    • Format: ddddd,sssss.fffffff
  • $ZTIMEZONE

    • Renvoie ou définit le décalage UTC local du système en minutes.
  • $ZDATETIME() / $ZDT()

    • Conversion du format $HOROLOG en un format d'affichage spécifique.
    • Peut être utilisé pour la conversion de l'heure locale du système à l'heure UTC (+0000).
  • $ZDATETIMEH() / $ZDTH()

    • Conversion d'une chaîne de date au format interne $HOROLOG.
    • Peut être utilisé pour convertir l'heure UTC (+0000) en heure locale.

Pour autant que je sache, ces fonctionnalités ne peuvent manipuler les dates qu'en utilisant le fuseau horaire du système local. Il ne semble pas y avoir de moyen de travailler avec des fuseaux horaires arbitraires en ObjectScript.

Accès à la bibliothèque tz sur Open Exchange

Pour faciliter la conversion vers et depuis des fuseaux horaires arbitraires, j'ai créé la bibliothèque de conversion de fuseaux horaires ObjectScript tz - ObjectScript Time Zone Conversion Library.

Cette bibliothèque accède à la base de données des fuseaux horaires installée sur votre système afin d'offrir un support pour la conversion des horodatages entre les fuseaux horaires et les formats.

Par exemple, si vous disposez de l'heure locale de Los Angeles (Amérique/Los_Angeles), vous pouvez la convertir dans le fuseau horaire utilisé aux Bahamas (Amérique/New_York) ou dans le fuseau horaire utilisé à Londres (Europe/Londres):

USER>zw ##class(tz.Ens).TZ("2024-12-20 3:14 PM", "America/Los_Angeles", "America/New_York")
"2024-12-20 06:14 PM"

USER>zw ##class(tz.Ens).TZ("2024-12-20 3:14 PM", "America/Los_Angeles", "Europe/London")
"2024-12-20 11:14 PM"

Si l'on vous donne un horodatage avec un décalage, vous pouvez le convertir en heure locale à Eucla, Australie (Australie/Eucla), même si vous ne connaissez pas le fuseau horaire d'origine:

USER>zw ##class(tz.Ens).TZ("2024-12-20 08:00 PM -0500", "Australia/Eucla")
"2024-12-21 09:45 AM +0845"

Si vous travaillez avec des messages HL7, la bibliothèque tz dispose de plusieurs méthodes associées aux règles d'interopérabilité et aux DTL pour vous aider à convertir facilement les fuseaux horaires, les heures locales, les heures avec décalage, etc.:

// Conversion de l'heure locale d'un fuseau horaire à l'autre 	 
set datetime = "20240102033045"
set newDatetime = ##class(tz.Ens).TZ(datetime,"America/New_York","America/Chicago")

// Conversion de l'heure locale en décalage 	 
set datetime = "20240102033045"
set newDatetime = ##class(tz.Ens).TZOffset(datetime,"America/Chicago","America/New_York")

// Conversion du décalage en heure locale 	 
set datetime = "20240102033045-0500"
set newDatetime = ##class(tz.Ens).TZLocal(datetime,"America/Chicago")

// Conversion vers un format alternatif au HL7 	 
set datetime = "20240102033045-0500"
set newDatetime = ##class(tz.Ens).TZ(datetime,"America/Chicago",,"%m/%d/%Y %H:%M:%S %z")

Résumé

Je vous remercie de m'avoir suivi dans ce "voyage à travers le monde" où nous avons rencontré des fuseaux horaires, l'heure d'été, les cartes du monde et les "bombes à explosion retardée". J'espère que ce travail vous a permis d'éclairer (et de simplifier) les nombreuses complexités liées à l'utilisation des dates et des fuseaux horaires.

Consultez la bibliothèque tz - ObjectScript Time Zone Conversion Library et faites-moi savoir si vous avez des questions (ou des corrections/clarifications à propos de quelque chose que j'ai dit ici.

Merci!

Références / Liens intéressants

0
0 85
Article Iryna Mykhailova · Déc 13, 2024 3m read

Comme beaucoup d'autres se retrouvent probablement, nous étions obligés de faire un mappage de données en direct dans notre moteur d'interface, ce que nous ne voulions vraiment pas faire, mais nous n'avions pas de bon choix alternatif. Nous voulons uniquement conserver les mappages aussi longtemps que nécessaire, puis purger les lignes expirées en fonction d'une valeur TTL. Nous avions en fait 4 cas d'utilisation pour cela nous-mêmes avant de créer cela. Cas d'utilisation :

0
0 38
InterSystems officiel Adeline Icard · Déc 12, 2024

Les premiers aperçus pour les développeurs de la plateforme de données InterSystems IRIS®, InterSystems IRIS® for Health et HealthShare® Health Connect 2025.1 ont été publiés sur le site d'aperçus pour les développeurs sur WRC. Les conteneurs sont disponibles dans notre registre de conteneurs et sont étiquetés latest-preview.

0
0 45
Article Iryna Mykhailova · Déc 3, 2024 2m read

L'audit est une fonctionnalité essentielle pour garantir la sécurité de votre serveur. Depuis un certain temps déjà, nous avons inclus la possibilité d'auditer les instructions SQL exécutées sur le serveur.

Avec la version 2024.3 déjà disponible, nous proposons des options plus précises pour définir ces événements à auditer.

0
0 30
Article Iryna Mykhailova · Nov 28, 2024 1m read

La possibilité de renvoyer facilement des messages a toujours été une caractéristique importante de nos capacités d'interopérabilité.

Avec la sortie de la version 2024.3, nous avons rendu cela encore plus facile !

0
0 43