Indietro

Architettura di riferimento: implementa Langfuse su MKS di OVHcloud per l'osservabilità degli LLM e il monitoraggio dei costi dell'IA

Eléa Petton23/07/202615 min. di lettura

Architettura di riferimento: implementa Langfuse su MKS di OVHcloud per l'osservabilità degli LLM e il monitoraggio dei costi dell'IA

Contesto

AI Endpoints di OVHcloud fornisce un'API compatibile con OpenAI che permette alle applicazioni di accedere a un ampio catalogo di modelli open weight, come Qwen, Llama, Mistral e gpt-oss, modelli di embedding, guard e vocali, senza che i team debbano gestire l’infrastruttura di inferenza. È il livello di inferenza basato sull'utilizzo monitorato da questa architettura.

OVHcloud Managed Kubernetes Service (MKS) elimina gli oneri operativi legati all’esecuzione del Control Plane di Kubernetes: i pool di nodi, gli aggiornamenti e l'alta disponibilità sono gestiti da OVHcloud, e l’utente mantiene il pieno controllo di ciò che viene eseguito sui nodi di lavoro (worker). È lo spazio ideale per eseguire applicazioni stateless come i processi web e di lavoro di Langfuse, mentre i componenti stateful (database, object storage) risiedono nei servizi gestiti di OVHcloud.

Langfuse fornisce un livello di osservabilità per le applicazioni che utilizzano AI Endpoints. Dato che l’integrazione con l’SDK di OpenAI è un sostituzione drop-in (da langfuse.openai import openai anziché import openai), puntare una base di codice esistente compatibile con OpenAI verso AI Endpoints e ottenere una tracciabilità completa è una modifica di due righe di codice, non una riscrittura.

Questi tre componenti forniscono uno stack di osservabilità self-hosted e con attribuzione di costi per qualsiasi applicazione che chiama AI Endpoints, senza inviare token di dati di prompt o completamento al di fuori dell'infrastruttura controllata dall’utente.

Architettura Langfuse

Langfuse su MKS di OVHcloud per l'osservabilità degli LLM e il monitoraggio del consumo di token

Panoramica dell'architettura

I deploy web e di lavoro di Langfuse vengono eseguiti all'interno del cluster MKS. La gestione degli ingressi e dei certificati viene eseguita in parallelo, come add-on del cluster separato e riutilizzabile. Ogni dipendenza stateful (Postgres, Valkey, ClickHouse, object storage) è un servizio gestito da OVHcloud al di fuori del cluster, cui si accede tramite TLS.

1. Flusso di dati

Associando tutti gli elementi, una richiesta tracciata funziona così:

flusso di dati

Flusso di dati

1. L'applicazione chiama direttamente AI Endpoints

Il client drop-in openai.OpenAI() invia la richiesta all'inference API: Langfuse si trova completamente al di fuori di questa chiamata, quindi un'interruzione di Langfuse non influisce in alcun modo sulla capacità dell’applicazione di ottenere una risposta.

2. AI Endpoints ritrasmette la risposta

L'ultimo chunk contiene i dati sull'utilizzo dei token.

3. L'SDK esporta ciò che ha appena visto come uno span batch di OpenTelemetry

Questa operazione viene effettuata in modo asincrono, tramite HTTPS, verso /api/public/otel/v1/traces sull'istanza Langfuse.

Il processo viene eseguito in background e non aggiunge latenza alla risposta che l'applicazione ha già ricevuto nello step 2.

4. Langfuse web ingerisce il batch

Verifica la chiave API della richiesta rispetto al suo progetto in Postgres (un lookup memorizzato nella cache in Valkey, non una nuova query ad ogni chiamata), scrive il batch così com'è nell’object storage e invia solo un riferimento ad esso su una coda Valkey.

5. Il worker elabora la coda secondo un proprio programma, separatamente da qualsiasi richiesta specifica

.

Estrae il riferimento da Valkey, recupera l'intero batch dall’object storage, risolve la voce Prompt Management a cui è collegato (se presente) tramite Postgres e salva i record di traccia e generazione in ClickHouse (modello, conteggi dei token, latenza, prezzi).

6. Il worker gestisce anche tutto ciò che è programmato o in bulk

Le esportazioni di batch e i caricamenti di media vengono effettuati in S3 indipendentemente dal momento in cui è stata effettuata la richiesta originale.⚠️ NB: Dallo step 3

2. API di AI Endpoints

Tutto ciò che segue chiama una delle due API OVHcloud AI Endpoints:

Si tratta dell'API con cui l’applicazione comunica. Implementa l’interfaccia API di OpenAI, quindi qualsiasi SDK compatibile con OpenAI può essere utilizzato modificando il base_url e la chiave API:
 

bash
import openai 
client = openai.OpenAI(
     api_key="<your-ai-endpoints-token>",
     base_url="https://oai.endpoints.kepler.ai.cloud.ovh.net/v1",
 )
 
 response = client.chat.completions.create(
     model="Qwen3.5-397B-A17B",
     messages=[{"role": "user", "content": "hello"}],
 )

Se recuperi lo schema OpenAPI direttamente dal gateway (GET /openapi.json), vedrai che l'interfaccia disponibile va ben oltre i suggerimenti per la chat.
 È utile chiamare direttamente l'API GET /v1/models almeno una volta: restituisce tutti i modelli ai quali il tuo token garantisce l'accesso.

La sezione seguente si concentra sulla catalog API, che consente di ottenere ulteriori informazioni sui modelli, ad esempio dettagli sui prezzi necessari per monitorare i costi.

Si tratta dell'API su cui si basa la pagina del catalogo web AI Endpoints: è una semplice richiesta GET che non richiede autenticazione e che mostra l'elenco completo dei modelli insieme ai metadati presenti nell'interfaccia utente del catalogo: descrizione, punteggi di riferimento, editor, licenza, dimensione del contesto, link al playground e alla documentazione, oltre a un blocco usage_information.pricing:

bash
curl -s https://catalog.endpoints.ai.ovh.net/rest/v1/models_v2 | jq '.[0]'

Risposte:

bash
{
   "id": "qwen-3-5-397b",
   "name": "Qwen3.5-397B-A17B",
   "category": "Visual LLM",
   "metadata": {
     "aliases": ["Qwen/Qwen3.5-397B-A17B", "qwen3.5-397b-a17b"],
     "context": "262k",
     "usage_information": {
       "pricing": [
         {"price": 0.6, "price_unit": "million_input_tokens"},
         {"price": 3.6, "price_unit": "million_output_tokens"}
       ]
     }
   }
 }

Le due API sono complementari:

  • la catalog API è un’estrazione una tantum o periodica, utilizzata per creare tabelle locali di prezzi e metadati;
  • l' inference API è un’API che un'applicazione in esecuzione chiama a ogni richiesta.

Le due API sono complementari:

  • la catalog API è un’estrazione una tantum o periodica, utilizzata per creare tabelle locali di prezzi e metadati;
  • l' inference API è un’API che un'applicazione in esecuzione chiama a ogni richiesta.
Inference API e catalog API di AI Endpoints

Inference API e catalog API di AI Endpoints

⚠️ NB: i prezzi di AI Endpoints sono in euro.

Prerequisiti

Prima di iniziare, assicurati di avere:

  • Un account Public Cloud OVHcloud
  • Un utente OpenStack con il ruolo di Amministratore
  • Una chiave API AI Endpoints
  • Un dominio che puoi puntare a un Load Balancer
  • kubectlinstallato e helm installato (versione 3.x minimo)

Ora che disponi di tutti gli ingredienti, è giunto il momento di implementare Langfuse utilizzando OVHcloud MKS e altri servizi gestiti!

Guida all'architettura: deploy di Langfuse sui servizi gestiti del Public Cloud OVHcloud

Step 1 – Provisioning del cluster Kubernetes e dei servizi gestiti di OVHcloud

I processi web e worker di Langfuse sono di per sé leggeri: la scelta delle risorse dipende quasi interamente dai servizi gestiti circostanti. Di seguito ti mostriamo alcuni passaggi necessari per la configurarli.

Tutto quanto segue viene creato nello Spazio Cliente OVHcloud, nella sezione Public Cloud del tuo progetto.

1. Crea cluster MKS e pool di nodi

1.1. Configura i cluster

Dallo Spazio Cliente OVHcloud, crea un cluster Kubernetes utilizzando il MKS:

  • Nome: langfuse-cluster
  • Localizzazione: Region 1-AZ – Gravelines (GRA11)
  • Piano: Free (o Standard)
  • Rete: connettere una Rete privata (es. 0000 - AI Private Network)
  • Versione: ultima versione stabile (es. 1.35)
1.2. Crea pool di nodi

Durante la creazione del cluster, configura i due pool di nodi.

Il primo è il np-system. Esegue componenti a livello di cluster, tra cui Traefik (ingress) e cert-manager (certificati TLS) e i daemonsets di sistema predefiniti Kubernetes.

  • Nome del pool di nodi: np-system
  • Flavor: B3-8
  • Numero di nodi: 3
  • Autoscaling: disattivato (OFF)

Il secondo è il np-workload, dedicato ai pod dell’applicazione Langfuse (web + worker).

  • Nome del pool di nodi: np-workload
  • Flavor: B3-16
  • Numero di nodi: 1
  • Autoscaling: disattivato (OFF)
1.3. Configura l'accesso a Kubernetes

Una volta che è stato effettuato il provisioning dei nodi, puoi scaricare il file Kubeconfig e configurare kubectl con il tuo cluster MKS.

bash
# configure kubectl with your MKS cluster
 export KUBECONFIG=/path/to/your/kubeconfig-xxxxxx.yml
 
 # verify cluster connectivity
 kubectl cluster-info
 kubectl get nodes
Returns:
NAME STATUS ROLES AGE VERSION
 np-system-node-388e55 Ready <none> 12d v1.35.2
 np-system-node-4c5326 Ready <none> 12d v1.35.2
 np-system-node-93bc1c Ready <none> 12d v1.35.2
 np-workload-node-3a76f7 Ready <none> 12d v1.35.2

2. Configura i database

2.1. Database Postgre per i dati transazionali Langfuse

Dalla sezione Database nel Public Cloud OVHcloud, clicca su Crea un servizio e configuralo in questo modo:

  • Motore: PostgreSQL
  • Versione: 17
  • Localizzazione: GRA
  • Piano: Business
  • Istanza: Db1-4
  • Storage: 80 GB (predefinito)
  • Rete: rete pubblica (Internet)

Conserva le informazioni seguenti prima di passare allo step successivo:
 - host
 - port
 - nome del database
 - username
 - password
 - URI

2.2. Database Valkey per il caching e il queuing dei job

Dalla sezione Database nel Public Cloud OVHcloud, fai clic su Crea un servizio e configuralo in questo modo:

  • Motore: Valkey
  • Versione: 8.1
  • Localizzazione: GRA
  • Piano: Business
  • Istanza: Db1-4
  • Storage: 80 GB (predefinito)
  • Rete: rete pubblica (Internet)

Conserva le informazioni seguenti prima di passare allo step successivo:
 - host
 - port
 - nome del database
 - username
 - password
 - URI

2.3. ClickHouse, il cuore dei dati di osservabilità

Dalla sezione Analytics nel Public Cloud OVHcloud, clicca su Crea un servizio e configuralo come segue:

  • Motore: ClickHouse
  • Versione: 25.8
  • Localizzazione: EU-WEST-PAR
  • Piano: Production
  • Istanza: B3-16
  • Storage: 100 GB (predefinito)
  • Rete: rete pubblica (Internet)

Segnati le informazioni seguenti prima di passare allo step successivo:
 - host
 - port
 - nome del database
 - username
 - password
 - URI

⚠ NB: i database gestiti da OVHcloud (Postgres, Valkey, ClickHouse) rifiutano di default tutte le connessioni fino a quando non vengono aggiunti gli IP sorgente consentiti nella pagina "Restrizioni IP" di ciascuna istanza nello Spazio Cliente OVHcloud. Ricorda che è necessario aggiungere gli IP pubblici del tuo pool di nodi MKS a tutti e tre i database prima di implementare Langfuse, altrimenti ogni connessione dal cluster scadrà.

Dalla scheda Configurazione di ogni database, applica il whitelisting degli IP come mostrato in questo esempio:

Whitelisting degli IP pubblici del pool di nodi MKS

Whitelisting degli IP pubblici del pool di nodi MKS

3. Crea un bucket compatibile con S3 come backend di storage

Dalla sezione Object Storage del Public Cloud OVHcloud, crea un container di oggetti:

  • Tipo di container: API compatibile con S3
  • Localizzazione: GRA

Segnati le informazioni seguenti prima di passare allo step successivo:
 - nome del bucket
 - endpoint
 - access key
 - secret key

Step 2 – Configura namespace e quote

Crea namespace dedicati per l’ingress controller, il gestore di certificati e Langfuse, e limita il consumo del namespace Langfuse in modo che un carico di lavoro incontrollato non possa bloccare il resto del cluster.

Prima di tutto crea:

In seguito, avvia il deploy.

bash
kubectl apply -f deploy/bootstrap/namespaces.yaml
kubectl apply -f deploy/bootstrap/resourcequota.yaml

Step 3 – Installa l'ingress controller e il certificate manager

Questa architettura utilizza Traefik anziché ingress-nginx.I comandi di installazione completi sono inclusi in 

deploy/ingress/install.sh. Puoi eseguire:. You can run:

bash
 bash deploy/ingress/install.sh

helm upgrade --install fornisce automaticamente un nuovo Load Balancer OVHcloud con un IP pubblico. Aspetta che venga assegnato prima di procedere:

bash
kubectl -n traefik get svc traefik -w

cert-manager gestisce l'emissione e il rinnovo dei certificati. Installalo dal registro OCI, che OVHcloud e upstream attualmente consigliano rispetto al vecchio repository Helm.

Scarica lo script cert-manager/install.sh ed esegui:

bash
bash cert-manager/install.sh

In seguito, crea un ClusterIssuer per Let's Encrypt, utilizzando Traefik come “solver” HTTP-01.

Prima di tutto, definisci il tuo indirizzo email nel file cert-manager/cluster-issuer.yaml.

⚠️ NB: Let's Encrypt utilizza questo indirizzo per le notifiche di scadenza e il registro cert-manager accetterà tacitamente un valore predefinito se dimenticherai di indicarne uno. Per questo step devi attendere che cert-manager sia in esecuzione e che la ingress class di Traefik sia implementata, in modo che il resolver possa farvi riferimento. Quindi, eseguilo una volta che le due installazioni descritte sopra sono complete:

bash
kubectl apply -f cert-manager/cluster-issuer.yaml

⚠️ NB: è necessario fissare chiaramente la versione del chart (--version). In caso contrario, i due comandi sopra utilizzeranno, di default, l'ultima versione disponibile al momento dell'installazione, il che significa che il deploy non può essere riprodotto esattamente nel tempo.

Step 4 – Configura il DNS affinché punti al Load Balancer

Una volta che il servizio Traefik ha un IP esterno, crea un record A per l'hostname dove Langfuse sarà disponibile:

bash
kubectl -n traefik get svc traefik -o jsonpath='{.status.loadBalancer.ingress[0].ip}'

Crea langfuse. {},<your-domain> -> quell’IP nella tua zona DNS e conferma che venga risolto prima di continuare: altrimenti, la challenge HTTP-01 di cert-manager fallirà silenziosamente e verrà ritentata indefinitamente.

Step 5 – Salva le credenziali in un secret Kubernetes e configura i valori Helm

Il chart Helm di Langfuse legge ogni credenziale da un secret e non da valori semplici, quindi nessun dato sensibile può essere presente nei file di valori:

bash
kubectl -n langfuse create secret generic langfuse-secrets \
   --from-literal=LANGFUSE_SALT="$(openssl rand -base64 32)" \
   --from-literal=LANGFUSE_SECRET_KEY="$(openssl rand -hex 32)" \
   --from-literal=NEXTAUTH_SECRET="$(openssl rand -base64 32)" \
   --from-literal=POSTGRES_PASSWORD="<your-postgres-password>" \
   --from-literal=VALKEY_PASSWORD="<your-valkey-password>" \
   --from-literal=CLICKHOUSE_PASSWORD="<your-clickhouse-password>" \
   --from-literal=S3_ACCESS_KEY="<your-s3-access-key>" \
   --from-literal=S3_SECRET_KEY="<your-s3-secret-key>"

Il chart utilizzato è il chart ufficiale langfuse/langfuse-k8s. Puoi trovare il file completo nel repository GitHub di OVHcloud public-cloud-examples: deploy/langfuse/values.yaml

⚠️ NB: ogni deploy: false dice al chart di non installare i propri sub-chart Postgres/Valkey/ClickHouse/MinIO e di connettersi invece alle istanze gestite da OVHcloud. Per questo motivo, si tratta di un deploy di servizi gestiti e non di un deploy autogestito.

Step 6 – Installa Langfuse

Recupera il file deploy/langfuse/values.yaml dal repository e apporta le modifiche necessarie:

  • <your-domain>
  • <your-postgresql-host>
  • <your-valkey-host>
  • <your-clickhouse-host>
  • <your-bucket>

Quindi salva i values.yaml aggiornati ed esegui deploy/langfuse/install.sh.

bash
bash deploy/langfuse/install.sh

Si tratta della fase finale dell'installazione: richiede il namespace e il secret degli step 2 e 5, la risoluzione DNS dello step 4 (altrimenti il certificato TLS non può essere emesso) e il ClusterIssuer dello step 3, che deve già esistere.

Successivamente, verifica che tutto il processo di deploy sia avvenuto in modo efficace:

bash
kubectl -n langfuse get pods
curl -s https://langfuse.<your-domain>/api/public/health

{"status":"OK","version":"<chart appVersion>"} sull’health endpoint e entrambi i pod Running senza riavvii, significa che lo stack è attivo: ingress, TLS, Postgres, Valkey, ClickHouse e S3 sono tutti raggiungibili.

Step 7 – Strumentare un’applicazione

1. Configura l'SDK nella tua applicazione.

Una volta che Langfuse è raggiungibile, per puntare un'applicazione verso di esso è sufficiente sostituire l’SDK, non riscrivere l’applicazione. Per un'applicazione che utilizza l’SDK Python di openai con gli AI Endpoints:

bash
from dotenv import load_dotenv
 
 load_dotenv()  # OPENAI_API_KEY, OPENAI_BASE_URL, LANGFUSE_* must be loaded first
 
 from langfuse.openai import openai  # drop-in replacement for `import openai`
 
 client = openai.OpenAI()  # reads OPENAI_API_KEY / OPENAI_BASE_URL
 
 response = client.chat.completions.create(
     model="Qwen3.5-397B-A17B",
     messages=[{"role": "user", "content": "hello"}],
     stream=True,
     stream_options={"include_usage": True},
     name="chat-response",
     metadata={
         "langfuse_session_id": "session-123",
         "langfuse_user_id": "user-456",
         "langfuse_tags": ["feature:chat"],
     },
 )

⚠️ NB: usa examples/.env.example e modifica questo file .envcon le tue variabili d'ambiente. Poi, carica le variabili d’ambiente e configura il client Langfuse prima di importare langfuse.openai.

Per deploy di riferimento completi e testati di questo schema, che coprono conversazioni multi-turn, tagging di sessione/utente e gestione dei prompt in quattro diversi profili di utilizzo (generazione di codice, FAQ, riassunto di documenti, contenuti long-form):

⚠️ Attenzione: se consumi una risposta in streaming, non interrompere l'iterazione non appena finish_reason == "stop". Diversi provider compatibili con OpenAI, inclusi AI Endpoints, inviano il chunk contenente l’utilizzo del token dopo quel punto; interrompere anticipatamente significa che Langfuse non lo vede mai e che il costo della traccia viene visualizzato come zero, anche se i token sono stati effettivamente consumati.

Qualche modifica trasforma un'integrazione funzionale in un’integrazione utile:

Tabella delle caratteristiche

2. Tracciamento dei costi per l'utilizzo di AI Endpoints

Langfuse calcola il costo per traccia da una tabella di prezzi di modelli e non ha alcuna entry di default per i modelli ospitati su OVHcloud: ogni traccia un costo di 0$ finché non viene specificato il prezzo di ciascun modello. Ecco a cosa serve la catalog API di cui parlavamo prima ("https://catalog.endpoints.ai.ovh.net/rest/v1/models_v2"): recupera il costo una volta, registra il prezzo di ogni modello con la Models API di Langfuse per poi calcolarlo automaticamente per ogni chiamata successiva.

bash
import os
 import requests
 
 LANGFUSE_BASE_URL = os.environ["LANGFUSE_BASE_URL"]
 LANGFUSE_PUBLIC_KEY = os.environ["LANGFUSE_PUBLIC_KEY"]
 LANGFUSE_SECRET_KEY = os.environ["LANGFUSE_SECRET_KEY"]
 
 catalog = requests.get(
     "https://catalog.endpoints.ai.ovh.net/rest/v1/models_v2"
 ).json()
 
 for model in catalog:
     pricing = model.get("metadata", {}).get("usage_information", {}).get("pricing")
     if not pricing:
         continue
     prices = {
         {"million_input_tokens": "inputPrice", "million_output_tokens": "outputPrice"}[p["price_unit"]]: p["price"] / 1_000_000
         for p in pricing
         if p["price_unit"] in ("million_input_tokens", "million_output_tokens")
     }
     if not prices:
         continue
     requests.post(
         f"{LANGFUSE_BASE_URL}/api/public/models",
         auth=(LANGFUSE_PUBLIC_KEY, LANGFUSE_SECRET_KEY),
         json={
             "modelName": f"ovh-ai-endpoints/{model['id']}",
             "matchPattern": f"(?i)^({model['name']})$",
             "unit": "TOKENS",
             **prices,
         },
     )

Questa è una chiamata API unica, non uno script tenuto in questo repository: una volta che il prezzo di un modello è registrato, risiede in Langfuse e qualsiasi cliente può trovarlo lì. Vedi gli esempi/README.md per una spiegazione completa, incluso il motivo per cui i prezzi vengono mostrati in euro nonostante Langfuse utilizzi il simbolo del dollaro.

Una volta che esiste una definizione di prezzo corrispondente, il costo appare immediatamente sulle nuove tracce.

In una chiamata reale verso Qwen3.5-397B-A17B: 

  • 28 token di input (0,60 € per milione di token)
  • 1.430 token di output (3,60 € per milione di token)

Il calculatedTotalCost di Langfuse è risultato essere: 28 x 0,0000006 + 1430 x 0.0000036 = 0,0051648 €

Langfuse Cost Dashboard

Langfuse Cost Dashboard

⚠️ NB: Langfuse visualizza sempre il costo con un prefisso $; non esiste alcuna impostazione della valuta per progetto. Se la tabella dei prezzi che importi è in euro, come nel caso delle tariffe di AI Endpoints di OVHcloud, ogni cifra nell'UI Langfuse è un importo in euro visualizzato con il simbolo del dollaro.

È inoltre possibile controllare le diverse metriche per la latenza del modello:

Langfuse Latency Dashboard

Langfuse Latency Dashboard

Puoi spingerti oltre e analizzare le tracce, che rappresentano richieste o operazioni.

Esempio di traccia Langfuse

Esempio di traccia Langfuse

Congratulazioni! Ora hai accesso a tutte le funzionalità di Langfuse in un ambiente controllato.

Spingiti oltre

  • Alta disponibilità: questa architettura esegue un’unica replica web e worker, che è sufficiente per convalidare la configurazione ma non permette l’eliminazione di un pod senza downtime. Aumenta le repliche fino a 2 o più sul web per un deploy pubblico, e aggiungi un PodDisruptionBudget di dimensioni adeguate: una configurazione con una singola replica non protegge nulla.
  • Autoscaling: né HPA né KEDA sono abilitati di default; abilitane uno se il volume delle richieste è imprevedibile.
  • Avviso sui costi: la stessa models API utilizzata per inizializzare i prezzi può essere interrogata nuovamente tramite l'API delle metriche di Langfuse per creare notifiche sui costi automatiche per team o funzionalità, in modo da evitare di controllare manualmente le dashboard.
  • Policy di rete: non sono definite in questa configurazione; ti consigliamo di limitare l'egress dal namespace Langfuse solo agli endpoints dei servizi gestiti di cui ha bisogno.

Conclusioni

Questa architettura ti offre un deploy Langfuse che:

  • Funziona su MKS di OVHcloud senza database auto-gestiti: Postgres, Valkey, ClickHouse e Object Storage sono tutti servizi gestiti da OVHcloud;
  • Termina automaticamente TLS tramite Traefik e cert-manager, rinnovando i certificati senza intervento manuale;
  • Ottiene tutte le tracce, incluso l'utilizzo dei token e la latenza, da qualsiasi applicazione che chiama AI Endpoints di OVHcloud tramite una modifica di due righe all’SDK;
  • Attribuisce i costi per modello, per utente e per sessione, utilizzando il catalogo prezzi di AI Endpoints anziché fare supposizioni;
  • Mantiene ogni prompt, completamento e costo all'interno dell'infrastruttura che controlli.

Condividi su::