新しい投稿

查找

記事
· 2024年5月17日 52m read

『 ?ó?? ??????????? Monitorizar ?????????? 】

🙂 Buenos días comunidad.

Me gustaría compartir con ustedes, en este artículo, una manera muy práctica, de obtener información relevante de todos los Namespaces de un Entorno. ¿Para qué?. Pues por ejemplo para uno de los casos de uso que más nos encontramos los desarrolladores con respecto a Healtshare: el desafío de necesitar crear 1 servicio, y la odisea de ir entorno a entorno, namespace a namespace, buscando si el puerto XYZAB está libre o no... 🙃

Para ello, vamos a construirnos un Servicio REST, que reciba peticiones desde el POSTMAN, y entrege toda la información de los namespaces del Entorno consultado.

Supongamos que en una primera aproximación, simplemente queremos obtener todos los datos de 1 Namespace concreto. 

En el Studio nos creamos el Servicio REST así:

Class Servicios.REST.Monitorizacion.ConsultarElementosProduccion Extends Ens.BusinessService
{

Parameter ADAPTER = "EnsLib.HTTP.InboundAdapter";
Parameter EnsServicePrefix = "/monitorizacion";
Method OnProcessInput(pInput As %Stream.Object, Output pOutput As %Stream.Object) As %Status
{
    Set tCmd=$ZConvert(pInput.Attributes("HttpRequest"),"U")
    Set tURL=$ZConvert(pInput.Attributes("URL"),"I","URL")
    
    Set tService="/"_$Piece(tURL,"/",2)    
    
    Quit:..#EnsServicePrefix'=tService $$$ERROR($$$EnsErrGeneral,"Service "_tService_"/ not supported.")
    
    Set tType=$Piece(tURL,"/",3)
    
    set namespace = $Piece(tURL,"/",4)
    
    if (tType = "ConsultarElementosProduccion") {
        do ..ConsultarElementosProduccion(pInput,.pOutput,namespace)
    } 
    
    Quit $$$OK
}

///     Devuelve un mensajes con los Namespaces, sus Producciones y Componentes
Method ConsultarElementosProduccion(pInput As %Stream.Object, Output pOutput As %Stream.Object, namespace As %String(MAXLEN="")) As %Status
{    
    Set pOutput  = ##class(%GlobalBinaryStream).%New()
    set claseAux = ##class(%ZEN.Auxiliary.jsonProvider).%New()
    
    if (##class(Util.FuncionesComunes).getClear(namespace) '= ""){
        set response = ##class(Servicios.REST.Monitorizacion.ConsultarElementosProduccion.Code).ConsultarElementosProduccion(namespace)
    }else{
        set response = ##class(Mensajes.Response.Monitorizacion.ConsultarElementosProduccionResponse).%New()
        set response.error = "Al final de la URL se debe indicar el NAMESPACE del cual necesitamos obtener datos, por ejemplo: 'DRAGOAP', 'ESBSSCC', 'ESBHCDSNS'..."
    }
    
    set tSC = claseAux.%WriteJSONStreamFromObject(.pOutput,.response,,,,"aeloqtuw")
    
    Do:$$$ISOK(tSC) pOutput.SetAttribute("Content-Type","application/json")
    do pOutput.SetAttribute("Access-Control-Allow-Origin","*")
    do pOutput.SetAttribute("Access-Control-Allow-Credentials","true")
    do pOutput.SetAttribute("Access-Control-Allow-Methods","GET")
    do pOutput.SetAttribute("Access-Control-Allow-Headers","request,Access-Control-Allow-Headers, Origin,Accept, X-Requested-With, Content-Type, Access-Control-Request-Method, Access-Control-Request-Headers")
    Quit tSC
}

}

Añadimos el Servicio en la Producción mediante el Portal de Gestión:

 

Lo que hemos hecho hasta ahora es un Servicio que recibe mediante: 
    http://[Entorno]:[Puerto]/monitorizacion/ConsultarElementosProduccion/[NombreDelNamespace]
    
    
Ahora viene el núcleo de la cuestión, el meollo de la lógica. Mediante el siguiente código, recibimos el namespace y estructuramos su información:

Class Servicios.REST.Monitorizacion.ConsultarElementosProduccion.Code
{

ClassMethod ConsultarElementosProduccion(namespace As %String(MAXLEN="")) As Mensajes.Response.Monitorizacion.ConsultarElementosProduccionResponse
{
    ; Se registra un mensaje de información al entrar en el método ConsultarElementosProduccion
    Do ##class(Ens.Util.Log).LogInfo("","","Entra en Servicios.REST.Monitorizacion.ConsultarElementosProduccion.Code ConsultarElementosProduccion()")
    set response = ##class(Mensajes.Response.Monitorizacion.ConsultarElementosProduccionResponse).%New()
    
    ;set string = ""
    
    set rs = ##class(%ResultSet).%New()
    try {
        ; Configuración y ejecución de la consulta para obtener la lista de namespaces
        set rs.ClassName = "%SYS.Namespace"
        set rs.QueryName = "List"
        set tSC = rs.%Execute() 
        if 'tSC {
            ; Si hay un error al ejecutar la consulta, se registran mensajes de error y se sale del método
            Do ##class(Ens.Util.Log).LogInfo("","","catch inicial") 
            Do ##class(Ens.Util.Log).LogError("","",$system.OBJ.DisplayError(tSC)) 
            Do ##class(Ens.Util.Log).LogError("","",$System.Status.GetErrorText(tSC)) 
            kill rs
            quit
        }
        set currentNamespace = $SYSTEM.SYS.NameSpace()
        ; Se registra el namespace actual antes de cambiarlo
        Do ##class(Ens.Util.Log).LogInfo("","","currentNamespace: "_currentNamespace) 
        New $NAMESPACE        
        While rs.%Next(.tSC){
            ; Se recorren los namespaces obtenidos de la consulta
            Do ##class(Ens.Util.Log).LogInfo("","","Entra en WHILE para recorrer Namespaces") 
            set nsp = ""
            set nsp = rs.Data("Nsp")
            Do ##class(Ens.Util.Log).LogInfo("","","1 nsp: "_nsp) 
            
            ; Consultar 1 único namespace según la URL
            if ( nsp = namespace ){
                ; Se registra la entrada al bloque IF
                Do ##class(Ens.Util.Log).LogInfo("","","Entra en IF '= %SYS...")
                Do ##class(Ens.Util.Log).LogInfo("","","2 nsp: "_nsp)
                ; Se cambia el namespace
                Set $NAMESPACE=nsp
                Do ##class(Ens.Util.Log).LogInfo("","","3 nsp: "_nsp)
                Do ##class(Ens.Util.Log).LogInfo("","","Antes de Set $NAMESPACE=nsp")

                Do ##class(Ens.Util.Log).LogInfo("","","Después de Set $NAMESPACE=nsp")
                ; Se crea un objeto para representar el namespace en la base de datos
                set Namespace = ##class(EsquemasDatos.Monitorizacion.Namespace).%New()
                set Namespace.Nombre = $SYSTEM.SYS.NameSpace()
                Do ##class(Ens.Util.Log).LogInfo("","","1111 Namespace.Nombre: "_Namespace.Nombre_"("_nsp_")")
                
                ; Se preparan consultas SQL para obtener información sobre las producciones
                set resultset = ##class(%ResultSet).%New()
                set statement=##class(%SQL.Statement).%New()
                 set enumerate=statement.%PrepareClassQuery("Ens.Config.Production","EnumerateConfigItems")
                 Do ##class(Ens.Util.Log).LogAlert("","","enumerate: "_enumerate)
                 
                 set status=statement.%PrepareClassQuery("Ens.Config.Production","ProductionStatus")
                 Do ##class(Ens.Util.Log).LogAlert("","","status: "_status)
                 Do ##class(Ens.Util.Log).LogInfo("","","status: "_status)
                 
                 set resultset=statement.%Execute()
                 while resultset.%Next() {
                     ; Se recorren las producciones obtenidas de la consulta
                     Do ##class(Ens.Util.Log).LogInfo("","","Entra en el WHILE desde ESBSSCC, que recorre las Producciones")
                     set produccionName = resultset.%Get("Production")
                     set estado = resultset.%Get("StatusEnum")
                     set iniciadoDesde = resultset.%Get("LastStartTime")
                     set paradoDesde = resultset.%Get("LastStopTime")
                     
                     ; Se crea un objeto para representar la producción en la base de datos
                     set Produccion = ##class(EsquemasDatos.Monitorizacion.Produccion).%New()
                     set Produccion.Nombre = produccionName
                     set Produccion.Estado = "Suspendida"
                     set Produccion.Fecha = iniciadoDesde
                         
                     if (estado = 1) {
                         ; Si la producción está en ejecución, se actualiza la información
                         set Produccion.Estado = "En ejecución"
                         set Produccion.Fecha = paradoDesde
                         
                         ; Se obtiene información detallada sobre los componentes de la producción
                         set tProduction = ##class(Ens.Config.Production).%OpenId(produccionName,,.tSC)
                        if (tSC) {
                            Do ##class(Ens.Util.Log).LogInfo("","","tProduction.Items.Count(): "_tProduction.Items.Count())
                            For i=1:1:tProduction.Items.Count() {
                                #dim item as Ens.Config.Item
                                set item = tProduction.Items.GetAt(i)
                                set Componente = ##class(EsquemasDatos.Monitorizacion.Componente).%New()
                                set Componente.Nombre = item.Name
                                
                                set tipo = item.BusinessType()
                                set x = 0
                                if (tipo = "1") {
                                    set Componente.Tipo = "Servicio"
                                    set x = item.GetSetting("Port",.port)
                                    
                                    ; 06/02/2024 Para obtener el puerto de los Servicios DICOM
                                    if (x '= 1)
                                    {
                                        set x = item.GetSetting("IPPort",.port)    
                                    }
                                    
                                } elseif (tipo = "2") {
                                       set Componente.Tipo = "Proceso"
                                       
                                } elseif (tipo = "3") {
                                    set Componente.Tipo = "Operacion"
                                    // Si es SOAP la URL se configura en "WebServiceURL"
                                    set tSC = item.GetSetting("WebServiceURL",.endpoint)
                                    if (tSC = 1){
                                        set Componente.Endpoint = endpoint    
                                    }else{
                                        // Si es REST la URL se configura en "HTTPServer" y/o "URL"
                                        set tSC = item.GetSetting("HTTPServer",.endpoint)
                                        if (tSC = 1){
                                            set Componente.Endpoint = endpoint    
                                        }
                                        set tSC = item.GetSetting("URL",.endpoint)
                                        if (tSC = 1){    
                                            set Componente.Endpoint = Componente.Endpoint_endpoint
                                        }else{
                                            // Si es TCP/HL7 la URL se configura en "IPAddress" y "Port"
                                            set tSC = item.GetSetting("IPAddress",.endpoint)
                                            if (tSC = 1){
                                                set Componente.Endpoint = endpoint
                                                set tSC = item.GetSetting("Port",.endpoint)    
                                                if (tSC = 1){
                                                    set Componente.Endpoint = Componente.Endpoint_":"_endpoint    
                                                }
                                            }else{
                                                // Si ES BBDD se conecta al "DSN"    
                                                set tSC = item.GetSetting("DSN",.endpoint)
                                                if (tSC = 1){
                                                    set Componente.Endpoint = endpoint
                                                }
                                            }
                                                
                                        }        
                                    }
                                }
                                set Componente.Categoria = item.Category
                                ; 24/01/2024 Añadimos para incorporar el PoolSize en la respuesta de los Componentes
                                try{
                                    set Componente.PoolSize = item.PoolSize
                                }catch{
                                    Do ##class(Ens.Util.Log).LogWarning("","","Error en set Componente.PoolSize = item.PoolSize")    
                                }
                                
                                ; Añadimos 30/01/2024 para expresar si está encendido el elemento
                                set Componente.Habilitado = item.Enabled
                                if (x=1) && (tipo="1") {
                                    set Componente.Puerto = port
                                }
                                do Namespace.Componentes.Insert(Componente)    
                            }
                        } else {
                            Do ##class(Ens.Util.Log).LogWarning("","","tSC: "_tSC)
                        }

                     } elseif (estado = 2) {
                         ; Si la producción está detenida, se actualiza la información
                         set Produccion.Estado = "Detenida"
                         set Produccion.Fecha = paradoDesde
                         
                     }
                     do Namespace.Producciones.Insert(Produccion)
                }
                 Do ##class(Ens.Util.Log).LogInfo("","","Antes de do response.Namespaces.Insert(Namespace)")
                do response.Namespaces.Insert(Namespace)
            }
        }
        do rs.Close()
        kill rs
        kill comp
        kill nsp
        kill tSC
        kill statement
        kill status
        kill resultset
        Set $NAMESPACE=currentNamespace
        kill currentNamespace
    } catch {
        ; En caso de excepción, se registran mensajes de error y se limpian las variables
        Do ##class(Ens.Util.Log).LogInfo("","","catch final")
        Do ##class(Ens.Util.Log).LogError("","",$system.OBJ.DisplayError(tSC))
        Do ##class(Ens.Util.Log).LogError("","",$System.Status.GetErrorText(tSC))
        do rs.Close()
        kill rs
        kill comp
        kill nsp
        kill tSC
        kill statement
        kill status
        kill resultset
        Set $NAMESPACE=currentNamespace
        kill currentNamespace
    }
    ; Se retorna la respuesta generada durante la ejecución del método
    quit response
}

}

 

De esta forma, si probamos, obtendremos una respuesta tal que así:

{
    "Namespaces": [
        {
            "Nombre": "ESBCentrales",
            "Producciones": [
                {
                    "Nombre": "Nombre1",
                    "Estado": "Detenida",
                    "Fecha": ""
                },
                {
                    "Nombre": "Producion.ESBCentrales",
                    "Estado": "En ejecución",
                    "Fecha": ""
                }
            ],
            "Componentes": [
                {
                    "Nombre": "EnvioADT",
                    "Tipo": "Operacion",
                    "Categoria": "Gestion de Pacientes",
                    "Puerto": "",
                    "PoolSize": 1,
                    "Habilitado": false,
                    "Endpoint": "[Entorno1]:[Puerto1]"
                },
       
                {
                    "Nombre": "EnrutadorREPOSICIONES",
                    "Tipo": "Proceso",
                    "Categoria": "Logística",
                    "Puerto": "",
                    "PoolSize": 1,
                    "Habilitado": true,
                    "Endpoint": ""
                },
                {
                    "Nombre": "Servicios.UnidadCuidadosIntensivosv01r00",
                    "Tipo": "Servicio",
                    "Categoria": "UCI",
                    "Puerto": 1989,
                    "PoolSize": 1,
                    "Habilitado": false,
                    "Endpoint": ""
                },
                {
                    "Nombre": "Operaciones.BBDD.ConsultarRecursosSanitarios",
                    "Tipo": "Operacion",
                    "Categoria": "Prenatal",
                    "Puerto": "",
                    "PoolSize": 1,
                    "Habilitado": false,
                    "Endpoint": "DataSourcePRENATALES"
                }           
            ]
        }
    ],
    "error": ""
}

 

 

Si vamos un paso más allá, y necesitamos obtener todos los elementos de todos los Namespaces y todas las Producciones de 1 Entorno, podríamos duplicar el Servicio:

Class Servicios.REST.Monitorizacion.ConsultarElementosProduccionTodosNamespaces Extends Ens.BusinessService
{

Parameter ADAPTER = "EnsLib.HTTP.InboundAdapter";
Parameter EnsServicePrefix = "/monitorizacion";
Method OnProcessInput(pInput As %Stream.Object, Output pOutput As %Stream.Object) As %Status
{
    Set tCmd=$ZConvert(pInput.Attributes("HttpRequest"),"U")
    Set tURL=$ZConvert(pInput.Attributes("URL"),"I","URL")
    
    Set tService="/"_$Piece(tURL,"/",2)    
    
    Quit:..#EnsServicePrefix'=tService $$$ERROR($$$EnsErrGeneral,"Service "_tService_"/ not supported.")
    
    Set tType=$Piece(tURL,"/",3)
    
    set tSC = '$$$OK
    if (tType = "ConsultarElementosProduccion") {
        set tSC = ..ConsultarElementosProduccion(pInput,.pOutput)
    }elseif (tType = "VerEstado") {
        set tSC =  ..VerEstado(.pOutput)
    }  
    
    Quit tSC
}

///     Devuelve un mensajes con los Namespaces, sus Producciones y Componentes
Method ConsultarElementosProduccion(pInput As %Stream.Object, Output pOutput As %Stream.Object) As %Status
{
    Set pOutput  = ##class(%GlobalBinaryStream).%New()
    set claseAux = ##class(%ZEN.Auxiliary.jsonProvider).%New()
    
    set response = ##class(Servicios.REST.Monitorizacion.ConsultarElementosProduccionTodosNamespaces.Code).ConsultarElementosProduccion()

    set tSC = claseAux.%WriteJSONStreamFromObject(.pOutput,.response,,,,"aeloqtuw")
    
    Do:$$$ISOK(tSC) pOutput.SetAttribute("Content-Type","application/json")
    do pOutput.SetAttribute("Access-Control-Allow-Origin","*")
    do pOutput.SetAttribute("Access-Control-Allow-Credentials","true")
    do pOutput.SetAttribute("Access-Control-Allow-Methods","GET")
    do pOutput.SetAttribute("Access-Control-Allow-Headers","request,Access-Control-Allow-Headers, Origin,Accept, X-Requested-With, Content-Type, Access-Control-Request-Method, Access-Control-Request-Headers")
    Quit tSC
}

Method VerEstado(Output pOutput As %Stream.Object) As %Status
{
    Set pOutput = ##class(%GlobalBinaryStream).%New()
    set respuesta = {"estado": "OK"}
    set respuesta = respuesta.%ToJSON()
    do pOutput.Write(respuesta)
    
    do pOutput.SetAttribute("Content-Type","application/json")
    do pOutput.SetAttribute("Access-Control-Allow-Origin","*")
    do pOutput.SetAttribute("Access-Control-Allow-Credentials","true")
    do pOutput.SetAttribute("Access-Control-Allow-Methods","GET")
    do pOutput.SetAttribute("Access-Control-Allow-Headers","request,Access-Control-Allow-Headers, Origin,Accept, X-Requested-With, Content-Type, Access-Control-Request-Method, Access-Control-Request-Headers")    
    quit $$$OK
}

}

Y adaptaríamos la clase auxiliar para que sepa qué hacer con todos los Namespaces:

Class Servicios.REST.Monitorizacion.ConsultarElementosProduccionTodosNamespaces.Code
{

ClassMethod ConsultarElementosProduccion() As Mensajes.Response.Monitorizacion.ConsultarElementosProduccionResponse
{
    ; Se registra un mensaje de información al entrar en el método ConsultarElementosProduccion
    Do ##class(Ens.Util.Log).LogInfo("","","Entra en Servicios.REST.Monitorizacion.ConsultarElementosProduccion.Code ConsultarElementosProduccion()")
    set response = ##class(Mensajes.Response.Monitorizacion.ConsultarElementosProduccionResponse).%New()
    
    ;set string = ""
    
    set rs = ##class(%ResultSet).%New()
    try {
        ; Configuración y ejecución de la consulta para obtener la lista de namespaces
        set rs.ClassName = "%SYS.Namespace"
        set rs.QueryName = "List"
        set tSC = rs.%Execute() 
        if 'tSC {
            ; Si hay un error al ejecutar la consulta, se registran mensajes de error y se sale del método
            Do ##class(Ens.Util.Log).LogInfo("","","catch inicial") 
            Do ##class(Ens.Util.Log).LogError("","",$system.OBJ.DisplayError(tSC)) 
            Do ##class(Ens.Util.Log).LogError("","",$System.Status.GetErrorText(tSC)) 
            kill rs
            quit
        }
        set currentNamespace = $SYSTEM.SYS.NameSpace()
        ; Se registra el namespace actual antes de cambiarlo
        Do ##class(Ens.Util.Log).LogInfo("","","currentNamespace: "_currentNamespace) 
        New $NAMESPACE        
        While rs.%Next(.tSC){
            ; Se recorren los namespaces obtenidos de la consulta
            Do ##class(Ens.Util.Log).LogInfo("","","Entra en WHILE para recorrer Namespaces") 
            set nsp = ""
            set nsp = rs.Data("Nsp")
            Do ##class(Ens.Util.Log).LogInfo("","","1 nsp: "_nsp) 
            
            ; Se verifica si el namespace está en la lista de namespaces permitidos
            If (( nsp = "ESBSSCC-DCM")||( nsp = "ESBLAPALMA")||( nsp = "ESBLANZAROTE")||( nsp = "ESBLAGOMERA")
            ||( nsp = "ESBHUGCDN")||( nsp = "ESBHUC")||( nsp = "ESBHCDSNS")||( nsp = "ESBHCDNEGRIN")
            ||( nsp = "ESBHCDLAPALMA")||( nsp = "ESBHCDLANZAROTE")||( nsp = "ESBHCDLAGOMERA")
            ||( nsp = "ESBHCDHUNSC")||( nsp = "ESBHCDFUERTEVENTURA")||( nsp = "ESBHCDELHIERRO")
            ||( nsp = "ESBHCDCHUIMI")||( nsp = "ESBFUERTEV")||( nsp = "ESBELHIERRO")||( nsp = "ESBCHUIMI")
            ||( nsp = "ENSEMBLE")||( nsp = "ESBSSCC")||( nsp = "DRAGOAP")||( nsp = "DRAGOAE")){
                
                ; Se registra la entrada al bloque IF
                Do ##class(Ens.Util.Log).LogInfo("","","Entra en IF '= %SYS...")
                Do ##class(Ens.Util.Log).LogInfo("","","2 nsp: "_nsp)
                ; Se cambia el namespace
                Set $NAMESPACE=nsp
                Do ##class(Ens.Util.Log).LogInfo("","","3 nsp: "_nsp)
                Do ##class(Ens.Util.Log).LogInfo("","","Antes de Set $NAMESPACE=nsp")
                Do ##class(Ens.Util.Log).LogInfo("","","Después de Set $NAMESPACE=nsp")
                
                ; Se crea un objeto para representar el namespace en la base de datos
                set Namespace = ##class(EsquemasDatos.Monitorizacion.Namespace).%New()
                set Namespace.Nombre = $SYSTEM.SYS.NameSpace()
                Do ##class(Ens.Util.Log).LogInfo("","","1111 Namespace.Nombre: "_Namespace.Nombre_"("_nsp_")")
                
                ; Se preparan consultas SQL para obtener información sobre las producciones
                set resultset = ##class(%ResultSet).%New()
                set statement=##class(%SQL.Statement).%New()
                 set enumerate=statement.%PrepareClassQuery("Ens.Config.Production","EnumerateConfigItems")
                 Do ##class(Ens.Util.Log).LogAlert("","","enumerate: "_enumerate)
                 
                 set status=statement.%PrepareClassQuery("Ens.Config.Production","ProductionStatus")
                 Do ##class(Ens.Util.Log).LogAlert("","","status: "_status)
                 Do ##class(Ens.Util.Log).LogInfo("","","status: "_status)
                 
                 set resultset=statement.%Execute()
                 while resultset.%Next() {
                     ; Se recorren las producciones obtenidas de la consulta
                     Do ##class(Ens.Util.Log).LogInfo("","","Entra en el WHILE desde ESBSSCC, que recorre las Producciones")
                     set produccionName = resultset.%Get("Production")
                     set estado = resultset.%Get("StatusEnum")
                     set iniciadoDesde = resultset.%Get("LastStartTime")
                     set paradoDesde = resultset.%Get("LastStopTime")
                     
                     ; Se crea un objeto para representar la producción en la base de datos
                     set Produccion = ##class(EsquemasDatos.Monitorizacion.Produccion).%New()
                     set Produccion.Nombre = produccionName
                     set Produccion.Estado = "Suspendida"
                     set Produccion.Fecha = iniciadoDesde
                         
                     if (estado = 1) {
                         ; Si la producción está en ejecución, se actualiza la información
                         set Produccion.Estado = "En ejecución"
                         set Produccion.Fecha = paradoDesde
                         
                         ; Se obtiene información detallada sobre los componentes de la producción
                         set tProduction = ##class(Ens.Config.Production).%OpenId(produccionName,,.tSC)
                        if (tSC) {
                            Do ##class(Ens.Util.Log).LogInfo("","","tProduction.Items.Count(): "_tProduction.Items.Count())
                            For i=1:1:tProduction.Items.Count() {
                                #dim item as Ens.Config.Item
                                set item = tProduction.Items.GetAt(i)
                                set Componente = ##class(EsquemasDatos.Monitorizacion.Componente).%New()
                                set Componente.Nombre = item.Name
                                
                                set tipo = item.BusinessType()
                                set x = 0
                                if (tipo = "1") {
                                    set Componente.Tipo = "Servicio"
                                    set x = item.GetSetting("Port",.port)
                                    
                                    ; 06/02/2024 Para obtener el puerto de los Servicios DICOM
                                    if (x '= 1)
                                    {
                                        set x = item.GetSetting("IPPort",.port)    
                                    }
                                    
                                } elseif (tipo = "2") {
                                       set Componente.Tipo = "Proceso"
                                       
                                } elseif (tipo = "3") {
                                    set Componente.Tipo = "Operacion"
                                    // Si es SOAP la URL se configura en "WebServiceURL"
                                    set tSC = item.GetSetting("WebServiceURL",.endpoint)
                                    if (tSC = 1){
                                        set Componente.Endpoint = endpoint    
                                    }else{
                                        // Si es REST la URL se configura en "HTTPServer" y/o "URL"
                                        set tSC = item.GetSetting("HTTPServer",.endpoint)
                                        if (tSC = 1){
                                            set Componente.Endpoint = endpoint    
                                        }
                                        set tSC = item.GetSetting("URL",.endpoint)
                                        if (tSC = 1){    
                                            set Componente.Endpoint = Componente.Endpoint_endpoint
                                        }else{
                                            // Si es TCP/HL7 la URL se configura en "IPAddress" y "Port"
                                            set tSC = item.GetSetting("IPAddress",.endpoint)
                                            if (tSC = 1){
                                                set Componente.Endpoint = endpoint
                                                set tSC = item.GetSetting("Port",.endpoint)    
                                                if (tSC = 1){
                                                    set Componente.Endpoint = Componente.Endpoint_":"_endpoint    
                                                }
                                            }else{
                                                // Si ES BBDD se conecta al "DSN"    
                                                set tSC = item.GetSetting("DSN",.endpoint)
                                                if (tSC = 1){
                                                    set Componente.Endpoint = endpoint
                                                }
                                            }
                                                
                                        }        
                                    }
                                }
                                set Componente.Categoria = item.Category
                                ; 24/01/2024 Añadimos para incorporar el PoolSize en la respuesta de los Componentes
                                try{
                                    set Componente.PoolSize = item.PoolSize
                                }catch{
                                    Do ##class(Ens.Util.Log).LogWarning("Error en set Componente.PoolSize = item.PoolSize")    
                                }
                                
                                ; Añadimos 30/01/2024 para expresar si está encendido el elemento
                                set Componente.Habilitado = item.Enabled
                                
                                if (x=1) && (tipo="1") {
                                    set Componente.Puerto = port
                                }
                                do Namespace.Componentes.Insert(Componente)    
                            }
                        } else {
                            Do ##class(Ens.Util.Log).LogWarning("","","tSC: "_tSC)
                        }

                     } elseif (estado = 2) {
                         ; Si la producción está detenida, se actualiza la información
                         set Produccion.Estado = "Detenida"
                         set Produccion.Fecha = paradoDesde
                         
                     }
                     do Namespace.Producciones.Insert(Produccion)
                }
                 Do ##class(Ens.Util.Log).LogInfo("","","Antes de do response.Namespaces.Insert(Namespace)")
                do response.Namespaces.Insert(Namespace)
            }
        }
        do rs.Close()
        kill rs
        kill comp
        kill nsp
        kill tSC
        kill statement
        kill status
        kill resultset
        Set $NAMESPACE=currentNamespace
        kill currentNamespace
    } catch {
        ; En caso de excepción, se registran mensajes de error y se limpian las variables
        Do ##class(Ens.Util.Log).LogInfo("","","catch final")
        Do ##class(Ens.Util.Log).LogError("","",$system.OBJ.DisplayError(tSC))
        Do ##class(Ens.Util.Log).LogError("","",$System.Status.GetErrorText(tSC))
        do rs.Close()
        kill rs
        kill comp
        kill nsp
        kill tSC
        kill statement
        kill status
        kill resultset
        Set $NAMESPACE=currentNamespace
        kill currentNamespace
    }
    ; Se retorna la respuesta generada durante la ejecución del método
    quit response
}

}

A continuación subimos el Servicio al Portal Web:

Y ahora viene la parte curiosísima... Puesto que estamos cambiando de Namespace, esto implica que necesitamos desplegar el código del Servicio de TODOS los Namespaces y su clase auxiliar, en cada uno de los NAMESPACES que queramos consultar, es decir, los que incluyamos en el if:

            
            ; Se verifica si el namespace está en la lista de namespaces permitidos
            If (( nsp = "ESBSSCC-DCM")||( nsp = "ESBLAPALMA")||( nsp = "ESBLANZAROTE")||( nsp = "ESBLAGOMERA")
            ||( nsp = "ESBHUGCDN")||( nsp = "ESBHUC")||( nsp = "ESBHCDSNS")||( nsp = "ESBHCDNEGRIN")
            ||( nsp = "ESBHCDLAPALMA")||( nsp = "ESBHCDLANZAROTE")||( nsp = "ESBHCDLAGOMERA")
            ||( nsp = "ESBHCDHUNSC")||( nsp = "ESBHCDFUERTEVENTURA")||( nsp = "ESBHCDELHIERRO")
            ||( nsp = "ESBHCDCHUIMI")||( nsp = "ESBFUERTEV")||( nsp = "ESBELHIERRO")||( nsp = "ESBCHUIMI")
            ||( nsp = "ENSEMBLE")||( nsp = "ESBSSCC")||( nsp = "DRAGOAP")||( nsp = "DRAGOAE")){

 

Una vez hecho lo anterior, ya estamos listos para probar mediante:
    http://[Entorno]:[Puerto]/monitorizacion/ConsultarElementosProduccion/
    

Observando como resultado:

{
    "Namespaces": [
        {
            "Nombre": "DRAGOExternosActivos",
            "Producciones": [
                {
                    "Nombre": "Candelaria",
                    "Estado": "Detenida",
                    "Fecha": ""
                },
                {
                    "Nombre": "Producción.HistoriaClínica",
                    "Estado": "En ejecución",
                    "Fecha": ""
                }
            ],
            "Componentes": [
                {
                    "Nombre": "ProcesarMedicamentos",
                    "Tipo": "Proceso",
                    "Categoria": "ESB",
                    "Puerto": "",
                    "PoolSize": 1,
                    "Habilitado": true,
                    "Endpoint": ""
                },
                {
                    "Nombre": "ESB_ConsultasInterhospitalarias",
                    "Tipo": "Operacion",
                    "Categoria": "ESB",
                    "Puerto": "",
                    "PoolSize": 1,
                    "Habilitado": false,
                    "Endpoint": ""
                },
                {
                    "Nombre": "JavaGateway",
                    "Tipo": "Servicio",
                    "Categoria": "",
                    "Puerto": "",
                    "PoolSize": 1,
                    "Habilitado": true,
                    "Endpoint": ""
                },
                {
                    "Nombre": "ServicioUnionPacientes",
                    "Tipo": "Servicio",
                    "Categoria": "",
                    "Puerto": "",
                    "PoolSize": 1,
                    "Habilitado": true,
                    "Endpoint": ""
                }
            ]
        },
        {
            "Nombre": "DRAGOPrimerosAuxilios",
            "Producciones": [
                {
                    "Nombre": "ITB.Production.TestNACK",
                    "Estado": "Detenida",
                    "Fecha": ""
                },
                {
                    "Nombre": "Produccion.DRAGOPrincipiosActivos",
                    "Estado": "En ejecución",
                    "Fecha": ""
                }
            ],
            "Componentes": [
                {
                    "Nombre": "HTTPOperacionUnificada",
                    "Tipo": "Operacion",
                    "Categoria": "LABORATORIO",
                    "Puerto": "",
                    "PoolSize": 1,
                    "Habilitado": true,
                    "Endpoint": ""
                },
                {
                    "Nombre": "HTTPProcesoLogística",
                    "Tipo": "Proceso",
                    "Categoria": "",
                    "Puerto": "",
                    "PoolSize": 0,
                    "Habilitado": true,
                    "Endpoint": ""
                },
                {
                    "Nombre": "Consultas Privadas to Ambulatorio",
                    "Tipo": "Servicio",
                    "Categoria": "",
                    "Puerto": 19010,
                    "PoolSize": 1,
                    "Habilitado": false,
                    "Endpoint": ""
                },
         
                {
                    "Nombre": "PeticionesLaboratorioCanarias",
                    "Tipo": "Operacion",
                    "Categoria": "Antigenos,LABORATORIO",
                    "Puerto": "",
                    "PoolSize": 1,
                    "Habilitado": true,
                    "Endpoint": "http://pre:ABCDE/csp/XDYZA/Servicios.Laboratorio.Recetas.CLS"
                },
            ]
            "Nombre": "ENSEMBLE",
            "Producciones": [
                {
                    "Nombre": "Produccion.ENSEMBLE",
                    "Estado": "Detenida",
                    "Fecha": "2024-05-15 13:44:07.868"
                },
                {
                    "Nombre": "TestAlert.ProdManaged",
                    "Estado": "Detenida",
                    "Fecha": ""
                },
                {
                    "Nombre": "TestAlert.ProdRouting",
                    "Estado": "Detenida",
                    "Fecha": ""
                }
            ],
            "Componentes": []
        }
    ],
    "error": ""
}

De esta forma ya hemos construido una manera de obtener todo lo relevante de una Producción, y podría desarrollarse una aplicación y/o web mediante la cual visualizar estos datos e incluso buscar si cierto puerto está ocupado o libre.

 

Ojalá que les halla resultado interesante y sobre todo un aporte :=)

 

Además me gustaría agradecer de manera sincera y honesta que han participado de alguna u otra forma o bien en el desarrollo directo, o bien en la idea y en la resolución de dudas prácticas, y me han ayudado al respecto:

?duardo Pérez Mederos ✅

?ntonio Gabriel Sánchez ☑️

?arlos Gómez Castro ✔️

?drián Vargas Rodríguez 🟦

 

Ojalá que les halla ayudado el artículo.

 

Por último me gustaría recordarles que es muy probable y posible que sea el código compartido muy mejorable y se podría hacer de maneras más completas, correctas y estructuradas. Por tanto a modo de reflexión para que sean comprensivos con este artículo me parece positivo compartir esta imagen:

Viñeta que aparece en la revista: "Linux Format" con fecha 30 Abril de 2023, página 14

- WE SHIPPED THE CODE WITH BUGS? HOW MANY DID YOU FIND? (¿ENVIAMOS EL CÓDIGO CON ERRORES? ¿CUÁNTOS ENCONTRASTE?)

- ONE ... (UNO...)

 

 

 

- IT SHIPPED WITH A BUG! THAT'S AWFUL! (¡SE ENVIÓ CON UN ERROR! ¡ESO ES TERRIBLE!)

- ... HUNDRED AND THIRTEEN (...CIENTO TRECE)

 

 

 

- YOU DIDN'T LET ME FINISH MY SENTENCE (NO ME DEJASTE TERMINAR MI FRASE)

 

 

🙂

ディスカッション (0)1
続けるにはログインするか新規登録を行ってください
質問
· 2024年5月17日

SSL Handshake error, possibly SNI support related?

Hi,

I'm trying to get an Ensemble 2017.1 environment to make a https connection to a webservice, but currently seeing SSL handshake errors. A fare bit of troubleshooting later, this looks to be related to SNI support, as the webservice I'm trying to hit will only take connections from clients that have SNI support, and has had TLS.v1 enabled for the troubleshooting. Testing this on 2017.2 versions and above the connection works fine, but on 2017.1 and below am seeing handshake errors. Has anyone else had similar issues and has found a work around for this, or is the only way to get this working to upgrade to a newer version?

2 Comments
ディスカッション (2)2
続けるにはログインするか新規登録を行ってください
質問
· 2024年5月17日

How are Stream saved?

Hi, I was working with %sStream.FileBynary and following the doc when I find an info that I'm not sure of.
In the part of the doc where it talks about saving streams, it does not precise where it is saved.
I tried to fill my stream, then rewind, then set the file and finally saved.
And it puts in my default directory with the temporary name.
If I do a zwrite of my stream, I get these properties about the file and directory.
(StoreFile) = "zKc2m8v1.stream"
(NormalizedDirectory) = "C:\InterSystems\Community\mgr\user\stream\"

I figured it was maybe because I used a relative path while using LinkToFile. Tried a full path and it changed the property of the Stream but the save doesn't seem to work.

With zw I can see those two properties.

(StoreFile) = "test.cms"

(TempFile) = "test.cms"

Do I need to remove the tempFile? Am I missing something?
https://docs.intersystems.com/irislatest/csp/docbook/DocBook.UI.Page.cls...

6 Comments
ディスカッション (6)3
続けるにはログインするか新規登録を行ってください
お知らせ
· 2024年5月17日

[Vidéo] Capacités multi-modèles d'InterSystems IRIS

Salut la Communauté!

Profitez de regarder la nouvelle vidéo sur la chaîne Youtube d'InterSystems France

📺 Capacités multi-modèles d'InterSystems IRIS

Découvrez comment l'architecture multimodèle de la plateforme de données InterSystems IRIS peut bénéficier à vos applications. Utilisez le modèle de données adapté à chaque tâche (accès relationnel, objet ou natif) tout en travaillant dans la langue de votre choix.

Cette vidéo est doublée grâce à Bard, l'intelligence artificielle de Google. 

N'oubliez pas à partager vos réflexions et impressions dans des commentaires après avoir regardé cette vidéo !

ディスカッション (0)1
続けるにはログインするか新規登録を行ってください
InterSystems公式
· 2024年5月17日

InterSystems anuncia InterSystems IRIS 2024.1.0.267.2, que incluye compatibilidad con Ubuntu 24.04

InterSystems se complace en anunciar la disponibilidad general de

  • InterSystems IRIS Data Platform 2024.1.0.267.2
  • InterSystems IRIS for Health 2024.1.0.267.2
  • HealthShare Health Connect 2024.1.0.267.2

Esta versión añade compatibilidad con el sistema operativo Ubuntu 24.04.  Ubuntu 24.04 incluye Linux kernel 6.8, mejoras de seguridad, junto con mejoras en el instalador y en la interfaz de usuario.  InterSystems IRIS IntegratedML aún no está disponible en Ubuntu 24.04.

Además, esta versión soluciona dos defectos para todas las plataformas

  • Una corrección para algunas consultas SQL que utilizan "NOT %INLIST" y devuelven resultados incorrectos. Anteriormente habíamos emitido una alerta sobre este error.
  • Se ha corregido un problema con las stack traces incompletas en determinadas circunstancias.

Cómo conseguir el software

Como es habitual, las versiones de mantenimiento extendido (EM) vienen con paquetes de instalación clásicos para todas las plataformas compatibles, así como imágenes de contenedor en formato de contenedor Docker. Para obtener una lista completa, consultad la página Plataformas compatibles.

Paquetes de instalación clásicos

Los paquetes de instalación están disponibles en la página de Versiones de Mantenimiento Extendido del WRC. Además, los kits también se pueden encontrar en el sitio web de los Servicios de Evaluación.

Contenedores

Las imágenes de contenedores para las ediciones Enterprise y Community de InterSystems IRIS e IRIS for Health y todos los componentes correspondientes están disponibles en la interfaz web de InterSystems Container Registry.

Los contenedores están etiquetados como "2024.1" o "latest-em".
 

ディスカッション (0)1
続けるにはログインするか新規登録を行ってください