新しい投稿

Encontrar

記事
· 2024年9月20日 4m read

Desenvolvendo SMART em aplicações FHIR com Auth0 e InterSystems IRIS FHIR Server - Aplicação Angular

Nós concluímos essa série de artigos SMART On FHIR com Auth0 e InterSystems FHIR Repository revisando nossa aplicação desenvolvida em Angular 16.

Vamos relembrar como foi definida a arquitetura da nossa solução:

Nossa aplicação front-end corresponde à segunda coluna e como você pode ver ela tem duas funções:

  1. Redirecionar a requisição de login para Auth0 e receber a resposta
  2. Enviar e receber a resposta de requisições via REST enviadas ao servidor FHIR

Angular

Angular é uma framework de aplicação web desenvolvida em TypeScript, código aberto, mantida pelo Google, usada para criar e manter aplicações web de página única. Esse design de "aplicação de página única" permite que façamos aplicações muito mais dinâmicas para o usuário. Como já explicamos no primeiro artigo, vamos usar NGINX como um servidor de  aplicação e proxy reverso que vai evitar problemas derivados de CORS ao modificar os cabeçalhos das chamadas para corresponder com os do servidor.

Design da aplicação

Nós fizemos o design da aplicação com Material Angular para simular o design de uma aplicação mobile. Em nosso exemplo, a aplicação tem a intenção de gravar uma série de dados de paciente como batimentos cardíacos, pressão sanguínea e peso, e para isso vamos enviar dois tipos de recursos FHIR ao servidor. O primeiro é do tipo paciente, com o qual o usuário vai registrar seus dados; o segundo corresponde ao recurso de observações no qual vamos mandar cada tipo de dado que vamos enviar.

A aplicação vai permitir que o usuário veja um gráfico com a evolução dos dados gravados.

Página de Login

Quando o usuário acessa a rota https://localhost, a página inicial será exibida, da qual ele pode requisitar um log in.

 

Ao clicar no botão de login, a aplicação vai automaticamente redirecionar o usuário à página Auth0 habilitada para a API configurada:

Após entrar com nosso usuário e senha, o Auth0 vai pedir permissão para a aplicação acessar nossos dados. Uma vez que o acesso aos dados seja confirmado, Auth0 vai redirecionar à URL que indicamos durante o processo de configuração. Uma vez que o Token de Acesso seja gerado, a livraria Auth0 será responsável por incluí-lo no cabeçalho de todas as chamadas que lançarmos sobre o servidor. Como podemos ver na seguinte imagem:

Tela inicial

Uma vez feito o log in, vamos ter a primeira comunicação com o servidor FHIR para requisitar a informação disponível ao usuário que entrou. Para isso vamos usar uma consulta por parâmetro enviando uma chamada GET do seguinte tipo:

https://localhost:8443/smart/fhir/r5/Patient?email=lperezra%40intersyste...

A resposta do servidor será um tipo Bundle de recurso com a seguinte informação:

{
    "resourceType":"Bundle",
    "id":"8c5b1efd-cfdd-11ee-a06b-0242ac190002",
    "type":"searchset",
    "timestamp":"2024-02-20T10:48:14Z",
    "total":0,
    "link":[
        {
            "relation":"self",
            "url":"https://localhost:8443/smart/fhir/r5/Patient?email=lperezra%40intersystems.com"
        }
    ]
}

Como vemos, temos um total de 0 paciente com esse email. Assim a nossa aplicação nos mostra uma tela inicial de onde poderemos registrar nossos dados.

 

Como você pode ver, temos o campo de email já preenchido com o email do usuário que entrou. Isso é porque, como você viu na consulta inicial, nós vamos usá-lo como um identificador. Com o formulário preenchido, vamos enviar uma chamada do seguinte tipo via POST:

https://localhost:8443/smart/fhir/r5/Patient

Com o corpo de mensagem formado por um recurso de Patient:

{
    "resourceType":"Patient",
    "birthDate":"1982-03-08",
    "gender":"male",
    "identifier":[
        {
            "type":{
                "text":"ID"
            },
            "value":"12345678A"
        }
    ],
    "name":[
        {
            "family":"PÉREZ RAMOS",
            "given":[
                "LUIS ÁNGEL"
                ]
        }
    ],
    "telecom":[
        {
            "system":"phone",
            "value":"600102030"
        },
        {
            "system":"email",
            "value":"lperezra@intersystems.com"
        }
    ]
}

Com os dados de Patient registrados no nosso servidor, a consulta de paciente irá agora retornar um resultado, então estamos preparados para gravar as diferentes observações. Vamos ver como se parece a tela inicial:

Tela de observações

Da mesma maneira que enviamos os dados dos pacientes, vamos enviar as observações desde suas telas específicas:

Para cada recurso enviado ao servidor, a aplicação vai adicionar um novo ponto ao gráfico:

Para isso, irá lançar uma query ao servidor requisitando recursos do tipo Observation que pertençam ao usuário:

https://localhost/smart/fhir/r5/Observation?patient=Patient/1

E o servidor vai novamente retornar um recurso do tipo Bundle com todas as observações gravadas para o paciente:

With the result obtained, the application will extract all the numerical values and construct the relevant graphs.

Conclusão

Como você viu nos dois artigos anteriores, o design e criação de aplicações SMART On FHIR não é muito complexo e permite que criemos de maneira rápida e ágil aplicações que aproveitam todas as funcionalidades disponíveis no nosso servidor FHIR.

Uma aplicação deste tipo não necessitará do desenvolvimento de um backend complexo para lidar com operações do tipo CRUD nos dados, e com o uso de OAuth2 não vamos precisar lidar com usuários da aplicação, delegando a funcionalidade ao Auth0 ou o servidor de autenticação e autorização escolhidos.

Com SMART On FHIR podemos, numa maneira fácil e simples, tornar disponível aos pacientes e profissionais médicos as ferramentas necessárias para a administração de dados clínicos.

Muito obrigado pela sua atenção!

ディスカッション (0)1
続けるにはログインするか新規登録を行ってください
記事
· 2024年9月20日 15m read

eBPF: Seguimiento de eventos del Kernel para IRIS Workloads (Cargas de trabajo)

Asistí a la Cloud Native Security Con en Seattle con la plena intención de aprovechar el día de OTEL, para luego profundizar en el tema de la seguridad aplicada a las cargas de trabajo nativas en la nube en los días siguientes, culminando con el CTF como ejercicio profesional. Esto fue felizmente interrumpido por un nuevo entendimiento de eBPF, lo cual supuso una mejora muy necesaria para mis pantallas, carrera, cargas de trabajo y actitud, gracias a nuevos enfoques para resolver problemas relacionados con las cargas de trabajo.

Así que llegué a la "fiesta" de eBPF y desde entonces he estado asistiendo a clínica tras clínica sobre el tema. Aquí me gustaría "desempaquetar" eBPF como una solución técnica, mapeada directamente a lo que hacemos en la práctica (aunque no siempre coincida del todo), y recorrer eBPF a través de mis experimentos en el soporte de las cargas de trabajo de InterSystems IRIS, particularmente en Kubernetes, pero sin excluir las cargas de trabajo independientes.

Pasos de eBee con eBPF y Cargas de Trabajo de InterSystems IRIS


 

eBPF

eBPF (Extended Berkeley Packet Filter) es una increíble funcionalidad del kernel de Linux que implementa una máquina virtual dentro del espacio del kernel, lo que permite ejecutar aplicaciones en un entorno aislado de forma segura, con ciertas guías o restricciones. Estas aplicaciones pueden "mapear" datos al espacio de usuario para la observabilidad, rastreo, seguridad y redes. Lo veo como un "sniffer" del sistema operativo, donde tradicionalmente se asociaba con BPF y redes, y la versión extendida "olfatea" puntos de traza, procesos, planificación, ejecución y acceso a dispositivos de bloque. Si no te convence mi analogía de eBPF, aquí tienes una de los expertos:

"Lo que JavaScript es para el navegador, eBPF lo es para el kernel de Linux.

JavaScript os permite adjuntar funciones de callback a eventos en el DOM para añadir características dinámicas a vuestra página web. De manera similar, eBPF permite engancharse a eventos del kernel y extender su lógica cuando dichos eventos son activados. ¡Es como añadir dinamismo al funcionamiento del kernel!

Inmediatamente aplicable

SI; la siguiente métrica de Prometheus os parece imposible, emplead eBPF para vigilar los procesos que se supone deben estar presentes y monitorizad en banda a través del kernel.

# HELP iris_instance_status The thing thats down telling us its down.
# TYPE iris_instance_status gauge
iris_instance_status 0
    

SI; estáis cansados de rogar por un sidecar para obtener la observabilidad que necesitáis. Adiós, sidecars.

  iris-sidecar:    
    resources:
      requests:
        memory: "2Mi"
        cpu: "125m"

Donde

Una de las cosas más satisfactorias de cómo se aplica eBPF es dónde se ejecuta... en una máquina virtual dentro del kernel. Y gracias al Namespacing de Linux, os podéis imaginar lo potente que es en un entorno nativo de la nube, sin mencionar un kernel que corre en algún tipo de entorno virtualizado o en una máquina potente con hardware de alta gama.

 

Obligatorio "Hola Mundo".

Para aquellos de vosotros que os gusta probar las cosas por vosotros mismos y desde el "principio", os saludo con un obligatorio hello world o "Hola Mundo", ligeramente retorcido para ser un poco más "irisy". Sin embargo, es bien sabido que programar en eBPF no será una habilidad que se practique con frecuencia, sino que estará concentrada en quienes desarrollan el kernel de Linux o construyen herramientas de monitorización de próxima generación.

Yo uso Pop OS/Ubuntu, y aquí os dejo mi truco para adentrarse rápidamente en el mundo de eBPF en la versión 23.04:

sudo apt install -y zip bison build-essential cmake flex git libedit-dev \
  libllvm15 llvm-15-dev libclang-15-dev python3 zlib1g-dev libelf-dev libfl-dev python3-setuptools \
  liblzma-dev libdebuginfod-dev arping netperf iperf libpolly-15-dev
git clone https://github.com/iovisor/bcc.git
mkdir bcc/build; cd bcc/build
cmake ..
make
sudo make install
cmake -DPYTHON_CMD=python3 .. # build python3 binding
pushd ../src/python/
make
sudo make install
popd
cd bcc
make install

Primero, aseguraos de que el kernel de destino tenga todo lo necesario...

cat /boot/config-$(uname -r) | grep 'CONFIG_BPF'
CONFIG_BPF=y

Si `CONFIG_BPF=y` está habilitado en vuestro sistema, estamos listos para continuar.

Lo que queremos lograr con este simple hello world o "Hola Mundo" es obtener visibilidad sobre cuándo IRIS realiza llamadas al sistema de Linux, sin utilizar nada más que las herramientas de eBPF y el propio kernel.

Aquí hay una buena manera de abordar la exploración:

1️⃣ Encontrad una llamada al sistema de Linux que os interese.

sudo ls /sys/kernel/debug/tracing/events/syscalls

Para este ejemplo, vamos a capturar cuando alguien (modificado para capturar IRIS) cree un directorio a través de la llamada al sistema `sys_enter_mkdir`.



2️⃣ Incorporadlo en el siguiente Hello World o "Hola Mundo":

El programa BPF que debéis cargar y ejecutar está en la variable `BPF_SOURCE_CODE`. Modificadlo para incluir la llamada al sistema que queréis capturar.

# Example eBPF program to a Linux kernel tracepoint
# Modified to trap irisdb
# requires bpfcc-tools
# To run: sudo python3 irismadeadir.py
from bcc import BPF
from bcc.utils import printb

BPF_SOURCE_CODE = r"""
TRACEPOINT_PROBE(syscalls, sys_enter_mkdir) {
bpf_trace_printk("Directory was created by IRIS: %s\n", args->pathname);
return 0;
}
"""
bpf = BPF(text = BPF_SOURCE_CODE)

print("Go create a dir with IRIS...")
print("CTRL-C to exit")

while True:
    try:
        (task, pid, cpu, flags, ts, msg) = bpf.trace_fields()
        #print(task.decode("utf-8"))
        if "iris" in task.decode("utf-8"):
            printb(b"%s-%-6d %s" % (task, pid, msg))
    except ValueError:
        continue
    except KeyboardInterrupt:
        break

 

3️⃣ Cargadlo en el Kernel, activadlo

Cread un directorio en IRIS.

¡Inspeccionad el rastro!

Binarios potenciados por eBPF

No tarda mucho al explorar el repositorio de bcc y darse cuenta de que hay muchos ejemplos, herramientas y binarios que aprovechan eBPF para realizar trazas interesantes. En este caso, utilizar "grep" será suficiente para extraer algo de valor.

 

Hagamos exactamente eso en el inicio y parada de IRIS con algunos ejemplos proporcionados

`execsnoop` traza nuevos procesos a través de las llamadas al sistema `exec()`.

Este aquí cuenta la historia de los argumentos que se pasan a `irisdb` al iniciar y detener.

 
sudo python3 execsnoopy.py | grep iris

`statsnoop` traza llamadas al sistema `stat()`, devolviendo atributos de archivos sobre un inodo y el acceso a archivos/directorios.

Este aquí es informativo para el acceso a nivel de directorio y archivo durante el inicio/parada. Es un poco ruidoso, pero ofrece información sobre lo que IRIS está haciendo durante el arranque, incluyendo el acceso a CPF, diarios, actividad de WIJ y el uso de herramientas del sistema para completar el trabajo.

 
sudo python3 statsnoop.py | grep iris

Flamegraphs

Una de las cosas más interesantes que encontré con las herramientas de eBPF fue la implementación de flamegraphs de Brendan Gregg sobre la salida de bpf para entender el rendimiento y los rastros de pila.

Dado el siguiente registro de perf durante el inicio/parada de IRIS:

sudo perf record -F 99 -a -g -- sleep 60
[ perf record: Woken up 7 times to write data ]
[ perf record: Captured and wrote 3.701 MB perf.data (15013 samples) ]

Generad el siguiente flamegraph con lo siguiente:

sudo perf script > out.perf
./stackcollapse-perf.pl out.perf > /tmp/gar.thing
./flamegraph.pl /tmp/gar.thing > flamegraph.svg

Intenté subir el SVG, pero no funcionó con este editor y, por alguna razón, no pude adjuntarlo. Entended, sin embargo, que es interactivo y se puede hacer clic para profundizar en los rastros de pila, además de simplemente verse bien.

  1. La función en la parte inferior es la función en el CPU. Cuanto más arriba en el eje y, más anidada está la función.
  2. El ancho de cada función en el gráfico representa el tiempo que esa función tardó en ejecutarse como un porcentaje del tiempo total de su función principal.
  3. Encontrar funciones que estén tanto altas en el eje y (profundamente anidadas) como anchas en el eje x (intensivas en tiempo) es una excelente manera de identificar problemas de rendimiento y optimización.

"alto y ancho" <--- 👀

red == user-level

orange == kernel

yellow == c++

green == JIT, java etc.

Me gustó mucho esta explicación sobre la interpretación de flamegraphs que se presenta aquí (crédito a la explicación anterior), de donde obtuve una comprensión básica sobre cómo leer *flamegraphs*. Es especialmente potente para aquellos que ejecutan Python en IRIS en producciones con código en el espacio de usuario y buscan optimización.

Avanzando y mejorando, espero que esto haya despertado vuestro interés. Ahora, pasemos al mundo de las aplicaciones eBPF, donde los expertos han desarrollado soluciones fenomenales para poner eBPF a trabajar en flotas de sistemas de manera segura y ligera.

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

Using HS.FHIRServer.Interop.Service as Facade with bearer token

I am trying to use IRIS for Health as a Facade for an external FHIR Server, where IRIS provides the proper authentication.
The client authenticates using a bearer token obtained from the IRIS OAuth2 server via a jwt client assertion.
The IRIS endpoint, however, returns a 401 as soon as I remove the Unauthenticated access

Is there w way to make this work through configuration?

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

xml attribute in double quotes

I am converting a HL7 msg to xml and one of the field is as below -
 
DTL = <assign value='"Message"' property='target.{req.ID.scope}' action='set' />

DTL response = <ID scope='Message'>3</ID>

my xsd has -
<xsd:element name="ID">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="SimpleContent" minOccurs="0"/>
</xsd:sequence>
<xsd:attribute name="scope"/>
</xsd:complexType>
</xsd:element>

I would like to get it DTL response as  = <ID scope="Message">3</ID>

Message in double quotes as - "Message"
Is there a way to get xml attribute in double quotes ? How can I do that ?

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