OpenTelemetry
Ajanınız zaten OpenTelemetry yayıyorsa, mcpd bir endpoint değişikliğinden ibarettir. Bu sayfa OTLP yolunun tamamıdır: üç endpoint, kodlama ve mcpd'nin okuduğu her öznitelik.
Üç endpoint
mcpd, OTLP HTTP endpoint'lerini sorgu API'si ve arayüzüyle aynı porttan sunar. Önüne konacak bir collector, ikinci bir konteyner ve ayrı bir alıcı portu yoktur.
| Endpoint | Kabul ettiği | Yanıtladığı |
|---|---|---|
POST /v1/traces | ExportTraceServiceRequest | partialSuccess.rejectedSpans |
POST /v1/logs | ExportLogsServiceRequest | partialSuccess.rejectedLogRecords |
POST /v1/metrics | ExportMetricsServiceRequest | partialSuccess.rejectedDataPoints |
Başarılı her dışa aktarım, OTLP'nin bir sayı taşıyan kendi
partialSuccess biçimiyle yanıtlanır. Bir collector'ın
gönderene bir şey düşürdüğünü söyleme yolu budur ve exporter'lar bunu okur.
Boş bir gövde döndürmek, gönderenin almadığı bir başarıyı bildirmesine yol
açardı.
Bir exporter'ı buraya yöneltmek
İşi iki değişken görür. Bunları ajanınızı çalıştıran sürecin ortamında ayarlayın, başka hiçbir şey değişmez.
exporter
# Taban adres. /v1/traces yolunu exporter'ın kendisi ekler.
export OTEL_EXPORTER_OTLP_ENDPOINT=http://localhost:4317
export OTEL_EXPORTER_OTLP_PROTOCOL=http/json
# İsteğe bağlı. Payload'larınız büyükse gzip gönderin.
export OTEL_EXPORTER_OTLP_COMPRESSION=gzip
# Yalnızca mcpd --ingest-key ile çalışıyorsa.
export OTEL_EXPORTER_OTLP_HEADERS="Authorization=Bearer YOUR_INGEST_KEY"
Bir sessizliğin nedenini aramadan önce bilinmeye değer iki ayrıntı var.
Birincisi, OTEL_EXPORTER_OTLP_ENDPOINT bir taban adrestir ve
exporter sinyal yolunu onun sonuna kendisi ekler. Yolu da içeren tam adresi
vermek isterseniz bunun yerine
OTEL_EXPORTER_OTLP_TRACES_ENDPOINT ayarlayın. İkincisi,
OpenTelemetry'de 4317 portu alışılageldiği üzere gRPC portudur, 4318 ise
HTTP portudur. mcpd her şeyi tek porttan sunduğu için HTTP'yi 4317'den
sunar; yani varsayılan portunda bırakılmış bir exporter 4318'e gönderir ve
siz hiçbir şeyin geldiğini görmezsiniz. Portu açıkça yazın.
Trace'ler için her iki kodlama
/v1/traces, content-type başlığını okur ve iki
kodlamayı da kabul eder: içinde protobuf geçiyorsa
OTLP/protobuf, geçmiyorsa OTLP/JSON. OpenTelemetry'nin varsayılanı
protobuf'tur, yani mcpd'ye yöneltilmiş, değiştirilmemiş bir SDK'nın
gönderdiği trace'ler hiçbir yapılandırma olmadan yerine ulaşır.
/v1/logs ve /v1/metrics yalnızca JSON kabul eder.
Oraya gelen bir protobuf gövdesi body is not valid JSON
diyerek geri çevrilir. Üç sinyali de gönderiyorsanız protokolü bir kez,
genel olarak ayarlayın:
her sinyal için json
export OTEL_EXPORTER_OTLP_PROTOCOL=http/json
Hiç content-type gönderilmediğinde mcpd
application/json varsayar.
Sıkıştırma ve boyut
Bir istek gövdesi content-encoding: gzip ile,
identity ile ya da hiç kodlama başlığı olmadan gelebilir. Başka
her şey adıyla geri çevrilir: content-encoding "br" is not supported;
use gzip or send the body uncompressed. Yanıtlar içerik pazarlığıyla
sıkıştırılır, yani yavaş bir hat üzerinden geri okunan büyük bir trace de
sıkıştırılır.
Tek bir isteğe iki sınır uygulanır. Gövde sınırı 32 MiB; gelen şeyin
üzerinden ölçülür, yani gzip size yer kazandırır. Yığın sınırı 10.000
sinyaldir ve her alım kapısında kod çözüldükten sonra sayılır:
/v1/traces üzerinde span'ler, /v1/logs üzerinde
kayıtlar, /v1/metrics üzerinde veri noktaları ve
/v1/ingest üzerinde istekteki her şey. Daha büyük bir yığın,
iki sayıyı da adlandıran 413 payload_too_large ile geri
çevrilir. İki sınır da birer ayardır:
Yapılandırma
sayfasında anlatılan --max-body-bytes ve
--max-batch-signals.
Gelmekle saklanmak arasında ne olur
Bir OTLP span'i ile yerel bir span aynı yoldan geçer. Hattın ortak olmasının amacı budur: aşağıdaki sıra iki kapı arasında ayrışamaz.
-
Decode
OTLP or native, gzip or plain
-
Sample
Decided once, at the root
-
Redact
Before anything is written
-
Price
From the configured price book
-
Store
One transaction per batch
Redaction is stage three, not a cleanup job. A value that a rule matches never reaches storage at all.
Bir OTLP span'inin maliyet rakamı almasının sebebi, maliyetin alım anında hesaplanmasıdır. mcpd, span geldiği anda bu sunucunun çalıştığı fiyat listesine göre onu fiyatlandırır; böylece oranlarınızı sonradan değiştirmeniz geçen ayın maliyetini sessizce yeniden yazamaz. Bakınız Maliyet muhasebesi.
Her iki semantik kural kümesi
Yapay zekâ span'leri için birbiriyle yarışan iki öznitelik adı kümesi
kullanılıyor: OpenTelemetry'nin kendi gen_ai.* adları ve
OpenInference'ın openinference.span.kind ile birlikte gelen
llm.* adları. mcpd ikisini de okur, üstüne kendi
mcpd.* adlarını da. Hiçbir şeyi yeniden adlandırmazsınız.
Aşağıdaki her satır sırayla okunur, ilk eşleşen kazanır. Hiçbir satırın adlandırmadığı bir öznitelik yine de saklanır: düzleştirilmiş öznitelik haritasının tamamı span'in üzerinde durur, yani gönderdiğiniz hiçbir şey eşlenmediği için kaybolmaz.
Model, payload ve kullanım
| mcpd alanı | Sırayla şuradan okunur |
|---|---|
model | gen_ai.request.model, gen_ai.response.model, llm.model_name, mcpd.model |
provider | gen_ai.system, llm.provider, mcpd.provider |
input | input.value, gen_ai.prompt, mcpd.input |
output | output.value, gen_ai.completion, mcpd.output |
entity_name | gen_ai.agent.name, mcpd.entity.name |
usage.input_tokens | gen_ai.usage.input_tokens, gen_ai.usage.prompt_tokens, llm.token_count.prompt, mcpd.usage.input_tokens |
usage.output_tokens | gen_ai.usage.output_tokens, gen_ai.usage.completion_tokens, llm.token_count.completion, mcpd.usage.output_tokens |
usage.total_tokens | llm.token_count.total, gen_ai.usage.total_tokens |
input_details.cache_read | gen_ai.usage.cache_read_input_tokens, llm.token_count.prompt_details.cache_read, mcpd.usage.cache_read_tokens |
input_details.cache_write | gen_ai.usage.cache_creation_input_tokens, llm.token_count.prompt_details.cache_write, mcpd.usage.cache_write_tokens |
input_details.audio | llm.token_count.prompt_details.audio |
output_details.reasoning | llm.token_count.completion_details.reasoning, gen_ai.usage.reasoning_tokens |
output_details.audio | llm.token_count.completion_details.audio |
Üç token sayısından hiçbirini taşımayan bir span, sıfırlarla dolu bir kullanım nesnesi yerine hiç kullanım nesnesi taşımaz. Sıfır girdi token'ı ile bilinmeyen girdi token'ı farklı olgulardır ve ikincisi kastedilirken birincisine dayanılarak kurulmuş bir maliyet raporu, kimsenin fark etmeyeceği bir biçimde yanlıştır.
İlişkilendirme
İlişkilendirme alanları, tek bir kullanıcının ya da tek bir oturumun çalıştırmalarını istemenizi sağlayan şeydir. Önce span öznitelikleri, sonra kaynak öznitelikleri okunur.
| mcpd alanı | Sırayla şuradan okunur |
|---|---|
project | span üzerindeki mcpd.project, sonra kaynak üzerindeki, sonra daemon'ın --project değeri |
environment | mcpd.environment, kaynak deployment.environment.name, kaynak deployment.environment |
service_name | kaynak service.name |
service_version | kaynak service.version |
session_id | gen_ai.conversation.id, session.id, mcpd.session_id |
thread_id | mcpd.thread_id, thread.id |
user_id | user.id, enduser.id, mcpd.user_id |
request_id | mcpd.request_id, http.request.id |
release | mcpd.release, kaynak service.version |
run_id, resource_id, experiment_id | mcpd.run_id, mcpd.resource_id, mcpd.experiment_id |
tags | dize dizisi olarak mcpd.tags |
Durum ve hatalar
OTLP durum kodu 1 ise ok, 2 ise
error olur. Bitiş zamanı olan ve durumu ayarlanmamış bir span
ok olarak kaydedilir, çünkü şikâyet etmeden biten bir span
başarılı olmuştur. Bitiş zamanı olmayan ve durumu ayarlanmamış bir span
unset kalır: span hâlâ çalışıyordur ve mcpd bir sonuç
uydurmak yerine onu böyle saklar.
Hatalı bir span'de mesaj önce status.message, sonra
exception.message alanından gelir; ikisi de yoksa
unspecified error dizesi yazılır. Hata türü
exception.type alanından, yığın izi
exception.stacktrace alanından gelir. Hatalı bir span her zaman
bir mesaj taşır, çünkü metni olmayan bir "bir şey başarısız oldu" ile
yapabileceğiniz bir şey yoktur.
Span türü
Tür, bir span'in şelalede nasıl çizileceğini belirler. mcpd bunu
özgüllük sırasına göre çıkarır ve her zaman güvenli olan
generic değerine düşer. Bir span'i yanlış etiketlemek, hiç
etiketlememekten kötüdür.
- mcpd'nin bildiği bir türü adlandırdığında
mcpd.span.kind. openinference.span.kind.gen_ai.operation.name.- Yalnızca tek bir span türünün taşıdığı bir özniteliğin varlığı.
| Öznitelik değeri | mcpd türü |
|---|---|
openinference.span.kind=LLM | model_generation |
openinference.span.kind=CHAIN | workflow_run |
openinference.span.kind=TOOL | tool_call |
openinference.span.kind=AGENT | agent_run |
openinference.span.kind=RETRIEVER | retrieval |
openinference.span.kind=EMBEDDING | rag_embedding |
openinference.span.kind=RERANKER | rag_action |
openinference.span.kind=GUARDRAIL | guardrail |
openinference.span.kind=EVALUATOR | scorer_run |
gen_ai.operation.name=chat | model_generation |
gen_ai.operation.name=text_completion | model_generation |
gen_ai.operation.name=generate_content | model_generation |
gen_ai.operation.name=embeddings | rag_embedding |
gen_ai.operation.name=execute_tool | tool_call |
gen_ai.operation.name=invoke_agent | agent_run |
gen_ai.operation.name=create_agent | agent_run |
gen_ai.system, llm.model_name, llm.provider özniteliklerinden herhangi biri varsa | model_generation |
mcp.tool.name varsa | mcp_tool_call |
http.request.method ya da http.method varsa | http_request |
| başka her şey | generic |
openinference.span.kind ya da
gen_ai.operation.name altında mcpd'nin tanımadığı bir span
türü, geri çevrilmek yerine generic değerine düşer. Türlerin
tam listesi
veri modelinde
bulunur.
Loglar ve metrikler
Log kayıtları, spesifikasyonun öngördüğü gibi önem derecesi numarasına göre
eşlenir: 1 ile 4 arası trace, 5 ile 8 arası debug, 9 ile 12 arası info, 13
ile 16 arası warn, 17 ile 20 arası error ve bunun üstündeki her şey fatal.
Önem derecesi numarası olmayan bir kayıt info sayılır. Mesaj
body.stringValue alanından, logger adı scope adından gelir;
traceId ve spanId geçerli oldukları sürece
saklanır, ki bir log satırını onu yayan span'in yanına koyan şey budur.
Metriklerde sum'lar counter, gauge'ler gauge olur. Histogramlar toplamları ve sayılarıyla, bucket sınırları korunarak kaydedilir: mcpd, önceden toplanmış bir histogramdan kesin bir kuantili yeniden türetebiliyormuş gibi yapmaz. Exemplar'lar saklanır, ki bir grafikteki sıçramadan onu doğuran çalıştırmayı açmanızı sağlayan şey budur. Çoğu araç bunları atar.
Id'ler ve W3C traceparent
mcpd, OpenTelemetry'nin tanımlayıcı biçimlerini birebir kullanır: trace id 128 bittir ve 32 küçük harfli onaltılık karakterle, span id 64 bittir ve 16 karakterle yazılır. Çeviri katmanını ortadan kaldıran şey, tel biçiminin aynı tutulmasıdır. Tümü sıfır olan id, "trace yok" anlamına ayrılmıştır ve mcpd'nin kendi ürettiği id'ler de dahil olmak üzere geçtiği her yerde geri çevrilir.
OTLP/JSON, id alanları için onaltılık öngörür, ama birkaç SDK base64 yayar. mcpd ikisini de kabul eder ve onaltılık saklar. Id'leri eksik, yanlış uzunlukta ya da tümü sıfır olan bir span atlanır ve yığının geri kalanı yine de yazılır; çünkü bir tane kötü span yüzünden on bin iyi span'i geri çeviren bir collector, insanların kapattığı bir collector'dır.
Zaman damgaları, Unix epoch'undan bu yana geçen nanosaniyelerdir.
253 değerini aştıkları için OTLP/JSON onları dize olarak gönderir
ve mcpd de dize olarak ayrıştırır. Kayan noktalı sayı olarak okumak
duyarlılık kaybettirir; bu da aslında öyle olmadığı hâlde birbirinden
mikrosaniyelerle ayrılmış gibi görünen span'ler olarak ortaya çıkar.
0 olan ya da hiç bulunmayan bir endTimeUnixNano,
span'in bitmediği anlamına gelir.
Bir traceparent başlığı
version-traceid-parentid-flags biçimindedir. mcpd bunu
spesifikasyonun koyduğu kurallarla ayrıştırır: ff sürümü geri
çevrilir, 00 sürümünde tam olarak dört alan bulunmalıdır,
sonraki sürümler daha fazlasını taşıyabilir, id'ler doğrulanmalıdır ve
bayrak baytının 0. biti örneklenmiş bayrağıdır. Bozuk bir başlık hiçbir
zaman bir isteği geri çevirme nedeni değildir. mcpd onun yerine yeni bir
trace başlatır.
Bunun önemli olduğu yer: mcpd SDK'ları gelen bir traceparent
başlığını okur ve giden çağrılarda bir tane yayar, böylece bir trace servis
sınırından sağ çıkar. OTLP endpoint'leri id'lerini payload'dan alır, çünkü
exporter'ınız onları zaten span'lerin içine koymuştur. Bir trace, mcpd ile
ölçümlemediğiniz bir serviste başlıyorsa onun traceparent
başlığını iletin; iki yarı da tek bir trace id altında yerine ulaşsın.
Bir istek, eksiksiz
Yukarıdakilerin hiçbiri SDK istemez. Bu, bir terminale yapıştırabileceğiniz eksiksiz ve geçerli bir dışa aktarımdır:
ham OTLP/JSON
curl -X POST http://localhost:4317/v1/traces \
-H 'content-type: application/json' \
-d '{
"resourceSpans": [{
"resource": { "attributes": [
{ "key": "service.name", "value": { "stringValue": "checkout-agent" } }
]},
"scopeSpans": [{
"spans": [{
"traceId": "4bf92f3577b34da6a3ce929d0e0e4736",
"spanId": "00f067aa0ba902b7",
"name": "chat gpt-4o",
"startTimeUnixNano": "1700000000000000000",
"endTimeUnixNano": "1700000001500000000",
"status": { "code": 1 },
"attributes": [
{ "key": "gen_ai.system", "value": { "stringValue": "openai" } },
{ "key": "gen_ai.request.model", "value": { "stringValue": "gpt-4o" } },
{ "key": "gen_ai.operation.name", "value": { "stringValue": "chat" } },
{ "key": "gen_ai.usage.input_tokens", "value": { "intValue": "1200" } },
{ "key": "gen_ai.usage.output_tokens", "value": { "intValue": "350" } }
]
}]
}]
}]
}'
# {"partialSuccess":{"rejectedSpans":0,"errorMessage":""}} OTLP'nin taşıyamadıkları
OTLP'nin span, log ve metrik için bir biçimi vardır. Bir makine puanı, bir insanın başparmak aşağısı ya da bir yön notu için hiçbir biçimi, modern bir sağlayıcının fatura kestiği token ayrıntısı için de hiçbir sözcük dağarcığı yoktur. Bunları göndermenin iki yolu var:
-
Veri modelinin tamamını tek bir istekte taşıyan, mcpd'nin yerel yığın uç
noktası
POST /v1/ingest. -
OTLP üzerinden zaten gönderdiğiniz bir trace'e iliştirilen
POST /v1/api/scoresvePOST /v1/api/feedback.
İkisini karıştırmak olağandır ve beklenir. Span'leri zaten çalıştırdığınız OpenTelemetry SDK'sıyla dışa aktarın, puanları da değerlendirme işinizden gönderin. Trace id üzerinden birleşirler. Bakınız Puanlar ve geri bildirim ve HTTP API.
Portu açmadan önce
--ingest-key ayarlanmamışsa 4317'ye erişebilen herkes oraya
yazabilir; --read-key ayarlanmamışsa saklanan her prompt'u
okuyabilir. mcpd, ikisinden biri açık bırakılmışken loopback dışı bir adrese
bağlandığında başlangıçta bir uyarı loglar. Bunları
yapılandırmayla
ayarlayın, sonra anahtarı Authorization: Bearer olarak
gönderin; yukarıdaki OTEL_EXPORTER_OTLP_HEADERS tam da bunu
yapar.
anahtarlarla çalıştır
mcpd --ingest-key $INGEST_KEY --read-key $READ_KEY