İçeriğe geç
mcpd
daemon yok
Kaynak

Yapılandırma

Her ayar bir seçenektir ve her seçeneğin aynı anlama gelen bir ortam değişkeni vardır. Komut satırına sığmayacak kadar yapılı olan birkaç ayar tek bir JSON dosyasında durur. Bu sayfa hepsini anlatır.

Aynı şeyi söylemenin iki yolu

mcpd'yi hiçbir argüman vermeden çalıştırın, iş görür: 0.0.0.0:4317 adresini dinler, veriyi ./mcpd.db içinde tutar, sırları maskeler ve her trace'i sonsuza kadar saklar. Aşağıdaki her şey bu kararlardan birini değiştirir.

Bir seçenek her zaman kendi ortam değişkenini yener. İkisi de geneldir, yani bir alt komuttan önce de sonra da kabul edilir.

Referans

Seçenek Değişken Varsayılan
--listen MCPD_LISTEN 0.0.0.0:4317
--data MCPD_DATA ./mcpd.db
--project MCPD_PROJECT default
--retention-days MCPD_RETENTION_DAYS ayarsız: her şey saklanır
--ingest-key MCPD_INGEST_KEYS yok: alım açıktır
--read-key MCPD_READ_KEYS yok: okuma açıktır
--write-key MCPD_WRITE_KEYS yok: alım anahtarları kabul edilir
--admin-key MCPD_ADMIN_KEYS yok: okuma anahtarları kabul edilir
--execute-key MCPD_EXECUTE_KEYS yok: yazma anahtarları kabul edilir
--worker-key MCPD_WORKER_KEYS yok: yazma anahtarları kabul edilir
--runs-data MCPD_RUNS_DATA uzantısından önce .runs eklenmiş --data yolu
--trusted-identity-header MCPD_TRUSTED_IDENTITY_HEADER yok: hiçbir özne kaydedilmez
--trusted-proxy-cidr MCPD_TRUSTED_PROXY_CIDRS yok: hiçbir adres o başlığı ayarlayamaz
--sample MCPD_SAMPLE ayarsız: her trace saklanır
--quota-per-minute MCPD_QUOTA_PER_MINUTE ayarsız: tavan yok
--no-redact MCPD_NO_REDACT kapalı: maskeleme açıktır
--redact-key MCPD_REDACT_KEY yerleşik bir anahtar, herkese açık
--redact-key-contains MCPD_REDACT_KEY_CONTAINS yok: yalnızca yerleşik kurallar
--redact-max-string MCPD_REDACT_MAX_STRING 128 KiB
--cors-origin MCPD_CORS_ORIGINS yok: yalnızca aynı köken
--request-timeout-seconds MCPD_REQUEST_TIMEOUT_SECONDS 30
--max-body-bytes MCPD_MAX_BODY_BYTES 33554432, yani 32 MiB
--max-batch-signals MCPD_MAX_BATCH_SIGNALS 10000
--log-format MCPD_LOG_FORMAT text
--clickhouse-url MCPD_CLICKHOUSE_URL kapalı: gömülü dosya kullanılır
--clickhouse-database MCPD_CLICKHOUSE_DATABASE mcpd
--clickhouse-user MCPD_CLICKHOUSE_USER yok
--clickhouse-password MCPD_CLICKHOUSE_PASSWORD yok
--postgres-url MCPD_POSTGRES_URL kapalı: gömülü dosya kullanılır
--config-file MCPD_CONFIG_FILE yok
--forward-endpoint MCPD_FORWARD_ENDPOINT kapalı: hiçbir şey iletilmez
--forward-header MCPD_FORWARD_HEADERS yok
yok MCPD_LOG mcpd=info,mcpd_server=info,tower_http=warn

--listen

Bağlanılacak adres. Tek bir port OTLP uçlarını, yerel alım ucunu, sorgu API'sini, yoklamaları, metrikleri ve arayüzü birlikte sunar; dolayısıyla mcpd'nin tek adresi budur.

Bir geri döngü adresine bağlanmak sessiz seçimdir: mcpd, açık alım için yalnızca bağlandığı adres geri döngü değilse uyarır. Hiç anahtar ayarlanmadan 0.0.0.0 üzerinde başlatıldığında açılışta iki kez uyarır, biri alım biri okuma için.

--data

SQLite dosyasının yolu. Üst dizinler yoksa oluşturulur. Arkasında hiçbir şey bırakmayan bir depo için :memory: verin; bu bir gösterim veya test için doğru, yarın bakmak isteyeceğiniz bir şey için yanlıştır.

--project

Gönderen bir proje adı vermediğinde sinyalin düştüğü proje. Proje kiracılık sınırıdır: her sorgu tek bir projeyle sınırlıdır. Saklama taraması hem bu proje hem de projects bloğundaki her proje için çalışır; ikisine de girmeyen bir proje hiç budanmaz, ki gönderenleriniz kendi projelerini adlandırıyorsa bu önemlidir.

--retention-days

Bu kadar günden eski sinyalleri silin. Ayarsız bırakmak her şeyi saklar; bir dizüstü için doğru varsayılan budur ve başka her yerde bilerek verilmesi gereken bir karardır.

Pencere 1 ile 36500 gün arasındadır; bir projenin retention_days değeri için de aynısı geçerlidir. Sıfır, saklama yok diye okunmaz, başlangıçta reddedilir: kesim noktasını şimdiye koyardı ve ilk geçiş açılışta çalıştığı için projenin tüm sinyallerini silerdi. Her şeyi tutmak için ayarı hiç vermeyin.

Tarama sorgu anında değil saatlik bir zamanlayıcıyla çalışır, böylece büyük bir silme hiçbir zaman kullanıcının isteğinin içine düşmez. Span'ler, trace'ler, loglar ve metrikler mcpd'nin onları aldığı ana göre kesilir; puanlar, geri bildirimler ve yön notları kendi zaman damgalarına göre. Satırları silmek dosyayı küçültmez. Bakınız İşletme.

--ingest-key, --read-key, --write-key, --admin-key, --execute-key ve --worker-key

Altı kapsam, çünkü taşıdıkları risk gerçekten farklıdır. Her uç, ihtiyaç duyduğu kapsamı spec/mcpd.spec.json içinde bildirir, arkasındaki işleyici de aynı şekilde etiketlenir ve make check ikisini karşılaştırır; yani burada belgelenen kapsam, çalışan sunucunun uyguladığı kapsamdır.

Kapsam Ayarlandığı yer Neyi açar
ingest --ingest-key Dört alım ucunu. Hiçbir şey okumaz.
read --read-key Sorgu API'sini: trace'ler, span'ler, loglar, metrikler, puanlar, analiz.
write --write-key Puanlar, geri bildirimler, veri kümeleri, deneyler, onaylar ve bir çalıştırmanın veri kümesine alınması.
admin --admin-key Bir trace'i silmeyi, denetim günlüğünü okumayı ve aşağıdaki iki kapsamın açtığı her şeyi.
execute --execute-key Bir çalıştırmayı başlatmayı, iptal etmeyi, ona sinyal göndermeyi ve olay yayımlamayı.
worker --worker-key Tanım kaydetmeyi, adım almayı ve sonucunu bildirmeyi. Hiçbir trace okumaz.

En çok önem taşıyan ayrım ingest ile geri kalan her şey arasındakidir. Alım anahtarı, span üreten her süreçte bulunur; yazmadığınız kodu çalıştıranlarda bile. Bu kalabalığa, saklanmış her prompt'u da geri okuyabilen bir kimlik bilgisi vermek, mcpd'nin kolaylaştırmadığı bir hatadır: sorgu API'sine sunulan bir alım anahtarı reddedilir.

write, aynı nedenle daha küçük ölçekte ingest'ten ayrıdır. Bir çalıştırmayı veri kümesine almak, o çalıştırmanın girdisini ve çıktısını okur; yani yazma kılığına girmiş bir okumadır ve filonuzun taşıdığı anahtarda yeri yoktur.

admin, read'den ayrıdır çünkü bir çalıştırmayı silmek onu okumak değildir. --admin-key ayarlanana kadar okuma anahtarı okuduğu gibi siler de; mcpd bunu açılışta söyler.

execute ile worker, çalıştırma yüzeyinin iki kapsamıdır. Bir çalıştırmayı başlatmak, birinin worker'ına iş yaptırır ve para harcatır; bir trace'e not düşmek bunu yapmaz, o yüzden bu write değildir. Worker anahtarı, adım gövdelerini çalıştıran ve genellikle sağlayıcı kimlik bilgisini tutan süreçte durur; bu yüzden yalnızca lease protokolünü açar, saklanmış bir prompt'u okuyan hiçbir şeyi açmaz. İki seçeneği ayarlayana kadar her ikisi için yazma anahtarları kabul edilir, admin anahtarı ise her zaman geçerlidir.

Kesinti olmadan yükseltmek

Ayarlanmamış bir --write-key alım anahtarlarını, ayarlanmamış bir --admin-key ise okuma anahtarlarını kabul eder. Bu iki kapsam var olmadan önce yapılandırılmış bir kurulum böylece tam olarak sahip olduğu erişimi korur ve yükseltmede hiçbir şey bozulmaz. Daha dar yetkilere geçmek için iki seçeneği ayarlayın; hangi durumda olduğunuzu mcpd config söyler: kapsamın kendi anahtarları varsa key required, devraldığında ise key required (ingest keys) veya key required (read keys) yazar.

Birden çok anahtar için altı seçenekten herhangi birini tekrarlayın; bir anahtarı kesintisiz döndürmenin yolu budur. Ortam değişkenleri virgülle ayrılmış bir liste alır. Çağıran, anahtarı Authorization: Bearer KEY veya X-Mcpd-Key: KEY olarak sunar; karşılaştırma sabit zamanlıdır, yani ne uzunluk ne de ilk farkın konumu gözlemlenebilir.

mcpd'nin tanımadığı bir anahtar 401'dir. mcpd'nin tanıdığı ama kapsamının kapsamadığı bir uçta kullanılan anahtar 403'tür. İkisini ayrı tutmak önemlidir: 401, gayet doğru olan bir anahtarda yazım hatası aramaya gönderir.

Hiç anahtar yapılandırılmadığında her kapsam açıktır. Bu bilinçlidir, çünkü ilk çalıştırma bir kimlik bilgisi istememelidir; açılış uyarısının nedeni de budur.

Anahtarların neyi kapsamadığına dikkat edin: bu sürümde /healthz, /readyz, /metrics ve arayüzün kendisi anahtarsız sunulur. Sizin için önemliyse bunları kendi girişinizin arkasına koyun.

Boş bir girdi, listeyi herhangi bir şey okumadan önce atılır. MCPD_EXECUTE_KEYS= ya da bir Kubernetes Secret'ındaki boş bir değer gibi, ayarlanmış ama hiç anahtar içermeyen bir liste servisin başlamasını engeller ve ret iletisi seçeneği ve değişkeni adlandırır; kapsamı ayarlanmamış bırakmak için değişkeni hiç koymayın; boş bir anahtar başlığı gönderen bir istek hiç anahtar sunmamış sayılır. deploy/ içindeki örnek dosyalardan kalan bir yer tutucu, yani büyük ya da küçük harfle REPLACE_WITH veya replace-me ile başlayan her değer, servisin başlamasını engeller; ret iletisi değeri asla değil, seçeneği ya da proje listesini adlandırır. Aynısı --redact-key için de geçerlidir. Her anahtarı openssl rand -hex 32 ile üretin. --write-key, --execute-key ve --worker-key ayarlanmamışsa alım anahtarları çalıştırma da başlatır ve adım da üstlenir; mcpd bunu başlarken ve mcpd doctor içinde uyarır.

Denetim günlüğü

Yük geri veren işleyiciler kimin neyi okuduğunu kaydeder: GET /v1/api/traces/{id}, span ve log aramaları, geri bildirim, veri kümesi öğeleri, alma ve silme. Her satır zamanı, işlemi yapan anahtarın kısa bir özetini, eylemi, projeyi, kaynağı ve yetkilendirmenin izin verip vermediğini taşır. Anahtarın kendisi hiçbir zaman yazılmaz.

Günlüğü GET /v1/api/audit ile okuyun; admin kapsamı ister. --retention-days ile budanmaz: kendini, anlattığı verinin takvimiyle silen bir günlük, artık ortada olmayan veriyi kimin okuduğunu söyleyemezdi. Bir satırın yazılması, anlattığı okumayı hiçbir zaman başarısız kılmaz; yazılamayan satır loglanır ve /metrics üzerinde mcpd_audit_write_failures_total olarak sayılır, ki bu bir uyarıya değer.

--sample

0.0 ile 1.0 arasında bir kesir. Bu aralığın dışındaki bir değer sessizce kırpılmaz, açılışta hata verir: --sample must be between 0.0 and 1.0, got 2.

Karar, trace kimliğinin özeti alınarak verilir; böylece bir yük dengeleyici arkasındaki mcpd örnekleri birbirleriyle konuşmadan aynı trace'leri tutar ve aynılarını atar. Karar her trace için bir kez verilir ve yığındaki o trace'in her span'i tarafından devralınır, çünkü yarım kaydedilmiş bir trace, gözlediğiniz sistemde bir hata gibi görünür.

Özet, trace kimliğinin son baytlarını okur. Bazı üreticiler baştaki baytları bir zaman damgasından türetir; bunlara bakan bir örnekleyici günün saatiyle ilişkilenir ve sessizce koca saatleri düşürürdü.

Politika türü ayrıca "hataları her zaman tut" ve "şundan yavaş olanları her zaman tut" seçeneklerini taşır, ancak bunlar bir trace bittikten sonra verilen kuyruk kararına uygulanır. Bu sürüm yalnızca başta örnekler ve kuyruk örneklemesini açan bir seçenek yoktur. Örnekleme bu ödünleşimi anlatır.

--no-redact, --redact-key, --redact-key-contains ve --redact-max-string

Maskeleme varsayılan olarak açıktır ve her şey yazılmadan önce çalışır; böylece hiç kalıcı olmaması gereken bir değer hiç kalıcı olmaz. Sonradan silmek aynı güvence değildir. Anahtar adının küçük harfli parçalarıyla eşleşen üç kural kümesi yerleşik gelir:

Kural Anahtar şunu içerdiğinde uygulanır Ne saklanır
Tam api_key, apikey, api-key, secret, password, passwd, access_token, refresh_token, id_token, bearer, authorization, auth_token, private_key, client_secret, session_token, credential, signature, x-api-key [redacted]
Kısmi email, phone, ssn, credit_card, card_number, iban İlk iki ve son iki karakter, ab…yz. Altı karakter veya daha kısa bir değer, çoğunu sızdırmak yerine tamamen maskelenir
Özet user_id, userid sha256: ve anahtarlı bir özetin 12 baytı; böylece bir kullanıcıyı saklamadan yine de kullanıcıya göre gruplayabilirsiniz

Nesne veya dizi tutan eşleşmiş bir anahtarın altındaki her şey de maskelenir, böylece {"credentials": {"token": "..."}} yalnızca iç içe addan yararlanıp sıyrılamaz. 128 KiB'den uzun herhangi bir tek dize, bayt sayısını bildiren bir işaretle kısaltılır; bu da kaçak bir prompt'un diskinize yapabileceğini sınırlar.

--redact-key, özetleme kuralının anahtarıdır. Eşit girdiler tek bir anahtar altında eşit özet verir, gruplamayı çalıştıran budur; anahtarı döndürmek bu bağı bilerek koparır. Özet alan her kurulumda ayarlayın: yerleşik varsayılan kaynak kodda durur, yani anahtarsız özetler tahmin edilebilir.

--redact-key-contains, yerleşik üç kuralın üzerine kendi maskeleme kuralınızı ekler. Yerleşik kurallar kimlik bilgilerinin genelde hangi adlarla saklandığını bilir; kendi araçlarınızın müşteri hesap numarasını koyduğu alanı bilmez. Değer, yerleşik kurallarla aynı şekilde, anahtarın küçük harfli bir parçası olarak eşleştirilir; yani --redact-key-contains ticket hem ticket_id hem de supportTicket alanlarını, eşleşen anahtarın altındaki her şeyle birlikte maskeler. Birden çoğu için seçeneği tekrarlayın veya MCPD_REDACT_KEY_CONTAINS değişkenine virgülle ayrılmış bir liste verin.

--redact-max-string, uzunluk sınırını yerleşik 128 KiB değerinden aşağı çeker. Sınırdan uzun bir dize, kaç baytın atıldığını bildiren bir işaretle, saklanmadan önce orada kesilir.

--no-redact, uzunluk sınırı dâhil tüm hattı kapatır. Ortam değişkeni olarak MCPD_NO_REDACT=true yazılır. Yalnızca yukarı akışta bir şey zaten maskeleme yapıyorsa mantıklıdır ve yukarıdaki iki ekten biri yanında ayarlanmışsa daemon başlamayı reddeder, çünkü uygulanacakları bir şey kalmaz.

--runs-data

Çalıştırma deposunun yeri: tanımlar, adım denemelerinin günlüğü, her son tarih ve her bekleme. Sinyal deposu ne olursa olsun bu gömülü bir dosyadır; yani Postgres veya ClickHouse üzerinde bile çalıştırmalar daemon'un yanında tek bir dosyada durur ve çalıştırma yüzeyini tek bir kopya sunar. Varsayılan olarak --data yolunun uzantısından önce .runs eklenmiş hâlidir, varsayılan için ./mcpd.runs.db, ve --data öyleyse :memory: olur. --runs-data off hiç çalıştırma sunmaz: her çalıştırma ucu bu seçeneği adıyla anan bir 503 döndürür ve daemon'un geri kalanı değişmez.

Deponun zamanlamaları yapılandırma dosyasında runs altında, tam milisaniye olarak durur: lease_ttl_ms, reclaim_window_ms, stall_window_ms, idempotency_window_ms, park_ttl_ms ve max_depth. Varsayılanlar, 30 saniyelik lease ve 30 saniyelik geri alma penceresi, tek makinede tek daemon için doğrudur ve bir worker kaydolduğunda geri okuduğu değerlerdir.

--cors-origin

Sorgu API'sini başka bir siteden hangi tarayıcı kökenlerinin çağırabileceği. Hiçbiri ayarlanmadığında kökenler arası bir istek access-control-allow-origin başlığı almaz ve tarayıcı yanıtı sayfaya vermeyi reddeder. Varsayılan budur ve dizüstünüzdeki, okuma API'si açık bir daemon'un aynı tarayıcıda açık herhangi bir web sayfası tarafından okunmasını engelleyen de budur. Birlikte gelen arayüz daemon'un kendi kökeninden sunulur ve bu seçeneğe hiç ihtiyaç duymaz.

Arayüzü başka bir yerden, bir CDN'den veya bir iç portaldan sunmak, bu seçeneğin var olma nedenidir: o kökeni şema ve sunucu adı olarak yazın, örneğin --cors-origin https://console.example. Birden çoğu için tekrarlayın veya MCPD_CORS_ORIGINS değişkenine virgülle ayrılmış bir liste verin. Köken olmayan bir değer, console.example ya da sonunda eğik çizgi olan biri, başlangıcı seçeneği adıyla anarak reddeder. Bu, sizi bağlanamayan bir arayüzle ve nedenini bilmediğiniz bir sorunla baş başa bırakmaktan iyidir. --cors-origin '*' her kökene izin verir, ki daha eski sürümler bunu sormadan yapıyordu.

/healthz, /readyz ve /metrics bu seçenekle yönetilmez. Saklanmış veri taşımazlar ve arayüz her şeyden önce /healthz yoklaması yapar, bu yüzden her kökenden okunabilir kalırlar.

--request-timeout-seconds

Daemon yanıt vermeden önce bir isteğin, gövdenin okunması dâhil, sürebileceği en uzun süre. Bu süreyi aşan bir işleyiciye, gövdesinde timeout ve bu seçeneğin adı bulunan bir 503 ile yanıt verilir. Varsayılan 30 saniyedir; büyük bir yığının okunup saklanmasına yetecek kadar uzun, bağlantı kabul edip hiç yanıt vermeyen bir depolama arka ucunun beklenmek yerine bildirilmesini sağlayacak kadar kısadır. Kapatılamaz; bir işlem gerçekten daha uzun süre gerektiriyorsa yükseltin.

--max-body-bytes ve --max-batch-signals

Tek bir isteğin iki sınırı. --max-body-bytes, daemon'un okuduğu en büyük gövdedir, varsayılan olarak 32 MiB, ve hiçbiri henüz çözülmeden bir isteğin ne kadar bellek alabileceğini belirleyen odur. Daha büyük bir gövde, iki sayıyı da anan bir 413 ile reddedilir; sıkıştırılmış bir gövde ise açıldıktan sonra aynı rakama tutulur, yani bin katına genişleyen bir gövde genişletilmek yerine reddedilir.

--max-batch-signals, çözüldükten sonra bir isteğin taşıyabileceği sinyal sayısıdır, varsayılan olarak 10.000. İsteğin tamamı boyunca sayılır, yani yığınlardan oluşan bir dizi ve bir NDJSON akışı, tek bir yığınla aynı sayıya tutulur. Sınırı aşan bir istekte hiçbir şey saklanmaz: ret, ilk yazmadan sonra değil, öncesinde gelir.

İkisi aynı zamanda yapılandırma dosyası anahtarıdır, max_body_bytes ve max_batch_signals, ve ikisi de ayarlıysa seçenek kazanır. Hiçbiri kapatılamaz ve sıfır, "sınır yok" diye okunmak yerine açılışta reddedilir: sıfırlık bir gövde sınırı her isteği reddeder, yani cömert görünen okuma alımı düşüren okumadır.

--log-format ve MCPD_LOG

Terminal için text, log hattı için json. MCPD_LOG bir tracing filtre dizesi alır ve bir seçeneği yoktur, çünkü bir kurulum kararı değil bir hata ayıklama denetimidir. İstek başına ayrıntı görmek istediğinizde mcpd_server=debug olarak ayarlayın.

İki istek sınırı nerede geçerlidir

Gövde sınırı, sorgu API'si dâhil gövde okuyan her yol için geçerlidir. Sinyal sınırı alım kapıları için geçerlidir ve her birinde saydığı şudur.

Kapı Sinyal sınırının saydığı
POST /v1/ingest İstekteki her span, log, metrik, puan, geri bildirim parçası ve yön notu; tek bir yığın olarak da, yığınlardan oluşan bir dizi olarak da, NDJSON satırlarından oluşan bir akış olarak da gelmiş olsa hepsi toplanarak
POST /v1/traces Gönderenin gönderdiği span'ler, eşlenmeden önce sayılır; gönderenin üzerinde işlem yapabileceği sayı budur
POST /v1/logs Aktarımdaki log kayıtları
POST /v1/metrics Aktarımdaki veri noktaları, içindeki her metrik boyunca

Alt komutlar

Komut Ne yapar
mcpd serve Daemon'u çalıştırır. Hiç alt komut verilmediğinde olan da budur
mcpd demo Depoya gerçekçi bir örnek çalıştırma yazar, sonra sunar; böylece arayüzü ilk açtığınızda içinde bir şey olur
mcpd config Bu çağrının kullanacağı yapılandırmayı yazdırır ve çıkar
mcpd mcp Model Context Protocol'ü stdio üzerinden sunar; böylece bir ajan çalışan bir daemon'dan kendi trace'lerini okuyabilir
mcpd doctor Bu kurulumu notlandırır ve neyin yanlış yapılandırıldığını bildirir. Bir kusurda 2 koduyla çıkar, yani bir dağıtımı durdurabilir. Bakınız İşletme

mcpd config, birazdan bir konteynerle yaşayacağınız tartışma için vardır. Seçenekler, ortam değişkenleri ve varsayılanlar hep tek bir yerde toplanır; bu komut da sunucu başlatmadan ve veri dosyasına dokunmadan o yeri yazdırır:

çözümlenen yapılandırma
$ MCPD_INGEST_KEYS=k1,k2 mcpd --retention-days 30 --sample 0.1 configlisten          0.0.0.0:4317storage         sqlite at ./mcpd.dbconfig file     nonelog format      textproject         defaultprojects        noneretention       30 daysingest auth     key requiredread auth       openwrite auth      key required (ingest keys)admin auth      openexecute auth    key required (ingest keys)worker auth     key required (ingest keys)runs            sqlite at ./mcpd.runs.dbrun settings    lease_ttl_ms 30000, reclaim_window_ms 30000, stall_window_ms 300000, idempotency_window_ms 86400000, park_ttl_ms 86400000, max_depth 8, max_step_repeats 16identity        offsampling        deterministic 0.1quota           unlimitedredaction       onredact key      built in, which is public; set --redact-keycors            same-origin onlytimeout         30s per requestlimits          32 MiB per request, 10000 signals per batchderived         duration and token metricsaspects         offmonitors        noneobjectives      nonejudge           offforwarding      off

Bir şey dağıtmadan önce altı yetki satırını okuyun. open, porta erişebilen herkese açık demektir. Köşeli parantez içindeki bir satır, o kapsamın devraldığı daha geniş listeyi adlandırır; eski bir sürümden yükseltilen bir kurulumun başladığı durum budur.

Yapılandırılmış bir kurulum

Buradaki hiçbir şey mcpd'ye özgü değildir: değişkenler sıradan ortam değişkenleridir, yani Compose'da, bir Kubernetes bildiriminde ve bir systemd biriminde aynı şekilde çalışırlar.

compose

services:
  mcpd:
    image: ghcr.io/mcpd/mcpd
    ports: ['4317:4317']
    volumes: ['mcpd-data:/data']
    environment:
      MCPD_LISTEN: 0.0.0.0:4317
      MCPD_DATA: /data/mcpd.db
      MCPD_PROJECT: checkout
      MCPD_RETENTION_DAYS: '30'
      MCPD_INGEST_KEYS: write-key-one,write-key-two
      MCPD_READ_KEYS: read-key
      MCPD_REDACT_KEY: a-long-random-string
      MCPD_LOG_FORMAT: json
      MCPD_LOG: mcpd=info,mcpd_server=warn

volumes:
  mcpd-data:

Bir kabuk veya bir birim dosyası için aynı ayarlar, seçenek olarak:

mcpd --listen 0.0.0.0:4317 --data /data/mcpd.db --retention-days 30 --ingest-key $KEY --log-format json

SDK'ların okuduğu değişkenler

Bu değişkenleri daemon değil, ajanınızın süreci okur. Burada listelenmelerinin nedeni iki kümenin ad paylaşması ve hem bir ajan hem de mcpd çalıştıran bir konteynerin tek bir ortamla yapılandırılmasıdır.

Değişken Varsayılan
MCPD_ENDPOINThttp://localhost:4317
MCPD_API_KEYayarsız
MCPD_PROJECTdefault
MCPD_ENVIRONMENTayarsız
MCPD_SERVICE_NAMEayarsız
MCPD_SERVICE_VERSIONayarsız
MCPD_SAMPLE1.0
MCPD_ENABLEDtrue
MCPD_CAPTURE_PAYLOADStrue
MCPD_LOG_LEVELdebug

MCPD_PROJECT ve MCPD_SAMPLE iki tarafta da aynı anlama gelir, ki genelde istediğiniz budur: bir kez ayarlayın, ajan ve daemon proje üzerinde anlaşsın. Üzerinde düşünülmesi gereken örneklemedir. SDK bir trace'i gönderilmeden önce atar, bu da ağı korur. Daemon onu saklanmadan önce atar, ki oranın denetlemediğiniz gönderenlere uygulanabileceği tek yer burasıdır. Oranı iki yerde değil tek yerde ayarlayın, yoksa zaten süzülmüş bir akışı süzüyorsunuz demektir.

MCPD_ENABLED=false, her SDK çağrısını geçerli nesneler döndürmeyi sürdüren bir boş işleme çevirir; böylece mcpd, hiç kod değiştirmeden testlerde kapatılabilir. MCPD_CAPTURE_PAYLOADS=false, prompt'ları ve tamamlamaları süreç içinde tutar: span'ler yine de zamanlamaları, kullanımları, modelleri ve hatalarıyla gelir, ancak input ve output kuyruğa alınmadan önce atılır, yani hiç ağdan geçmez. Daemon üzerindeki maskeleme aynı telin öbür ucudur ve baytları hiç göndermemesi gereken bir ekip için yanlış uçtur. Dile göre ayrıntı her SDK sayfasındadır.

--config-file

Komut satırına sığmayan ayarları tutan bir JSON dosyası: izleyiciler, hizmet düzeyi hedefleri, değerlendirildikleri aralık, iletme, yargıç, çalıştırma deposunun zamanlamaları, iki istek sınırı ve aşağıdaki proje bazlı blok. YAML veya TOML yerine JSON, çünkü mcpd zaten diğer her şey için JSON çözümlüyor; yani dosya ne yeni bir bağımlılık ne de öğrenilecek ikinci bir sözdizimi getiriyor. Bir Kubernetes ConfigMap olarak olduğu gibi bağlanır.

max_body_bytes ve max_batch_signals komut satırının yanı sıra burada da bulunur, böylece bir filo bunları birlikte dağıtıldıkları izleyicilerin yanında tutabilir. Seçenek dosyayı yener; tek bir örneğin, ortak dosya herkes için düzenlenmeden farklı bir sınır almasının yolu budur.

Bilinmeyen bir anahtar yok sayılmak yerine başlangıcı düşürür, çünkü sessizce hiçbir şeyi izlemeyen bir yazım hatası mevcut en kötü sonuçtur.

Arka plandaki bir zamanlayıcının çalışamayacağı bir değer de başlangıcı düşürür: 0 dahil ile 1 hariç arasında olmayan bir objective, 1 ile 365 dışında bir hedef window_days değeri, 86400'ü aşan monitor_interval_seconds, 1 ile 31536000 dışında bir aspects.window_seconds, 604800'ü aşan aspects.interval_seconds ve 1 ile 300 dışında bir judge.timeout_seconds. Her ret, anahtarı ve aralığı söyler.

{
  "max_body_bytes": 33554432,
  "max_batch_signals": 10000,
  "monitor_interval_seconds": 60,
  "monitors": [
    {
      "id": "error-rate",
      "name": "Error rate above 5%",
      "project": "checkout",
      "watch": "error_rate",
      "compare": "above",
      "threshold": 0.05,
      "window_seconds": 300,
      "min_samples": 20,
      "webhook": "https://hooks.example.com/mcpd"
    }
  ],
  "forward": {
    "endpoint": "https://otlp.example.com",
    "headers": [["Authorization", "Bearer sk-..."]],
    "batch_size": 256,
    "enabled": true
  }
}

Projeler ve onlara erişen anahtarlar

Proje kiracılık anahtarıdır. Bunu süs olmaktan çıkarıp gerçek kılan, anahtarları bir projenin altında listelemektir: bir projenin bloğundaki anahtar o projeye erişir, başkasına erişmez; böylece tek bir daemon, hiçbiri diğerlerinin prompt'larını okuyamadan birkaç ekibe hizmet eder.

{
  "projects": {
    "checkout": {
      "ingest_keys": ["ck-write-..."],
      "read_keys": ["ck-read-..."],
      "admin_keys": ["ck-admin-..."],
      "retention_days": 30,
      "sample": 0.25
    },
    "support": {
      "ingest_keys": ["sp-write-..."],
      "read_keys": ["sp-read-..."],
      "retention_days": 90
    }
  }
}

Altı listenin altısı da proje başına vardır: ingest_keys, read_keys, write_keys, admin_keys, execute_keys ve worker_keys; ve aynı şekilde geri düşerler: write_keys olmayan bir proje kendi alım anahtarlarını, admin_keys olmayan bir proje kendi okuma anahtarlarını kabul eder. Yukarıdaki support bloğu ikisini de ayarlamıyor, yani tam olarak bu iki kapsam var olmadan önceki gibi davranır.

Altı üst düzey seçenekten herhangi biriyle ayarlanan bir anahtar her projeye erişir. Tek kiracılı yol budur ve basit olan yol olarak kalır: bu bloğu hiç açmazsanız hiçbiriyle karşılaşmazsınız.

retention_days ve sample, bir proje bunları ayarlamadığında genel seçeneklere geri düşer. İkisi de anahtarlarla aynı nedenle proje bazlıdır: bir ekibin doksan günlük gereksinimi herkesin verisinin saklanmasını zorunlu kılmamalı ve bir ekibin trafiği başka bir ekibin nasıl örnekleneceğine karar vermemelidir.

Bir yığın birkaç projeyi adlandırabilir. Kapsamlı bir alım anahtarı, eriştiklerini yazar, geri kalanını reddeder ve reddi sessizce düşürmek yerine yanıtta bildirir; böylece yanlış projeye yönlendirilmiş bir filo, zaten okumakta olduğu yanıttan görülebilir.

Anahtarınızın erişmediği bir proje için gelen okuma isteği, o projenin var olup olmadığı söylenmeden reddedilir. Paylaşılan bir daemon'da proje adları çoğu zaman ekiplerin veya müşterilerin adlarıdır.

İzleyiciler ve hizmet düzeyi hedefleri İzleyiciler ve uyarılar sayfasında ele alınır; hedefler monitors yanındaki bir slos dizisine girer ve aynı zamanlayıcıyla değerlendirilir. judge bloğu bir modelin notlandırdığı puanlamayı açar ve Regresyon testi sayfasında anlatılır. Siz ayarlayana kadar kapalıdır ve bir istek adını anmadıkça yargıç kullanan bir puanlayıcı hiç çalışmaz, çünkü notlandırma okuduğu her çalıştırmada para harcar.

{
  "judge": {
    "endpoint": "http://localhost:11434/v1",
    "model": "qwen2.5:14b",
    "api_key": "",
    "criteria": {
      "answer_relevance": "Does the answer address the question that was asked?"
    }
  }
}

monitor_interval_seconds, izleyicilerin ve hedeflerin ne sıklıkla değerlendirildiğidir. Varsayılanı 60’tır ve 5’in altındaki bir değer 5’e yükseltilir.

derived_metrics

Servisin sakladığı span’lerden türettiği metrikler. Blok yoksa iki yarı da açıktır. durations, biten her ajan, araç, iş akışı, model üretimi ya da işlemci span’i için bir süre noktası yazar. tokens, kullanımını bildiren her model üretimi span’i için on üçe kadar token sayacı yazar. Birini yazmayı durdurmak için false yapın; yazılmayan bir alan açık kalır. Bunun için bir seçenek yoktur. Türetilen noktalar proje başına tavandan sonra eklenir ve bir alım yanıtının bildirdiği accepted sayısına girmez.

{
  "derived_metrics": { "durations": true, "tokens": false }
}

aspects

Servisin yön notlarını temalara kümeleyip kümelemediği ve hangi sınırlar içinde yaptığı. Blok yoksa kapalıdır. enabled geçişi açar ve model ya da kimlik bilgisi gerektirmez, çünkü outcome yönünü servis kendisi yazar. interval_seconds bir geçişin ne sıklıkla çalıştığıdır, varsayılanı 300’dür ve 30’un altındaki bir değer 30’a yükseltilir. window_seconds bir geçişin notları ne kadar geriye kadar okuduğudur, varsayılanı 86400’dür. disabled hiçbir geçişin kümelemediği görünüşleri adlandırır; bunlardan biri altında kaydedilmiş notlar okunabilir kalır.

{
  "aspects": {
    "enabled": true,
    "interval_seconds": 300,
    "window_seconds": 86400,
    "disabled": ["sentiment"]
  }
}

--forward-endpoint

Saklanan her span'i başka bir OTLP/HTTP ucuna kopyalar. Temel URL'yi verin; sonuna /v1/traces eklenir. Yerel yazma her zaman önce olur, yani çalışmayan bir hedef size hiçbir şeye mal olmaz.

Bu seçenek, yapılandırma dosyasındaki forward bloğunu yener; böylece tek bir örnek, ortak bir ConfigMap düzenlenmeden başka bir yere yönlendirilebilir. Bakınız İletme.

--forward-header

İletilen her yığınla gönderilen bir başlık, Name: value biçiminde yazılır. Birden fazlası için seçeneği tekrarlayın. Ortam değişkeni virgülle ayrılmış bir liste alır.

İki nokta içermeyen bir değer atılmaz; çalışan biçim gösterilerek başlangıçta reddedilir. OpenTelemetry tarzı bir key=value başlığı burada key: value olarak yazılır.

--clickhouse-url

Bir ClickHouse sunucusunun HTTP ucu, örneğin http://clickhouse:8123. Ayarlamak depoyu gömülü dosyadan ClickHouse'a geçirir ve --data artık okunmaz. Şema açılışta oluşturulur.

Gömülü depodaki tek yazıcı ve tek kopya sınırlarını kaldıran ayar budur. Saklama süresi aylarca üretim trafiğiyle ölçüldüğünde ona uzanın, daha önce değil: İşletme bu ödünleşimi anlatır.

--clickhouse-database, --clickhouse-user, --clickhouse-password

Tabloların oluşturulacağı veritabanı ve ona erişilecek kimlik bilgileri. Parolası olmayan bir kullanıcı parolasız gönderilir; bu, özel bir ağdaki bir konteyner için doğru, başka her yerde yanlıştır.

--postgres-url

Bir Postgres bağlantı dizesi, örneğin postgres://mcpd:secret@db:5432/mcpd. Ayarlamak depoyu gömülü dosyadan Postgres'e geçirir ve --data artık okunmaz. Şema açılışta oluşturulur.

Bu orta seçenektir. ClickHouse'un kaldırdığı tek yazıcı ve tek kopya sınırlarını, sizden zaten sahip olmadığınız bir veritabanını çalıştırmanızı istemeden kaldırır. Hem bunu hem --clickhouse-url adlandırmak, birini seçmek yerine başlangıcı düşürür.

Göç bir danışma kilidi alır, yani birkaç kopyanın birlikte başlaması güvenlidir; uygulanacak bir şey olmadan yapılan bir başlangıç ise şemaya hiç dokunmaz.

TLS için bağlantı dizesine sslmode=require ekleyin. mcpd bağlantıyı şifreler ve sunucunun sertifikasını her zaman doğrular. Sertifikayı genel sertifika yetkililerine göre, ya da sslrootcert=/yol/ca.pem verilirse o dosyadaki yetkiliye göre denetler; kendi yetkilisi olan yönetilen bir hizmet bunu gerektirir. verify-ca ve verify-full, require olarak okunur. Varsayılan prefer ya da disable ile bağlantı şifrelenmez.

Yalnızca hangi anahtarı değil, kimi kaydetmek

Denetim günlüğü, işlemi yapan anahtarın bir özetini kaydeder. Bu, "bir admin anahtarı bu çalıştırmayı sildi" sorusunu yanıtlar, "hangi kişi sildi" sorusunu değil. mcpd'nin bir kimlik sağlayıcısı yoktur; bu yüzden kimlik, zaten önünde duran girişten gelmelidir.

Vekil sunucunuzun ayarladığı başlığı ve onu ayarlamasına izin verilen adresleri verin:

kimliği güvendiğiniz bir girişten alın

mcpd serve \ --trusted-identity-header x-forwarded-user \ --trusted-proxy-cidr 10.42.0.0/16

İkisi de zorunludur ve bunu güvenli kılan adres listesidir. Başlık, porta soket açabilen herkesin gönderebileceği bir dizedir; bu yüzden mcpd onu yalnızca adını verdiğiniz bir adresten okur. Başka bir yerden gelen istek normal şekilde karşılanır ve denetim satırı hiçbir özne taşımaz, ki tahmin yürütmek yerine dürüst yanıt budur. Değerin uzunluğu da sınırlanır ve denetim karakterlerinden arındırılır, çünkü proxy öyle olmasa da bir başlık saldırganın etkisindedir.

İki seçenek de ayarlanmadığında hiçbir şey değişmez ve hiçbir özne kaydedilmez. Varsayılan budur.

Tek bir proje daemon'un tamamını harcayamaz

mcpd'yi boğan bir proje, üzerindeki diğer her projeye mal olur: disk dolar, saklama yetişemez ve çalıştırmalarını kaybeden, yanlış bir şey yapmamış olan ekip olur. --quota-per-minute bunu durduran tavandır.

her proje için bir tavan, birine daha büyüğü

mcpd serve --quota-per-minute 10000

Ayarsız olması tavan yok demektir, yani hiç ayarlamayan bir kurulum tam olarak kotalar var olmadan önceki gibi davranır. Ayarlandığında üç şeyi kapsar: projects bloğunda kendi quota_per_minute değerini vermeyen her projeyi, --project ile adlandırılan projeyi ve yapılandırmanın hiç listelemediği her projeyi.

Bunu bir öneri değil bir tavan yapan, sonuncusudur. Proje adı istek gövdesinin içinde gelir; yani hiçbir yapılandırma dosyasının listelemediği bir ad seçen gönderen eskiden hiçbir hesaba yazılmıyor ve sınırsızca saklayabiliyordu. Gönderenin bir dize uydurarak çıkabildiği sınır, sınır değildir.

Listelenmemiş her proje, her birine bir tane verilmesi yerine tek bir sayacı paylaşır. Ad başına bir sayaç, herhangi bir gönderenin ad uydurarak sürebileceği bir tahsis olurdu; aynı deliğin başka bir biçimi. Paylaşmak, bin uydurma ada yayılmış bir taşkının toplamda bu sayıyla sınırlı kalması demektir; ve kendi payını hak eden bir projenin, payı olan projects içinde adlandırılması gerektiği anlamına gelir.

Tavanın gerçekte neyi sınırladığı

Sayaç iki pencereli ağırlıklı türdendir: bu dakikanın sayısı, artı ondan önceki dakikanın, şu an biten pencerenin ne kadarını hâlâ kapsadığıyla ağırlıklandırılmış hâli. Sürekli hızı tavanda tutar ve üstüne bir tavan kadarlık ani yüke izin verir, çünkü dolu bir kuyruğu boşaltan SDK tek bir yığın olarak gelir ve bunu reddedecek bir sayaç sıradan trafiği de reddederdi.

Bu ikisinin, saklanmak yerine söylenmeye değer aritmetik bir sonucu vardır. Bir proje 60 saniyelik bir aralık içinde tavanının kılpayı iki katını saklayabilir: bir pencerenin en sonunda tam bir tavan ve bir sonrakinin en sonunda yine tam bir tavan. Bu, yaklaşıklığın bir yan etkisi değildir. Bir projenin tavanını bir anda ve sonrasında dakikada bir tavan daha harcamasına izin veren her sınırlayıcı, bunu bir sınır üzerinde mümkün kılar; kaldırmanın tek yolu ani yükü reddetmektir.

Pencere bir dakikadır ve yapılandırılamaz. Seçenek birimi kendi adında taşıyor; "dakika başına"nın ne demek olduğunu değiştiren ikinci bir ayar, ilk sayıyı okunamaz kılardı.

Fazlasına ne olur

Tavanı aşan sinyaller reddedilir ve bildirilir, hiçbir zaman sessizce düşürülmez. Yığının tamamı reddedilmez: mcpd sığanı saklar ve sığmayanı size söyler.

  • Span'ler trace bütünlüğünde gider. Yarım bir çalıştırmada, ebeveynini kimsenin saklamadığı span'ler olur; bu, eksik bir çalıştırma değil bozuk bir çalıştırma gibi okunur. Kalan yere sığmayacak kadar büyük bir trace atlanır ve bir sonraki denenir, böylece tek bir büyük çalıştırma payın kalanını hiçbir şeye harcamaz.
  • Loglar, metrikler, puanlar ve geri bildirimler tek başına durur, yani kalan yeri geliş sırasına göre doldururlar.
  • Yalnızca saklanan hesaba yazılır. Budama trace'leri bütün tuttuğu için izin verilenden daha az sinyal saklayabilir ve fark geri verilir. Bu olmasaydı, çalıştırmaları kalan payından büyük olan bir proje hiçbir şey saklamadan payını sıfıra kadar harcardı.
  • Aynı istekteki diğer projelere dokunulmaz. Tavanını aşan bir proje, yanında gönderdiği sinyalleri başka bir projeye mal etmez.

Yanıt, sayıyı rejected içinde ve projeyi ile tavanını adlandıran bir satırı errors içinde taşır. Yapılandırmanın hiç listelemediği bir proje farklı bir cümle alır, çünkü analytics-v2 projesinin tavanını aştığını duymak, yanıt projeyi eklemekken sizi var olmayan bir ayarı aramaya gönderir:

kimsenin yapılandırmadığı bir projeye sekiz sinyal, paylaşılan tavan beşken
$ curl -sX POST "$MCPD/v1/ingest" -H content-type:application/json -d @batch.json | jq{  "accepted": 5,  "rejected": 3,  "duplicate": 0,  "errors": [    {      "signal": "span",      "index": 0,      "message": "3 signal(s) named project analytics-v2, which                  no configuration lists. Every unlisted project                  shares one ceiling of 5 per minute and it was                  full, so they were not stored. Add analytics-v2                  to the `projects` block to give it an allowance                  of its own, or raise --quota-per-minute."    }  ]}

Bir ret, mcpd_signals_rejected_total yanında mcpd_signals_over_quota_total içinde de sayılır; böylece sınırlanan bir filo, bozuk veri gönderen bir filodan ayırt edilebilir. Bakınız İşletme.

Ayarlarken bakılacak iki şey

Tavan, sinyal saklayan her kapıyı kapsar: yığın kapıları /v1/ingest, /v1/traces, /v1/logs ve /v1/metrics, ve tek kayıtlık kapılar POST /v1/api/scores ile POST /v1/api/feedback. İkisi, tavanını aşan bir projeye bilerek farklı yanıt verir. Yığın kapısı sığanı saklar ve kalanını bir gerekçeyle rejected olarak bildirir, çünkü bir yığın birkaç projeyi adlandırabilir ve isteğin tamamını reddetmek tavanı içindeki projeleri cezalandırırdı. Tek kayıtlık kapının verecek kısmi bir yanıtı yoktur, bu yüzden 429 ile ve o projenin sayacının başka bir sinyali kabul etmesine kaç saniye kaldığını taşıyan bir Retry-After başlığıyla reddeder. Sayı sayacın kendisinden gelir, yani ona uyan bir istemci sabit bir gecikme dolduğunda değil yer açıldığında geri döner.

Bir yazma kapısı buna yazılmaz: saklanan çalıştırmalar üzerinde puanlayıcı çalıştıran POST /v1/api/score. Ürettiği puanları doğrudan depolamaya verir, yani tavanı çoktan harcanmış bir proje için de bir geçiş diske düşer; ve o satırlar ne mcpd_signals_over_quota_total ne de mcpd_signals_unbounded_total tarafından sayılır. Bir filonun yöneldiği bir kapı değil, kendi açtığınız bir kapıdır; bu yüzden tavanı diske erişebilen her şeyin değil, gönderenlerin içeri itebileceğinin sınırı sayın.

--max-batch-signals değerinin, varsayılan olarak 10.000, altında bir tavan, tek bir geçerli yığının koca bir dakikanın payını aşabileceği ve gönderen ne kadar iyi davranırsa davransın budanacağı anlamına gelir. mcpd doctor bunu limits altında notlandırır ve geçerli olduğu projeleri adlandırır. Ayrıca proje başına bir tavan ayarlanmış ve yanında üst düzey bir tavan ayarlanmamışsa uyarır; her listelenmemiş projeyi sınırsız bırakan yapılandırma budur.

mcpd config, sınırlanan projeleri adlarıyla yazdırır; böylece ayarın neyi kapsadığını çıkarım yapmak yerine geri okuyabilirsiniz. Yalnızca adlandırılmış tavanları yazdırır, bu yüzden paylaşılanı seçeneğin kendisinden doğrulayın.