[comment]: # aside:5

[comment]: # ({f2a0429f-ebcec779})
# Enviar dados para o Zabbix server ou proxy

O [zabbix\_utils](https://github.com/zabbix/python-zabbix-utils/blob/main/README.md) permite enviar valores de item para um [item trapper](/manual/config/items/itemtypes/trapper) no Zabbix server ou proxy (de forma semelhante ao [Zabbix sender](/manual/concepts/sender)).

Você pode enviar um único valor, múltiplos valores ou até mesmo direcionar múltiplos clusters Zabbix.

Os dados podem ser enviados em modo síncrono ou assíncrono:

-   No modo síncrono, seu script Python envia valores e aguarda uma resposta antes de continuar; isso é adequado para operações simples, sequenciais e previsíveis.
-   No modo assíncrono, o script envia valores sem esperar por cada resposta, permitindo que outras operações prossigam em paralelo; isso é mais eficiente para solicitações lentas ou grandes lotes de dados.

Os exemplos nesta página focam no modo síncrono, embora o [modo assíncrono](#asynchronous-mode) siga padrões semelhantes.
Exemplos adicionais estão disponíveis no repositório GitHub do [zabbix_utils](https://github.com/zabbix/python-zabbix-utils/tree/main/examples).

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

[comment]: # ({33a3626c-2b58225a})
#### Importação

Para usar o zabbix\_utils para enviar valores de item, importe a classe `Sender` em seu script:

```python
from zabbix_utils import Sender
```

Para enviar múltiplos valores, você também pode importar a classe `ItemValue`:

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

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

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

Para enviar o valor de um item:

1. Crie uma instância de `Sender`, especificando o endereço IP e a porta do seu Zabbix server ou proxy.
2. Chame o método `send_value()` na instância de `Sender` usando o seguinte formato:

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

Por exemplo, para enviar `1` para o item trapper `service.status` no host `Linux server`:

```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})
##### Usando IP não padrão

Se o servidor que executa seu script tiver vários endereços IP, você pode especificar um `source_ip` para o `Sender` usar ao enviar valores para o Zabbix server ou proxy:

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

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

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

Você pode definir um `timeout` de resposta para o `Sender` para controlar quanto tempo seu script deve aguardar por uma resposta do Zabbix server ou proxy antes de desistir:

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

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

[comment]: # ({04ae72fb-62dd1793})
##### Usando o arquivo de configuração do agent

Você pode permitir que o zabbix\_utils leia os parâmetros [`Server`](/manual/appendix/config/zabbix_agentd#server) ou [`ServerActive`](/manual/appendix/config/zabbix_agentd#serveractive) de um arquivo de configuração local do Zabbix agent ou agent 2.
Nesses casos, você não precisa especificar os parâmetros de conexão ao criar uma instância do `Sender`:

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

::: noteimportant
Se `ServerActive` contiver um ou mais clusters Zabbix com múltiplas instâncias de server, o `Sender` enviará dados para o primeiro server disponível em cada cluster.
Se `ServerActive` não estiver definido, o endereço de `Server` com a porta padrão (10051) será usado.
:::

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

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

O `Sender` não inclui suporte de criptografia embutido, mas você pode fornecê-lo criando um wrapper usando bibliotecas de terceiros:

```python
def psk_wrapper(sock, tls):
    # ...
    # Implementação do wrapper TLS PSK para o socket
    # ...

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

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

[comment]: # ({e0a8b11b-b6a3d94d})
##### Resposta para valor único

A resposta retornada pelo server ou proxy Zabbix é processada pela biblioteca e retornada como um objeto `TrapperResponse`:

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

print(response.processed)
# 1

print(response.failed)
# 0

print(response.total)
# 1
```

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

[comment]: # ({d5faab4e-9eeea215})
##### Modo assíncrono

O modo assíncrono permite que seu script Python envie valores sem esperar por uma resposta do Zabbix server ou proxy.
Isso pode tornar seu script mais eficiente quando ele precisa enviar muitos valores ou quando alguns valores demoram muito para serem enviados.

Ao usar o modo assíncrono, há algumas diferenças importantes em relação ao modo síncrono:

-   Importe o módulo `asyncio` do Python (você deve primeiro [instalar](/devel/python/install) as dependências necessárias).
-   Importe `AsyncSender` em vez de `Sender`.
-   Escreva seu código dentro de uma função `async`.
-   Use `await` ao chamar o método `send_value()`.

Por exemplo, para enviar um único valor usando o modo assíncrono:

```python
# 1. Importe asyncio para o modo assíncrono e AsyncSender do zabbix_utils:
import asyncio
from zabbix_utils import AsyncSender

# 2. Defina a função principal async onde todas as operações de envio de dados (devem usar await) serão executadas:
async def main():
    sender = AsyncSender(server='127.0.0.1', port=10051)
    response = await sender.send_value('Linux server', 'service.status', 1)

    # 3. Imprima a resposta retornada pelo Zabbix server ou proxy:
    print(response)

# 4. Execute a função async main() usando o event loop do asyncio:
asyncio.run(main())
```

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

[comment]: # ({b845706b-34e0ff6d})
#### Enviar múltiplos valores

Para enviar múltiplos valores:

1. Prepare um array de objetos `ItemValue`, cada um usando o mesmo formato do método [`send_value()`](#send-single-value).
2. Crie uma instância de `Sender`, especificando o endereço IP e a porta do seu Zabbix server ou proxy.
3. Chame o método `send()` (em vez de `send_value()`) na instância de `Sender`, especificando o array de objetos com os valores a serem enviados.

Por exemplo, para enviar cinco valores para diferentes hosts:

```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(server='127.0.0.1', port=10051)
response = sender.send(items)
```

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

[comment]: # ({c0410a6d-5848e96f})
##### Usando tamanho de bloco personalizado

Se você precisar enviar mais valores do que um item trapper pode aceitar em uma única solicitação, poderá dividi-los em blocos.

Por padrão, o tamanho do bloco é de 250 valores.
Você pode alterá-lo definindo o parâmetro `chunk_size` ao criar uma instância de `Sender`.

Por exemplo, para enviar cinco valores em três blocos (2-2-1), defina o parâmetro `chunk_size` como `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(server='127.0.0.1', port=10051, chunk_size=2)
response = sender.send(items)
```

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

[comment]: # ({b06724dd-5a0b5783})
##### Enviar valores para vários clusters Zabbix

Para enviar valores para vários clusters Zabbix:

1. Prepare um array de clusters Zabbix. Se um cluster tiver vários nós, o valor será enviado para o primeiro nó **disponível** de cada cluster.
2. Crie um `Sender`, especificando seu array de clusters Zabbix.
3. Chame o método `send_value()` na instância do `Sender` usando o mesmo formato do método [`send_value()`](#send-single-value).

Por exemplo, para enviar um valor para o primeiro nó disponível em cada cluster:

```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 para múltiplos valores

Por padrão, o `Sender` retorna um resultado agregado do envio de valores em todos os hosts ou clusters:

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

Se você precisar de informações mais detalhadas, pode inspecionar os resultados para cada cluster e cada chunk usando o atributo `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})
