Notes
L’accès à cette page nécessite une autorisation. Vous pouvez essayer de vous connecter ou de modifier des répertoires.
L’accès à cette page nécessite une autorisation. Vous pouvez essayer de modifier des répertoires.
Le service DICOM® charge automatiquement les fichiers DICOM dans Azure Data Lake Storage (ADLS) lors de l’utilisation de STOW-RS. De cette façon, les utilisateurs peuvent interroger leurs données à l’aide d’API DICOMweb™, comme WADO-RS, ou des API Azure Blob/Data Lake. Toutefois, avec l’indexation du stockage, le service DICOM indexe automatiquement les fichiers DICOM après leur chargement directement dans le système de fichiers ADLS Gen 2. Que les fichiers aient été chargés à l’aide de STOW-RS, d’un Kit de développement logiciel (SDK) Blob Azure ou même d’AzCopy, ils sont accessibles à l’aide d’API DICOMweb™ ou ADLS Gen 2.
Conditions préalables
- Un compte de stockage Azure configuré avec des espaces de noms hiérarchiques (HNS) activés
- Un service DICOM facultatif connecté au système de fichiers Azure Data Lake Storage
Configuration de l’indexation du stockage
Le service DICOM indexe un système de fichiers ADLS Gen2 en réagissant aux événements de stockage Blob ou Data Lake. Ces événements doivent être lus à partir d’une file d’attente de stockage Azure dans le compte de stockage Azure qui contient le système de fichiers. Une fois dans la file d’attente, le service DICOM traite de façon asynchrone chaque événement et met à jour l’index en conséquence.
Créer la destination des événements de stockage
Tout d’abord, créez une file d’attente de stockage dans le même compte de stockage Azure connecté au service DICOM. Le service DICOM doit également avoir accès à la file d’attente. Il doit pouvoir à la fois retirer et ajouter des messages, y compris les messages d’erreur et les tâches complexes décomposées. Par conséquent, assurez-vous que la même identité managée utilisée par le service DICOM, affectée par l’utilisateur ou affectée par le système, a le rôle Contributeur aux données de file d’attente de stockage attribué.
Publier les événements de stockage dans la file d’attente
Une fois la file d’attente de stockage en place, les événements doivent être publiés à partir du compte de stockage vers une rubrique système Azure Event Grid et routés vers la file d’attente à l’aide d’un abonnement Azure Event Grid. Avant de créer l’abonnement à l’événement, veillez à accorder le rôle Storage Queue Data Message Sender à l’abonnement à l’événement ; l’abonnement à l’événement nécessite des autorisations pour placer les messages en file d’attente. L’abonnement aux événements peut utiliser une identité gérée attribuée par l’utilisateur ou par le système à partir du sujet système pour authentifier ses opérations.
Remarque
Par défaut, les abonnements aux événements envoient tous les types d’événements auxquels ils sont abonnés vers leur sortie désignée. Toutefois, alors que le service DICOM gère correctement n’importe quel message, il ne peut traiter correctement que ceux qui répondent aux critères suivants :
- Le message doit être un CloudEvent Base64
- Le type d’événement doit être l’un des types d’événements suivants :
Microsoft.Storage.BlobCreated
Microsoft.Storage.BlobDeleted
- Le système de fichiers doit être le même que celui configuré pour le service DICOM
- Le chemin d’accès au fichier doit se trouver dans
AHDS/{workspace-name}/dicom/{dicom-service-name}[/{partition-name}]
- Le fichier doit être un fichier DICOM tel que défini dans la partie 10 de la norme DICOM
- L’opération ne peut pas être effectuée par le service DICOM lui-même.
L’abonnement aux événements peut être configuré pour filtrer les données non pertinentes afin d’éviter le traitement et la facturation inutiles. Veillez à configurer le filtre de sorte que :
- Le sujet doit commencer par
/blobServices/default/containers/{file-system-name}/blobs/AHDS/{workspace-name}/dicom/{dicom-service-name}/
- Si vous le souhaitez, l’objet se termine par
.dcm
- Sous filtres avancés, la clé
data.clientRequestId
ne commence pas partag:{workspace-name}-{dicom-service-name}.dicom.azurehealthcareapis.com,
Activer l’indexation du stockage
Une fois l’abonnement Event Grid configuré, le service DICOM doit savoir où lire les événements de stockage. Dans la préversion, l’indexation du stockage peut uniquement être configurée à l’aide d’un modèle Azure Resource Manager (ARM) à l’aide de la version 2025-04-01-preview
, qui a introduit une nouvelle propriété appelée storageConfiguration.storageIndexingConfiguration.storageEventQueueName
. Il n’est actuellement pas disponible pour configurer via le portail Azure.
L’exemple de modèle ARM suivant peut être déployé à l’aide d’Azure CLI. Il inclut toutes les ressources nécessaires pour un service DICOM :
{
"$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"workspaceName": {
"type": "String"
},
"dicomServiceName": {
"type": "String"
},
"enableDataPartitions": {
"defaultValue": false,
"type": "bool"
},
"storageAccountName": {
"type": "String"
},
"storageAccountSku": {
"defaultValue": "Standard_LRS",
"type": "String"
},
"fileSystemName": {
"type": "String"
},
"storageEventQueueName": {
"defaultValue": "storage-events",
"type": "String"
},
"systemTopicName": {
"type": "String"
},
"eventSubscriptionName": {
"defaultValue": "dicom-storage-events",
"type": "String"
}
},
"variables": {
"storageBlobDataContributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'ba92f5b4-2d11-453d-a403-e96b0029c9fe')]",
"storageQueueDataContributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '974c5e8b-45b9-4653-ba55-5f855dd0fb88')]",
"storageQueueDataMessageSender": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c6a89b2d-59bc-44d0-9896-0f6e12d7b80a')]",
"dicomIdentityName": "[concat(parameters('storageAccountName'), '-', parameters('storageEventQueueName'))]"
},
"resources": [
{
"type": "Microsoft.ManagedIdentity/userAssignedIdentities",
"apiVersion": "2023-01-31",
"name": "[variables('dicomIdentityName')]",
"location": "[resourceGroup().location]"
},
{
"type": "Microsoft.ManagedIdentity/userAssignedIdentities",
"apiVersion": "2023-01-31",
"name": "[parameters('systemTopicName')]",
"location": "[resourceGroup().location]"
},
{
"type": "Microsoft.Storage/storageAccounts",
"apiVersion": "2022-05-01",
"name": "[parameters('storageAccountName')]",
"location": "[resourceGroup().location]",
"sku": {
"name": "[parameters('storageAccountSku')]"
},
"kind": "StorageV2",
"properties": {
"isHnsEnabled": true,
"accessTier": "Hot",
"supportsHttpsTrafficOnly": true,
"minimumTlsVersion": "TLS1_2",
"defaultToOAuthAuthentication": true,
"allowBlobPublicAccess": false,
"allowSharedKeyAccess": false,
"encryption": {
"keySource": "Microsoft.Storage",
"requireInfrastructureEncryption": true,
"services": {
"blob": {
"enabled": true
},
"queue": {
"enabled": true
}
}
}
}
},
{
"type": "Microsoft.Storage/storageAccounts/blobServices/containers",
"apiVersion": "2022-05-01",
"name": "[format('{0}/default/{1}', parameters('storageAccountName'), parameters('fileSystemName'))]",
"dependsOn": [
"[resourceId('Microsoft.Storage/storageAccounts', parameters('storageAccountName'))]"
]
},
{
"type": "Microsoft.Storage/storageAccounts/queueServices/queues",
"apiVersion": "2024-01-01",
"name": "[format('{0}/default/{1}', parameters('storageAccountName'), parameters('storageEventQueueName'))]",
"dependsOn": [
"[resourceId('Microsoft.Storage/storageAccounts', parameters('storageAccountName'))]"
]
},
{
"type": "Microsoft.Storage/storageAccounts/queueServices/queues",
"apiVersion": "2024-01-01",
"name": "[format('{0}/default/{1}-poison', parameters('storageAccountName'), parameters('storageEventQueueName'))]",
"dependsOn": [
"[resourceId('Microsoft.Storage/storageAccounts', parameters('storageAccountName'))]"
]
},
{
"type": "Microsoft.Authorization/roleAssignments",
"apiVersion": "2021-04-01-preview",
"name": "[guid(resourceGroup().id, parameters('workspaceName'), parameters('dicomServiceName'))]",
"location": "[resourceGroup().location]",
"dependsOn": [
"[resourceId('Microsoft.Storage/storageAccounts', parameters('storageAccountName'))]",
"[resourceId('Microsoft.ManagedIdentity/userAssignedIdentities', variables('dicomIdentityName'))]"
],
"properties": {
"roleDefinitionId": "[variables('storageBlobDataContributor')]",
"principalId": "[reference(resourceId('Microsoft.ManagedIdentity/userAssignedIdentities', variables('dicomIdentityName'))).principalId]",
"principalType": "ServicePrincipal"
},
"scope": "[concat('Microsoft.Storage/storageAccounts', '/', parameters('storageAccountName'))]"
},
{
"type": "Microsoft.Authorization/roleAssignments",
"apiVersion": "2021-04-01-preview",
"name": "[guid(resourceGroup().id, parameters('workspaceName'), parameters('dicomServiceName'), parameters('storageEventQueueName'))]",
"location": "[resourceGroup().location]",
"dependsOn": [
"[resourceId('Microsoft.Storage/storageAccounts', parameters('storageAccountName'))]",
"[resourceId('Microsoft.ManagedIdentity/userAssignedIdentities', variables('dicomIdentityName'))]"
],
"properties": {
"roleDefinitionId": "[variables('storageQueueDataContributor')]",
"principalId": "[reference(resourceId('Microsoft.ManagedIdentity/userAssignedIdentities', variables('dicomIdentityName'))).principalId]",
"principalType": "ServicePrincipal"
},
"scope": "[concat('Microsoft.Storage/storageAccounts', '/', parameters('storageAccountName'))]"
},
{
"type": "Microsoft.Authorization/roleAssignments",
"apiVersion": "2021-04-01-preview",
"name": "[guid(resourceGroup().id, parameters('systemTopicName'), parameters('storageEventQueueName'))]",
"location": "[resourceGroup().location]",
"dependsOn": [
"[resourceId('Microsoft.Storage/storageAccounts', parameters('storageAccountName'))]",
"[resourceId('Microsoft.ManagedIdentity/userAssignedIdentities', parameters('systemTopicName'))]"
],
"properties": {
"roleDefinitionId": "[variables('storageQueueDataMessageSender')]",
"principalId": "[reference(resourceId('Microsoft.ManagedIdentity/userAssignedIdentities', parameters('systemTopicName'))).principalId]",
"principalType": "ServicePrincipal"
},
"scope": "[concat('Microsoft.Storage/storageAccounts', '/', parameters('storageAccountName'))]"
},
{
"type": "Microsoft.EventGrid/systemTopics",
"apiVersion": "2025-02-15",
"name": "[parameters('systemTopicName')]",
"location": "[resourceGroup().location]",
"identity": {
"type": "userAssigned",
"userAssignedIdentities": {
"[resourceId('Microsoft.ManagedIdentity/userAssignedIdentities/', parameters('systemTopicName'))]": {}
}
},
"dependsOn": [
"[resourceId('Microsoft.Storage/storageAccounts', parameters('storageAccountName'))]",
"[resourceId('Microsoft.ManagedIdentity/userAssignedIdentities', parameters('systemTopicName'))]"
],
"properties": {
"source": "[resourceId('Microsoft.Storage/storageAccounts', parameters('storageAccountName'))]",
"topicType": "Microsoft.Storage.StorageAccounts"
}
},
{
"type": "Microsoft.EventGrid/systemTopics/eventSubscriptions",
"apiVersion": "2025-02-15",
"name": "[concat(parameters('systemTopicName'), '/', parameters('eventSubscriptionName'))]",
"dependsOn": [
"[resourceId('Microsoft.EventGrid/systemTopics', parameters('systemTopicName'))]"
],
"properties": {
"deliveryWithResourceIdentity": {
"identity": {
"type": "UserAssigned",
"userAssignedIdentity": "[resourceId('Microsoft.ManagedIdentity/userAssignedIdentities', parameters('systemTopicName'))]"
},
"destination": {
"properties": {
"resourceId": "[resourceId('Microsoft.Storage/storageAccounts', parameters('storageAccountName'))]",
"queueName": "[parameters('storageEventQueueName')]",
"queueMessageTimeToLiveInSeconds": 604800
},
"endpointType": "StorageQueue"
}
},
"filter": {
"subjectBeginsWith": "[format('/blobServices/default/containers/{0}/blobs/AHDS/{1}/dicom/{2}/', parameters('fileSystemName'), parameters('workspaceName'), parameters('dicomServiceName'))]",
"subjectEndsWith": ".dcm",
"includedEventTypes": [
"Microsoft.Storage.BlobCreated",
"Microsoft.Storage.BlobDeleted"
],
"isSubjectCaseSensitive": true,
"enableAdvancedFilteringOnArrays": true,
"advancedFilters": [
{
"values": [
"[format('tag:{0}-{1}.dicom.azurehealthcareapis.com,', parameters('workspaceName'), parameters('dicomServiceName'))]"
],
"operatorType": "StringNotBeginsWith",
"key": "data.clientRequestId"
}
]
},
"labels": [],
"eventDeliverySchema": "CloudEventSchemaV1_0",
"retryPolicy": {
"maxDeliveryAttempts": 30,
"eventTimeToLiveInMinutes": 1440
}
}
},
{
"type": "Microsoft.HealthcareApis/workspaces",
"name": "[parameters('workspaceName')]",
"apiVersion": "2025-04-01-preview",
"location": "[resourceGroup().location]"
},
{
"type": "Microsoft.HealthcareApis/workspaces/dicomservices",
"apiVersion": "2025-04-01-preview",
"name": "[concat(parameters('workspaceName'), '/', parameters('dicomServiceName'))]",
"location": "[resourceGroup().location]",
"dependsOn": [
"[resourceId('Microsoft.HealthcareApis/workspaces', parameters('workspaceName'))]",
"[resourceId('Microsoft.ManagedIdentity/userAssignedIdentities', variables('dicomIdentityName'))]",
"[resourceId('Microsoft.EventGrid/systemTopics/eventSubscriptions', parameters('systemTopicName'), parameters('eventSubscriptionName'))]"
],
"identity": {
"type": "userAssigned",
"userAssignedIdentities": {
"[resourceId('Microsoft.ManagedIdentity/userAssignedIdentities/', variables('dicomIdentityName'))]": {}
}
},
"properties": {
"storageConfiguration": {
"storageResourceId": "[resourceId('Microsoft.Storage/storageAccounts', parameters('storageAccountName'))]",
"fileSystemName": "[parameters('fileSystemName')]",
"storageIndexingConfiguration": {
"storageEventQueueName": "[parameters('storageEventQueueName')]"
}
},
"enableDataPartitions": "[parameters('enableDataPartitions')]"
}
}
]
}
Diagnostic des problèmes
Si une erreur survient lors du traitement d’un événement, l’événement problématique est mis en file d’attente dans une « file d’attente des éléments défectueux » appelée {queue-name}-poison
dans le même compte de stockage. Vous trouverez des détails sur chaque événement traité dans les tableaux AHDSDicomAuditLogs
et AHDSDicomDiagnosticLogs
en filtrant tous les journaux où OperationName = 'index-storage'
. Les journaux d’audit enregistrent uniquement lorsque l’opération a démarré et terminé, tandis que la table de diagnostic fournit des détails sur chaque opération, y compris les erreurs, le cas échéant. Les opérations peuvent être corrélées entre les tables à l’aide de CorrelationId
.
Les échecs sont divisés en deux types : User
et Server
. Les erreurs utilisateur incluent tout problème de connexion au compte de stockage ou au fichier DICOM lui-même, tandis que les erreurs du serveur incluent une erreur inattendue qui empêche le traitement. Contrairement aux erreurs de serveur, le service DICOM ne réessaye pas d’erreurs utilisateur.