[{"data":1,"prerenderedAt":1897},["ShallowReactive",2],{"doc:\u002Fdocs\u002Fintegrations\u002Fmonitoring":3,"docs-nav":1681},{"id":4,"title":5,"body":6,"description":1672,"extension":1673,"meta":1674,"navigation":1676,"path":1677,"seo":1678,"stem":1679,"__hash__":1680},"docs\u002Fdocs\u002Fintegrations\u002Fmonitoring.md","Monitoring",{"type":7,"value":8,"toc":1652},"minimark",[9,13,46,51,225,229,234,248,273,428,447,458,462,477,481,543,550,560,563,652,658,662,679,683,690,772,787,791,798,844,847,882,893,916,920,924,931,1102,1111,1293,1299,1303,1309,1326,1329,1344,1347,1481,1485,1488,1541,1545,1565,1569,1607,1611,1648],[10,11,5],"h1",{"id":12},"monitoring",[14,15,16,17,21,22,26,27,29,30,33,34,37,38,41,42,45],"p",{},"Tabularia's engine publishes Prometheus metrics on ",[18,19,20],"code",{},"\u002Fmetrics",", every service answers a\nhealth check, and the ",[23,24,25],"strong",{},"Administration"," menu has the pages an operator watches: a\nGrafana dashboard under ",[23,28,5],{},", run and preview timings under ",[23,31,32],{},"Performance",",\nthe live ",[23,35,36],{},"Queue",", the ",[23,39,40],{},"Workers"," and, on Kubernetes, the ",[23,43,44],{},"Cluster",". The Docker\nCompose development stack ships a complete monitoring stack; the Helm chart deploys\nnone, so that you point the monitoring you already run at Tabularia.",[47,48,50],"h2",{"id":49},"at-a-glance","At a glance",[52,53,54,70],"table",{},[55,56,57],"thead",{},[58,59,60,64,67],"tr",{},[61,62,63],"th",{},"What",[61,65,66],{},"Where",[61,68,69],{},"Who",[71,72,73,88,110,128,141,158,171,184,195,206],"tbody",{},[58,74,75,79,85],{},[76,77,78],"td",{},"Prometheus metrics",[76,80,81,84],{},[18,82,83],{},"GET \u002Fmetrics"," on the engine API (port 8000)",[76,86,87],{},"no sign-in; kept off the public network (below)",[58,89,90,93,107],{},[76,91,92],{},"Health checks",[76,94,95,96,99,100,103,104],{},"gateway ",[18,97,98],{},"GET \u002Fhealth",", engine ",[18,101,102],{},"GET \u002Fhealthcheck\u002F",", frontend ",[18,105,106],{},"GET \u002Flogin",[76,108,109],{},"probes, load balancers",[58,111,112,115,121],{},[76,113,114],{},"Grafana dashboard",[76,116,117,120],{},[23,118,119],{},"Administration → Monitoring"," (embedded)",[76,122,123,124,127],{},"administrators and observers; ",[23,125,126],{},"«Open Grafana»"," for administrators",[58,129,130,133,138],{},[76,131,132],{},"Run, preview and warehouse timings",[76,134,135],{},[23,136,137],{},"Administration → Performance",[76,139,140],{},"administrators and observers",[58,142,143,146,151],{},[76,144,145],{},"Jobs running and waiting",[76,147,148],{},[23,149,150],{},"Administration → Queue",[76,152,153,154,157],{},"read: administrators and observers; ",[23,155,156],{},"«Stop»",": administrators",[58,159,160,163,168],{},[76,161,162],{},"Processes per worker",[76,164,165],{},[23,166,167],{},"Administration → Workers",[76,169,170],{},"read: administrators and observers; change: administrators",[58,172,173,176,182],{},[76,174,175],{},"Pods, CPU, memory, warning events",[76,177,178,181],{},[23,179,180],{},"Administration → Cluster"," (Kubernetes only)",[76,183,140],{},[58,185,186,189,192],{},[76,187,188],{},"Host RAM",[76,190,191],{},"the badge in the top bar",[76,193,194],{},"everyone signed in; only when a node-exporter is configured",[58,196,197,200,203],{},[76,198,199],{},"Application logs",[76,201,202],{},"standard output of every container",[76,204,205],{},"your log collector",[58,207,208,211,217],{},[76,209,210],{},"Audit log",[76,212,213,216],{},[23,214,215],{},"Audit",", and forwarded to a SIEM",[76,218,219,220],{},"see ",[221,222,224],"a",{"href":223},"\u002Fdocs\u002Fsiem-splunk","Audit log to Splunk",[47,226,228],{"id":227},"how-it-works","How it works",[230,231,233],"h3",{"id":232},"the-engines-metrics","The engine's metrics",[14,235,236,237,240,241,244,245,247],{},"The engine API (the ",[18,238,239],{},"backend"," service in Compose, the ",[18,242,243],{},"engine"," Deployment of the chart)\nexposes ",[18,246,83],{}," in the Prometheus text format. It is one of two paths the engine\nserves without the gateway's internal token, together with the health checks: every\nother request is refused unless the gateway sent it.",[14,249,250,251,257,258,261,262,261,265,268,269,272],{},"It holds the request metrics of\n",[221,252,256],{"href":253,"rel":254},"https:\u002F\u002Fgithub.com\u002Ftrallnag\u002Fprometheus-fastapi-instrumentator",[255],"nofollow","prometheus-fastapi-instrumentator","\n(",[18,259,260],{},"http_requests_total",", ",[18,263,264],{},"http_request_duration_seconds",[18,266,267],{},"http_request_size_bytes",",\n",[18,270,271],{},"http_response_size_bytes",", labelled by handler, method and status), the process metrics\nof the Prometheus client, and Tabularia's own:",[52,274,275,291],{},[55,276,277],{},[58,278,279,282,285,288],{},[61,280,281],{},"Metric",[61,283,284],{},"Type",[61,286,287],{},"Labels",[61,289,290],{},"Meaning",[71,292,293,327,362,380,394],{},[58,294,295,300,303,310],{},[76,296,297],{},[18,298,299],{},"dataprep_preview_duration_ms",[76,301,302],{},"histogram",[76,304,305,261,307],{},[18,306,243],{},[18,308,309],{},"outcome",[76,311,312,313,315,316,261,319,322,323,326],{},"Duration of the previews, in milliseconds. Buckets from 100 ms to 120 s. ",[18,314,309],{}," is ",[18,317,318],{},"ok",[18,320,321],{},"superseded"," (a newer preview of the same step replaced it) or ",[18,324,325],{},"error",".",[58,328,329,334,337,344],{},[76,330,331],{},[18,332,333],{},"dataprep_preview_phase_ms_total",[76,335,336],{},"counter",[76,338,339,261,341],{},[18,340,243],{},[18,342,343],{},"phase",[76,345,346,347,261,350,261,353,261,356,261,359,326],{},"Time the previews spent in each phase: ",[18,348,349],{},"client",[18,351,352],{},"stepcache",[18,354,355],{},"sql",[18,357,358],{},"query",[18,360,361],{},"decode",[58,363,364,372,375,377],{},[76,365,366,261,369],{},[18,367,368],{},"dataprep_cache_hits",[18,370,371],{},"dataprep_cache_misses",[76,373,374],{},"gauge",[76,376],{},[76,378,379],{},"Step cache: previews that reused a cached step, and those that did not. Totals that only grow.",[58,381,382,387,389,391],{},[76,383,384],{},[18,385,386],{},"dataprep_cache_entries",[76,388,374],{},[76,390],{},[76,392,393],{},"Steps in the cache now.",[58,395,396,404,406,411],{},[76,397,398,261,401],{},[18,399,400],{},"dataprep_storage_bytes",[18,402,403],{},"dataprep_storage_objects",[76,405,374],{},[76,407,408],{},[18,409,410],{},"prefix",[76,412,413,414,261,417,261,420,423,424,427],{},"Size and number of objects under ",[18,415,416],{},"raw",[18,418,419],{},"datasets",[18,421,422],{},"cache"," and ",[18,425,426],{},"out"," in the bucket.",[14,429,430,431,434,435,438,439,442,443,446],{},"The ",[18,432,433],{},"dataprep_*"," values are kept in Valkey, not in the process: the previews, the runs\nand the workers all count in the same place, and each scrape reads it. Two things follow:\nthe workers need no metrics endpoint of their own, and ",[23,436,437],{},"every engine replica reports the\nsame totals",". Aggregate them with ",[18,440,441],{},"max",", not ",[18,444,445],{},"sum"," (the examples below do). If Valkey\nloses its data, the totals start again from zero.",[14,448,449,450,453,454,457],{},"The storage sizes are measured by the scheduler (",[18,451,452],{},"beat",") every\n",[18,455,456],{},"METRICS__STORAGE_STATS_INTERVAL_SECONDS"," (60 by default), a listing of the four prefixes.",[230,459,461],{"id":460},"celery-workers","Celery workers",[14,463,464,465,468,469,472,473,476],{},"The run and preview workers expose no HTTP endpoint. They send Celery task events (they\nstart with ",[18,466,467],{},"-E","), which a Celery exporter reads from the broker and turns into metrics:\ntasks running per worker, task durations, outcomes, queue length. The two queues are\n",[18,470,471],{},"celery"," (runs, database imports, exports) and ",[18,474,475],{},"preview"," (the previews of the editor and\nthe Viewer).",[230,478,480],{"id":479},"the-pages-in-the-interface","The pages in the interface",[482,483,484,495,508,516,528,533],"ul",{},[485,486,487,489,490,494],"li",{},[23,488,5],{}," embeds the Grafana dashboard ",[491,492,493],"em",{},"Tabularia — Overview"," in kiosk mode,\nrefreshed every 10 seconds: preview p50 and p95 by engine, previews per minute by\noutcome, where the preview time goes, cache hits and misses, Celery tasks running,\nrun durations, storage growth by prefix, memory per container, and which scrape\ntargets are up.",[485,496,497,499,500,503,504,507],{},[23,498,32],{}," needs no metrics stack: it reads the run history (a window of 1 to\n90 days, at most 20,000 runs), the preview counters in Valkey and, when the external\nClickHouse engine is configured, the heaviest queries of its ",[18,501,502],{},"query_log",". The ",[491,505,506],{},"wait","\ncolumn is the time between launch and a worker taking the run: when it grows, the\nworkers are not enough.",[485,509,510,512,513,515],{},[23,511,36],{}," shows the workers online, the jobs running and the jobs waiting, refreshed\nevery 2 seconds. Only the task's name, id, worker and duration are shown, never its\narguments. ",[23,514,156],{}," interrupts a job and is written to the audit log.",[485,517,518,520,521,523,524,527],{},[23,519,40],{}," (a section of ",[23,522,25],{},") shows the processes of each worker and\nchanges how many there are, within seconds and without restarts; on Kubernetes, with\n",[18,525,526],{},"adminScaling.enabled"," and the workers' autoscaling on, also the minimum and maximum\npods of the two worker Deployments.",[485,529,530,532],{},[23,531,44],{}," shows, on Kubernetes, the pods of Tabularia and of its users' code, their\nstate and restarts, CPU and memory against their limits (with metrics-server in the\ncluster) and the warning events. On Docker Compose the page says it has nothing to show.",[485,534,430,535,538,539,542],{},[23,536,537],{},"RAM badge"," of the top bar reads the host's memory directly from a node-exporter\n(",[18,540,541],{},"MONITORING__NODE_EXPORTER_URL","), not from the metrics store: it is the live value.\nWith the variable empty the badge is not shown.",[14,544,545],{},[546,547],"img",{"alt":548,"src":549},"The Queue page: two online workers, two jobs running, none waiting; one worker busy on two Datasource ingest jobs, each with its Stop button","\u002Fmedia\u002Fguide\u002Fintegrations\u002Fqueue-page.png",[14,551,552],{},[491,553,554,556,557,326],{},[23,555,36],{}," while a flow group refreshes two datasources: one worker has both slots busy, the jobs show their id, worker and time, and ",[23,558,559],{},"Stop",[230,561,92],{"id":562},"health-checks",[52,564,565,578],{},[55,566,567],{},[58,568,569,572,575],{},[61,570,571],{},"Service",[61,573,574],{},"Request",[61,576,577],{},"Answers",[71,579,580,602,617,636],{},[58,581,582,592,596],{},[76,583,584,585,423,588,591],{},"Gateway (both roles: ",[18,586,587],{},"api",[18,589,590],{},"orchestrator",")",[76,593,594],{},[18,595,98],{},[76,597,598,601],{},[18,599,600],{},"200 {\"status\": \"ok\"}"," while the process serves. The chart uses it for the startup, readiness and liveness probes.",[58,603,604,607,611],{},[76,605,606],{},"Engine API",[76,608,609],{},[18,610,102],{},[76,612,613,616],{},[18,614,615],{},"200 {\"status\": \"healthy\"}",". The chart's readiness and liveness probes.",[58,618,619,621,626],{},[76,620,606],{},[76,622,623],{},[18,624,625],{},"GET \u002Fhealthcheck\u002Fredis",[76,627,628,631,632,635],{},[18,629,630],{},"200",", or ",[18,633,634],{},"503"," when Valkey cannot be reached.",[58,637,638,641,645],{},[76,639,640],{},"Frontend",[76,642,643],{},[18,644,106],{},[76,646,647,648,651],{},"the sign-in page. ",[18,649,650],{},"\u002F"," redirects, so the probes ask for the page itself.",[14,653,654,655,657],{},"The workers and ",[18,656,452],{}," have no HTTP endpoint: watch them through the Queue page, the\nCelery exporter or the state of their pods.",[230,659,661],{"id":660},"logs","Logs",[14,663,664,665,668,669,672,673,676,677,326],{},"Every process writes its log to standard output at the ",[18,666,667],{},"INFO"," level: collect it with\nwhatever already collects your containers' logs. What a Script or Container node printed,\nand the engine's full traceback of a failed run, are kept with the run and shown on the\n",[23,670,671],{},"Runs"," page, then emptied after ",[18,674,675],{},"ORCHESTRATOR__LOG_RETENTION_DAYS"," (30 days by\ndefault; the run itself stays). The audit log is a different thing, kept in the\ndatabase and forwarded to a SIEM if you want: ",[221,678,224],{"href":223},[47,680,682],{"id":681},"docker-compose-everything-included","Docker Compose: everything included",[14,684,685,686,689],{},"The development stack in ",[18,687,688],{},"infrastructure\u002Fdocker-compose.yml"," runs:",[52,691,692,701],{},[55,693,694],{},[58,695,696,698],{},[61,697,571],{},[61,699,700],{},"Role",[71,702,703,713,742,752,762],{},[58,704,705,710],{},[76,706,707],{},[18,708,709],{},"victoriametrics",[76,711,712],{},"Prometheus-compatible store and scraper, every 15 seconds, 3 months of retention. No port on the host.",[58,714,715,720],{},[76,716,717],{},[18,718,719],{},"grafana",[76,721,722,723,727,728,731,732,735,736,731,739,741],{},"Dashboards on ",[221,724,725],{"href":725,"rel":726},"http:\u002F\u002Flocalhost:3001",[255],", user ",[18,729,730],{},"GRAFANA_ADMIN_USER"," \u002F ",[18,733,734],{},"GRAFANA_ADMIN_PASSWORD"," (",[18,737,738],{},"admin",[18,740,738],{}," by default).",[58,743,744,749],{},[76,745,746],{},[18,747,748],{},"celery-exporter",[76,750,751],{},"Celery task metrics, from the broker.",[58,753,754,759],{},[76,755,756],{},[18,757,758],{},"cadvisor",[76,760,761],{},"CPU, memory, disk and network per container.",[58,763,764,769],{},[76,765,766],{},[18,767,768],{},"node-exporter",[76,770,771],{},"The host: CPU, memory, disk, load. Also the source of the RAM badge.",[14,773,774,775,778,779,782,783,786],{},"The scrape targets are in ",[18,776,777],{},"infrastructure\u002Fmonitoring\u002Fscrape.yml","; Grafana's data source\nand the dashboard are provisioned from ",[18,780,781],{},"infrastructure\u002Fgrafana\u002F",". Grafana lets\nanonymous visitors view the dashboards (that is what lets the Monitoring page embed it\nwithout a second sign-in): the port is bound to ",[18,784,785],{},"127.0.0.1",", and if you open the stack\nto others, close it or put an authenticating proxy in front of it.",[47,788,790],{"id":789},"kubernetes-bring-your-own","Kubernetes: bring your own",[14,792,793,794,797],{},"The chart deploys no Prometheus, Grafana, exporter or ",[18,795,796],{},"ServiceMonitor",": a cluster usually\nruns its own. Two features of the interface depend on them and stay quiet without them:",[52,799,800,813],{},[55,801,802],{},[58,803,804,807,810],{},[61,805,806],{},"Feature",[61,808,809],{},"Without monitoring",[61,811,812],{},"To turn it on",[71,814,815,830],{},[58,816,817,819,822],{},[76,818,537],{},[76,820,821],{},"not shown",[76,823,824,827,828],{},[18,825,826],{},"monitoring.nodeExporterUrl",": your node-exporter's ",[18,829,20],{},[58,831,832,835,838],{},[76,833,834],{},"Monitoring page",[76,836,837],{},"an empty frame",[76,839,840,843],{},[18,841,842],{},"frontend.publicGrafanaUrl",": Grafana as the browser reaches it, with the dashboard imported (below)",[14,845,846],{},"To use the dashboard of the Compose stack in your Grafana:",[848,849,850,865,871],"ol",{},[485,851,852,853,856,857,860,861,864],{},"Import ",[18,854,855],{},"infrastructure\u002Fgrafana\u002Fdashboards\u002Fdataprep.json"," and keep its uid,\n",[18,858,859],{},"dataprep-overview",": the Monitoring page opens ",[18,862,863],{},"\u002Fd\u002Fdataprep-overview\u002F…"," on the Grafana\nyou set.",[485,866,867,868,870],{},"Its panels use a Prometheus-type data source with the uid ",[18,869,709],{},": give\nyour data source that uid, or replace it in the file before importing.",[485,872,873,874,877,878,881],{},"Allow embedding (",[18,875,876],{},"GF_SECURITY_ALLOW_EMBEDDING=true","), and make the dashboard visible\nto the people who open the page. The page frames only the site and\n",[18,879,880],{},"NUXT_PUBLIC_GRAFANA_URL",", through the frontend's Content-Security-Policy.",[14,883,884,885,888,889,892],{},"The memory panels match the container names of Compose and the Celery panels need a\nCelery exporter: on a cluster, edit them for your pod names, or deploy\n",[18,886,887],{},"danihodovic\u002Fcelery-exporter"," with ",[18,890,891],{},"CE_BROKER_URL"," pointing at the same Valkey or Redis\nas Tabularia.",[14,894,895,896,899,900,903,904,907,908,911,912,915],{},"If Grafana is served on the same host as Tabularia, a proxy with forward authentication\ncan let only administrators and observers through: the gateway's ",[18,897,898],{},"GET \u002Fauth\u002Fobserver","\n(under the API prefix, ",[18,901,902],{},"\u002Fapi\u002Fauth\u002Fobserver"," with the chart's ingress) answers ",[18,905,906],{},"204"," to\nthem, from the session cookie, and ",[18,909,910],{},"401"," or ",[18,913,914],{},"403"," to everyone else.",[47,917,919],{"id":918},"examples","Examples",[230,921,923],{"id":922},"scrape-the-engine-on-kubernetes","Scrape the engine on Kubernetes",[14,925,926,927,930],{},"A Prometheus job that finds the engine pods by their labels, assuming the release is\ninstalled in the namespace ",[18,928,929],{},"tabularia",":",[932,933,938],"pre",{"className":934,"code":935,"language":936,"meta":937,"style":937},"language-yaml shiki shiki-themes github-dark-dimmed github-light","scrape_configs:\n  - job_name: tabularia-engine\n    metrics_path: \u002Fmetrics\n    kubernetes_sd_configs:\n      - role: pod\n        namespaces:\n          names: [tabularia]\n    relabel_configs:\n      - source_labels: [__meta_kubernetes_pod_label_app_kubernetes_io_component]\n        regex: engine\n        action: keep\n      - source_labels: [__meta_kubernetes_pod_container_port_name]\n        regex: http\n        action: keep\n","yaml","",[18,939,940,953,969,980,988,1002,1010,1024,1032,1047,1058,1069,1083,1093],{"__ignoreMap":937},[941,942,945,949],"span",{"class":943,"line":944},"line",1,[941,946,948],{"class":947},"shb1k","scrape_configs",[941,950,952],{"class":951},"ssh_m",":\n",[941,954,956,959,962,965],{"class":943,"line":955},2,[941,957,958],{"class":951},"  - ",[941,960,961],{"class":947},"job_name",[941,963,964],{"class":951},": ",[941,966,968],{"class":967},"sXfbr","tabularia-engine\n",[941,970,972,975,977],{"class":943,"line":971},3,[941,973,974],{"class":947},"    metrics_path",[941,976,964],{"class":951},[941,978,979],{"class":967},"\u002Fmetrics\n",[941,981,983,986],{"class":943,"line":982},4,[941,984,985],{"class":947},"    kubernetes_sd_configs",[941,987,952],{"class":951},[941,989,991,994,997,999],{"class":943,"line":990},5,[941,992,993],{"class":951},"      - ",[941,995,996],{"class":947},"role",[941,998,964],{"class":951},[941,1000,1001],{"class":967},"pod\n",[941,1003,1005,1008],{"class":943,"line":1004},6,[941,1006,1007],{"class":947},"        namespaces",[941,1009,952],{"class":951},[941,1011,1013,1016,1019,1021],{"class":943,"line":1012},7,[941,1014,1015],{"class":947},"          names",[941,1017,1018],{"class":951},": [",[941,1020,929],{"class":967},[941,1022,1023],{"class":951},"]\n",[941,1025,1027,1030],{"class":943,"line":1026},8,[941,1028,1029],{"class":947},"    relabel_configs",[941,1031,952],{"class":951},[941,1033,1035,1037,1040,1042,1045],{"class":943,"line":1034},9,[941,1036,993],{"class":951},[941,1038,1039],{"class":947},"source_labels",[941,1041,1018],{"class":951},[941,1043,1044],{"class":967},"__meta_kubernetes_pod_label_app_kubernetes_io_component",[941,1046,1023],{"class":951},[941,1048,1050,1053,1055],{"class":943,"line":1049},10,[941,1051,1052],{"class":947},"        regex",[941,1054,964],{"class":951},[941,1056,1057],{"class":967},"engine\n",[941,1059,1061,1064,1066],{"class":943,"line":1060},11,[941,1062,1063],{"class":947},"        action",[941,1065,964],{"class":951},[941,1067,1068],{"class":967},"keep\n",[941,1070,1072,1074,1076,1078,1081],{"class":943,"line":1071},12,[941,1073,993],{"class":951},[941,1075,1039],{"class":947},[941,1077,1018],{"class":951},[941,1079,1080],{"class":967},"__meta_kubernetes_pod_container_port_name",[941,1082,1023],{"class":951},[941,1084,1086,1088,1090],{"class":943,"line":1085},13,[941,1087,1052],{"class":947},[941,1089,964],{"class":951},[941,1091,1092],{"class":967},"http\n",[941,1094,1096,1098,1100],{"class":943,"line":1095},14,[941,1097,1063],{"class":947},[941,1099,964],{"class":951},[941,1101,1068],{"class":967},[14,1103,1104,1105,1108,1109,930],{},"The chart's network policy (",[18,1106,1107],{},"networkPolicy.enabled",", on by default) lets only\nTabularia's own pods reach the engine. A Prometheus in another namespace needs a rule of\nits own, here for a namespace called ",[18,1110,12],{},[932,1112,1114],{"className":934,"code":1113,"language":936,"meta":937,"style":937},"apiVersion: networking.k8s.io\u002Fv1\nkind: NetworkPolicy\nmetadata:\n  name: tabularia-engine-metrics\n  namespace: tabularia\nspec:\n  podSelector:\n    matchLabels:\n      app.kubernetes.io\u002Fname: tabularia\n      app.kubernetes.io\u002Fcomponent: engine\n  policyTypes: [Ingress]\n  ingress:\n    - from:\n        - namespaceSelector:\n            matchLabels:\n              kubernetes.io\u002Fmetadata.name: monitoring\n      ports:\n        - protocol: TCP\n          port: 8000\n",[18,1115,1116,1126,1136,1143,1153,1163,1170,1177,1184,1193,1202,1214,1221,1231,1241,1249,1260,1268,1281],{"__ignoreMap":937},[941,1117,1118,1121,1123],{"class":943,"line":944},[941,1119,1120],{"class":947},"apiVersion",[941,1122,964],{"class":951},[941,1124,1125],{"class":967},"networking.k8s.io\u002Fv1\n",[941,1127,1128,1131,1133],{"class":943,"line":955},[941,1129,1130],{"class":947},"kind",[941,1132,964],{"class":951},[941,1134,1135],{"class":967},"NetworkPolicy\n",[941,1137,1138,1141],{"class":943,"line":971},[941,1139,1140],{"class":947},"metadata",[941,1142,952],{"class":951},[941,1144,1145,1148,1150],{"class":943,"line":982},[941,1146,1147],{"class":947},"  name",[941,1149,964],{"class":951},[941,1151,1152],{"class":967},"tabularia-engine-metrics\n",[941,1154,1155,1158,1160],{"class":943,"line":990},[941,1156,1157],{"class":947},"  namespace",[941,1159,964],{"class":951},[941,1161,1162],{"class":967},"tabularia\n",[941,1164,1165,1168],{"class":943,"line":1004},[941,1166,1167],{"class":947},"spec",[941,1169,952],{"class":951},[941,1171,1172,1175],{"class":943,"line":1012},[941,1173,1174],{"class":947},"  podSelector",[941,1176,952],{"class":951},[941,1178,1179,1182],{"class":943,"line":1026},[941,1180,1181],{"class":947},"    matchLabels",[941,1183,952],{"class":951},[941,1185,1186,1189,1191],{"class":943,"line":1034},[941,1187,1188],{"class":947},"      app.kubernetes.io\u002Fname",[941,1190,964],{"class":951},[941,1192,1162],{"class":967},[941,1194,1195,1198,1200],{"class":943,"line":1049},[941,1196,1197],{"class":947},"      app.kubernetes.io\u002Fcomponent",[941,1199,964],{"class":951},[941,1201,1057],{"class":967},[941,1203,1204,1207,1209,1212],{"class":943,"line":1060},[941,1205,1206],{"class":947},"  policyTypes",[941,1208,1018],{"class":951},[941,1210,1211],{"class":967},"Ingress",[941,1213,1023],{"class":951},[941,1215,1216,1219],{"class":943,"line":1071},[941,1217,1218],{"class":947},"  ingress",[941,1220,952],{"class":951},[941,1222,1223,1226,1229],{"class":943,"line":1085},[941,1224,1225],{"class":951},"    - ",[941,1227,1228],{"class":947},"from",[941,1230,952],{"class":951},[941,1232,1233,1236,1239],{"class":943,"line":1095},[941,1234,1235],{"class":951},"        - ",[941,1237,1238],{"class":947},"namespaceSelector",[941,1240,952],{"class":951},[941,1242,1244,1247],{"class":943,"line":1243},15,[941,1245,1246],{"class":947},"            matchLabels",[941,1248,952],{"class":951},[941,1250,1252,1255,1257],{"class":943,"line":1251},16,[941,1253,1254],{"class":947},"              kubernetes.io\u002Fmetadata.name",[941,1256,964],{"class":951},[941,1258,1259],{"class":967},"monitoring\n",[941,1261,1263,1266],{"class":943,"line":1262},17,[941,1264,1265],{"class":947},"      ports",[941,1267,952],{"class":951},[941,1269,1271,1273,1276,1278],{"class":943,"line":1270},18,[941,1272,1235],{"class":951},[941,1274,1275],{"class":947},"protocol",[941,1277,964],{"class":951},[941,1279,1280],{"class":967},"TCP\n",[941,1282,1284,1287,1289],{"class":943,"line":1283},19,[941,1285,1286],{"class":947},"          port",[941,1288,964],{"class":951},[941,1290,1292],{"class":1291},"swcJU","8000\n",[14,1294,1295,1296,1298],{},"The rule opens the engine's port, not only ",[18,1297,20],{},"; the engine still refuses every\nother path without the gateway's internal token.",[230,1300,1302],{"id":1301},"queries-and-alerts","Queries and alerts",[14,1304,1305,1306,1308],{},"Preview p95 by engine, in milliseconds (",[18,1307,441],{}," because every engine replica reports the\nsame totals):",[932,1310,1314],{"className":1311,"code":1312,"language":1313,"meta":937,"style":937},"language-promql shiki shiki-themes github-dark-dimmed github-light","histogram_quantile(0.95,\n  max by (le, engine) (rate(dataprep_preview_duration_ms_bucket{outcome=\"ok\"}[5m])))\n","promql",[18,1315,1316,1321],{"__ignoreMap":937},[941,1317,1318],{"class":943,"line":944},[941,1319,1320],{},"histogram_quantile(0.95,\n",[941,1322,1323],{"class":943,"line":955},[941,1324,1325],{},"  max by (le, engine) (rate(dataprep_preview_duration_ms_bucket{outcome=\"ok\"}[5m])))\n",[14,1327,1328],{},"Failed previews per minute, and the bucket's size by prefix:",[932,1330,1332],{"className":1311,"code":1331,"language":1313,"meta":937,"style":937},"max(rate(dataprep_preview_duration_ms_count{outcome=\"error\"}[5m])) * 60\nmax by (prefix) (dataprep_storage_bytes)\n",[18,1333,1334,1339],{"__ignoreMap":937},[941,1335,1336],{"class":943,"line":944},[941,1337,1338],{},"max(rate(dataprep_preview_duration_ms_count{outcome=\"error\"}[5m])) * 60\n",[941,1340,1341],{"class":943,"line":955},[941,1342,1343],{},"max by (prefix) (dataprep_storage_bytes)\n",[14,1345,1346],{},"Two alerting rules, for the engine going away and for previews slower than 10 seconds\nat the p95 for a quarter of an hour:",[932,1348,1350],{"className":934,"code":1349,"language":936,"meta":937,"style":937},"groups:\n  - name: tabularia\n    rules:\n      - alert: TabulariaEngineDown\n        expr: up{job=\"tabularia-engine\"} == 0\n        for: 2m\n        annotations:\n          summary: \"The Tabularia engine API is not answering its \u002Fmetrics\"\n      - alert: TabulariaSlowPreviews\n        expr: |\n          histogram_quantile(0.95,\n            max by (le, engine) (rate(dataprep_preview_duration_ms_bucket{outcome=\"ok\"}[10m]))) > 10000\n        for: 15m\n        annotations:\n          summary: \"Tabularia previews take more than 10 s at the p95\"\n",[18,1351,1352,1359,1370,1377,1389,1399,1409,1416,1426,1437,1447,1452,1457,1466,1472],{"__ignoreMap":937},[941,1353,1354,1357],{"class":943,"line":944},[941,1355,1356],{"class":947},"groups",[941,1358,952],{"class":951},[941,1360,1361,1363,1366,1368],{"class":943,"line":955},[941,1362,958],{"class":951},[941,1364,1365],{"class":947},"name",[941,1367,964],{"class":951},[941,1369,1162],{"class":967},[941,1371,1372,1375],{"class":943,"line":971},[941,1373,1374],{"class":947},"    rules",[941,1376,952],{"class":951},[941,1378,1379,1381,1384,1386],{"class":943,"line":982},[941,1380,993],{"class":951},[941,1382,1383],{"class":947},"alert",[941,1385,964],{"class":951},[941,1387,1388],{"class":967},"TabulariaEngineDown\n",[941,1390,1391,1394,1396],{"class":943,"line":990},[941,1392,1393],{"class":947},"        expr",[941,1395,964],{"class":951},[941,1397,1398],{"class":967},"up{job=\"tabularia-engine\"} == 0\n",[941,1400,1401,1404,1406],{"class":943,"line":1004},[941,1402,1403],{"class":947},"        for",[941,1405,964],{"class":951},[941,1407,1408],{"class":967},"2m\n",[941,1410,1411,1414],{"class":943,"line":1012},[941,1412,1413],{"class":947},"        annotations",[941,1415,952],{"class":951},[941,1417,1418,1421,1423],{"class":943,"line":1026},[941,1419,1420],{"class":947},"          summary",[941,1422,964],{"class":951},[941,1424,1425],{"class":967},"\"The Tabularia engine API is not answering its \u002Fmetrics\"\n",[941,1427,1428,1430,1432,1434],{"class":943,"line":1034},[941,1429,993],{"class":951},[941,1431,1383],{"class":947},[941,1433,964],{"class":951},[941,1435,1436],{"class":967},"TabulariaSlowPreviews\n",[941,1438,1439,1441,1443],{"class":943,"line":1049},[941,1440,1393],{"class":947},[941,1442,964],{"class":951},[941,1444,1446],{"class":1445},"s6PUj","|\n",[941,1448,1449],{"class":943,"line":1060},[941,1450,1451],{"class":967},"          histogram_quantile(0.95,\n",[941,1453,1454],{"class":943,"line":1071},[941,1455,1456],{"class":967},"            max by (le, engine) (rate(dataprep_preview_duration_ms_bucket{outcome=\"ok\"}[10m]))) > 10000\n",[941,1458,1459,1461,1463],{"class":943,"line":1085},[941,1460,1403],{"class":947},[941,1462,964],{"class":951},[941,1464,1465],{"class":967},"15m\n",[941,1467,1468,1470],{"class":943,"line":1095},[941,1469,1413],{"class":947},[941,1471,952],{"class":951},[941,1473,1474,1476,1478],{"class":943,"line":1243},[941,1475,1420],{"class":947},[941,1477,964],{"class":951},[941,1479,1480],{"class":967},"\"Tabularia previews take more than 10 s at the p95\"\n",[230,1482,1484],{"id":1483},"check-the-services-by-hand","Check the services by hand",[14,1486,1487],{},"From a container of the Compose network (on Kubernetes, the same paths on the release's\ngateway and engine Services):",[932,1489,1493],{"className":1490,"code":1491,"language":1492,"meta":937,"style":937},"language-bash shiki shiki-themes github-dark-dimmed github-light","curl -s http:\u002F\u002Fgateway:8000\u002Fhealth          # {\"status\":\"ok\"}\ncurl -s http:\u002F\u002Fbackend:8000\u002Fhealthcheck\u002F    # {\"status\":\"healthy\"}\ncurl -s http:\u002F\u002Fbackend:8000\u002Fmetrics | grep '^dataprep_storage_bytes'\n","bash",[18,1494,1495,1511,1523],{"__ignoreMap":937},[941,1496,1497,1501,1504,1507],{"class":943,"line":944},[941,1498,1500],{"class":1499},"sqRhv","curl",[941,1502,1503],{"class":1291}," -s",[941,1505,1506],{"class":967}," http:\u002F\u002Fgateway:8000\u002Fhealth",[941,1508,1510],{"class":1509},"sgHix","          # {\"status\":\"ok\"}\n",[941,1512,1513,1515,1517,1520],{"class":943,"line":955},[941,1514,1500],{"class":1499},[941,1516,1503],{"class":1291},[941,1518,1519],{"class":967}," http:\u002F\u002Fbackend:8000\u002Fhealthcheck\u002F",[941,1521,1522],{"class":1509},"    # {\"status\":\"healthy\"}\n",[941,1524,1525,1527,1529,1532,1535,1538],{"class":943,"line":971},[941,1526,1500],{"class":1499},[941,1528,1503],{"class":1291},[941,1530,1531],{"class":967}," http:\u002F\u002Fbackend:8000\u002Fmetrics",[941,1533,1534],{"class":1445}," |",[941,1536,1537],{"class":1499}," grep",[941,1539,1540],{"class":967}," '^dataprep_storage_bytes'\n",[47,1542,1544],{"id":1543},"permissions","Permissions",[482,1546,1547,1553,1562],{},[485,1548,1549,1550,1552],{},"The Monitoring, Performance, Queue and Cluster pages, and the Workers section, are\nshown to administrators and observers only, and the gateway refuses their data to\neveryone else. Observers read; stopping a job, changing the workers and the\n",[23,1551,126],{}," link are for administrators.",[485,1554,1555,1557,1558,1561],{},[18,1556,20],{}," and the health checks ask for no sign-in. In Compose the engine publishes\nno port on the host; on Kubernetes its Service is ",[18,1559,1560],{},"ClusterIP"," and the network policy\nlimits who reaches it. Keep it that way: the metrics name the engines, the request\npaths and the size of the bucket.",[485,1563,1564],{},"The RAM badge needs only a signed-in user: it is a health indicator, not data.",[47,1566,1568],{"id":1567},"limits","Limits",[482,1570,1571,1578,1586,1589,1600],{},[485,1572,1573,1574,1577],{},"The gateway exposes no metrics of its own; its health is ",[18,1575,1576],{},"\u002Fhealth",", and what it does\nis in the run history (Performance) and the audit log.",[485,1579,1580,1581,911,1583,326],{},"The chart ships no monitoring component, ",[18,1582,796],{},[18,1584,1585],{},"PodMonitor",[485,1587,1588],{},"The dashboard's container and Celery panels are written for the Compose stack.",[485,1590,1591,423,1593,1595,1596,1599],{},[18,1592,368],{},[18,1594,371],{}," only grow but are exposed as gauges:\n",[18,1597,1598],{},"rate()"," works on them; a Valkey that loses its data resets them.",[485,1601,1602,1603,1606],{},"The preview counters behind Performance and ",[18,1604,1605],{},"dataprep_preview_*"," live in Valkey: they\ncover every worker of the installation, and start again from zero if Valkey loses\nits data. For history over time, keep the scraped series in your metrics store.",[47,1608,1610],{"id":1609},"related","Related",[482,1612,1613,1619,1632,1638,1644],{},[485,1614,1615],{},[221,1616,1618],{"href":1617},"\u002Fdocs\u002Fintegrations","Integrations",[485,1620,1621,964,1625,268,1628,261,1630],{},[221,1622,1624],{"href":1623},"\u002Fdocs\u002Fconfiguration#monitoring","Configuration reference",[18,1626,1627],{},"MONITORING__*",[18,1629,456],{},[18,1631,880],{},[485,1633,1634],{},[221,1635,1637],{"href":1636},"\u002Fdocs\u002Fdeploy\u002Fkubernetes","Kubernetes and Helm",[485,1639,1640],{},[221,1641,1643],{"href":1642},"\u002Fdocs\u002Fengine-settings","Settings from the panel",[485,1645,1646],{},[221,1647,224],{"href":223},[1649,1650,1651],"style",{},"html pre.shiki code .shb1k, html code.shiki .shb1k{--shiki-default:#8DDB8C;--shiki-light:#22863A}html pre.shiki code .ssh_m, html code.shiki .ssh_m{--shiki-default:#ADBAC7;--shiki-light:#24292E}html pre.shiki code .sXfbr, html code.shiki .sXfbr{--shiki-default:#96D0FF;--shiki-light:#032F62}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html.light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html pre.shiki code .swcJU, html code.shiki .swcJU{--shiki-default:#6CB6FF;--shiki-light:#005CC5}html pre.shiki code .s6PUj, html code.shiki .s6PUj{--shiki-default:#F47067;--shiki-light:#D73A49}html pre.shiki code .sqRhv, html code.shiki .sqRhv{--shiki-default:#F69D50;--shiki-light:#6F42C1}html pre.shiki code .sgHix, html code.shiki .sgHix{--shiki-default:#768390;--shiki-light:#6A737D}",{"title":937,"searchDepth":955,"depth":971,"links":1653},[1654,1655,1662,1663,1664,1669,1670,1671],{"id":49,"depth":955,"text":50},{"id":227,"depth":955,"text":228,"children":1656},[1657,1658,1659,1660,1661],{"id":232,"depth":971,"text":233},{"id":460,"depth":971,"text":461},{"id":479,"depth":971,"text":480},{"id":562,"depth":971,"text":92},{"id":660,"depth":971,"text":661},{"id":681,"depth":955,"text":682},{"id":789,"depth":955,"text":790},{"id":918,"depth":955,"text":919,"children":1665},[1666,1667,1668],{"id":922,"depth":971,"text":923},{"id":1301,"depth":971,"text":1302},{"id":1483,"depth":971,"text":1484},{"id":1543,"depth":955,"text":1544},{"id":1567,"depth":955,"text":1568},{"id":1609,"depth":955,"text":1610},"Tabularia's engine publishes Prometheus metrics on \u002Fmetrics, every service answers a\nhealth check, and the Administration menu has the pages an operator watches: a\nGrafana dashboard under Monitoring, run and preview timings under Performance,\nthe live Queue, the Workers and, on Kubernetes, the Cluster. The Docker\nCompose development stack ships a complete monitoring stack; the Helm chart deploys\nnone, so that you point the monitoring you already run at Tabularia.","md",{"source":1675},"docs\u002Fintegrations\u002Fmonitoring.md",true,"\u002Fdocs\u002Fintegrations\u002Fmonitoring",{"title":5,"description":1672},"docs\u002Fintegrations\u002Fmonitoring","vKS-eDx2yuGx6znsSG1ju1bYsMTFyzvMZjFHmf5PIMY",[1682,1701,1757,1789,1821,1844,1868,1889],{"title":1683,"icon":1684,"intro":1685,"items":1686},"Getting started","start","Install it on one machine, learn the few ideas everything else is built on, and run a first flow.",[1687,1689,1692,1695,1698],{"path":1688,"title":1683},"\u002Fdocs\u002Fgetting-started",{"path":1690,"title":1691},"\u002Fdocs\u002Fgetting-started-docker-compose","Walkthrough with Docker Compose",{"path":1693,"title":1694},"\u002Fdocs\u002Fdeploy\u002Fminikube","Try it on your computer (minikube)",{"path":1696,"title":1697},"\u002Fdocs\u002Fconcepts","Concepts",{"path":1699,"title":1700},"\u002Fdocs\u002Foverview","Overview (README)",{"title":1702,"icon":1703,"intro":1704,"items":1705},"Capabilities","capabilities","What you can build: visual flows, analysis on any step, AI questions, pixel-perfect reports, dashboards, Python, R and SQL scripts, containers and the orchestration that ties them together.",[1706,1709,1712,1715,1718,1721,1724,1727,1730,1733,1736,1739,1742,1745,1748,1751,1754],{"path":1707,"title":1708},"\u002Fdocs\u002Fcapabilities","All capabilities",{"path":1710,"title":1711},"\u002Fdocs\u002Fcapabilities\u002Fflows","Low-code flows",{"path":1713,"title":1714},"\u002Fdocs\u002Fcapabilities\u002Fpreview-and-analysis","Preview and analysis",{"path":1716,"title":1717},"\u002Fdocs\u002Fcapabilities\u002Fask-your-data","Ask your data with AI",{"path":1719,"title":1720},"\u002Fdocs\u002Fcapabilities\u002Freports","Pixel-perfect reports",{"path":1722,"title":1723},"\u002Fdocs\u002Fcapabilities\u002Freport-functions","Report functions",{"path":1725,"title":1726},"\u002Fdocs\u002Fcapabilities\u002Fdashboards","Dashboards",{"path":1728,"title":1729},"\u002Fdocs\u002Fscripting","Python and R",{"path":1731,"title":1732},"\u002Fdocs\u002Fsql-scripts","SQL scripts",{"path":1734,"title":1735},"\u002Fdocs\u002Fcapabilities\u002Fnotebooks","marimo notebooks as apps",{"path":1737,"title":1738},"\u002Fdocs\u002Fcontainer-node","Docker images in flows",{"path":1740,"title":1741},"\u002Fdocs\u002Fcapabilities\u002Fflow-groups","Flow groups: orchestration",{"path":1743,"title":1744},"\u002Fdocs\u002Fcapabilities\u002Fscheduling","Scheduling",{"path":1746,"title":1747},"\u002Fdocs\u002Fpushmail","Pushmail: datasources, reports and dashboards by email",{"path":1749,"title":1750},"\u002Fdocs\u002Fplaceholders","Dynamic dates",{"path":1752,"title":1753},"\u002Fdocs\u002Fcapabilities\u002Fengines","Engines",{"path":1755,"title":1756},"\u002Fdocs\u002Fengines\u002Fengine-differences","Engine differences",{"title":1758,"icon":1759,"intro":1760,"items":1761},"Sources","sources","Every way data comes in: files, databases, buckets, SFTP folders, HTTP APIs, SharePoint, Google Sheets, and the results of your own flows.",[1762,1765,1768,1771,1774,1777,1780,1783,1786],{"path":1763,"title":1764},"\u002Fdocs\u002Fsources","All sources",{"path":1766,"title":1767},"\u002Fdocs\u002Fsources\u002Ffiles","Uploaded files",{"path":1769,"title":1770},"\u002Fdocs\u002Fsources\u002Fdatabases","Database tables and queries",{"path":1772,"title":1773},"\u002Fdocs\u002Fs3-datasource","S3 buckets",{"path":1775,"title":1776},"\u002Fdocs\u002Fsftp","SFTP folders",{"path":1778,"title":1779},"\u002Fdocs\u002Fapi-datasource","HTTP APIs",{"path":1781,"title":1782},"\u002Fdocs\u002Fsources\u002Fsharepoint","Excel on SharePoint",{"path":1784,"title":1785},"\u002Fdocs\u002Fsources\u002Fgoogle-sheets","Google Sheets",{"path":1787,"title":1788},"\u002Fdocs\u002Fsources\u002Fflow-outputs","Results of flows and scripts",{"title":1790,"icon":1791,"intro":1792,"items":1793},"Connections","connections","The systems Tabularia reads from and writes to, how each connection is set up, and who may use it.",[1794,1797,1800,1803,1806,1808,1809,1811,1812,1815,1818],{"path":1795,"title":1796},"\u002Fdocs\u002Fconnections","All connections",{"path":1798,"title":1799},"\u002Fdocs\u002Fconnections\u002Fdatabases","Databases",{"path":1801,"title":1802},"\u002Fdocs\u002Fsqlserver","Microsoft SQL Server driver",{"path":1804,"title":1805},"\u002Fdocs\u002Fconnections\u002Fs3","S3 and compatible storage",{"path":1775,"title":1807},"SFTP servers",{"path":1778,"title":1779},{"path":1781,"title":1810},"SharePoint",{"path":1784,"title":1785},{"path":1813,"title":1814},"\u002Fdocs\u002Fconnections\u002Fsmtp","SMTP email",{"path":1816,"title":1817},"\u002Fdocs\u002Fcontainer-registries","Container registries",{"path":1819,"title":1820},"\u002Fdocs\u002Fconnections\u002Fdestinations","Writing data out",{"title":1618,"icon":1822,"intro":1823,"items":1824},"integrations","How Tabularia fits your stack: AI providers, the REST API and webhooks, dbt, OpenLineage, single sign-on, SIEM and monitoring.",[1825,1827,1830,1833,1836,1839,1842,1843],{"path":1617,"title":1826},"All integrations",{"path":1828,"title":1829},"\u002Fdocs\u002Fintegrations\u002Fai","AI: where it is used",{"path":1831,"title":1832},"\u002Fdocs\u002Fapi","API, tokens and webhooks",{"path":1834,"title":1835},"\u002Fdocs\u002Fdbt-export","Export to dbt",{"path":1837,"title":1838},"\u002Fdocs\u002Fopenlineage","OpenLineage",{"path":1840,"title":1841},"\u002Fdocs\u002Fsso-keycloak","Single sign-on with Keycloak",{"path":223,"title":224},{"path":1677,"title":5},{"title":1845,"icon":1846,"intro":1847,"items":1848},"Security & governance","governance","Who may see and do what, what is recorded, and how data quality and personal data are kept in check.",[1849,1852,1854,1856,1859,1862,1865],{"path":1850,"title":1851},"\u002Fdocs\u002Fgovernance","Overview",{"path":1853,"title":1544},"\u002Fdocs\u002Fgovernance\u002Fpermissions",{"path":1855,"title":210},"\u002Fdocs\u002Fgovernance\u002Faudit-log",{"path":1857,"title":1858},"\u002Fdocs\u002Fgovernance\u002Fdata-contracts","Data contracts",{"path":1860,"title":1861},"\u002Fdocs\u002Fdesign\u002Fsso-group-mapping","SSO and group mapping",{"path":1863,"title":1864},"\u002Fdocs\u002Fexamples\u002Fkeycloak","Keycloak example on a laptop",{"path":1866,"title":1867},"\u002Fdocs\u002Fengines\u002Fclickhouse-ai-user","A ClickHouse user for the AI assistant",{"title":1869,"icon":1870,"intro":1871,"items":1872},"Install & operate","operate","Run it in production on Kubernetes, configure it, upgrade it and keep it healthy.",[1873,1874,1877,1880,1883,1885,1886],{"path":1636,"title":1637},{"path":1875,"title":1876},"\u002Fdocs\u002Fdeploy\u002Fkind","A company-like cluster on one computer (kind)",{"path":1878,"title":1879},"\u002Fdocs\u002Fdeploy\u002Fupgrading","Upgrading, backups and restore",{"path":1881,"title":1882},"\u002Fdocs\u002Fdeploy\u002Frelease-checklist","Install and upgrade checklist",{"path":1884,"title":1624},"\u002Fdocs\u002Fconfiguration",{"path":1642,"title":1643},{"path":1887,"title":1888},"\u002Fdocs\u002Fdatabase-migrations","Database migrations",{"title":1890,"icon":1891,"intro":1892,"items":1893},"Reference","reference","Release process and the remaining reference pages.",[1894],{"path":1895,"title":1896},"\u002Fdocs\u002Frelease-process","Release process",1793656372120]