[comment]: # aside:5

[comment]: # ({f2a0429f-ebcec779})
# Enviar dades al servidor o proxy de Zabbix

[zabbix\_utils](https://github.com/zabbix/python-zabbix-utils/blob/main/README.md) us permet enviar valors d'element a [element de trapper](/manual/config/itemtypes/trapper) al servidor o proxy de Zabbix (similarment a [l'emissor de Zabbix](/manual/concepts).

Podeu enviar un únic valor, diversos valors o fins i tot orientar diversos clústers de Zabbix.

Les dades es poden enviar en mode síncron o asíncron:

- En mode síncron, el vostre script Python envia valors i espera una resposta abans de continuar; això és adequat per a operacions senzilles, seqüencials i predictibles.
- En mode asíncron, l'script envia valors sense esperar cada resposta, permetent que altres operacions procedeixin en paral·lel; això és més eficient per a peticions lentes o grans lots de dades.

Els exemples d'aquesta pàgina se centren en el mode síncron, encara que [mode asíncron](#asynchronous-mode) segueix patrons similars.
Exemples addicionals estan disponibles al repositori [zabbix_utils](https://github.com/zabbix/python-zabbix-utils/tree/main/examples) GitHub.

[comment]: # ({/f2a0429f-ebcec779})

[comment]: # ({33a3626c-2b58225a})
#### Importar

Per utilitzar zabbix\_utils per enviar valors d'element, importa la classe `Sender` de l'script:

```python
from zabbix_utils import Sender
```

Per a l'enviament de diversos valors, també podeu importar la classe `ItemValue`:

```python
from zabbix_utils import Sender, ItemValue
```

[comment]: # ({/33a3626c-2b58225a})

[comment]: # ({6215a382-248fa427})
#### Enviar un únic valor

Per enviar un valor d'element:

1. Creeu una instància `Remitent`, especificant l'adreça IP i el port del vostre servidor o proxy de Zabbix.
2. Crideu el mètode `send_value()` a la instància `Sender` utilitzant el següent format:

```python
sender_instance.send_value('host', 'item.key', 'value', optional_timestamp, opcional_nanoseconds)
```

Per exemple, per enviar `1` a l'element `service.status` trapper a l'equip `Servidor Linux`:

```python
sender = Sender(server='127.0.0.1', port=10051)
response = sender.send_value('Linux server', 'service.status', 1)
```

[comment]: # ({/6215a382-248fa427})

[comment]: # ({ba5ab006-8c41d6ba})
##### Emprant adreces IP que no són per defecte IP

Si el servidor que executa l'script té diverses adreces IP, podeu especificar un `source_ip` perquè el `remetent` s'empri en enviar valors al servidor o proxy de Zabbix:

```python
sender = Sender(
    server='127.0.0.1',
    port=10051,
    source_ip='10.10.7.1'
)
```

[comment]: # ({/ba5ab006-8c41d6ba})

[comment]: # ({bff53bf5-de824c12})
##### Ús de temps d'espera

Podeu establir una resposta `temps d'espera` per al `Remitent` per controlar quant de temps ha d'esperar el vostre script per a una resposta del servidor o proxy de Zabbix abans de renunciar:

```python
sender = Sender(
    server='127.0.0.1',
    port=10051,
    timeout=30
)
```

[comment]: # ({/bff53bf5-de824c12})

[comment]: # ({04ae72fb-62dd1793})
##### Ús del fitxer de configuració de l'agent

Podeu deixar que zabbix\_utils llegeixi els paràmetres [`Server`](/manual/appendix/config/zabbix_agentd#server) o [`ServerActive`]/manual/appendix/config/zabbix_agentd#serveractive) des d'un fitxer de configuració local de Zabbix o agent 2.
En aquests casos, no cal especificar els paràmetres de connexió quan creeu una instància `Remitent`:

```python
sender= Sender(
    use_config=True,
    config_path='/etc/zabbix/zabbix_agent2.conf'
)
```

::: nota important
Si `ServerActive` conté un o més clústers de Zabbix amb múltiples instàncies de servidor, `Sender` envia dades al primer servidor disponible a cada clúster.
Si `ServerActive` no és pas establert, s'empra l'adreça de `Server` amb el port per defecte (10051).
:::

[comment]: # ({/04ae72fb-62dd1793})

[comment]: # ({f95d47a7-a8b30296})
##### Ús del xifrat

El `Sender` no inclou compatibilitat amb el xifrat integrat, però podeu proporcionar-la creant un contenidor utilitzant biblioteques de tercers:

# Implementació del contenidor TLS PSK per al sòcol

```python
def psk_wrapper(sock, tls):
    # ...
    # Implementació del contenidor TLS PSK per al socket
    # ...

sender= Sender(
    server='127.0.0.1',
    port=10051,
    socket_wrapper=psk_wrapper
)
```

[comment]: # ({/f95d47a7-a8b30296})

[comment]: # ({e0a8b11b-b6a3d94d})
##### Resposta per a un valor únic

La resposta retornada pel servidor o proxy de Zabbix és processada per la biblioteca i retornada com a objecte `TrapperResponse`:

```python
print(response)
# {"processat": 1, "fallit": 0, "total": 1, "temps": "0.000123", "chunk": 1}

print(response.processed)
# 1

print(response.failed)
# 0

print(response.total)
# 1
```

[comment]: # ({/e0a8b11b-b6a3d94d})

[comment]: # ({d5faab4e-9eeea215})
##### Mode asíncron

El mode asíncron permet que el vostre script Python enviï valors sense esperar una resposta del servidor o del proxy de Zabbix.
Això pot fer que el vostre script sigui més eficient quan necessita enviar molts valors o quan alguns valors triguen molt a enviar-los.

Quan s'utilitza el mode asíncron, hi ha algunes diferències importants en comparació amb el mode síncron:

- Importar el mòdul `asyncio` de Python (primer heu de [instal·lar](/devel/python/install) les dependències requerides).
- Importació `AsyncSender` en lloc de `Remitent`.
- Escriu el teu codi dins d'una funció `async`.
- Utilitzeu `await` quan crideu el mètode `send_value()`.

Per exemple, per enviar un únic valor utilitzant el mode asíncron:

```python
# 1. Importa asyncio per al mode asíncron, i AsyncSender de zabbix_utils:
import asyncio
from zabbix_utils import AsyncSender

# 2. Definir la funció principal async on s'executaran totes les operacions d'enviament de dades (s'ha d'esperar):
async def main():
    sender = AsyncSender(server='127.0.0.1', port=10051)
    response = await sender.send_value('Linux server', 'service.status', 1)

    # 3. Imprimeix la resposta retornada pel servidor Zabbix o proxy:
    print(response)

# 4. Executeu la funció async main() utilitzant el bucle d'esdeveniments d'asyncio:
asyncio.run(main()))
```

[comment]: # ({/d5faab4e-9eeea215})

[comment]: # ({b845706b-34e0ff6d})
##### Envia diversos valors

Per enviar diversos valors:

1. Prepareu una matriu d'objectes `ItemValue`, cadascun utilitzant el mateix format que el mètode [`send_value()`](#send-single-value).
2. Creeu una instància `Remitent`, especificant l'adreça IP i el port del vostre servidor o proxy de Zabbix.
3. Crida el mètode `send()` (en lloc de `send_value()`) a la instància `Sender`, especificant l'array d'objectes amb valors a enviar.

Per exemple, per enviar cinc valors a diferents equips:

```python
items = [
    ItemValue('server-de', 'service.status', 'up', 1770887205, 100),
    ItemValue('server-fr', 'service.status', 'up', 1770887205, 100),
    ItemValue('server-uk', 'service.status', 'up', 1770887205, 100),
    ItemValue('server-nl', 'service.status', 'up', 1770887205, 100),
    ItemValue('server-pl', 'service.status', 'up', 1770887205, 100),
]

sender = Sender(servidor='127.0.0.1', port=10051)
response = sender.send(elements)
```

[comment]: # ({/b845706b-34e0ff6d})

[comment]: # ({c0410a6d-5848e96f})
###### Ús de la mida del tros personalitzat

Si necessiteu enviar més valors que un element de caçador pot acceptar en una sola petició, podeu dividir-los en trossos.

Per defecte, la mida del tros és de 250 valors.
Podeu canviar-lo establint el paràmetre `chunk_size` quan creeu una instància `Sender`.

Per exemple, per enviar cinc valors en tres trossos (2-2-1), establiu el paràmetre `chunk_size` a `2`:

```python
items = [
    ItemValue('server-de', 'service.status', 'up'),
    ItemValue('server-fr', 'service.status', 'up'),
    ItemValue('server-uk', 'service.status', 'up'),
    ItemValue('server-nl', 'service.status', 'up'),
    ItemValue('server-pl', 'service.status', 'up'),
]

sender = Sender(servidor='127.0.0.1', port=10051, chunk_size=2)
response = sender.send(elements)
```

[comment]: # ({/c0410a6d-5848e96f})

[comment]: # ({b06724dd-5a0b5783})
###### Envia valors a múltiples clústers de Zabbix

Per enviar valors a diversos clústers de Zabbix:

1. Prepareu una sèrie de clústers de Zabbix. Si un clúster té múltiples nodes, el valor s'enviarà al primer **node disponible** de cada clúster.
2. Creeu un 'Sender', especificant la vostra matriu de clústers de Zabbix.
3. Crida el mètode `send_value()` a la instància `Sender` utilitzant el mateix format que el mètode [`send_value()`](#send-single-value).

Per exemple, per enviar un valor al primer node disponible en cada clúster:

```python
zabbix_clusters = [
    ['zabbix.cluster1.node1', 'zabbix.cluster1.node2:10051'],
    ['zabbix.cluster2.node1:10051', 'zabbix.cluster2.node2', 'zabbix.cluster2.node3']
]

sender = Sender(clusters=zabbix_clusters)
response = sender.send_value('Linux server', 'service.status', 1)
```

[comment]: # ({/b06724dd-5a0b5783})

[comment]: # ({2c3cc8b2-d7964287})
##### Resposta per a valors múltiples

Per defecte, `Sender` retorna un resultat afegit d'enviar valors a través de tots els equips o clústers:

```python
print(response)
# {"processed": 2, "failed": 0, "total": 2, "time": "0.000108", "chunk": 2}
```

Si necessiteu informació més detallada, podeu inspeccionar els resultats de cada clúster i de cada tros mitjançant l'atribut `response.details`:

```python
print(response)
# {"processed": 2, "failed": 0, "total": 2, "time": "0.000108", "chunk": 2}

if response.failed == 0:
    print(f"Value sent successfully in {response.time}")
else:
    print(response.details)
    # {
    #     127.0.0.1:10051: [
    #         {
    #             "processed": 1,
    #             "failed": 0,
    #             "total": 1,
    #             "time": "0.000051",
    #             "chunk": 1
    #         }
    #     ],
    #     zabbix.example.local:10051: [
    #         {
    #             "processed": 1,
    #             "failed": 0,
    #             "total": 1,
    #             "time": "0.000057",
    #             "chunk": 1
    #         }
    #     ]
    # }

    for node, chunks in response.details.items():
        for resp in chunks:
            print(f"Processed {resp.processed} of {resp.total} at {node.address}:{node.port}")
            # Processed 1 of 1 at 127.0.0.1:10051
            # Processed 1 of 1 at zabbix.example.local:10051
```

[comment]: # ({/2c3cc8b2-d7964287})
