{"id":178554,"date":"2026-11-05T10:24:56","date_gmt":"2026-11-05T09:24:56","guid":{"rendered":"https:\/\/fotc.com\/?p=178554"},"modified":"2026-11-05T10:25:05","modified_gmt":"2026-11-05T09:25:05","slug":"a-google-cloud-spend-capje-a-projektet-vedi-az-anomaliadetektor-segit-megitelni-mi-tortenik-az-egesz-fiokon","status":"publish","type":"post","link":"https:\/\/fotc.com\/hu\/blog\/a-google-cloud-spend-capje-a-projektet-vedi-az-anomaliadetektor-segit-megitelni-mi-tortenik-az-egesz-fiokon\/","title":{"rendered":"A Google Cloud spend capje a projektet v\u00e9di. Az anom\u00e1liadetektor seg\u00edt meg\u00edt\u00e9lni, mi t\u00f6rt\u00e9nik az eg\u00e9sz fi\u00f3kon"},"content":{"rendered":"\n<div class=\"wp-block-group fotc-article is-layout-constrained wp-block-group-is-layout-constrained\">\n<style data-wp-block-html=\"css\">\n\/* Tokens from FOTC-Design-System\/tokens (colors, typography, spacing) *\/\n.fotc-article{--fotc-red:#E3322B;--fotc-link:#C22B25;--fotc-link-hover:#9B221D;--fotc-amber:#FAB001;--fotc-green:#00A855;\n  --fotc-ink:#000000;--fotc-body:#4A4A4A;--fotc-muted:#6B6B6B;--fotc-ink300:#D1D1D1;\n  --fotc-surface:#F6F6F6;--fotc-border:#E8E8E8;--fotc-border-subtle:#F0F0F0;\n  --fotc-accent-soft:#EBF7FC;--fotc-accent-100:#D1ECF8;--fotc-radius:12px;\n  --fotc-shadow:0 1px 3px rgba(11,27,43,.08),0 1px 2px rgba(11,27,43,.04);--fotc-shadow-md:0 6px 16px rgba(11,27,43,.08);\n  --fotc-ease:cubic-bezier(.2,0,0,1);\n  font-family:'Fira Sans',-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,'Helvetica Neue',Arial,'Noto Sans',sans-serif;\n  font-size:1rem;font-weight:300;color:var(--fotc-body);line-height:1.55;max-width:46rem;\n  -webkit-font-smoothing:antialiased;text-rendering:optimizeLegibility}\n.fotc-article h1,.fotc-article h2,.fotc-article h3{font-weight:500;line-height:1.15;letter-spacing:-.01em;color:var(--fotc-ink);text-wrap:balance}\n.fotc-article h1{font-size:2.25rem;margin:0 0 1.25rem}\n.fotc-article h2{font-size:1.75rem;margin:2.75rem 0 .75rem}\n.fotc-article h3{font-size:1.25rem;margin:1.75rem 0 .5rem}\n.fotc-article p{margin:0 0 1rem;text-wrap:pretty}\n.fotc-article .fotc-lead{font-size:1.125rem;color:#333333}\n.fotc-article a{color:var(--fotc-link);text-decoration:none;transition:color .12s}\n.fotc-article a:hover{color:var(--fotc-link-hover)}\n.fotc-article :focus-visible{outline:3px solid #F5B5B3;outline-offset:2px}\n.fotc-article strong{font-weight:500;color:var(--fotc-ink)}\n.fotc-article ul{margin:0 0 1rem 1.25rem;padding:0}\n.fotc-article li{margin:0 0 .4rem}\n.fotc-article .fotc-eyebrow{display:inline-block;font-size:.72rem;font-weight:500;letter-spacing:.08em;text-transform:uppercase;color:var(--fotc-accent);margin-bottom:.5rem}\n\/* reveal (only when JS is present) *\/\n.fotc-article.fotc-js [data-reveal]{opacity:0;transform:translateY(14px);transition:opacity .6s var(--fotc-ease),transform .6s var(--fotc-ease)}\n.fotc-article.fotc-js [data-reveal].is-in{opacity:1;transform:none}\n\/* stats *\/\n.fotc-article .fotc-stats{display:grid;grid-template-columns:repeat(4,1fr);gap:12px;margin:1.75rem 0}\n.fotc-article .fotc-stat{position:relative;overflow:hidden;border:1px solid var(--fotc-border);border-radius:var(--fotc-radius);padding:14px 16px;box-shadow:var(--fotc-shadow);background:#fff;transition:transform .25s var(--fotc-ease),box-shadow .25s var(--fotc-ease)}\n.fotc-article .fotc-stat:hover{transform:translateY(-3px);box-shadow:var(--fotc-shadow-md)}\n.fotc-article .fotc-stat::after{content:\"\";position:absolute;left:0;right:0;bottom:0;height:3px;background:var(--fotc-accent);transform:scaleX(0);transform-origin:left;transition:transform .8s var(--fotc-ease)}\n.fotc-article .fotc-stat.is-in::after{transform:scaleX(1)}\n.fotc-article .fotc-stat b{display:block;font-size:1.75rem;font-weight:500;color:var(--fotc-accent);line-height:1.1;font-variant-numeric:tabular-nums}\n.fotc-article .fotc-stat span{display:block;font-size:.8125rem;color:var(--fotc-muted);margin-top:6px;line-height:1.4}\n\/* figures *\/\n.fotc-article figure{margin:1.75rem 0;padding:16px 16px 12px;border:1px solid var(--fotc-border);border-radius:var(--fotc-radius);background:#fff;box-shadow:var(--fotc-shadow)}\n.fotc-article .fotc-chart{width:100%;height:auto;display:block}\n.fotc-article figcaption{font-size:.875rem;color:var(--fotc-muted);margin-top:.75rem;line-height:1.45}\n.fotc-article .fotc-fig-head{display:flex;justify-content:space-between;align-items:center;gap:12px;flex-wrap:wrap;margin-bottom:10px}\n.fotc-article .fotc-fig-title{font-size:.9375rem;font-weight:500;color:var(--fotc-ink)}\n.fotc-article .fotc-controls{display:flex;gap:8px;flex-wrap:wrap;align-items:center}\n.fotc-article .fotc-btn{appearance:none;border:1px solid var(--fotc-border);background:#fff;color:var(--fotc-ink);font:inherit;font-size:.8125rem;font-weight:500;padding:6px 12px;border-radius:999px;cursor:pointer;transition:all .15s var(--fotc-ease)}\n.fotc-article .fotc-btn:hover{border-color:var(--fotc-accent);color:var(--fotc-accent)}\n.fotc-article .fotc-btn.is-on{background:var(--fotc-accent);border-color:var(--fotc-accent);color:#fff}\n.fotc-article .fotc-btn--dot::before{content:\"\";display:inline-block;width:9px;height:9px;border-radius:50%;background:var(--dot);margin-right:7px;vertical-align:0}\n.fotc-article .fotc-range{display:flex;align-items:center;gap:8px;font-size:.8125rem;color:var(--fotc-muted)}\n.fotc-article .fotc-range input{accent-color:var(--fotc-accent);width:120px}\n.fotc-article .fotc-range output{font-variant-numeric:tabular-nums;color:var(--fotc-ink);font-weight:500;min-width:3.5ch}\n.fotc-article .fotc-tip{position:fixed;z-index:50;pointer-events:none;background:var(--fotc-ink);color:#fff;font-size:12.5px;padding:6px 10px;border-radius:8px;opacity:0;transition:opacity .1s;white-space:nowrap;box-shadow:var(--fotc-shadow-md)}\n\/* timeline *\/\n.fotc-article .fotc-timeline .tl-fill{stroke-dasharray:100;stroke-dashoffset:100}\n.fotc-article .fotc-timeline.is-play .tl-fill{animation:fotc-draw 2.6s var(--fotc-ease) forwards}\n.fotc-article .fotc-timeline.is-play .tl-cursor{animation:fotc-cursor 2.6s var(--fotc-ease) forwards}\n.fotc-article .fotc-timeline .tl-mark .tl-dot{transition:transform .3s var(--fotc-ease);transform-box:fill-box;transform-origin:center}\n.fotc-article .fotc-timeline .tl-mark.is-lit .tl-dot{transform:scale(1.25)}\n.fotc-article .fotc-timeline .tl-mark.is-lit .tl-pulse{animation:fotc-pulse 1.2s ease-out 1}\n.fotc-article .fotc-timeline .tl-stop,.fotc-article .fotc-timeline .tl-stoplabel{transition:opacity .4s}\n.fotc-article .fotc-timeline.is-done .tl-stop,.fotc-article .fotc-timeline.is-done .tl-stoplabel{opacity:1}\n.fotc-article .fotc-timeline.is-done .tl-stop{animation:fotc-march 1.2s linear infinite}\n@keyframes fotc-march{to{stroke-dashoffset:-12}}\n.fotc-article.no-js .fotc-timeline .tl-fill,.fotc-article .fotc-timeline.is-static .tl-fill{stroke-dashoffset:0}\n@keyframes fotc-draw{to{stroke-dashoffset:0}}\n@keyframes fotc-cursor{to{transform:translateX(var(--tl-x))}}\n@keyframes fotc-pulse{0%{opacity:.9;r:9}100%{opacity:0;r:26}}\n\/* attack *\/\n.fotc-article .fotc-attack rect{fill:#fff;stroke:var(--fotc-border);stroke-width:1.5;transition:all .35s var(--fotc-ease)}\n.fotc-article .fotc-attack .t{fill:var(--fotc-ink)} .fotc-article .fotc-attack .s{fill:var(--fotc-muted)}\n.fotc-article .fotc-attack .at-step,.fotc-article .fotc-attack .at-link,.fotc-article .fotc-attack .at-layer,.fotc-article .fotc-attack .at-verdict{opacity:.35;transition:opacity .35s var(--fotc-ease)}\n.fotc-article .fotc-attack .at-path{opacity:.35;stroke-dasharray:100;stroke-dashoffset:100;transition:opacity .3s}\n.fotc-article .fotc-attack .at-path.at-miss{stroke:var(--fotc-ink300)}\n.fotc-article .fotc-attack .at-path.at-hit{stroke:var(--fotc-accent)}\n.fotc-article .fotc-attack .at-verdict.at-miss{fill:var(--fotc-red)} .fotc-article .fotc-attack .at-verdict.at-hit{fill:var(--fotc-accent)}\n.fotc-article .fotc-attack .is-lit{opacity:1}\n.fotc-article .fotc-attack .at-path.is-lit{animation:fotc-draw .7s var(--fotc-ease) forwards}\n.fotc-article .fotc-attack .at-step.is-lit rect{stroke:var(--fotc-red)}\n.fotc-article .fotc-attack .at-layer.at-miss.is-lit rect{fill:var(--fotc-surface);stroke:var(--fotc-ink300)}\n.fotc-article .fotc-attack .at-layer.at-hit.is-lit rect{fill:var(--fotc-accent-soft);stroke:var(--fotc-accent);stroke-width:2.5}\n.fotc-article .fotc-attack .at-runner{transition:cx .5s var(--fotc-ease),cy .5s var(--fotc-ease),opacity .3s}\n.fotc-article .fotc-attack.is-static .at-step,.fotc-article .fotc-attack.is-static .at-link,.fotc-article .fotc-attack.is-static .at-layer,.fotc-article .fotc-attack.is-static .at-verdict{opacity:1}\n.fotc-article .fotc-attack.is-static .at-path{opacity:1;stroke-dashoffset:0}\n\/* coverage grid *\/\n.fotc-article .fotc-grid{display:grid;grid-template-columns:repeat(30,1fr);gap:4px;margin:6px 0 10px}\n.fotc-article .fotc-cell{aspect-ratio:1;border-radius:3px;background:var(--fotc-ink300);transition:transform .2s var(--fotc-ease),opacity .25s,background .35s;cursor:default}\n.fotc-article .fotc-cell[data-s=\"api\"]{background:var(--fotc-green)}\n.fotc-article .fotc-cell[data-s=\"man\"]{background:var(--fotc-amber)}\n.fotc-article .fotc-cell:hover{transform:scale(1.35);position:relative;z-index:2}\n.fotc-article .fotc-grid.f-api .fotc-cell:not([data-s=\"api\"]),.fotc-article .fotc-grid.f-man .fotc-cell:not([data-s=\"man\"]),.fotc-article .fotc-grid.f-none .fotc-cell:not([data-s=\"none\"]){opacity:.15}\n.fotc-article .fotc-legend{display:flex;gap:14px;flex-wrap:wrap;font-size:.8125rem;color:var(--fotc-muted)}\n.fotc-article .fotc-legend b{font-weight:500;color:var(--fotc-ink);font-variant-numeric:tabular-nums}\n.fotc-article .fotc-zout{font-size:.875rem;color:var(--fotc-muted);margin:.5rem 0 0} .fotc-article .fotc-zout b{font-weight:500}\n.fotc-article .fotc-bars{display:flex;height:10px;border-radius:999px;overflow:hidden;background:var(--fotc-ink300);margin:8px 0 6px}\n.fotc-article .fotc-bars i{display:block;height:100%;transition:width .5s var(--fotc-ease)}\n\/* cadence *\/\n.fotc-article .fotc-bar rect{transition:height .7s var(--fotc-ease),y .7s var(--fotc-ease),opacity .25s,fill .25s}\n.fotc-article .fotc-bar:hover rect{opacity:.75}\n.fotc-article .fotc-cadence.only-alerts .fotc-bar.no-alert{opacity:.18}\n.fotc-article .fotc-bar circle,.fotc-article .fotc-bar text{transition:opacity .4s}\n\/* cards *\/\n.fotc-article .fotc-cols{display:grid;grid-template-columns:1fr 1fr;gap:12px;margin:1.25rem 0 1.75rem}\n.fotc-article .fotc-col{border-radius:var(--fotc-radius);padding:14px 16px;border:1px solid var(--fotc-border)}\n.fotc-article .fotc-col--stop{border-top:4px solid var(--fotc-red)}\n.fotc-article .fotc-col--flow{border-top:4px solid var(--fotc-accent)}\n.fotc-article .fotc-col h3{font-size:1rem;margin:0 0 .5rem}\n.fotc-article .fotc-col ul{margin:0 0 0 1.1rem;font-size:.9375rem}\n.fotc-article .fotc-cards{display:grid;grid-template-columns:1fr 1fr;gap:12px;margin:1.5rem 0}\n.fotc-article .fotc-card{border:1px solid var(--fotc-border);border-radius:var(--fotc-radius);padding:14px 16px;background:#fff;box-shadow:var(--fotc-shadow);transition:transform .25s var(--fotc-ease),box-shadow .25s var(--fotc-ease),border-color .25s}\n.fotc-article .fotc-card:hover{transform:translateY(-3px);box-shadow:var(--fotc-shadow-md);border-color:var(--fotc-accent-100)}\n.fotc-article .fotc-card h3{font-size:1rem;margin:0 0 .4rem}\n.fotc-article .fotc-card p{font-size:.9375rem;margin:0;color:var(--fotc-body)}\n.fotc-article .fotc-card .fotc-tag{display:inline-block;font-size:.7rem;font-weight:500;letter-spacing:.04em;text-transform:uppercase;color:var(--fotc-red);margin-bottom:.4rem}\n.fotc-article.fotc-js .fotc-cards [data-reveal]:nth-child(2){transition-delay:.1s} .fotc-article.fotc-js .fotc-cards [data-reveal]:nth-child(3){transition-delay:.2s} .fotc-article.fotc-js .fotc-cards [data-reveal]:nth-child(4){transition-delay:.3s}\n.fotc-article .fotc-callout{margin:1.75rem 0;padding:1rem 1.25rem;border-left:4px solid var(--fotc-accent);background:var(--fotc-accent-soft);border-radius:0 var(--fotc-radius) var(--fotc-radius) 0}\n.fotc-article .fotc-callout p:last-child{margin-bottom:0}\n\/* terminal *\/\n.fotc-article .fotc-term{background:#1B1D21;border-radius:var(--fotc-radius);overflow:hidden;box-shadow:var(--fotc-shadow-md)}\n.fotc-article .fotc-term-bar{display:flex;align-items:center;gap:6px;padding:10px 14px;background:#25282E;color:#9AA0A6;font-size:.75rem}\n.fotc-article .fotc-term-bar i{width:10px;height:10px;border-radius:50%;background:#3C4043} .fotc-article .fotc-term-bar span{margin-left:8px}\n.fotc-article .fotc-term-body{margin:0;padding:14px 16px 16px;font-family:SFMono-Regular,Menlo,Monaco,Consolas,monospace;font-size:.78rem;line-height:1.6;color:#E8EAED;overflow-x:auto;min-height:23em}\n.fotc-article .fotc-term-body .tl{display:block;white-space:pre-wrap;min-height:1.6em}\n.fotc-article .fotc-term-body .cmd{color:#8AB4F8}\n.fotc-article .fotc-term-body .hl-red{color:#FF8A80} .fotc-article .fotc-term-body .hl-amber{color:#FDD663}\n.fotc-article .fotc-term-body b{font-weight:500;color:inherit;opacity:.9}\n.fotc-article .fotc-term-body .caret::after{content:\"\u258d\";color:#E8EAED;animation:fotc-blink 1s steps(1) infinite}\n.fotc-article.fotc-js .fotc-term.is-anim .tl{opacity:0} .fotc-article.fotc-js .fotc-term.is-anim .tl.is-on{opacity:1;transition:opacity .15s}\n.fotc-article.fotc-js .fotc-term.is-anim .tl.hl-red.is-on,.fotc-article.fotc-js .fotc-term.is-anim .tl.hl-amber.is-on{animation:fotc-flash .9s ease-out 1}\n@keyframes fotc-blink{50%{opacity:0}}\n@keyframes fotc-flash{0%{background:rgba(255,255,255,.18)}100%{background:transparent}}\n.fotc-article .fotc-tag--blue{color:var(--fotc-accent)}\n\/* code *\/\n.fotc-article .fotc-code{position:relative;margin:1.25rem 0}\n.fotc-article .fotc-code pre{margin:0;padding:1rem 1.25rem;overflow-x:auto;background:var(--fotc-surface);border:1px solid var(--fotc-border-subtle);border-radius:var(--fotc-radius);font-size:.85rem;line-height:1.5;color:#333333;max-height:280px;transition:max-height .4s var(--fotc-ease)}\n.fotc-article .fotc-code.is-open pre{max-height:2000px}\n.fotc-article .fotc-code .fotc-code-bar{display:flex;justify-content:flex-end;gap:6px;margin-bottom:8px}\n.fotc-article .fotc-code .fotc-fade{position:absolute;left:0;right:0;bottom:0;height:60px;background:linear-gradient(transparent,var(--fotc-surface));border-radius:0 0 var(--fotc-radius) var(--fotc-radius);pointer-events:none}\n.fotc-article .fotc-code.is-open .fotc-fade{display:none}\n.fotc-article code{font-family:SFMono-Regular,Menlo,Monaco,Consolas,'Liberation Mono','Courier New',monospace}\n.fotc-article p code{font-size:.9em;background:var(--fotc-surface);border:1px solid var(--fotc-border-subtle);padding:.05em .35em;border-radius:4px;color:#333333}\n.fotc-article .fotc-faq h3{font-size:1.0625rem;margin-top:1.5rem}\n.fotc-article .fotc-note{font-size:.875rem;color:var(--fotc-muted);border-top:1px solid var(--fotc-border);margin-top:2.5rem;padding-top:1rem}\n@media (prefers-reduced-motion:reduce){.fotc-article *{transition:none!important;animation-duration:.01s!important}.fotc-article.fotc-js [data-reveal]{opacity:1;transform:none}}\n@media (max-width:640px){.fotc-article h1{font-size:1.75rem}.fotc-article h2{font-size:1.375rem}\n  .fotc-article .fotc-stats{grid-template-columns:1fr 1fr}.fotc-article .fotc-cols,.fotc-article .fotc-cards{grid-template-columns:1fr}.fotc-article .fotc-grid{grid-template-columns:repeat(20,1fr)}}\n\/* tables *\/\n.fotc-article .fotc-table-scroll{overflow-x:auto;margin:1.25rem 0}\n.fotc-article table{width:100%;border-collapse:collapse;margin:0;font-size:.9rem;font-variant-numeric:tabular-nums}\n.fotc-article th{text-align:left;font-weight:500;color:var(--fotc-ink);border-bottom:2px solid var(--fotc-accent);padding:.55rem .5rem;vertical-align:bottom}\n.fotc-article td{border-bottom:1px solid var(--fotc-border);padding:.55rem .5rem;vertical-align:top}\n.fotc-article td:first-child{font-weight:500;color:var(--fotc-ink)}\n.fotc-article tr:nth-child(even) td{background:var(--fotc-surface)}\n<\/style>\n\n<script data-wp-block-html=\"js\">\n(function () {\nfunction init() {\n  var root = document.querySelector(\".fotc-article\"); if (!root) return;\n  var LX = {\"day\": \"nap\", \"per_run\": \"fi\u00f3k fut\u00e1sonk\u00e9nt\", \"alert1\": \"riaszt\u00e1s\", \"alertN\": \"riaszt\u00e1s\", \"legend\": \"embereknek k\u00fcld\u00f6tt riaszt\u00e1sok\", \"obs\": \"megfigyel\u00e9s\", \"project\": \"projekt\", \"service\": \"szolg\u00e1ltat\u00e1s\", \"api\": \"API \u00e1ltal igazolt cap\", \"man\": \"ember \u00e1ltal bejelentett cap\", \"none\": \"korl\u00e1t n\u00e9lk\u00fcl\", \"mean\": \"\u00e1tlag\", \"median\": \"medi\u00e1n\", \"incident\": \"incidens\", \"day1\": \"1. nap\", \"day21\": \"21. nap \u00b7 n\u00e9gyzetgy\u00f6k\u00f6s tengely\", \"days\": \" nap\", \"copy\": \"M\u00e1sol\u00e1s\", \"copied\": \"M\u00e1solva\", \"expand\": \"Kibont\u00e1s\", \"collapse\": \"\u00d6sszecsuk\u00e1s\", \"zout\": \"Az incidens m\u00e1sodik napja: z \u00e1tlaggal \u00e9s sz\u00f3r\u00e1ssal {a}, z medi\u00e1nnal \u00e9s MAD-dal {b}.\"};\n  root.classList.add(\"fotc-js\");\n  var reduce = window.matchMedia ? matchMedia(\"(prefers-reduced-motion: reduce)\").matches : false;\n  var NS = \"http:\/\/www.w3.org\/2000\/svg\";\n  var el = function (t, a, p) { var e = document.createElementNS(NS, t); for (var k in a) e.setAttribute(k, a[k]); if (p) p.appendChild(e); return e; };\n  var tip = document.getElementById(\"fotcTip\");\n  var showTip = function (e, text) { tip.textContent = text; tip.style.left = (e.clientX + 14) + \"px\"; tip.style.top = (e.clientY - 10) + \"px\"; tip.style.opacity = 1; };\n  var hideTip = function () { tip.style.opacity = 0; };\n  var lt = function (a, b) { return Math.sign(b - a) === 1; };\n  var fmt = function (n) { return String(n).replace(\/\\B(?=(\\d{3})+(?!\\d))\/g, \"\u00a0\"); };\n\n  \/* ---- reveal + one-shot triggers ---- *\/\n  var onIn = {};\n  var io = (\"IntersectionObserver\" in window) ? new IntersectionObserver(function (es) {\n    es.forEach(function (en) {\n      if (!en.isIntersecting) return;\n      en.target.classList.add(\"is-in\");\n      var k = en.target.getAttribute(\"data-trigger\"); if (onIn[k]) { onIn[k](); delete onIn[k]; }\n      io.unobserve(en.target);\n    });\n  }, { threshold: 0.3 }) : null;\n  root.querySelectorAll(\"[data-reveal],[data-trigger]\").forEach(function (n) { if (io) io.observe(n); else { n.classList.add(\"is-in\"); var k = n.getAttribute(\"data-trigger\"); if (onIn[k]) onIn[k](); } });\n\n  \/* ---- stats count-up ---- *\/\n  root.querySelectorAll(\".fotc-stat b[data-count]\").forEach(function (b) {\n    var target = +b.getAttribute(\"data-count\"), prefix = b.getAttribute(\"data-prefix\") || \"\";\n    b.textContent = prefix + \"0\";\n    onIn[\"stat-\" + target] = function () {\n      if (reduce) { b.textContent = prefix + target; return; }\n      var t0 = performance.now(), dur = 1100;\n      (function tick(t) { var p = Math.min(1, (t - t0) \/ dur), e = 1 - Math.pow(1 - p, 3); b.textContent = prefix + Math.round(target * e); if (p !== 1) requestAnimationFrame(tick); })(t0);\n    };\n    b.closest(\".fotc-stat\").setAttribute(\"data-trigger\", \"stat-\" + target);\n    if (io) io.observe(b.closest(\".fotc-stat\"));\n  });\n\n  \/* ---- spend cap timeline ---- *\/\n  var tl = root.querySelector(\".fotc-timeline\");\n  if (tl) {\n    var fill = tl.querySelector(\".tl-fill\"), marks = tl.querySelectorAll(\".tl-mark\"), timers = [];\n    tl.style.setProperty(\"--tl-x\", (fill.getAttribute(\"x2\") - fill.getAttribute(\"x1\")) + \"px\");\n    var play = function () {\n      timers.forEach(clearTimeout); timers = [];\n      tl.classList.remove(\"is-play\", \"is-done\", \"is-static\"); marks.forEach(function (m) { m.classList.remove(\"is-lit\"); });\n      if (reduce) { tl.classList.add(\"is-static\", \"is-done\"); marks.forEach(function (m) { m.classList.add(\"is-lit\"); }); return; }\n      void tl.getBoundingClientRect(); tl.classList.add(\"is-play\");\n      marks.forEach(function (m) { timers.push(setTimeout(function () { m.classList.add(\"is-lit\"); }, 2600 * (+m.getAttribute(\"data-at\") \/ 0.72))); });\n      timers.push(setTimeout(function () { tl.classList.add(\"is-done\"); }, 2700));\n      timers.push(setTimeout(play, 7000));\n    };\n    onIn[\"timeline\"] = play;\n    if (\"IntersectionObserver\" in window) new IntersectionObserver(function (es) { es.forEach(function (en) { if (!en.isIntersecting) { timers.forEach(clearTimeout); timers = []; } else if (!timers.length) { if (tl.classList.contains(\"is-play\")) play(); } }); }, { threshold: 0.2 }).observe(tl);\n  }\n\n  \/* ---- attack path ---- *\/\n  var at = root.querySelector(\".fotc-attack\");\n  if (at) {\n    var atTimers = [];\n    var lit = function (sel) { at.querySelectorAll(sel).forEach(function (n) { n.classList.add(\"is-lit\"); }); };\n    var runner = at.querySelector(\".at-runner\");\n    var playAt = function () {\n      atTimers.forEach(clearTimeout); atTimers = [];\n      at.classList.remove(\"is-static\"); at.querySelectorAll(\".is-lit\").forEach(function (n) { n.classList.remove(\"is-lit\"); });\n      if (reduce) { at.classList.add(\"is-static\"); return; }\n      var t = 0, step = 520;\n      runner.setAttribute(\"opacity\", 1); runner.setAttribute(\"cx\", 145); runner.setAttribute(\"cy\", 20);\n      for (var i = 0; i !== 4; i++) (function (i) {\n        atTimers.push(setTimeout(function () { lit(\".at-step-\" + i); runner.setAttribute(\"cy\", 20 + i * 72 + 28); if (i !== 3) lit(\".at-link-\" + i); }, t)); t += step;\n      })(i);\n      [0, 1].forEach(function (i) { atTimers.push(setTimeout(function () { lit(\".at-path-\" + i); lit(\".at-layer-\" + i); lit(\".at-verdict-\" + i); }, t)); t += step; });\n      atTimers.push(setTimeout(function () { lit(\".at-path-2\"); }, t)); t += 500;\n      atTimers.push(setTimeout(function () { lit(\".at-layer-2\"); lit(\".at-verdict-2\"); runner.setAttribute(\"cx\", 565); runner.setAttribute(\"cy\", 48 + 2 * 90 + 30); runner.setAttribute(\"fill\", \"#0097DA\"); }, t)); t += 6500;\n      atTimers.push(setTimeout(function () { runner.setAttribute(\"opacity\", 0); runner.setAttribute(\"fill\", \"#E3322B\"); }, t - 600));\n      atTimers.push(setTimeout(playAt, t));\n    };\n    onIn[\"attack\"] = playAt;\n    if (\"IntersectionObserver\" in window) new IntersectionObserver(function (es) { es.forEach(function (en) { if (!en.isIntersecting) { atTimers.forEach(clearTimeout); atTimers = []; } else if (!atTimers.length) { if (at.querySelector(\".is-lit\")) playAt(); } }); }, { threshold: 0.2 }).observe(at);\n  }\n\n  \/* ---- coverage grid ---- *\/\n  var grid = root.querySelector(\".fotc-grid\");\n  if (grid) {\n    var cols = 30, rows = 8, seed = 3;\n    var rnd = function () { seed = (seed * 9301 + 49297) % 233280; return seed \/ 233280; };\n    var cells = [];\n    for (var r = 0; r !== rows; r++) for (var c = 0; c !== cols; c++) {\n      var p = rnd(), w = 1 - c \/ cols, s = lt(p, 0.18 + 0.3 * w) ? \"api\" : lt(p, 0.4 + 0.35 * w) ? \"man\" : \"none\";\n      var d = document.createElement(\"div\"); d.className = \"fotc-cell\"; d.setAttribute(\"data-s\", s); d.setAttribute(\"data-c\", c);\n      d.setAttribute(\"data-label\", LX.project + \" \" + (c + 1) + \" \u00b7 \" + LX.service + \" \" + (r + 1)); grid.appendChild(d); cells.push(d);\n    }\n    var names = { api: LX.api, man: LX.man, none: LX.none };\n    var bars = root.querySelector(\".fotc-bars\"), legend = root.querySelector(\".fotc-legend\");\n    var recount = function () {\n      var n = { api: 0, man: 0, none: 0 }; cells.forEach(function (d) { n[d.getAttribute(\"data-s\")]++; });\n      var tot = cells.length;\n      if (bars) { bars.textContent = \"\"; [[n.api, \"#00A855\"], [n.man, \"#FAB001\"]].forEach(function (s) { var i = document.createElement(\"i\"); i.style.width = (100 * s[0] \/ tot) + \"%\"; i.style.background = s[1]; bars.appendChild(i); }); }\n      if (legend) legend.querySelectorAll(\"[data-n]\").forEach(function (x) { x.textContent = n[x.getAttribute(\"data-n\")]; });\n    };\n    recount();\n    grid.addEventListener(\"mousemove\", function (e) { var d = e.target.closest(\".fotc-cell\"); if (d) showTip(e, d.getAttribute(\"data-label\") + \" \u00b7 \" + names[d.getAttribute(\"data-s\")]); });\n    grid.addEventListener(\"mouseleave\", hideTip);\n    root.querySelectorAll(\"[data-filter]\").forEach(function (b) {\n      b.addEventListener(\"click\", function () {\n        var f = b.getAttribute(\"data-filter\"), on = b.classList.contains(\"is-on\");\n        root.querySelectorAll(\"[data-filter]\").forEach(function (x) { x.classList.remove(\"is-on\"); });\n        grid.classList.remove(\"f-api\", \"f-man\", \"f-none\");\n        if (!on) { if (f !== \"all\") { b.classList.add(\"is-on\"); grid.classList.add(\"f-\" + f); } }\n      });\n    });\n    var simTimers = [], flipped = [];\n    var simulate = function () {\n      simTimers.forEach(clearTimeout); simTimers = [];\n      flipped.forEach(function (d) { d.setAttribute(\"data-s\", \"none\"); }); flipped = []; recount();\n      if (reduce) return;\n      var queue = cells.filter(function (d) { return d.getAttribute(\"data-s\") === \"none\"; }).sort(function (a, b) { return a.getAttribute(\"data-c\") - b.getAttribute(\"data-c\"); }).slice(0, 60);\n      var t = 1800;\n      queue.forEach(function (d, i) { simTimers.push(setTimeout(function () { d.setAttribute(\"data-s\", \"man\"); flipped.push(d); recount(); }, t + i * 55)); });\n      simTimers.push(setTimeout(simulate, t + queue.length * 55 + 7000));\n    };\n    onIn[\"coverage\"] = simulate;\n    if (\"IntersectionObserver\" in window) new IntersectionObserver(function (es) { es.forEach(function (en) { if (!en.isIntersecting) { simTimers.forEach(clearTimeout); simTimers = []; } else if (!simTimers.length) { if (flipped.length) simulate(); } }); }, { threshold: 0.2 }).observe(grid);\n  }\n\n  \/* ---- cadence chart ---- *\/\n  var cad = root.querySelector(\".fotc-cadence\");\n  if (cad) {\n    var OBS = JSON.parse(cad.getAttribute(\"data-obs\")), AL = JSON.parse(cad.getAttribute(\"data-alerts\"));\n    var W = 720, Hh = 260, L = 40, R = 10, T = 26, B = 34, pw = W - L - R, ph = Hh - T - B, n = OBS.length, gap = 6, bw = (pw - gap * (n - 1)) \/ n, gmax = 50;\n    for (var g = 0; g !== gmax + 10; g += 10) { var y = T + ph - g \/ gmax * ph; el(\"line\", { x1: L, x2: L + pw, y1: y, y2: y, stroke: \"#E8E8E8\" }, cad); var tx = el(\"text\", { x: L - 8, y: y + 4, \"text-anchor\": \"end\", \"font-size\": 11, fill: \"#6B6B6B\" }, cad); tx.textContent = g; }\n    var barsC = [];\n    OBS.forEach(function (v, i) {\n      var a = AL[i], x = L + i * (bw + gap), h = v \/ gmax * ph, y0 = T + ph - h;\n      var gr = el(\"g\", { \"class\": \"fotc-bar \" + (a ? \"has-alert\" : \"no-alert\") }, cad);\n      var rect = el(\"rect\", { x: x, y: T + ph, width: bw, height: 0, rx: 2, fill: a ? \"#0097DA\" : \"#D1ECF8\" }, gr);\n      if (a) { var cy = y0 - 12; el(\"circle\", { cx: x + bw \/ 2, cy: cy, r: 7, fill: \"#E3322B\", opacity: 0 }, gr); var t2 = el(\"text\", { x: x + bw \/ 2, y: cy + 3.5, \"text-anchor\": \"middle\", \"font-size\": 9.5, \"font-weight\": 500, fill: \"#fff\", opacity: 0 }, gr); t2.textContent = a; }\n      var hit = el(\"rect\", { x: x - gap \/ 2, y: T, width: bw + gap, height: ph, fill: \"transparent\" }, gr);\n      hit.addEventListener(\"mousemove\", function (e) { showTip(e, LX.day + \" \" + (i + 1) + \" \u00b7 \" + v + \" \" + LX.per_run + \" \u00b7 \" + a + \" \" + (a === 1 ? LX.alert1 : LX.alertN)); });\n      hit.addEventListener(\"mouseleave\", hideTip);\n      if (i % 4 === 0) { var lb = el(\"text\", { x: x + bw \/ 2, y: T + ph + 18, \"text-anchor\": \"middle\", \"font-size\": 10, fill: \"#6B6B6B\" }, cad); lb.textContent = LX.day + \" \" + (i + 1); }\n      barsC.push({ rect: rect, y: y0, h: h, g: gr });\n    });\n    el(\"circle\", { cx: L + pw - 150, cy: 10, r: 5, fill: \"#E3322B\" }, cad); var lg = el(\"text\", { x: L + pw - 140, y: 14, \"font-size\": 11, fill: \"#6B6B6B\" }, cad); lg.textContent = LX.legend;\n    var grow = function () { barsC.forEach(function (b, i) { setTimeout(function () { b.rect.setAttribute(\"y\", b.y); b.rect.setAttribute(\"height\", b.h); b.g.querySelectorAll(\"circle,text\").forEach(function (m) { m.setAttribute(\"opacity\", 1); }); }, reduce ? 0 : i * 35); }); };\n    onIn[\"cadence\"] = grow;\n    var tog = root.querySelector(\"[data-only-alerts]\"); if (tog) tog.addEventListener(\"click\", function () { tog.classList.toggle(\"is-on\"); cad.classList.toggle(\"only-alerts\"); });\n    var counter = root.querySelector(\"[data-cad-counter]\");\n    if (counter) { var sumObs = OBS.reduce(function (a, b) { return a + b; }, 0) * 48, sumAl = AL.reduce(function (a, b) { return a + b; }, 0); counter.textContent = \"\u2248 \" + fmt(sumObs) + \" \" + LX.obs + \" \u00b7 \" + sumAl + \" \" + LX.alertN + \" \u00b7 \" + (100 * sumAl \/ sumObs).toFixed(2).replace(\".\", \",\") + \" %\"; }\n  }\n\n  \/* ---- baseline chart (interactive) ---- *\/\n  var bl = root.querySelector(\".fotc-baseline\");\n  if (bl) {\n    var W2 = 720, H2 = 240, L2 = 44, R2 = 12, T2 = 22, B2 = 30, pw2 = W2 - L2 - R2, ph2 = H2 - T2 - B2, N = 21;\n    var s0 = 7, rndb = function () { s0 = (s0 * 9301 + 49297) % 233280; return s0 \/ 233280; };\n    var base = []; for (var i = 0; i !== N; i++) base.push(Math.round((20 + (rndb() - 0.5) * 8) * 10) \/ 10);\n    var vmax = 2000, Y = function (v) { return T2 + ph2 - Math.sqrt(Math.max(0, v) \/ vmax) * ph2; }, X = function (i) { return L2 + i \/ (N - 1) * pw2; };\n    [0, 20, 100, 400, 1000, 2000].forEach(function (g) { var y = Y(g); el(\"line\", { x1: L2, x2: L2 + pw2, y1: y, y2: y, stroke: \"#E8E8E8\" }, bl); var t = el(\"text\", { x: L2 - 8, y: y + 4, \"text-anchor\": \"end\", \"font-size\": 11, fill: \"#6B6B6B\" }, bl); t.textContent = g; });\n    var barsB = []; for (var i = 0; i !== N; i++) barsB.push(el(\"rect\", { x: X(i) - 10, width: 20, rx: 2, fill: \"#D1ECF8\" }, bl));\n    var pMean = el(\"path\", { fill: \"none\", stroke: \"#E3322B\", \"stroke-width\": 2.5, \"stroke-linejoin\": \"round\" }, bl);\n    var pMed = el(\"path\", { fill: \"none\", stroke: \"#00A855\", \"stroke-width\": 2.5, \"stroke-linejoin\": \"round\" }, bl);\n    var lMean = el(\"text\", { \"font-size\": 11, \"font-weight\": 500, fill: \"#E3322B\" }, bl); lMean.textContent = LX.mean;\n    var lMed = el(\"text\", { \"font-size\": 11, \"font-weight\": 500, fill: \"#00A855\" }, bl); lMed.textContent = LX.median;\n    var lInc = el(\"text\", { \"text-anchor\": \"middle\", \"font-size\": 11, fill: \"#6B6B6B\" }, bl); lInc.textContent = LX.incident;\n    var ax = el(\"text\", { x: L2, y: H2 - 8, \"font-size\": 10, fill: \"#6B6B6B\" }, bl); ax.textContent = LX.day1;\n    var ax2 = el(\"text\", { x: L2 + pw2, y: H2 - 8, \"text-anchor\": \"end\", \"font-size\": 10, fill: \"#6B6B6B\" }, bl); ax2.textContent = LX.day21;\n    var zOut = root.querySelector(\"[data-z-out]\");\n    var median = function (w) { var s = w.slice().sort(function (a, b) { return a - b; }), m = Math.floor(s.length \/ 2); return s.length % 2 ? s[m] : (s[m - 1] + s[m]) \/ 2; };\n    var draw = function () {\n      var mag = +root.querySelector(\"[data-mag]\").value, win = +root.querySelector(\"[data-win]\").value;\n      var series = base.slice(); series[11] = mag; series[12] = Math.round(mag * 0.7); series[13] = Math.round(mag * 0.3);\n      var mean = [], med = [];\n      for (var i = 0; i !== N; i++) { var w = series.slice(Math.max(0, i - win), i); mean.push(!lt(w.length, 3) ? w.reduce(function (a, b) { return a + b; }, 0) \/ w.length : null); med.push(!lt(w.length, 3) ? median(w) : null); }\n      series.forEach(function (v, i) { barsB[i].setAttribute(\"y\", Y(v)); barsB[i].setAttribute(\"height\", T2 + ph2 - Y(v)); });\n      var path = function (vals) { var pts = []; vals.forEach(function (v, i) { if (v !== null) pts.push(X(i).toFixed(1) + \",\" + Y(v).toFixed(1)); }); return \"M\" + pts.join(\" L\"); };\n      pMean.setAttribute(\"d\", path(mean)); pMed.setAttribute(\"d\", path(med));\n      var li = Math.min(N - 1, 12 + Math.ceil(win \/ 2));\n      var lx = Math.min(X(li) + 6, L2 + pw2 - 62);\n      lMean.setAttribute(\"x\", lx); lMean.setAttribute(\"y\", Y(mean[li]) - 8);\n      lMed.setAttribute(\"x\", lx); lMed.setAttribute(\"y\", Y(med[li]) + 16);\n      lInc.setAttribute(\"x\", X(11)); lInc.setAttribute(\"y\", Y(mag) - 8);\n      if (zOut) {\n        var d2 = 12, w2 = series.slice(Math.max(0, d2 - win), d2), mu = w2.reduce(function (a, b) { return a + b; }, 0) \/ w2.length;\n        var sd = Math.sqrt(w2.reduce(function (a, b) { return a + (b - mu) * (b - mu); }, 0) \/ (w2.length - 1));\n        var md = median(w2), mad = median(w2.map(function (v) { return Math.abs(v - md); }));\n        var zMean = (series[d2] - mu) \/ Math.max(sd, 1), zMed = (series[d2] - md) \/ Math.max(1.4826 * mad, 0.05 * md, 1);\n        zOut.textContent = \"\"; LX.zout.split(\/(\\{[ab]\\})\/).forEach(function (part) { if (part === \"{a}\" || part === \"{b}\") { var b = document.createElement(\"b\"); b.style.color = part === \"{a}\" ? \"#E3322B\" : \"#00A855\"; b.textContent = part === \"{a}\" ? zMean.toFixed(1) : zMed.toFixed(0); zOut.appendChild(b); } else zOut.appendChild(document.createTextNode(part)); });\n      }\n      root.querySelector(\"[data-mag-out]\").textContent = fmt(mag); root.querySelector(\"[data-win-out]\").textContent = win + LX.days;\n    };\n    root.querySelectorAll(\"[data-mag],[data-win]\").forEach(function (inp) { inp.addEventListener(\"input\", draw); });\n    draw();\n  }\n\n  \/* ---- terminal typing ---- *\/\n  var term = root.querySelector(\".fotc-term\");\n  if (term) {\n    var lines = Array.prototype.slice.call(term.querySelectorAll(\".tl\")), tTimers = [], full = lines.map(function (l) { return l.innerHTML; });\n    var playTerm = function () {\n      tTimers.forEach(clearTimeout); tTimers = [];\n      if (reduce) { term.classList.remove(\"is-anim\"); return; }\n      term.classList.add(\"is-anim\");\n      lines.forEach(function (l, i) { l.classList.remove(\"is-on\", \"caret\"); l.innerHTML = full[i]; });\n      var t = 400;\n      lines.forEach(function (l, i) {\n        var isCmd = l.getAttribute(\"data-t\") === \"cmd\";\n        if (isCmd) {\n          var txt = l.textContent, n = txt.length, per = Math.max(6, Math.min(18, 1400 \/ n));\n          tTimers.push(setTimeout(function () { l.classList.add(\"is-on\", \"caret\"); l.textContent = \"\"; }, t));\n          for (var k = 1; !lt(n, k); k += 3) (function (k) { tTimers.push(setTimeout(function () { l.textContent = txt.slice(0, k); }, t + k * per)); })(k);\n          t += n * per + 250;\n          tTimers.push(setTimeout(function () { l.textContent = txt; l.classList.remove(\"caret\"); }, t)); t += 350;\n        } else {\n          tTimers.push(setTimeout(function () { l.classList.add(\"is-on\"); }, t)); t += l.classList.contains(\"gap\") ? 500 : 140;\n        }\n      });\n      tTimers.push(setTimeout(playTerm, t + 9000));\n    };\n    onIn[\"terminal\"] = playTerm;\n    if (\"IntersectionObserver\" in window) new IntersectionObserver(function (es) { es.forEach(function (en) { if (!en.isIntersecting) { tTimers.forEach(clearTimeout); tTimers = []; } else if (!tTimers.length) { if (term.classList.contains(\"is-anim\")) playTerm(); } }); }, { threshold: 0.2 }).observe(term);\n  }\n\n  \/* ---- code block ---- *\/\n  root.querySelectorAll(\".fotc-code\").forEach(function (box) {\n    var pre = box.querySelector(\"pre\"), copy = box.querySelector(\"[data-copy]\"), exp = box.querySelector(\"[data-expand]\");\n    if (copy) copy.addEventListener(\"click\", function () {\n      var txt = pre.innerText; var done = function () { copy.textContent = LX.copied; setTimeout(function () { copy.textContent = LX.copy; }, 1600); };\n      if (navigator.clipboard) navigator.clipboard.writeText(txt).then(done, done); else done();\n    });\n    if (exp) exp.addEventListener(\"click\", function () { box.classList.toggle(\"is-open\"); exp.textContent = box.classList.contains(\"is-open\") ? LX.collapse : LX.expand; });\n  });\n}\nif (document.readyState === \"loading\") document.addEventListener(\"DOMContentLoaded\", init); else init();\n})();\n<\/script>\n\n<p class=\"fotc-lead\">Ha olyan Google Cloud sz\u00e1ml\u00e1z\u00e1si fi\u00f3k\u00e9rt felelsz, amelyben b\u00e1rkinek van API kulcsa egy AI-szolg\u00e1ltat\u00e1shoz, ez a cikk neked sz\u00f3l. A Google nemr\u00e9g bevezette a Cloud Billingben a k\u00f6lt\u00e9si korl\u00e1tokat (spend caps), amelyek automatikusan felf\u00fcggesztik a lefedett szolg\u00e1ltat\u00e1s haszn\u00e1lat\u00e1t, ha a k\u00f6lt\u00e9s \u00e1tl\u00e9p egy megadott \u00f6sszeget. A FOTC \u00e1ltal fejlesztett k\u00f6lts\u00e9ganom\u00e1lia-detektorral (Cloud Anomaly Detector) egy\u00fctt teljes r\u00e1l\u00e1t\u00e1st ad a fi\u00f3k p\u00e9nz\u00fcgyeire \u2013 a korl\u00e1t a megadott \u00f6sszeget \u0151rzi, a detektor pedig megmutatja, norm\u00e1lis-e a k\u00f6lt\u00e9s, \u00e9s mi okozta a v\u00e1ltoz\u00e1st.<\/p>\n  <p class=\"fotc-lead\">Arr\u00f3l, hogyan seg\u00edtett a Cloud Anomaly Detector \u00f3r\u00e1kon bel\u00fcl meg\u00e1ll\u00edtani egy LLMjacking-incidenst, <a href=\"https:\/\/fotc.com\/hu\/blog\/mire-megerkezik-a-szamla-mar-tul-keso-igy-epitettunk-koltseganomalia-detektort-a-google-cloudhoz\/\">a sorozat el\u0151z\u0151 cikk\u00e9ben<\/a> \u00edrtunk. Ma m\u00e9lyebbre megy\u00fcnk \u2013 megtudod, mit ad val\u00f3j\u00e1ban a spend cap, hol vannak a hat\u00e1rai, \u00e9s hogyan oszd el a korl\u00e1tokat t\u00f6bb tucat projektre a termel\u00e9s le\u00e1ll\u00edt\u00e1s\u00e1nak kock\u00e1zata n\u00e9lk\u00fcl. Kapsz h\u00e1rom parancsot is, amellyel m\u00e9g ma ellen\u0151rizheted a saj\u00e1t fi\u00f3kodat.<\/p>\n  <div class=\"fotc-stats\" role=\"group\" aria-label=\"A detektor egy h\u00f3napja sz\u00e1mokban\">\n    <div class=\"fotc-stat\" data-reveal><b data-count=\"48\">48<\/b><span>detektorfut\u00e1s naponta, egyszerre t\u00f6bb sz\u00e1z fi\u00f3kon<\/span><\/div>\n    <div class=\"fotc-stat\" data-reveal><b data-count=\"20\" data-prefix=\"\u2248 \">\u2248 20<\/b><span>statisztikailag kiugr\u00f3 fi\u00f3k egy tipikus fut\u00e1sban<\/span><\/div>\n    <div class=\"fotc-stat\" data-reveal><b data-count=\"16\">16<\/b><span>embereknek k\u00fcld\u00f6tt riaszt\u00e1s 29 nap alatt. A t\u00f6bbi megfigyel\u00e9s.<\/span><\/div>\n    <div class=\"fotc-stat\" data-reveal><b data-count=\"2\">2<\/b><span>riaszt\u00e1sn\u00e1l kellett az \u00fcgyf\u00e9llel k\u00f6z\u00f6sen megkeresni a forr\u00e1st<\/span><\/div>\n  <\/div>\n  <p>Az els\u0151 cikk megjelen\u00e9se \u00f3ta a rendszer egy teljes h\u00f3napot dolgozott t\u00f6bb sz\u00e1z sz\u00e1ml\u00e1z\u00e1si fi\u00f3kon, Cloud Anomaly Detector lett a neve, \u00e9s a dashboardj\u00e1n \u00faj, a spend capeknek szentelt n\u00e9zetet kapott: egy t\u00e9rk\u00e9pet, amely megmutatja, mely projekteken van m\u00e1r cap, \u00e9s melyek \u00e1llnak m\u00e9g n\u00e9lk\u00fcle. A capekkel kezd\u00fcnk, mert ezek v\u00e1ltoztatj\u00e1k meg az er\u0151viszonyokat.<\/p>\n  <h2>Spend cap \u2013 hogyan m\u0171k\u00f6dik a mechanizmus<\/h2>\n  <p>K\u00f6lts\u00e9gkeretek r\u00e9g\u00f3ta l\u00e9teznek a Cloud Billingben, de csak \u00e9rtes\u00edtettek. A spend cap egy v\u00e9grehajt\u00e1ssal ell\u00e1tott k\u00f6lts\u00e9gkeret: amikor egy adott szolg\u00e1ltat\u00e1s becs\u00fclt k\u00f6lts\u00e9ge egy adott projektben t\u00fall\u00e9pi az \u00f6sszeget, a Google le\u00e1ll\u00edtja az \u00faj k\u00e9r\u00e9seket a szolg\u00e1ltat\u00e1s fel\u00e9. Senkinek nem kell kattintania. Aki l\u00e1tott m\u00e1r sz\u00e1ml\u00e1t h\u00e1rom napi ellen\u0151rizetlen inferenci\u00e1r\u00f3l, annak ez min\u0151s\u00e9gi v\u00e1ltoz\u00e1s. Egy cap egy szolg\u00e1ltat\u00e1st fed le egy projektben, \u00e9s a t\u00e1mogatott szolg\u00e1ltat\u00e1sok list\u00e1ja egyel\u0151re r\u00f6vid: Gemini API, Gemini Enterprise Agent Platform (kor\u00e1bban Vertex AI), Cloud Run \u00e9s Cloud Run functions. A cap kiz\u00e1r\u00f3lag havi id\u0151szakkal m\u0171k\u00f6dik, \u00e9s az eg\u00e9sz funkci\u00f3 2026. okt\u00f3ber 13. \u00f3ta \u00e1ltal\u00e1nosan el\u00e9rhet\u0151 (GA). Ez a dokument\u00e1ci\u00f3 2026. okt\u00f3ber 23-i \u00e1llapota. A Google azt \u00edg\u00e9ri, hogy a k\u00f6vetkez\u0151 kiad\u00e1sokban tov\u00e1bbi szolg\u00e1ltat\u00e1sokat von a capek al\u00e1, \u00e9s mindegyik egy \u00fajabb ter\u00fclet, amelyet \u00edgy meg lehet \u00e1ll\u00edtani.<\/p>\n  <p>A Cloud Anomaly Detector egy \u00e1ltalunk \u00e9p\u00edtett rendszer, amely f\u00e9l\u00f3r\u00e1nk\u00e9nt \u00f6sszeveti minden sz\u00e1ml\u00e1z\u00e1si fi\u00f3k k\u00f6lt\u00e9s\u00e9t a fi\u00f3k saj\u00e1t el\u0151zm\u00e9ny\u00e9vel, \u00e9s riaszt, ha valami elt\u00e9r t\u0151le. \u00d6nmag\u00e1ban semmit nem \u00e1ll\u00edt le. Ehelyett arra a k\u00e9rd\u00e9sre v\u00e1laszol, amelyet a cap sosem tesz fel: norm\u00e1lis-e ez a k\u00f6lt\u00e9s, \u00e9s honnan j\u00f6tt.<\/p>\n  <figure data-reveal data-trigger=\"timeline\">\n    <div class=\"fotc-fig-head\"><span class=\"fotc-fig-title\">Egy h\u00f3nap a spend cap \u00e9let\u00e9b\u0151l<\/span><\/div>\n<svg class='fotc-chart fotc-timeline' viewBox='0 0 720 160' role='img' aria-labelledby='tlT tlD' font-family='Fira Sans, -apple-system, Segoe UI, Roboto, sans-serif'>\n<title id='tlT'>A spend cap egy h\u00f3napja<\/title>\n<desc id='tlD'>Tengely a h\u00f3nap els\u0151 napj\u00e1t\u00f3l. E-mail az \u00f6sszeg 50, 80 \u00e9s 100 sz\u00e1zal\u00e9k\u00e1n\u00e1l; 100 sz\u00e1zal\u00e9k ut\u00e1n a Google le\u00e1ll\u00edtja a szolg\u00e1ltat\u00e1s \u00faj h\u00edv\u00e1sait a projektben. A korl\u00e1t a h\u00f3nap elej\u00e9n mag\u00e1t\u00f3l felold\u00f3dik, el\u0151tte csak k\u00e9zzel.<\/desc>\n<line x1='30' x2='690' y1='78' y2='78' stroke='#E8E8E8' stroke-width='8' stroke-linecap='round'\/>\n<line class='tl-fill' x1='30' x2='505.2' y1='78' y2='78' stroke='#0097DA' stroke-width='8' stroke-linecap='round' pathLength='100'\/>\n<line class='tl-stop' x1='505.2' x2='690' y1='78' y2='78' stroke='#E3322B' stroke-width='8' stroke-linecap='round' stroke-dasharray='2 10' opacity='0'\/>\n<text x='30' y='114' font-size='11' fill='#6B6B6B'>a h\u00f3nap 1. napja<\/text>\n<text x='690' y='114' text-anchor='end' font-size='11' fill='#6B6B6B'>h\u00f3nap v\u00e9ge<\/text>\n<text class='tl-stoplabel' x='597.6' y='56' text-anchor='middle' font-size='12' font-weight='500' fill='#E3322B' opacity='0'>h\u00edv\u00e1sok blokkolva<\/text>\n<g class='tl-mark' data-at='0.36'>\n<circle class='tl-pulse' cx='267.6' cy='78' r='9' fill='none' stroke='#FAB001' stroke-width='2' opacity='0'\/>\n<circle class='tl-dot' cx='267.6' cy='78' r='9' fill='#fff' stroke='#FAB001' stroke-width='3'\/>\n<text x='267.6' y='56' text-anchor='middle' font-size='12' font-weight='500' fill='#000000'>50 %<\/text>\n<text x='267.6' y='114' text-anchor='middle' font-size='11' fill='#6B6B6B'>e-mail<\/text><\/g>\n<g class='tl-mark' data-at='0.58'>\n<circle class='tl-pulse' cx='412.8' cy='78' r='9' fill='none' stroke='#FAB001' stroke-width='2' opacity='0'\/>\n<circle class='tl-dot' cx='412.8' cy='78' r='9' fill='#fff' stroke='#FAB001' stroke-width='3'\/>\n<text x='412.8' y='56' text-anchor='middle' font-size='12' font-weight='500' fill='#000000'>80 %<\/text>\n<text x='412.8' y='114' text-anchor='middle' font-size='11' fill='#6B6B6B'>e-mail<\/text><\/g>\n<g class='tl-mark' data-at='0.72'>\n<circle class='tl-pulse' cx='505.2' cy='78' r='9' fill='none' stroke='#E3322B' stroke-width='2' opacity='0'\/>\n<circle class='tl-dot' cx='505.2' cy='78' r='9' fill='#fff' stroke='#E3322B' stroke-width='3'\/>\n<text x='505.2' y='56' text-anchor='middle' font-size='12' font-weight='500' fill='#000000'>100 %<\/text>\n<text x='505.2' y='114' text-anchor='middle' font-size='11' fill='#6B6B6B'>e-mail + blokkol\u00e1s<\/text><\/g>\n<circle class='tl-cursor' cx='30' cy='78' r='6' fill='#0097DA' stroke='#fff' stroke-width='2'\/>\n<\/svg>\n    <figcaption>Az 50 \u00e9s 80&nbsp;%-os k\u00fcsz\u00f6b kiz\u00e1r\u00f3lag e-mail a sz\u00e1ml\u00e1z\u00e1si adminisztr\u00e1toroknak \u00e9s a projekt tulajdonosainak. 100&nbsp;% ut\u00e1n a Google blokkolja az \u00faj h\u00edv\u00e1sokat, de a folyamatban l\u00e9v\u0151 k\u00e9r\u00e9sek befejez\u0151dnek \u00e9s a sz\u00e1ml\u00e1ra ker\u00fclnek. A korl\u00e1t a k\u00f6vetkez\u0151 h\u00f3nap elej\u00e9n mag\u00e1t\u00f3l felold\u00f3dik. El\u0151tte k\u00e9zzel lehet feloldani, \u00e9s a szolg\u00e1ltat\u00e1s teljes helyre\u00e1ll\u00e1sa ak\u00e1r egy \u00f3r\u00e1t is ig\u00e9nybe vehet.<\/figcaption>\n  <\/figure>\n  <div class=\"fotc-cols\">\n    <div class=\"fotc-col fotc-col--stop\" data-reveal><h3>Mit blokkol a cap<\/h3><ul><li>Az adott szolg\u00e1ltat\u00e1s \u00faj API-h\u00edv\u00e1sai ebben a projektben<\/li><li>A k\u00f6vetkez\u0151 h\u00f3nap elej\u00e9ig vagy a k\u00f6lts\u00e9gkeret k\u00e9zi szerkeszt\u00e9s\u00e9ig<\/li><\/ul><\/div>\n    <div class=\"fotc-col fotc-col--flow\" data-reveal><h3>Mi megy tov\u00e1bb<\/h3><ul><li>Compute, storage \u00e9s m\u00e1s \u00e1lland\u00f3 er\u0151forr\u00e1sok<\/li><li>M\u00e1s projektek \u00e9s m\u00e1s szolg\u00e1ltat\u00e1sok<\/li><li>A folyamatban l\u00e9v\u0151 k\u00e9r\u00e9sek k\u00f6lts\u00e9ge, a v\u00e9grehajt\u00e1s nem azonnali<\/li><\/ul><\/div>\n  <\/div>\n  <p>Mindenkinek, akinek a szervezet\u00e9ben legal\u00e1bb egy AI-szolg\u00e1ltat\u00e1shoz van API kulcsa, ugyanazt mondjuk: <strong>ahol a Spend Caps el\u00e9rhet\u0151, tegy\u00e9l capet minden projektre, ahol a szolg\u00e1ltat\u00e1s be van kapcsolva, \u00e9s mindenre, ahol nincs<\/strong>. A m\u00e1sodik eset a fontosabb. Az els\u0151 cikkben le\u00edrt m\u00e1jusi incidens arr\u00f3l sz\u00f3lt, hogy egy t\u00e1mad\u00f3 olyan projektben kapcsolt be egy AI-szolg\u00e1ltat\u00e1st, amely soha nem haszn\u00e1lta. Egy sz\u00e1z eur\u00f3s cap egy olyan projekten, amelynek egy centet sem szabadna AI-ra k\u00f6ltenie, seg\u00edt korl\u00e1tozni az ilyen vissza\u00e9l\u00e9s k\u00f6lts\u00e9g\u00e9t. Az \u00f6sszeget tudatosan kell megv\u00e1lasztani, sz\u00e1molva a v\u00e9grehajt\u00e1s k\u00e9s\u00e9s\u00e9vel.<\/p>\n  <h2>Korl\u00e1t a projekten \u00e9s az eg\u00e9sz fi\u00f3k monitoroz\u00e1sa<\/h2>\n  <p>A spend cap egy projekt&nbsp;\u00d7&nbsp;szolg\u00e1ltat\u00e1s p\u00e1rt v\u00e9d. Az eg\u00e9sz fi\u00f3k monitoroz\u00e1sa az \u00fajonnan hozz\u00e1k\u00f6t\u00f6tt projektek k\u00f6lts\u00e9g\u00e9t is lefedi. A Google Cloud alap\u00e9rtelmezett be\u00e1ll\u00edt\u00e1sa a Project Creator szerepk\u00f6rt a domain minden felhaszn\u00e1l\u00f3j\u00e1nak megadja, a Billing Account User pedig sz\u00e9lesebb k\u00f6rben van kiosztva, mint b\u00e1rki eml\u00e9kezne r\u00e1. Ilyen jogosults\u00e1gokkal egy szkript \u00faj projektet hozhat l\u00e9tre, hozz\u00e1k\u00f6theti a sz\u00e1ml\u00e1z\u00e1st \u00e9s elind\u00edthat egy AI-szolg\u00e1ltat\u00e1st. Minden caped \u00e9s projektkerete a r\u00e9gi projektekben \u00e1ll.<\/p>\n  <figure data-reveal data-trigger=\"attack\">\n    <div class=\"fotc-fig-head\"><span class=\"fotc-fig-title\">\u00dat az \u00faj projekten \u00e1t \u00e9s h\u00e1rom v\u00e9delmi r\u00e9teg<\/span><\/div>\n<svg class='fotc-chart fotc-attack' viewBox='0 0 720 330' role='img' aria-labelledby='atT atD' font-family='Fira Sans, -apple-system, Segoe UI, Roboto, sans-serif'>\n<title id='atT'>\u00dat az \u00faj projekten \u00e1t \u00e9s h\u00e1rom v\u00e9delmi r\u00e9teg<\/title>\n<desc id='atD'>A t\u00e1mad\u00f3 \u00faj projektet hoz l\u00e9tre, sz\u00e1ml\u00e1z\u00e1st k\u00f6t hozz\u00e1 \u00e9s bekapcsol egy AI-szolg\u00e1ltat\u00e1st. A spend capek \u00e9s a projektkeretek a megnevezett projekteket fedik le. A sz\u00e1ml\u00e1z\u00e1si fi\u00f3k szint\u0171 \u00e9szlel\u00e9s az \u00faj projekteket is lefedi.<\/desc>\n<defs><marker id='arr' viewBox='0 0 10 10' refX='9' refY='5' markerWidth='8' markerHeight='8' orient='auto-start-reverse'><path d='M0,0 L10,5 L0,10 z' fill='#6B6B6B'\/><\/marker><\/defs>\n<g class='at-step at-step-0'><rect x='20' y='20' width='250' height='56' rx='12'\/><text class='t' x='34' y='46' font-size='13' font-weight='500'>Kisziv\u00e1rgott hiteles\u00edt\u0151 adatok<\/text><text class='s' x='34' y='66' font-size='11.5'>projekt l\u00e9trehoz\u00e1s\u00e1ra jogosult szerepk\u00f6r<\/text><\/g>\n<line class='at-link at-link-0' x1='145' x2='145' y1='76' y2='92' stroke='#6B6B6B' stroke-width='1.5' marker-end='url(#arr)'\/>\n<g class='at-step at-step-1'><rect x='20' y='92' width='250' height='56' rx='12'\/><text class='t' x='34' y='118' font-size='13' font-weight='500'>\u00daj projekt<\/text><text class='s' x='34' y='138' font-size='11.5'>Project Creator, gyakran alap\u00e9rtelmez\u00e9s<\/text><\/g>\n<line class='at-link at-link-1' x1='145' x2='145' y1='148' y2='164' stroke='#6B6B6B' stroke-width='1.5' marker-end='url(#arr)'\/>\n<g class='at-step at-step-2'><rect x='20' y='164' width='250' height='56' rx='12'\/><text class='t' x='34' y='190' font-size='13' font-weight='500'>Sz\u00e1ml\u00e1z\u00e1s hozz\u00e1k\u00f6t\u00e9se<\/text><text class='s' x='34' y='210' font-size='11.5'>Billing Account User<\/text><\/g>\n<line class='at-link at-link-2' x1='145' x2='145' y1='220' y2='236' stroke='#6B6B6B' stroke-width='1.5' marker-end='url(#arr)'\/>\n<g class='at-step at-step-3'><rect x='20' y='236' width='250' height='56' rx='12'\/><text class='t' x='34' y='262' font-size='13' font-weight='500'>AI-szolg\u00e1ltat\u00e1s API + kulcs<\/text><text class='s' x='34' y='282' font-size='11.5'>fogyaszt\u00e1s az els\u0151 perct\u0151l<\/text><\/g>\n<path class='at-path at-path-0 at-miss' d='M270,264 C 350,264 350,78 430,78' fill='none' stroke-width='2' pathLength='100' marker-end='url(#arr)'\/>\n<g class='at-layer at-layer-0 at-miss'><rect x='430' y='48' width='270' height='60' rx='12'\/><text class='t' x='444' y='74' font-size='13' font-weight='500'>Spend cap<\/text><text class='s' x='444' y='94' font-size='11.5'>a megnevezett projekt \u00e9s szolg\u00e1ltat\u00e1s<\/text><\/g>\n<text class='at-verdict at-verdict-0 at-miss' x='350' y='70' text-anchor='middle' font-size='11' font-weight='500'>kik\u00e9nyszer\u00edti az \u00f6sszeget<\/text>\n<path class='at-path at-path-1 at-miss' d='M270,264 C 350,264 350,168 430,168' fill='none' stroke-width='2' pathLength='100' marker-end='url(#arr)'\/>\n<g class='at-layer at-layer-1 at-miss'><rect x='430' y='138' width='270' height='60' rx='12'\/><text class='t' x='444' y='164' font-size='13' font-weight='500'>Projekt k\u00f6lts\u00e9gkeret<\/text><text class='s' x='444' y='184' font-size='11.5'>a megnevezett projekt<\/text><\/g>\n<text class='at-verdict at-verdict-1 at-miss' x='350' y='160' text-anchor='middle' font-size='11' font-weight='500'>riaszt az \u00f6sszegr\u0151l<\/text>\n<path class='at-path at-path-2 at-hit' d='M270,264 C 350,264 350,258 430,258' fill='none' stroke-width='2' pathLength='100' marker-end='url(#arr)'\/>\n<g class='at-layer at-layer-2 at-hit'><rect x='430' y='228' width='270' height='60' rx='12'\/><text class='t' x='444' y='254' font-size='13' font-weight='500'>Fi\u00f3kszint\u0171 \u00e9szlel\u00e9s<\/text><text class='s' x='444' y='274' font-size='11.5'>az \u00faj projekteket is<\/text><\/g>\n<text class='at-verdict at-verdict-2 at-hit' x='350' y='250' text-anchor='middle' font-size='11' font-weight='500'>\u00e9rt\u00e9kel \u00e9s eszkal\u00e1l<\/text>\n<circle class='at-runner' cx='145' cy='20' r='6' fill='#E3322B' opacity='0'\/>\n<\/svg>\n    <figcaption>A cap \u00e9s a projektkeret a megnevezett projektet fedi le. A sz\u00e1ml\u00e1z\u00e1si fi\u00f3k monitoroz\u00e1sa az \u00faj projektek k\u00f6lts\u00e9g\u00e9t is lefedi, amint megjelennek a sz\u00e1ml\u00e1z\u00e1si adatokban.<\/figcaption>\n  <\/figure>\n  <p><strong>Az egyik bet\u00f6r\u00e9sn\u00e9l, amelyn\u00e9l seg\u00edtett\u00fcnk, a t\u00e1mad\u00f3 \u00faj projektet hozott l\u00e9tre, \u00e9s az \u00e1ldozat sz\u00e1ml\u00e1z\u00e1si fi\u00f3kj\u00e1hoz k\u00f6t\u00f6tte.<\/strong> Az \u00fcgyf\u00e9l olyan sz\u00e1ml\u00e1t l\u00e1tott, amelyet nem tudott megmagyar\u00e1zni, \u00e9s a seg\u00edts\u00e9g\u00fcnket k\u00e9rte. Az els\u0151 k\u00e9rd\u00e9s nem az volt, hogy \u201eki&#8221;, hanem hogy \u201emelyik projekt&#8221;. Am\u00edg a k\u00f6lts\u00e9gnek nincs c\u00edme, a napl\u00f3kban nincs mit keresni.<\/p>\n  <p>Amikor a c\u00edm megvolt, a t\u00f6bbit az auditnapl\u00f3k mondt\u00e1k el. A k\u00f6rnyezet, amelyben a k\u00f6lts\u00e9g n\u0151tt, semmihez nem tartozott, amit az \u00fcgyf\u00e9l ismert, mert valaki a semmib\u0151l hozta l\u00e9tre, \u00e9s az \u00fcgyf\u00e9l sz\u00e1ml\u00e1z\u00e1si fi\u00f3kj\u00e1hoz k\u00f6t\u00f6tte. Ez\u00e9rt \u00e9rdemes az eg\u00e9sz fi\u00f3k v\u00e1ltoz\u00e1sait figyelni, nem csak az ismert projektek\u00e9t. Az olyan \u00faj k\u00f6lts\u00e9gt\u00e9tel, amely az els\u0151 \u00f3r\u00e1j\u00e1t\u00f3l k\u00f6lt, a detektor sz\u00e1m\u00e1ra k\u00fcl\u00f6n anom\u00e1liat\u00edpus.<\/p>\n  <p>Innen a szab\u00e1ly, amelyet az eg\u00e9sz portf\u00f3li\u00f3ra elfogadtunk: <strong>a spend cap kik\u00e9nyszer\u00edti a megadott \u00f6sszeget, a sz\u00e1ml\u00e1z\u00e1si fi\u00f3k szint\u0171 \u00e9szlel\u00e9s pedig felismeri a szokatlan v\u00e1ltoz\u00e1sokat, az \u00faj projektekben is<\/strong>. Ehhez k\u00e9t olcs\u00f3 IAM-l\u00e9p\u00e9s: az alap\u00e9rtelmezett Project Creator szerepk\u00f6r elv\u00e9tele a domaint\u0151l, \u00e9s annak \u00e1tn\u00e9z\u00e9se, kinek van val\u00f3ban Billing Account User jogosults\u00e1ga.<\/p>\n  <h3>Amikor el\u00e9g a korl\u00e1t \u00e9s a k\u00e9zi \u00e1tn\u00e9z\u00e9s<\/h3>\n  <p>Nem minden k\u00f6rnyezetnek kell detektor. Ha n\u00e9h\u00e1ny projekted van, egy csapatod, \u00e9s a domaint\u0151l elvetted a Project Creator szerepk\u00f6rt, akkor a capek a t\u00e1mogatott projekt&nbsp;\u00d7&nbsp;AI-szolg\u00e1ltat\u00e1s p\u00e1rokon, egy k\u00f6lts\u00e9gkeret az eg\u00e9sz fi\u00f3kra \u00e9s a k\u00f6lt\u00e9sek rendszeres \u00e1tn\u00e9z\u00e9se a konzolban el\u00e9g a napi k\u00f6lts\u00e9gkontrollhoz. A projektlista elf\u00e9r egy k\u00e9perny\u0151n, \u00e9s a sz\u00e1ml\u00e1n minden \u00faj t\u00e9telt felismer valaki a nev\u00e9r\u0151l. Ez a tan\u00e1cs akkor sz\u0171nik meg m\u0171k\u00f6dni, amikor t\u00f6bb tucat projekt van, \u00e9s a projektet l\u00e9trehozni jogosultak list\u00e1ja hosszabb, mint azok\u00e9, akik err\u0151l tudnak. Akkor m\u00e1r senki nem tartja fejben az eg\u00e9sz fi\u00f3kot, \u00e9s kell egy rendszer, amely az emberek helyett eml\u00e9kszik r\u00e1. Err\u0151l sz\u00f3l a cikk t\u00f6bbi r\u00e9sze.<\/p>\n  <h2>Hogyan k\u00f6zel\u00edtett\u00fck meg a capeket nagy l\u00e9pt\u00e9kben<\/h2>\n  <p>T\u00f6bb sz\u00e1z fi\u00f3kn\u00e1l \u00e9s t\u00f6bb ezer projektn\u00e9l t\u00e9rk\u00e9p kell. A detektor dashboardj\u00e1nak m\u00e1sodik lapjak\u00e9nt \u00e9p\u00edtett\u00fck meg. N\u00e9h\u00e1ny akkor hozott d\u00f6nt\u00e9s\u00fcnk nem f\u00fcgg a l\u00e9pt\u00e9kt\u0151l, \u00e9s ugyan\u00fagy m\u0171k\u00f6dik n\u00e9h\u00e1ny projektn\u00e9l, mint t\u00f6bb ezern\u00e9l.<\/p>\n  <figure data-reveal data-trigger=\"coverage\">\n    <div class=\"fotc-fig-head\"><span class=\"fotc-fig-title\">Lefedetts\u00e9gi t\u00e9rk\u00e9p: projekt&nbsp;\u00d7&nbsp;AI-szolg\u00e1ltat\u00e1s p\u00e1rok<\/span>\n      <div class=\"fotc-controls\">\n        <button type=\"button\" class=\"fotc-btn fotc-btn--dot\" style=\"--dot:#00A855\" data-filter=\"api\">API<\/button>\n        <button type=\"button\" class=\"fotc-btn fotc-btn--dot\" style=\"--dot:#FAB001\" data-filter=\"man\">bejelentett<\/button>\n        <button type=\"button\" class=\"fotc-btn fotc-btn--dot\" style=\"--dot:#D1D1D1\" data-filter=\"none\">korl\u00e1t n\u00e9lk\u00fcl<\/button>\n      <\/div>\n    <\/div>\n    <div class=\"fotc-grid\" aria-hidden=\"true\"><\/div>\n    <div class=\"fotc-bars\" aria-hidden=\"true\"><\/div>\n    <div class=\"fotc-legend\"><span><b data-n=\"api\">0<\/b> API \u00e1ltal igazolt<\/span><span><b data-n=\"man\">0<\/b> ember \u00e1ltal bejelentett<\/span><span><b data-n=\"none\">0<\/b> korl\u00e1t n\u00e9lk\u00fcl<\/span><\/div>\n    <figcaption>Minden mez\u0151 egy projekt&nbsp;\u00d7&nbsp;AI-szolg\u00e1ltat\u00e1s p\u00e1r. A nevez\u0151 minden, a fi\u00f3khoz k\u00f6t\u00f6tt projekt, az AI-haszn\u00e1lati el\u0151zm\u00e9ny n\u00e9lk\u00fcliek is. A z\u00f6ld \u00e9s a s\u00e1rga soha nem ad\u00f3dik \u00f6ssze egy sz\u00e1zal\u00e9kba. Szeml\u00e9ltet\u0151 elrendez\u00e9s, nem \u00e9les k\u00e9perny\u0151k\u00e9p; az anim\u00e1ci\u00f3 a munka sorrendj\u00e9t mutatja, a legkisebb k\u00f6rnyezetekt\u0151l kezdve.<\/figcaption>\n  <\/figure>\n  <p>El\u0151sz\u00f6r a nevez\u0151re \u00f6sszpontos\u00edtottunk, vagyis arra, mi ker\u00fcl egy\u00e1ltal\u00e1n a lefedetts\u00e9g sz\u00e1m\u00edt\u00e1s\u00e1ba. Minden, a fi\u00f3khoz k\u00f6t\u00f6tt projektet belesz\u00e1molunk, azt is, amelyik soha nem ny\u00falt AI-hoz. Ha csak az AI-t m\u00e1r haszn\u00e1l\u00f3 projekteket n\u00e9zn\u00e9nk, a t\u00e9rk\u00e9p z\u00f6lden vil\u00e1g\u00edtana, \u00e9s semmit nem mondana a kock\u00e1zatr\u00f3l. Azt v\u00e9ded, amit a t\u00e1mad\u00f3 majd bekapcsol.<\/p>\n  <p>M\u00e1sodszor \u00fagy d\u00f6nt\u00f6tt\u00fcnk, hogy a szolg\u00e1ltat\u00e1ssz\u0171r\u0151 n\u00e9lk\u00fcli k\u00f6lts\u00e9gkeret nem korl\u00e1t, hanem riaszt\u00e1s, \u00e9s nem szabad a lefedetts\u00e9gbe sz\u00e1molni. Amikor naivan sz\u00e1moltuk, a lefedetts\u00e9g t\u00f6bb tucatszor jobbnak t\u0171nt a val\u00f3s\u00e1gosn\u00e1l.<\/p>\n  <p>Harmadszor meg\u00e1llapodtunk, honnan j\u00f6n az \u00f6sszeg. A fi\u00f3k saj\u00e1t el\u0151zm\u00e9nye javasolja: a teljes h\u00f3napok \u00e1tlaga \u00e9s az utols\u00f3 teljes h\u00f3nap k\u00f6z\u00fcl a nagyobb. A foly\u00f3 h\u00f3nap kimarad, mert a h\u00f3nap k\u00f6zep\u00e9n sz\u00e1molt korl\u00e1t a forgalom fel\u00e9b\u0151l sz\u00e1molt korl\u00e1t. Mindig felfel\u00e9 kerek\u00edt\u00fcnk, mert a lefel\u00e9 kerek\u00edtett korl\u00e1t az al\u00e1 a forgalom al\u00e1 ker\u00fcl, amelyre m\u00e9retezt\u00e9k. A k\u00f6lt\u00e9s n\u00e9lk\u00fcli projekt szimbolikus \u00f6sszeget kap.<\/p>\n  <p>Negyedszer r\u00f6gz\u00edtett\u00fck a sorrendet. A list\u00e1t a legkisebb k\u00f6rnyezetekt\u0151l kezdj\u00fck, mert ott a legolcs\u00f3bb a hiba, \u00e9s ott van a legt\u00f6bb el\u0151zm\u00e9ny n\u00e9lk\u00fcli projekt. A val\u00f3s AI-forgalm\u00fa nagy k\u00f6rnyezetek csak az \u00f6sszegr\u0151l folytatott besz\u00e9lget\u00e9s ut\u00e1n kapnak capet. A rosszul megv\u00e1lasztott korl\u00e1t ugyanolyan hat\u00e9konyan \u00e1ll\u00edtja le az \u00fcgyf\u00e9l termel\u00e9s\u00e9t, mint egy t\u00e1mad\u00e1s.<\/p>\n  <p>\u00c9s a szab\u00e1ly, amelyet nem szeg\u00fcnk meg: amit az API igazolt, \u00e9s amit ember jel\u00f6lt be k\u00e9zzel a konzolban, k\u00fcl\u00f6n sz\u00ednt kap a t\u00e9rk\u00e9pen, \u00e9s soha nem \u00f6sszegz\u0151dik egy sz\u00e1zal\u00e9kba. A bejelent\u00e9s \u00e9rt\u00e9kes, mert nevet \u00e9s d\u00e1tumot hordoz. Bizony\u00edt\u00e9k csak az olvasat.<\/p>\n  <h2>Egy h\u00f3nap \u00e9lesben: a \u201ekiugrik&#8221; \u00e9s az \u201e\u00e9rdemes felkelteni valakit&#8221; k\u00f6z\u00f6tt<\/h2>\n  <p>A detektor minden fi\u00f3kot kiz\u00e1r\u00f3lag a saj\u00e1t el\u0151zm\u00e9ny\u00e9hez hasonl\u00edt, ez\u00e9rt minden fut\u00e1sban tucatnyi vagy t\u00f6bb fi\u00f3k t\u00e9r el a norm\u00e1j\u00e1t\u00f3l, \u00e9s ez \u00edgy van rendj\u00e9n. A rendszer teljes \u00e9rt\u00e9ke abban rejlik, hogyan v\u00e1lasztja ki ezekb\u0151l a megfigyel\u00e9sekb\u0151l azt a havi tucatnyit, amelyekn\u00e9l joga van megszak\u00edtani valakinek a napj\u00e1t.<\/p>\n  <figure data-reveal data-trigger=\"cadence\">\n    <div class=\"fotc-fig-head\"><span class=\"fotc-fig-title\" data-cad-counter>megfigyel\u00e9sek \u00e9s riaszt\u00e1sok<\/span><div class=\"fotc-controls\"><button type=\"button\" class=\"fotc-btn\" data-only-alerts>Csak riaszt\u00e1sos napok<\/button><\/div><\/div>\n    <svg class=\"fotc-chart fotc-cadence\" viewBox=\"0 0 720 260\" role=\"img\" aria-labelledby=\"cadT cadD\" data-obs=\"[21, 15, 20, 13, 40, 46, 21, 17, 17, 17, 14, 13, 13, 9, 18, 23, 15, 6, 5, 13, 17, 23, 23, 12, 4, 4, 15, 13, 17]\" data-alerts=\"[0, 0, 5, 1, 3, 0, 0, 1, 1, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0]\" font-family=\"Fira Sans, -apple-system, Segoe UI, Roboto, sans-serif\">\n      <title id=\"cadT\">Kiugr\u00f3 fi\u00f3kok fut\u00e1sonk\u00e9nt \u00e9s elk\u00fcld\u00f6tt riaszt\u00e1sok, 29 nap<\/title>\n      <desc id=\"cadD\">Oszlopok 4-t\u0151l 46 fi\u00f3kig fut\u00e1sonk\u00e9nt; riaszt\u00e1s csak t\u00edz napon, \u00f6sszesen tizenhat.<\/desc>\n    <\/svg>\n    <figcaption>Kiugr\u00f3 fi\u00f3kok \u00e1tlagos sz\u00e1ma egy fut\u00e1sra (oszlopok) \u00e9s az embereknek k\u00fcld\u00f6tt riaszt\u00e1sok (piros jel\u00f6l\u0151k). 29 egym\u00e1st k\u00f6vet\u0151 nap, 2026. augusztus \u00e9s szeptember, a detektor napl\u00f3ib\u00f3l. A legt\u00f6bb megfigyel\u00e9st hoz\u00f3 napok nem a riaszt\u00e1sos napok voltak.<\/figcaption>\n  <\/figure>\n  <p>Egy konkr\u00e9t eset szeptember 3-\u00e1r\u00f3l. Egy fi\u00f3k, amely \u00e1ltal\u00e1ban napi tizenvalah\u00e1ny eur\u00f3t k\u00f6lt, egyetlen nap alatt 500-at k\u00f6lt\u00f6tt. \u00d723-as szorz\u00f3, 2200 sz\u00e1zal\u00e9kos n\u00f6veked\u00e9s, gyakorlatilag az eg\u00e9sz egyetlen t\u00e9rk\u00e9pszolg\u00e1ltat\u00e1son. A detektor 3:00-kor l\u00e1tta meg, \u00e9s a k\u00f6vetkez\u0151 21 \u00f3r\u00e1ban 42-szer er\u0151s\u00edtette meg. Senkit nem \u00e9bresztett fel, mert az 500 eur\u00f3 nem l\u00e9pi \u00e1t azt az \u00f6sszeghat\u00e1rt, amelyn\u00e9l valakinek meg szabad szak\u00edtani a napj\u00e1t.<\/p>\n  <p>A riaszt\u00e1s m\u00e1snap reggel m\u00e9gis kiment, csak egy m\u00e1sik detektorb\u00f3l. A h\u00f3nap v\u00e9gi el\u0151rejelz\u00e9s 6000 eur\u00f3ig k\u00faszott az el\u0151z\u0151 h\u00f3napok 900-\u00e1val szemben. Egy nap l\u00e9pt\u00e9k\u00e9ben az \u00f6sszeg t\u00fal kicsi volt ahhoz, hogy b\u00e1rkit fel\u00e9bresszen. Egy h\u00f3nap l\u00e9pt\u00e9k\u00e9ben m\u00e1r nem.<\/p>\n  <p>Nem t\u00e1mad\u00e1s volt. Az \u00fcgyf\u00e9ln\u00e9l a t\u00e9rk\u00e9pes r\u00e9sz elromlott, a forgalom \u00e1tkapcsolt egy tartal\u00e9k projektre, \u00e9s ott kezdett k\u00f6lts\u00e9get termelni, ahol senki nem figyelte. \u00dczemzavar, nem bet\u00f6r\u00e9s, de a sz\u00e1mla ugyan\u00fagy n\u0151tt volna, am\u00edg senki bele nem n\u00e9z.<\/p>\n  <h3>A riaszt\u00e1snak r\u00e1 kell mutatnia<\/h3>\n  <p>A tizenhat riaszt\u00e1sb\u00f3l kett\u0151 az \u00fcgyf\u00e9llel k\u00f6z\u00f6s munkamenettel v\u00e9gz\u0151d\u00f6tt. Mindkett\u0151 ugyan\u00fagy n\u00e9zett ki: a k\u00e1rtya azt mondta, hogy a fi\u00f3k a szok\u00e1sos t\u00f6bbsz\u00f6r\u00f6s\u00e9t k\u00f6lti, a m\u00e1sik oldalon pedig senki nem tudta megmondani, melyik projektb\u0151l sz\u00e1rmazik ez a k\u00f6lts\u00e9g, \u00e9s melyik kulcs \u00e1ll m\u00f6g\u00f6tte. A sz\u00e1ml\u00e1z\u00e1si fi\u00f3k t\u00fal durva c\u00edm ahhoz, hogy b\u00e1rmit kezdj\u00fcnk vele.<\/p>\n  <p>Az \u00e9szlel\u00e9s ez\u00e9rt lejjebb ment, egyetlen projektre \u00e9s egyetlen SKU-ra, vagyis a legapr\u00f3bb t\u00e9telre, amelyet a Google a sz\u00e1ml\u00e1n felt\u00fcntet. A k\u00e1rty\u00e1n a szolg\u00e1ltat\u00e1sokat aszerint rendezz\u00fck, mekkora \u00f6sszeggel n\u0151ttek val\u00f3j\u00e1ban, nem sz\u00e1zal\u00e9k szerint. Az a szolg\u00e1ltat\u00e1s, amely egy centr\u0151l h\u00e9t eur\u00f3ra ugrott, h\u00e9tsz\u00e1z sz\u00e1zal\u00e9kkal n\u0151tt, \u00e9s semmit nem jelent. Az, amely h\u00e9tezer eur\u00f3val n\u0151tt, maga az esem\u00e9ny.<\/p>\n  <p>A bont\u00e1s ugyanabban a fut\u00e1sban k\u00e9sz\u00fcl, mint a k\u00e1rtya t\u00f6bbi r\u00e9sze, \u00e9s ez nem megval\u00f3s\u00edt\u00e1si r\u00e9szlet. A sz\u00e1ml\u00e1z\u00e1si export m\u00e9g \u00f3r\u00e1kkal a riaszt\u00e1s ut\u00e1n is t\u00f6lti az ablakot, \u00edgy a k\u00e1rtya megnyit\u00e1sakor sz\u00e1molt szolg\u00e1ltat\u00e1sok az adatok k\u00e9s\u0151bbi \u00e1llapot\u00e1b\u00f3l sz\u00e1rmazn\u00e1nak, mint a fejl\u00e9cben l\u00e9v\u0151 \u00f6sszeg. A k\u00e1rty\u00e1nak egyetlen pillanat felv\u00e9tel\u00e9nek kell lennie, m\u00e9g ha az a pillanat hi\u00e1nyos is.<\/p>\n  <h3>Alapvonal, amely kib\u00edrja, amit m\u00e9r<\/h3>\n  <p>El\u0151sz\u00f6r matematika n\u00e9lk\u00fcl. A detektor minden nap egy k\u00e9rd\u00e9sre v\u00e1laszol: norm\u00e1lis-e a mai k\u00f6lts\u00e9g enn\u00e9l a fi\u00f3kn\u00e1l? Ehhez k\u00e9t sz\u00e1mra van sz\u00fcks\u00e9ge: mi a norma, \u00e9s mennyire t\u00e9r el t\u0151le egy nap \u00e1ltal\u00e1ban. A gond akkor kezd\u0151dik, amikor az elm\u00falt h\u00e9ten m\u00e1r volt egy rossz nap.<\/p>\n  <p>Egy p\u00e9lda. A fi\u00f3k naponta k\u00f6r\u00fclbel\u00fcl 20 eur\u00f3t k\u00f6lt. H\u00e9tf\u0151n valaki 900-\u00e9rt futtat inferenci\u00e1t, kedden 640-\u00e9rt. A h\u00e9tf\u0151t b\u00e1rmelyik m\u00f3dszer elkapja, mert a 900 a 20-hoz k\u00e9pest m\u00e1s vil\u00e1g. A kedd az \u00e9rdekes.<\/p>\n  <p><strong>\u00c1tlaggal.<\/strong> Az utols\u00f3 h\u00e9t nap \u00e1tlaga, a h\u00e9tf\u0151i 900-zal egy\u00fctt, 146. A szok\u00e1sos sz\u00f3r\u00e1s, ugyanezekb\u0151l a napokb\u00f3l sz\u00e1molva, 2-r\u0151l 300 f\u00f6l\u00e9 n\u0151tt, mert a h\u00e9tf\u0151 felfel\u00e9 h\u00fazta. A keddi 640 az \u00faj norm\u00e1t\u00f3l kevesebb mint k\u00e9t ilyen sz\u00f3r\u00e1sra van. A statisztika sz\u00e1m\u00e1ra k\u00f6z\u00f6ns\u00e9ges nap. A riaszt\u00e1s az incidens k\u00f6zep\u00e9n elhal.<\/p>\n  <p><strong>Medi\u00e1nnal.<\/strong> A medi\u00e1n a rendez\u00e9s ut\u00e1ni k\u00f6z\u00e9ps\u0151 \u00e9rt\u00e9k. A h\u00e9t nap: 17, 19, 20, 21, 22, 23 \u00e9s 900, a k\u00f6z\u00e9ps\u0151 21. A h\u00e9tf\u0151 a lista v\u00e9g\u00e9n \u00e1ll, \u00e9s nincs szava. A sz\u00f3r\u00e1st ugyanezzel a tr\u00fckkel sz\u00e1moljuk: minden nap t\u00e1vols\u00e1g\u00e1t vessz\u00fck a 21-t\u0151l, \u00e9s megint a k\u00f6z\u00e9ps\u0151t, ami 2. Ez a MAD, az elt\u00e9r\u00e9sek medi\u00e1nja. A keddi 640 t\u00f6bb sz\u00e1z ilyen sz\u00f3r\u00e1sra van a norm\u00e1t\u00f3l. A riaszt\u00e1s megmarad, ahogy kell.<\/p>\n  <div class=\"fotc-table-scroll\">\n  <table>\n    <thead><tr><th><\/th><th>\u00c1tlag<\/th><th>Medi\u00e1n<\/th><\/tr><\/thead>\n    <tbody>\n      <tr><td>Norma h\u00e9tf\u0151 ut\u00e1n<\/td><td>146<\/td><td>21<\/td><\/tr>\n      <tr><td>Szok\u00e1sos sz\u00f3r\u00e1s<\/td><td>300 felett<\/td><td>2<\/td><\/tr>\n      <tr><td>Kedd 640-nel<\/td><td>szinte k\u00f6z\u00f6ns\u00e9ges nap<\/td><td>riaszt\u00e1s<\/td><\/tr>\n    <\/tbody>\n  <\/table>\n  <\/div>\n  <p>A sz\u00f3r\u00e1snak van als\u00f3 hat\u00e1ra, mert egy pontosan 20, 20, 20-at k\u00f6lt\u0151 fi\u00f3k sz\u00f3r\u00e1sa nulla lenne, \u00e9s minden cent katasztr\u00f3f\u00e1nak l\u00e1tszana. Az exportban sor n\u00e9lk\u00fcli nap pedig nulla k\u00f6lts\u00e9gnek sz\u00e1m\u00edt, hogy egy csendes h\u00e9t ne t\u0171nj\u00f6n el az el\u0151zm\u00e9nyb\u0151l. A diagram alatti cs\u00faszk\u00e1k ugyanazon a sorozaton mutatj\u00e1k a k\u00e9t vonalat.<\/p>\n  <figure data-reveal>\n    <div class=\"fotc-fig-head\"><span class=\"fotc-fig-title\">\u00c1tlag \u00e9s medi\u00e1n incidens ut\u00e1n<\/span>\n      <div class=\"fotc-controls\">\n        <label class=\"fotc-range\">incidens m\u00e9rete <input type=\"range\" min=\"100\" max=\"2000\" step=\"50\" value=\"900\" data-mag><output data-mag-out>900<\/output><\/label>\n        <label class=\"fotc-range\">ablak <input type=\"range\" min=\"5\" max=\"14\" step=\"1\" value=\"7\" data-win><output data-win-out>7 nap<\/output><\/label>\n      <\/div>\n    <\/div>\n    <svg class=\"fotc-chart fotc-baseline\" viewBox=\"0 0 720 240\" role=\"img\" aria-labelledby=\"blT blD\" font-family=\"Fira Sans, -apple-system, Segoe UI, Roboto, sans-serif\">\n      <title id=\"blT\">Mozg\u00f3\u00e1tlag \u00e9s medi\u00e1n h\u00e1romnapos incidens ut\u00e1n<\/title>\n      <desc id=\"blD\">Napi k\u00f6lts\u00e9g 20 k\u00f6r\u00fcl, h\u00e1rom incidensnappal. Az ablakos \u00e1tlag felugrik, \u00e9s az ablak hossz\u00e1ig \u00faj norm\u00e1nak tetteti mag\u00e1t; a medi\u00e1n 20-n\u00e1l marad.<\/desc>\n    <\/svg>\n    <p class=\"fotc-zout\" data-z-out><\/p>\n    <figcaption>Ugyanaz a k\u00f6lts\u00e9gsorozat, k\u00e9t alapvonal. Az incidens ut\u00e1n az \u00e1tlag az ablak teljes hossz\u00e1ban \u00faj norm\u00e1nak mutatja mag\u00e1t, ez\u00e9rt a k\u00f6vetkez\u0151 incidensnapok nyugodtnak l\u00e1tszanak. A medi\u00e1n h\u00faszn\u00e1l marad. A mechanizmus szeml\u00e9ltet\u00e9se, n\u00e9gyzetgy\u00f6k\u00f6s tengely.<\/figcaption>\n  <\/figure>\n  <p>K\u00e9t szomsz\u00e9dos csapda. A foly\u00f3 nap: reggel hatkor a fi\u00f3knak hat \u00f3r\u00e1ja van a h\u00e1ta m\u00f6g\u00f6tt, \u00edgy teljes napokhoz m\u00e9rve mindig cs\u00f6kken\u00e9snek l\u00e1tszik. Ez\u00e9rt a mai hat \u00f3r\u00e1t az el\u0151z\u0151 napok ugyanazon hat \u00f3r\u00e1j\u00e1val hasonl\u00edtjuk. Az \u00f3r\u00e1nk\u00e9nti \u00e9szlel\u00e9s: ha a vizsg\u00e1lt \u00f3ra ugyanabban a mint\u00e1ban \u00fcl, amelyb\u0151l a norm\u00e1t sz\u00e1molod, akkor maga emeli a norm\u00e1t, \u00e9s soha nem t\u00e9r el t\u0151le annyira, hogy \u00e1tl\u00e9pje a k\u00fcsz\u00f6b\u00f6t. Egy f\u00e9lmilli\u00f3s \u00f3ra ekkor enyh\u00e9n emelkedettnek l\u00e1tszik. A vizsg\u00e1lt \u00f3r\u00e1t ki kell hagyni a mint\u00e1b\u00f3l.<\/p>\n  <h2>A rendszernek tudnia kell, mit nem l\u00e1t<\/h2>\n  <p>Az anom\u00e1liadetektor legvesz\u00e9lyesebb \u00e1llapota a csend, amely nyugalomnak l\u00e1tszik.<\/p>\n  <p>Augusztus 25-\u00e9n a sz\u00e1ml\u00e1z\u00e1si export abbahagyta az \u00edr\u00e1st. Nem egy forr\u00e1s, hanem mind, egym\u00e1s ut\u00e1n, n\u00e9h\u00e1ny t\u00edz perc k\u00fcl\u00f6nbs\u00e9ggel. A detektor f\u00e9l\u00f3r\u00e1nk\u00e9nt tov\u00e1bb futott, reggel \u00f3ta v\u00e1ltozatlan t\u00e1bl\u00e1kat olvasott, \u00e9s minden alkalommal azt jelentette, hogy nincs anom\u00e1lia. Hat \u00f3r\u00e1n \u00e1t senki nem n\u00e9zte a flott\u00e1t, \u00e9s ennek az \u00e1llapotnak az egyetlen nyoma egy s\u00e1v volt a dashboardon, amelyre valakinek mag\u00e1t\u00f3l r\u00e1 kellett n\u00e9znie.<\/p>\n  <p>M\u00e9g aznap kijav\u00edtottuk, \u00e9s r\u00f6gt\u00f6n t\u00fal is l\u0151tt\u00fcnk a c\u00e9lon: a halott forr\u00e1s elkezdte fel\u00e9breszteni az \u00fcgyeletest. Azon az \u00e9jszak\u00e1n, nem sokkal \u00e9jf\u00e9l ut\u00e1n, az \u00fcgyeletes h\u00edv\u00e1st kapott egy befagyott exportt\u00e1bl\u00e1r\u00f3l, amellyel reggelig \u00fagysem tudott mit kezdeni. M\u00e1snap ezt az utat visszavontuk. A pager ma a k\u00f6lts\u00e9gnek van fenntartva, a forr\u00e1shiba pedig k\u00fcl\u00f6n csatorn\u00e1t kapott, csendben t\u00f6lt\u00f6tt \u00f3r\u00e1kban m\u00e9rt k\u00fcsz\u00f6bbel, mert a negyed\u00f3r\u00e1n \u00e1t vill\u00f3dz\u00f3 forr\u00e1s nem incidens, a f\u00e9l napig hallgat\u00f3 viszont igen.<\/p>\n  <p>N\u00e9gy \u00e1llapot, amelyet a naiv k\u00f3d egyform\u00e1n \u201enincs anom\u00e1lia&#8221;-k\u00e9nt jelent:<\/p>\n  <div class=\"fotc-cards\">\n    <div class=\"fotc-card\" data-reveal><span class=\"fotc-tag\">a forr\u00e1s meg\u00e1llt<\/span><h3>Az export \u00f3r\u00e1k \u00f3ta nem \u00edr<\/h3><p>A detektor befagyott t\u00e1bl\u00e1kat szkennel, \u00e9s sikert jelent. K\u00fcl\u00f6n m\u00e9r\u0151sz\u00e1m kell: mikor \u00edrt a forr\u00e1s b\u00e1rmit is, csendben t\u00f6lt\u00f6tt \u00f3r\u00e1kban m\u00e9rt k\u00fcsz\u00f6bbel.<\/p><\/div>\n    <div class=\"fotc-card\" data-reveal><span class=\"fotc-tag\">hiba eredm\u00e9ny helyett<\/span><h3>A lek\u00e9rdez\u00e9s elhasalt<\/h3><p>Az \u00fcres lista, mert a lek\u00e9rdez\u00e9s elhasalt, \u00e9s az \u00fcres lista, mert nem tal\u00e1ltunk semmit, k\u00e9t k\u00fcl\u00f6nb\u00f6z\u0151 t\u00e9ny, \u00e9s a k\u00f3dnak meg kell k\u00fcl\u00f6nb\u00f6ztetnie \u0151ket. A fut\u00e1s, amely nem l\u00e1tta a flott\u00e1t, hib\u00e1val v\u00e9gz\u0151dik, nem jelent\u00e9ssel.<\/p><\/div>\n    <div class=\"fotc-card\" data-reveal><span class=\"fotc-tag\">nem \u00edt\u00e9lhet\u0151 meg<\/span><h3>Fi\u00f3k egy teljes h\u00f3nap el\u0151zm\u00e9ny n\u00e9lk\u00fcl<\/h3><p>El\u0151rejelz\u00e9s nem k\u00e9sz\u00fcl, \u00e9s ez \u00edgy helyes, mert nincs mib\u0151l. De a fi\u00f3k sz\u00e1m\u00edt, \u00e9s \u201enem \u00e9rt\u00e9kelt&#8221;-k\u00e9nt l\u00e1tszik, azzal a d\u00e1tummal, amelyt\u0151l \u00e9rt\u00e9kelni kezdik.<\/p><\/div>\n    <div class=\"fotc-card\" data-reveal><span class=\"fotc-tag\">\u00fcres pillanatk\u00e9p<\/span><h3>Nulla fi\u00f3k t\u00f6bb sz\u00e1z helyett<\/h3><p>Az \u00fcres eredm\u00e9ny a fut\u00e1s hib\u00e1j\u00e1t jelenti. \u00dcres flotta csak els\u0151 telep\u00edt\u00e9skor fordul el\u0151, \u00e9s olyankor ezt kifejezetten deklar\u00e1lni kell.<\/p><\/div>\n  <\/div>\n  <div class=\"fotc-callout\" data-reveal><p><strong>A hi\u00e1nyz\u00f3 adat nem nulla.<\/strong> Minden \u00fat, amely nem tudja bizony\u00edtani, hogy adatot n\u00e9zett, a fut\u00e1st a monitoringban l\u00e1that\u00f3 hib\u00e1val z\u00e1rja. Az alternat\u00edva egy z\u00f6ld dashboard egy flotta f\u00f6l\u00f6tt, amelyet senki nem n\u00e9z.<\/p><\/div>\n  <h2>Hogyan ellen\u0151rizd magadn\u00e1l<\/h2>\n  <p>H\u00e1rom parancs v\u00e1laszol a cikk k\u00e9rd\u00e9s\u00e9re: megjelenhet-e a sz\u00e1ml\u00e1z\u00e1si fi\u00f3kod alatt olyan projekt, amelyr\u0151l senki nem tud? Az els\u0151 felsorolja a fi\u00f3khoz k\u00f6t\u00f6tt projekteket l\u00e9trehoz\u00e1si d\u00e1tummal, a leg\u00fajabbal az \u00e9len. A m\u00e1sodik megmutatja, ki hozhat l\u00e9tre projektet a szervezetben. A harmadik, ki k\u00f6theti \u0151ket a sz\u00e1ml\u00e1z\u00e1shoz.<\/p>\n  <figure data-reveal data-trigger=\"terminal\">\n    <div class=\"fotc-fig-head\"><span class=\"fotc-fig-title\">H\u00e1rom k\u00e9rd\u00e9s a sz\u00e1ml\u00e1z\u00e1si fi\u00f3khoz<\/span><\/div>\n    <div class=\"fotc-term\" role=\"img\" aria-label=\"Termin\u00e1l h\u00e1rom gcloud paranccsal: a fi\u00f3khoz k\u00f6t\u00f6tt projektek l\u00e9trehoz\u00e1si d\u00e1tummal, a szervezetben Project Creator szerepk\u00f6rt birtokl\u00f3k, a Billing Account User szerepk\u00f6rt birtokl\u00f3k. Kiemelve: egy tegnap l\u00e9trehozott projekt \u00e9s egy eg\u00e9sz domain projektl\u00e9trehoz\u00e1si joggal.\">\n      <div class=\"fotc-term-bar\"><i><\/i><i><\/i><i><\/i><span>sz\u00e1ml\u00e1z\u00e1si fi\u00f3k \u00b7 p\u00e9ldaadatok<\/span><\/div>\n      <pre class=\"fotc-term-body\"><span class=\"tl cmd\" data-t=\"cmd\">$ gcloud billing projects list --billing-account=0A1B2C-3D4E5F-6A7B8C --format=\"value(projectId)\" \\\n    | xargs -I{} gcloud projects describe {} --format=\"csv[no-heading](projectId,createTime.date('%Y-%m-%d'))\" \\\n    | sort -t, -k2 -r<\/span><span class=\"tl hl-red\" data-t=\"out\">gen-ai-tmp-4471,2026-09-10          <b>\u2190 tegnap l\u00e9trehozva, nulla k\u00f6lts\u00e9gel\u0151zm\u00e9ny<\/b><\/span><span class=\"tl\" data-t=\"out\">shop-prod,2023-04-12<\/span><span class=\"tl\" data-t=\"out\">shop-staging,2023-04-12<\/span><span class=\"tl\" data-t=\"out\">data-warehouse,2022-11-03<\/span><span class=\"tl\" data-t=\"out\">mobile-backend,2021-06-30<\/span><span class=\"tl gap\" data-t=\"out\"> <\/span><span class=\"tl cmd\" data-t=\"cmd\">$ gcloud organizations get-iam-policy 123456789012 --flatten=\"bindings[].members\" \\\n    --filter=\"bindings.role:roles\/resourcemanager.projectCreator\" --format=\"value(bindings.members)\"<\/span><span class=\"tl hl-amber\" data-t=\"out\">domain:example.com                  <b>\u2190 az eg\u00e9sz domain hozhat l\u00e9tre projektet (alap\u00e9rtelmez\u00e9s)<\/b><\/span><span class=\"tl\" data-t=\"out\">group:cloud-admins@example.com<\/span><span class=\"tl gap\" data-t=\"out\"> <\/span><span class=\"tl cmd\" data-t=\"cmd\">$ gcloud billing accounts get-iam-policy 0A1B2C-3D4E5F-6A7B8C --flatten=\"bindings[].members\" \\\n    --filter=\"bindings.role:roles\/billing.user\" --format=\"value(bindings.members)\"<\/span><span class=\"tl\" data-t=\"out\">group:cloud-admins@example.com<\/span><span class=\"tl hl-amber\" data-t=\"out\">user:dev-2019-contractor@example.com <b>\u2190 \u00e9vekkel ezel\u0151tti kulcs, senki nem tudja, mi\u00e9rt<\/b><\/span><span class=\"tl hl-amber\" data-t=\"out\">serviceAccount:ci-legacy@shop-prod.iam.gserviceaccount.com<\/span><\/pre>\n    <\/div>\n    <figcaption>A termin\u00e1l p\u00e9ldaadatokat mutat. A tegnapi d\u00e1tum\u00fa, k\u00f6lts\u00e9gel\u0151zm\u00e9ny n\u00e9lk\u00fcli projektet ellen\u0151rizni kell \u2013 van-e gazd\u00e1ja \u00e9s saj\u00e1t korl\u00e1tja? A <code>domain:<\/code> bejegyz\u00e9s a Project Creator alatt a Google Cloud alap\u00e9rtelmez\u00e9s\u00e9t jelenti: a c\u00e9gben b\u00e1rki l\u00e9trehozhat projektet.<\/figcaption>\n  <\/figure>\n  <p>Ugyanez a h\u00e1rom parancs, beilleszt\u00e9sre k\u00e9szen. T\u00f6ltsd ki a k\u00e9t v\u00e1ltoz\u00f3t fel\u00fcl, a t\u00f6bbit v\u00e1ltoztat\u00e1s n\u00e9lk\u00fcl illeszd be. A fi\u00f3kazonos\u00edt\u00f3t a <code>gcloud billing accounts list<\/code>, a szervezet sz\u00e1m\u00e1t a <code>gcloud organizations list<\/code> adja.<\/p>\n  <div class=\"fotc-code\" data-reveal>\n    <div class=\"fotc-code-bar\"><button type=\"button\" class=\"fotc-btn\" data-copy>M\u00e1sol\u00e1s<\/button><\/div>\n<pre><code class=\"language-bash\">export BILLING_ACCOUNT_ID=\"0X0X0X-0X0X0X-0X0X0X\"   # gcloud billing accounts list\nexport ORG_ID=\"123456789012\"                       # gcloud organizations list\necho \"== 1. A $BILLING_ACCOUNT_ID fi\u00f3khoz k\u00f6t\u00f6tt projektek, leg\u00fajabb el\u00f6l ==\"\ngcloud billing projects list --billing-account=\"$BILLING_ACCOUNT_ID\" --format=\"value(projectId)\" \\\n  | xargs -I{} gcloud projects describe {} --format=\"csv[no-heading](projectId,createTime.date('%Y-%m-%d'))\" \\\n  | sort -t, -k2 -r\necho; echo \"== 2. Ki hozhat l\u00e9tre projektet a $ORG_ID szervezetben ==\"\ngcloud organizations get-iam-policy \"$ORG_ID\" --flatten=\"bindings[].members\" \\\n  --filter=\"bindings.role:roles\/resourcemanager.projectCreator\" --format=\"value(bindings.members)\"\necho; echo \"== 3. Ki k\u00f6thet projektet a $BILLING_ACCOUNT_ID fi\u00f3khoz ==\"\ngcloud billing accounts get-iam-policy \"$BILLING_ACCOUNT_ID\" --flatten=\"bindings[].members\" \\\n  --filter=\"bindings.role:roles\/billing.user\" --format=\"value(bindings.members)\"<\/code><\/pre>\n  <\/div>\n  <div class=\"fotc-cards fotc-steps\">\n    <div class=\"fotc-card\" data-reveal><span class=\"fotc-tag fotc-tag--blue\">1. l\u00e9p\u00e9s<\/span><h3>N\u00e9zd \u00e1t a projektlist\u00e1t<\/h3><p>Minden projekt, amelyet nem ismersz fel, tulajdonost kap vagy t\u00f6rl\u0151dik. Ism\u00e9teld hetente, legjobb \u00fctemez\u00e9sb\u0151l, e-maillel.<\/p><\/div>\n    <div class=\"fotc-card\" data-reveal><span class=\"fotc-tag fotc-tag--blue\">2. l\u00e9p\u00e9s<\/span><h3>Sz\u0171k\u00edtsd a Project Creator \u00e9s Billing Account User k\u00f6r\u00e9t<\/h3><p>Vedd el a domaint\u0151l az alap\u00e9rtelmezett szerepk\u00f6rt, tartsd meg az admin csoportot. A sz\u00e1ml\u00e1z\u00e1st hozz\u00e1k\u00f6tni jogosultak list\u00e1ja f\u00e9rjen el egy k\u00e9zen.<\/p><\/div>\n    <div class=\"fotc-card\" data-reveal><span class=\"fotc-tag fotc-tag--blue\">3. l\u00e9p\u00e9s<\/span><h3>Cap minden projekt&nbsp;\u00d7&nbsp;AI-szolg\u00e1ltat\u00e1s p\u00e1ron<\/h3><p>Ott is, ahol nem haszn\u00e1lnak AI-t. Ott szimbolikus \u00f6sszeg; ahol val\u00f3s a forgalom, az el\u0151zm\u00e9nyb\u0151l sz\u00e1rmaz\u00f3, felfel\u00e9 kerek\u00edtett \u00f6sszeg.<\/p><\/div>\n    <div class=\"fotc-card\" data-reveal><span class=\"fotc-tag fotc-tag--blue\">4. l\u00e9p\u00e9s<\/span><h3>K\u00f6lts\u00e9gkeret az eg\u00e9sz fi\u00f3kra<\/h3><p>A val\u00f3s k\u00f6lt\u00e9shez igaz\u00edtott k\u00fcsz\u00f6bbel, ne kerek sz\u00e1mmal. Az ehhez a fi\u00f3khoz k\u00f6t\u00f6tt \u00faj projektek k\u00f6lt\u00e9s\u00e9t is lefedi.<\/p><\/div>\n  <\/div>\n  <p>Ez a n\u00e9gy l\u00e9p\u00e9s egy d\u00e9lut\u00e1nt vesz ig\u00e9nybe, \u00e9s a konzolon k\u00edv\u00fcl semmi nem kell hozz\u00e1. Kis k\u00f6rnyezetben lez\u00e1rja a cikk szcen\u00e1ri\u00f3j\u00e1t, nagyban jelent\u0151sen megnehez\u00edti.<\/p>\n  <h2>\u00d6sszefoglal\u00e1s<\/h2>\n  <p>A Google Cloud Spend Capjei automatikusan kik\u00e9nyszer\u00edtik a megadott \u00f6sszeget az \u00e1ltaluk lefedett szolg\u00e1ltat\u00e1sokra. Tedd fel mindenhov\u00e1, ahol lehet, k\u00fcl\u00f6n\u00f6s figyelemmel az AI-t nem haszn\u00e1l\u00f3 projektekre. A Cloud Anomaly Detector egy m\u00e1sodik kontrollr\u00e9teget tesz mell\u00e9: \u00f6sszeveti a k\u00f6lt\u00e9st a fi\u00f3k el\u0151zm\u00e9ny\u00e9vel, megmutatja, mi v\u00e1ltozott, \u00e9s fel\u00e9breszt valakit, aki reag\u00e1lni tud. A szokatlan k\u00f6lt\u00e9s akkor is figyelmet \u00e9rdemelhet, ha belef\u00e9r a havi korl\u00e1tba.<\/p>\n  <div class=\"fotc-callout\" data-reveal><p>A Spend Caps a megadott \u00f6sszeget \u0151rzi. A Cloud Anomaly Detector seg\u00edt felismerni a szokatlan k\u00f6lts\u00e9get \u00e9s eld\u00f6nteni, mi legyen vele.<\/p><\/div>\n  <p>A fenti n\u00e9gy l\u00e9p\u00e9s el\u00e9g az indul\u00e1shoz. Ahogy a k\u00f6rnyezet n\u0151, ellen\u0151rizd, hogy a capek m\u00e9g mindig azt fedik-e, amit kell. A hat\u00e1r ott van, ahol elkezd\u0151dik a k\u00e9rd\u00e9s: \u201eez t\u00e1mad\u00e1s vagy \u00faj funkci\u00f3?&#8221;, t\u00f6bb tucat projektn\u00e9l \u00e9s \u00e9vek alatt kiosztott kulcsokn\u00e1l. A FOTC-n\u00e1l ezt Cloud Anomaly Detector n\u00e9ven csin\u00e1ljuk: a sz\u00e1ml\u00e1z\u00e1si fi\u00f3k f\u00e9l\u00f3r\u00e1nk\u00e9nti monitoroz\u00e1sa, riaszt\u00e1sokkal a te csapatodnak \u00e9s a mi\u00e9nknek, \u00e9s amikor a riaszt\u00e1s m\u00e1r megj\u00f6tt, \u00e9s nem tudod, mit kezdj vele, \u00f3rad\u00edjas m\u00e9rn\u00f6ki t\u00e1mogat\u00e1sk\u00e9nt is, hossz\u00fa szerz\u0151d\u00e9s n\u00e9lk\u00fcl. Ha ink\u00e1bb magad csin\u00e1ln\u00e1d, a fentiek elegend\u0151k az indul\u00e1shoz.<\/p>\n  <section class=\"fotc-faq\">\n    <h2>GYIK<\/h2>\n    <h3>Megv\u00e9d a spend cap az LLMjackingt\u0151l?<\/h3>\n    <p>Korl\u00e1tozza a sz\u00e1ml\u00e1t azokban a projektekben, amelyeket lefedt\u00e9l. A t\u00e1mad\u00e1st nem \u00e1ll\u00edtja meg: a v\u00e9grehajt\u00e1s nem azonnali, a folyamatban l\u00e9v\u0151 k\u00e9r\u00e9sek sz\u00e1ml\u00e1z\u00f3dnak, \u00e9s a projektet l\u00e9trehozni jogosult t\u00e1mad\u00f3 \u00fajat hoz l\u00e9tre. A cap, a fi\u00f3kszint\u0171 \u00e9szlel\u00e9s \u00e9s a Project Creator, valamint Billing Account User szerepk\u00f6r\u00f6k \u00e1tn\u00e9z\u00e9se h\u00e1rom k\u00fcl\u00f6nb\u00f6z\u0151 r\u00e9st z\u00e1r be. Egyik sem helyettes\u00edti a m\u00e1sikat.<\/p>\n    <h3>Minek a Cloud Anomaly Detector, ha van Spend Caps?<\/h3>\n    <p>A Spend Caps felf\u00fcggeszti a megnevezett szolg\u00e1ltat\u00e1s haszn\u00e1lat\u00e1t a megadott \u00f6sszeg \u00e1tl\u00e9p\u00e9se ut\u00e1n. A detektor a fi\u00f3k norm\u00e1lis k\u00f6lt\u00e9s\u00e9t\u0151l val\u00f3 elt\u00e9r\u00e9seket keresi, \u00e9s seg\u00edt megmutatni a v\u00e1ltoz\u00e1s\u00e9rt felel\u0151s projektet \u00e9s szolg\u00e1ltat\u00e1st. Jelezhet olyan anom\u00e1li\u00e1t is, amely belef\u00e9r a korl\u00e1tba, ha teljes\u00edti a riaszt\u00e1si felt\u00e9teleket. A sz\u00e1ml\u00e1z\u00e1si exportb\u00f3l dolgozik, \u00edgy az \u00e9szlel\u00e9s ideje az adatok be\u00e9rkez\u00e9s\u00e9t\u0151l f\u00fcgg. Nincs garancia arra, hogy a riaszt\u00e1s a Spend Caps m\u0171k\u00f6d\u00e9se el\u0151tt \u00e9rkezik.<\/p>\n    <h3>Mekkora \u00f6sszeget \u00e1ll\u00edtsak be egy AI-t nem haszn\u00e1l\u00f3 projekten?<\/h3>\n    <p>Szimbolikusat, havi sz\u00e1zegyn\u00e9h\u00e1ny eur\u00f3 nagys\u00e1grend\u0171t. Annyit, hogy egy jogos tesztn\u00e9l senki ne vegye \u00e9szre, \u00e9s annyira keveset, hogy a vissza\u00e9l\u00e9st meg\u00e1ll\u00edtsa, miel\u0151tt megn\u0151. Amikor a projekt val\u00f3ban elkezd AI-t haszn\u00e1lni, tudatosan emeled a korl\u00e1tot.<\/p>\n    <h3>Le\u00e1ll\u00edthatja a cap a termel\u00e9semet?<\/h3>\n    <p>Igen, \u00e9s ez a dolga. Egy val\u00f3s forgalm\u00fa projekten rosszul megv\u00e1lasztott \u00f6sszeg le\u00e1ll\u00edtja a jogos inferenci\u00e1t, a korl\u00e1t pedig csak a k\u00f6vetkez\u0151 h\u00f3nap elej\u00e9n old\u00f3dik fel mag\u00e1t\u00f3l. El\u0151tte embernek kell feloldania, \u00e9s a helyre\u00e1ll\u00e1s ak\u00e1r egy \u00f3r\u00e1t is ig\u00e9nybe vehet. Ez\u00e9rt a termel\u00e9si projekteken az \u00f6sszeg az el\u0151zm\u00e9nyb\u0151l j\u00f6n \u00e9s felfel\u00e9 kerek\u00edt, \u00e9s valakinek, aki hozz\u00e1f\u00e9r a k\u00f6lts\u00e9gkerethez, h\u00e9tv\u00e9g\u00e9n is el\u00e9rhet\u0151nek kell lennie.<\/p>\n    <h3>Mi van, ha a BigQuery-be ir\u00e1nyul\u00f3 sz\u00e1ml\u00e1z\u00e1si export le\u00e1ll?<\/h3>\n    <p>Ez az egyetlen \u00e1llapot, amelyet egy k\u00f6lts\u00e9ganom\u00e1lia-detektor mag\u00e1t\u00f3l nem vesz \u00e9szre, mert a hi\u00e1nyz\u00f3 adat \u00fagy n\u00e9z ki, mint a k\u00f6lt\u00e9s hi\u00e1nya. A forr\u00e1s frissess\u00e9g\u00e9nek k\u00fcl\u00f6n m\u00e9r\u0151sz\u00e1mnak kell lennie k\u00fcl\u00f6n riaszt\u00e1ssal, \u00e9s a dashboardnak m\u00e1s sz\u00ednnel kell mondania, hogy \u201enem l\u00e1tok&#8221;, mint azt, hogy \u201enem t\u00f6rt\u00e9nik semmi&#8221;.<\/p>\n  <\/section>\n  <p class=\"fotc-note\">A spend capek le\u00edr\u00e1sa a <a href=\"https:\/\/docs.cloud.google.com\/billing\/docs\/how-to\/budgets-spend-caps\">Google Cloud nyilv\u00e1nos dokument\u00e1ci\u00f3j\u00e1b\u00f3l<\/a> sz\u00e1rmazik, 2026. okt\u00f3ber 23-\u00e1n ellen\u0151rizve. A Cloud Billing Spend Caps 2026. okt\u00f3ber 13. \u00f3ta \u00e1ltal\u00e1nosan el\u00e9rhet\u0151 (GA), a dokument\u00e1ci\u00f3 pedig b\u0151v\u00fcl\u0151 szolg\u00e1ltat\u00e1slist\u00e1t \u00edg\u00e9r. A detektor munk\u00e1j\u00e1r\u00f3l sz\u00f3l\u00f3 sz\u00e1mok val\u00f3sak, a napl\u00f3ib\u00f3l sz\u00e1rmaznak. A lefedetts\u00e9gi t\u00e9rk\u00e9p \u00e9s az alapvonal-diagram a mechanizmust szeml\u00e9lteti, nem \u00e9les k\u00e9perny\u0151k\u00e9p. A cikk a rendszer 6.x verzi\u00f3j\u00e1t (2026) \u00edrja le.<\/p>\n  <div class=\"fotc-tip\" id=\"fotcTip\" role=\"presentation\"><\/div>\n<\/div>\n","protected":false},"excerpt":{"rendered":"<p>Ha olyan Google Cloud sz\u00e1ml\u00e1z\u00e1si fi\u00f3k\u00e9rt felelsz, amelyben b\u00e1rkinek van API kulcsa egy AI-szolg\u00e1ltat\u00e1shoz, ez a cikk neked sz\u00f3l. A Google nemr\u00e9g bevezette a Cloud Billingben a k\u00f6lt\u00e9si korl\u00e1tokat (spend caps), amelyek automatikusan felf\u00fcggesztik a lefedett szolg\u00e1ltat\u00e1s haszn\u00e1lat\u00e1t, ha a k\u00f6lt\u00e9s \u00e1tl\u00e9p egy megadott \u00f6sszeget. A FOTC \u00e1ltal fejlesztett k\u00f6lts\u00e9ganom\u00e1lia-detektorral (Cloud Anomaly Detector) egy\u00fctt teljes&#8230;<\/p>\n","protected":false},"author":22,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_editorskit_title_hidden":false,"_editorskit_reading_time":0,"_editorskit_is_block_options_detached":false,"_editorskit_block_options_position":"{}","footnotes":""},"categories":[561],"tags":[],"class_list":["post-178554","post","type-post","status-publish","format-standard","hentry","category-google-cloud-platform-hu"],"_links":{"self":[{"href":"https:\/\/fotc.com\/hu\/wp-json\/wp\/v2\/posts\/178554","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/fotc.com\/hu\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/fotc.com\/hu\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/fotc.com\/hu\/wp-json\/wp\/v2\/users\/22"}],"replies":[{"embeddable":true,"href":"https:\/\/fotc.com\/hu\/wp-json\/wp\/v2\/comments?post=178554"}],"version-history":[{"count":0,"href":"https:\/\/fotc.com\/hu\/wp-json\/wp\/v2\/posts\/178554\/revisions"}],"wp:attachment":[{"href":"https:\/\/fotc.com\/hu\/wp-json\/wp\/v2\/media?parent=178554"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/fotc.com\/hu\/wp-json\/wp\/v2\/categories?post=178554"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/fotc.com\/hu\/wp-json\/wp\/v2\/tags?post=178554"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}