From d88d472b1315497f0b7e0a005c2448a5f3d706fc Mon Sep 17 00:00:00 2001 From: iameskild Date: Wed, 25 Oct 2023 07:26:36 -0700 Subject: [PATCH 1/2] Clean up main branch, removing lingering directories --- .github/workflows/kubernetes_test.yaml | 20 +- .../source/images/argo-workflows-user-tab.png | Bin 102104 -> 0 bytes docs/source/user_guide/argo_workflows.md | 32 - .../dashboards/Main/cluster_information.json | 978 -------- .../dashboards/Main/conda_store.json | 721 ------ .../dashboards/Main/jupyterhub_dashboard.json | 1350 ---------- .../monitoring/dashboards/Main/keycloak.json | 2165 ----------------- .../monitoring/dashboards/Main/traefik.json | 1254 ---------- .../dashboards/Main/usage_report.json | 296 --- 9 files changed, 9 insertions(+), 6807 deletions(-) delete mode 100644 docs/source/images/argo-workflows-user-tab.png delete mode 100644 docs/source/user_guide/argo_workflows.md delete mode 100644 nebari/template/stages/07-kubernetes-services/modules/kubernetes/services/monitoring/dashboards/Main/cluster_information.json delete mode 100644 nebari/template/stages/07-kubernetes-services/modules/kubernetes/services/monitoring/dashboards/Main/conda_store.json delete mode 100644 nebari/template/stages/07-kubernetes-services/modules/kubernetes/services/monitoring/dashboards/Main/jupyterhub_dashboard.json delete mode 100644 nebari/template/stages/07-kubernetes-services/modules/kubernetes/services/monitoring/dashboards/Main/keycloak.json delete mode 100644 nebari/template/stages/07-kubernetes-services/modules/kubernetes/services/monitoring/dashboards/Main/traefik.json delete mode 100644 nebari/template/stages/07-kubernetes-services/modules/kubernetes/services/monitoring/dashboards/Main/usage_report.json diff --git a/.github/workflows/kubernetes_test.yaml b/.github/workflows/kubernetes_test.yaml index 1e0843cff0..ce34caa6c2 100644 --- a/.github/workflows/kubernetes_test.yaml +++ b/.github/workflows/kubernetes_test.yaml @@ -5,12 +5,11 @@ on: paths: - ".github/workflows/kubernetes_test.yaml" - "tests/**" - - "tests_deployment/**" - - "tests_e2e/**" - "scripts/**" - "src/**" - "pyproject.toml" - "pytest.ini" + - ".cirun.yml" push: branches: - main @@ -19,12 +18,11 @@ on: paths: - ".github/workflows/kubernetes_test.yaml" - "tests/**" - - "tests_deployment/**" - - "tests_e2e/**" - "scripts/**" - "src/**" - "pyproject.toml" - "pytest.ini" + - ".cirun.yml" workflow_call: inputs: pr_number: @@ -148,14 +146,14 @@ jobs: env: CYPRESS_BASE_URL: https://github-actions.nebari.dev/ with: - working-directory: tests_e2e + working-directory: tests/tests_e2e - name: Playwright Tests env: KEYCLOAK_USERNAME: ${{ env.CYPRESS_EXAMPLE_USER_NAME }} KEYCLOAK_PASSWORD: ${{ env.CYPRESS_EXAMPLE_USER_PASSWORD }} NEBARI_FULL_URL: https://github-actions.nebari.dev/ - working-directory: tests_e2e/playwright + working-directory: tests/tests_e2e/playwright run: | # create environment file envsubst < .env.tpl > .env @@ -168,15 +166,15 @@ jobs: with: name: e2e-cypress path: | - ./tests_e2e/cypress/screenshots/ - ./tests_e2e/cypress/videos/ - ./tests_e2e/playwright/videos/ + ./tests/tests_e2e/cypress/screenshots/ + ./tests/tests_e2e/cypress/videos/ + ./tests/tests_e2e/playwright/videos/ - name: Deployment Pytests run: | export KEYCLOAK_USERNAME=${CYPRESS_EXAMPLE_USER_NAME} export KEYCLOAK_PASSWORD=${CYPRESS_EXAMPLE_USER_PASSWORD} - pytest tests_deployment/ -v -s + pytest tests/tests_deployment/ -v -s - name: JupyterHub Notebook Tests timeout-minutes: 2 @@ -191,7 +189,7 @@ jobs: --validate --no-verify-ssl \ --kernel python3 \ --stop-server \ - --notebook tests_deployment/assets/notebook/simple.ipynb \ + --notebook tests/tests_deployment/assets/notebook/simple.ipynb \ ### CLEANUP AFTER TESTS - name: Cleanup nebari deployment diff --git a/docs/source/images/argo-workflows-user-tab.png b/docs/source/images/argo-workflows-user-tab.png deleted file mode 100644 index ac2a5df13cb12438e760ac7d627c97eca73f0469..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 102104 zcmYJaby!=?^FAD`K!M^`ytrF&hvE*!wMcPyr_fT|U0d8e3GOZd8r!F8TOkYb=YLjwyU~rlm*Ar%p5pXD$RL%c(Mawzp2w zY(#Ee4QDKl2(L^rxVftkjA=r@KP+XeOi9uh2bNWlwkyziPgej+ zN~GD$9vnG|sV_*$$KRy!U#V(4Pp9IvfMoJ<@;z;D5`R6Mt!cQGIf55MdK3Ijl$-#S zRKWdEd?x}!9Esw)ehY8N7b;m30-DFi4?16UG~=mMabVbvAorcv|J{$3N2Zm<3OqHP zm8>P6woCgvDAuweg75v1tK087iP!&Nh_hHPN)n+Zc{hyneR%zfM1c=HAp@Fsa2RW| zF%i5$g$sSQ#sf4cffu+DX<|x?NQ3h=?T*TNk|vx_;MyQ%n7K3cq#0ceq?QPct2<-(P|3BgT0j z>1cX}#UpWos5nd-5Qb!&({w2$$`yh}PNd5WY@goQ(*`}m9F>{Q!oQuv`YW7pR`h&G z&Q0sc*~l+#_kn7aND4X$0L3>n8HLR&ov^qvUPJasBEipJ9k7(S!-{kXWuBJsdu@>a zlUb(yzrj~+BXnGc7zt*?#|gua<>YJz^I1YO_=JP~-ydy5Ep&RT;T!GQpsosnbMO?r zzn=cii}8oH@}-Q!I?Hy}Jm^bt3fi4{=d%MH42&jD>aSlKC7UV3n?outBthT4?Ii!( z@#0y3cOUb~V6(#fz|PfeahNn-nSxF8S{S!XT*5(Glt$c091(Fmp7^z`r_^>SYf7%z(&%spJ z6wnUmy7!ba7O#1)C~kWgchV-XCWsqPg(vgX_o6Xj!z{Zq@>gI_H3lL3Dt;B-k~+bT zH;p@w>o@zFFETKimnEAF-PN%-IKHIe^Z%53QdKoK;E5nGyE{V%R~wtTF(PG}(CxLJ zC=ajw#wzj#rgxB?-MZipdA9Ypei)hZ$Sp4`N6~>qaT@w!^8yoY8URSX78N%3Hnp=> zU7|-+DEFhG6)DF*lMT>6VOP~Gz%@nnm%^b)GeJc8tf2wAS+68@rI+^ zAZYxsc_WGx2s2#s`xjM0{uiW2ed}kX_3JMx;5+x=$ju#IAO!H!;Jnf2Sa*MuiP+M3 zCt&O4sa8vqr7`y@Y5dv3;zjm((x<)c-iP)%#=^mq(!bXy0%{(&0zSEg!UZh444p$Y zSVy@1PFgYlTiaz9IN)g&==t)pJ)-IAeRZH%3cIpz5l}0N08f%*yKvVJC*5v+1`djd z3Cr@H;u=0@!Xpjbh+%ENE29*`n$nhg<_RcmH-RMN*zZo3sxy2{lcjHOvO7QgBGk8p zb>M&1j1IC`y3%OFTn^_`_P>|4-M%(jiCv0g47kcP7Z|w_IyK=?X*8eJn~GXeQ_%^} z9?gNko@$-28nhJ^Uh3U|#pvAbOOh`U9Y!+WFZdO;O4*qc3s^demSD{OlKRbNSud^R ziyu!F@?{gFD$a{$Sf9z%m;eu;O*pS^LJ$(i9#78R;Yc4#n^j*kL^IG#&03vX9P{NU z_)|OW`ZH@<@zL*AA6RI>%^;lCWh=vfPCC#?ooN4T44Jv#0>4~7sd`iUav!uONo z&*041X+H&=mWZik95tK*(Z_(g6dfxIdj=>G7Vel;r4#Zfe48%JJ4s30eyX|dEpQ<{ zoX-~)BGMU?4$+dipCzZ1Lp1@ucVJt+yze?Vm{VyR=>)`&Q8(!lCP}$weWII;W9iPN zoaPr3yka-WARsk>;uEN@ZaG(EJ7wX(J!gA$c`&ip^rj-4tqVP-KVSQY; zp;y2hB4UvU2V~L898WbQev8+?fzQiQ`~$C4UoC&q{MuPa^9MFm(?Cb+1GvCnMuJXE zu7^Z>X4pN~h0JiSZ-J#0g`IgO`Sw0A-Jwh&(ZpOPlejG{;4k)L70Fpu<<2YDLq24< zZQ!#Tb=a3#7rO82KF^OC?HkuxD-V`O3ykMVmA=~!Kg9#}qt9#AFASfkOq%fko_y)< zj{?Ujtb*YErI%)j*>eaeA@9W3e(vi1MY)BrCwIVjbjr&P_ECI$%hSX>SZj&?MOdeE!gZ9UI)0uF% z!MDv3nw*p$rx2JxCHtKUwzWs20Ms5ApOey)?W0d<*8^GgJkBa*;Th-tXu{#48H&Hl-r3M<(aPw< zLDATA-uACL`R;nB74IoiR@Zwyr={ubfw0C5Er+{(dAmP{`OhOxWvSi^n|wt>$@btI z0kD0>QdML`-KD1l9}@)j=TS2Yt8*w8qq&aeZxtv1n9L2rP;nX55b-q+J{d~!Z?Qdc zOo+&lRBYt~j#;okEOIf_8e?-~?a<%9O=L#HA=y4_=1jB+jGxODra93`Bo?wsev_&{ zgyfBs9wb*FwY+p%unOK5y#Z3+?A*L?@Ej*H&Ys3>L0=|7CgkK}b_f7VU~ulEW_gzW z@BPWL26-W;97hDis6$Ia8?@j>v`S8XyuV2XXQ8a`<4y$W4ZmE4o6$7slk*B_D}((h zd0{2T`f%5#`6-#jNR<&-^gvtgbuxu!(;WdDv{;Qf$jZ`G6B7+0`Ap9WDR1*WDyk}4 zIWq>+)y$rjt+bw&K?F#+8t*%CLII9Vbv;&{*@HJlerSBO*gYzG4)8MA2wKsa6huNv zB>9N>u}{t8adI?{@mmFs5})6SC4R0QX4%0SS@j$|Ak^@o1NUmsL48t%--qmk+g6L6 z@Sj%@Y1M<7+6BH|^eM5!1`1l8FTFUNFCop|JReP17(Ua&fs^gu{WnxAo8vg z^b}kM_J4k!@?d%gR={~LpGl#64s~eW05akNe6I>zma8(d12%$F(0=*haBhd-x9hgv zb_YXG_U5(Cqhek@yhJN0Qc_n%{T$)=yjEsYjHk}g98G=j04jJNBCy_6IFUmg7AV7XSo7u1w2Vmfm(z>Dm;)~d%gZ+WY6d##qnp?d zl)yzc1_(Kv_&|EBlXZUx$qJ0YN%x*`R;*{d=?7W0%sIvys7@!q9Hv<6_&O^3d_t<3vO zbjA-p!)Qe{Lbb%jq`76Ws+bwB&`%S=%6)ay9J`Q?cJbCu{Q~h|nWLv~duQjs#U5`z z=KDLpLGf7ez@cAlckW+r&70dEo%^qkyu7^9(q>Svn*y$%GZym2@aY^G$y#q;{EKw2 zu3r|Py1-&RedY%3r&mUcW&p=tMUPY??Y2{kA^_cb?XlM?$a7$W?6&(%r2X`C%n)-` zi)y*$HYIQC_Bm=nOr7-B;Ayz((PV;=_!pST`#!t;SR(gtp5rUhU1jKQ-b+H}PjE8Y zxWOR=d(GOu2s|`eBtfYH0mcuU9-)X@4@%ocLVgYYZ14+b^HX{ZO7F(9moQvq8-?f4nD(ZfkFK1yY^?bIjcr=x5kR@aCJrxlgkFa=BDas3>e4vQ1L1jI@h% z?6!7xM<)R<5B2r+llApAT1L!dS;r-JZ{y`rYicp`8Zc#P_4GvO8N83KX11K~b|>-VAPou=AT0@hqn{9gj{O!v*LHkj*r*0n4_e}ymZS1#Ah}q4@-|Shf|Li<985^dg zY&I&N3`HfLUn$!+3%7i<9`reJYstLo@gV~MD)m6eP1k01$G)}X;-vpsnm7b+^ibeL zyWMVvOl0NOJ7T4uk*Pbu-|gfmM(-n_BO_Vl7Td*XZ~uzyxpe9T4xbF$XDKNGyb^C^ z74w_h|Hdc0tHt0pz&4yJUKk$y5 z4HcV=EGH*Ngh|-HVGur$5GUA?SJOn>kBLC4KrL!;BvaVW`(8tf9_Q_;V4hm3s{$|?_CSRPpi=%gRE(#hPa4_- zFUDtO3H2Dq4sYeoFlRY`WS3|nb}m|V920bHakd(fmHMX|dXVYuY<2WjGz1vCiU!Y1 z$e1$t>DPCn%_Wd(JXQ9NB8|GfKJjpE?l9r)j6cmL0$d2T#1;4NYa#%Dmc5xtu2de( zD&vwrFCFO@Tmz4>>Z6I-Y_HwWNq0kNpv*_+_! zU%#}g8uq;!f z^c`GDxCL9c*P3a3!YWnUx}M4djkC(7m3K0 z>oeFyo3Q9euq$1`q@Kc1^C8O2A-3ljyYdGmu+x~00QLUq*_cgROUt7&{M%pD{CMiL zl>6Ht`z_3%S3D6`e~oQfKc}r@r0#E|@8YC{U@4o1^a}ipHkgjGj)8G%!Z#ea+CRvf z_9ZP^BfGyE*d`U@6+p_^T6&!AQ#M^FhssT}1eVnPPqb)>qE5sQsPNnFL%PaCXu(3? zeqAj{8L=UW#;?K-I~(Vr&vdXEn;9<@>0cn#s?4<2GIjhU$gGdZR#(Uuy!55|tB-tq zrVnoQLPDZq9dP}~k}8{>O;7$}INcQrJWWc?zf^)Zlts+72bxDRx8t-+F35oZ)>>z< zG{3n;j|!O=FJtikP_Mj!5%!T>{BHfQ(tHvu)aw@u*=($9Q{!G335$V0mw+og4ug~c zL5jg1iTz$?B%-afk?tE*+M1!j@5wZSOLn;^e*vyIL`CFl;Hgh9c0cahq++Odql)L} zY77Ea0_OR9LIReEIkKho$i$TPhSG0hl2@e+tLzzI3)Zs|mjspCc z+h5iH*QAm7IF~X&YWYU4vXz=OXT|Z&`hVzJYGdJL;RTI>mNu!SOV=K6m&1nBamYkQ z{0^J*rUaO-9%6A8;)0}2y4xvCsf#7bTYwt2{2_r=H%~#{|08ew50>kr7Rxl^srr#a zl1hHk)>!}0q6rNIt6PM4R(v=X0i^`A>#12k89H36+!;WXJYi_sDyaF^*zO=XX=6 zZC;ZqdDoZarov&E)Kb*W;TXf*JfSO7^4aPZ52Al%9*7~qC$%jzii!Qy?_oRMpB1j& z-~TP{lcAZpU5#F_Zrke68gpLcd&5F?$1Kx|PK-nf!>#MQz0}$H5qLODvdywFX_eLg zxez+O9mbqxOzr}5d&(IQwFxzsPL3lkt|l__3xU+&V2G8us9wV7*DymROQA}^cHYN7 zc$_S#6l!B=ohOI$k~~? zT}D(KB1Vo-VAR?-fH=T^G#gykyN})svhk5(rMi7}Ov8gzjS6Z51krH-dMY_F)wkhl zGKmB-#FT^P<>Gy{<&yO3wQ$js|IbOtc*awU!_EJ2Ew=o&mW3s_r3OT%TXc9BL0Lc0 z$psTg#pe&QpXZT&NugZDcr&hK&QGX9^EZSK#9+LRr9&y!@x9FQ_!K)z_WS$?6@Yly z5tY)$As`$JHWvqnI)>be_i>o|v5pS|gW8^)Lc634#ytL?_amY4S|8xmKrufLeP8(e z7O?h;2`zaC<`+O8^3}yuSxj4UaWD#|f8C->|C*yU2_&(gx0e5_zxx=82L)p|Zyah* z@pyPo39MmqDlrOEeyLhCS;sfjaKpFa@kWWh6!cVCgNEb4X1lUsm*3%Gf2Y-d)UKCS zL%gJuJN-c(8qY)ZgQ@|6oi6*BlU&XbIUfFXs0h`aB>kjYLolb${{;by_ds(3Wf@et zQ>6GzbNwKkXRlPP*w4h+@vEreSZ0P|Z$nQ*@?$;mazV7pS+bL_JS{s;lkcZT9VV{7 zj_Vvp_p)8B&$8o{oiqqxvqlMo!Nw?X1jB>Lf8>FZqR9hesj{%BWP`L&J^G&7&UF8e zE)#ZwTM}h9Rj^Lep&Sn1(t9)s=E12-Y+T3#Eu=pZ279RnG1AF)Ah#DAr+pNfd0$nX zjkPaGVG;XAfc&pJ`ZCc zgucg-i2oRB+GdZ|cN&RQ%qK-_AtWx-kv1ab{u>VLzwm9T_rb=Fme?>(y|<@OyKhUm zwr7ylvhc4;WM~&fEf8GbC5@1TVGMDJ7%gy_>gwhK7O~^mEl)!-#cH+_*|?MOKiQVw z^fKyDM@TsoPtcOygp-QB&Dygy!*{jR3mBc|3YfF_2}xw1#u~oMc&C+gLSJfiE#xF! zxYlLJEZPG2c+stRjx^9-#$-C*%FD{T?aK~l*^nS% z-3uEfvg3*OLsZv&{+;p&8Mvf4xN)&LeKh4>^(WPBBl3>WTeNsZOJ7@8@8nXV zgr`V3GslL#x|r2#=guHHvQZwt2(5whpL-QBi%)Wwr_4~VepW#Zi_A`Gp(t6VH3TBu60U&WI<6^l7$bC0~7jsq9rB zt6J?g)y2+M>|eX_4}~~#*IrzNq6o5yH_x(j_G`3gS~F`m7BVoiC%f@*O;61d#}Y{s zcz;(lP3X^%w*%F7so6m=X1=l78bV?d(n1M-ev^Q%1@|U}-}Y4vH*?t$q2u{~Y4Dd( zcPbzn%8!i81e-wXGKjF8oi7rAO#~Hhk%n*ujaS-BR(~xB+I5bo?i`%{TMRjGW|UVK zWWp3IhQ&e*$!uPoplAjkR+R`=&!8ybn<@-Kh6a_CCtx74+!|s;(=yvNXk1tjO00t*sZG-)y|< z)w}k4^bPA^yh650z*m-sUv&e`z9;6-aeM={`xpJ^Q_nW~jZSxMd!$uysAb>23GOr= zKe<5+?j$KNw{ZL(PZjoie2a2@%zG}21X7F3dQwll^W@a_gP-W{15iKT@%-F!<{P^x zSLj>+5DK}zyQL(*Y<>G5azom~UASRbvQ*!Byk@l#o^RUQP_)q$euCE2OlU^7Up1nO zF#DSMPBvO@(R;L9It^yr6u#p{|6dNkHvXJGk1U^^M%I26aPlDOC4bmJ{Q^Ebll+O_ z-mtP@+Kb6adME4rYv+Juv*aRxPiPs}QPOBjS}f&i_r=U$SK*(CZ*!&XenM`a`cFih z6@5my?2k`G{9nGY`woA*(R|!%JwFLl8Gb%O%($e)1`2_as3BgSq{99WImebI!^|QN zTbq41(=+gGHxz%LhXH#zUH?>RCf#_Qj-0jzvU|)wU{-7nXH?QWnXTV(1O(~_cpaB# z&ZY-E))g!ypQ~Q@XOU^&+;8_;S`GIzc{~1@2%3@C6}Q+R|Ce#@0jnx(ZmxsRo%jfy zMU#2G*0=iGZZ{nps2Q3cD`&v=_ou8k>5MD)&_Yv#jH2_zM)d8h`-g)iBN4?6ud!f0 zw=%8c-DR48h-q`Ah6E1NHRC4Y3&G8D{8OzBZKMWU*o-pqSq_OnG_aNEUb*wn-fQ8& z+rRm`Qbf?t#kZ&e$Le(hTep_9B8cV@d3LkguG1yaV@kZY#+sEt=D+*>DYt+A6+d>_ zNr?7||0&#K<+}BoG_Af%uLs|mMvkorix^&x+X3(#F5{Xw!Et|AWX9pid)uL|a#O?( z^*eYy!G$KZe%{AW#|0hGC{@+FaYAkHzhC1~Hm{aqVd$Y~%k)yl^YRYhT%n2Wef$)6 zB6KbCBZ{KrV!7KfPC@1$;$-pGuTrOle+HW7yl8<(Zur!^6Gk<5%B%BEO~C@!4OFt? z#r78{V|M+Q<|n?jdmCLVW6;NoB>d@T=^!Te#mwd%v;G?em^E|vQ!X%Tx{z??L$fHW zPf;=RKmQP+5fFF~-=W};jsK*I15bg0bo=xyO73W-RR1rvYx@boK61`7&0Vtx2=O$K zSKS=C{<|Z?+F&oFljmmJN?!G|dBGhu>0dH0!>avh|JvJ$sJ+Jed8fF~+@y%g2X}0<-iDz23-GKwny?B?W>aZODp}mt3|MSTkXWg;ib*|iF zx_0f_2F3f{&yO8d2Pak?;2)NdVK={I=L4bY<1-EO>$*5f=dUeSxaMdp54n^U$UeV0 zPbDxiuEx8)2+vQll*)h&lV3$pZuFhme?#xPyVB2(bzC2cQL@mSqqm1v@UKaN5qc*Q zo@32}zR~94Hf+yiPO6xk9Gi)`@a(xBW=|@fBshT2UiuD$y1$PyUVx{^7pEW09cSfT znSK|KPEu{^`w$6%nMCaaxYbT-GbKGXdR6La+%~nt(Q5dE{Y-nXdfLZ}Yb!#2(cLom zt8c_@uZm-LC+>D{hDWm-IrNw(R^dF0H^cr?aht3hM)J>uLKR|b`rlS<%hdmSq1l=aWG?HPU=_ZFHz ztYUZdLP$F&dMl8SmG&&%V7kb1kq7BoOpK)GfPShyVPY9&RtT^Bo|28~k ztr)lh+JScYxm^P$yP-Rf)XdU|dUfhjVQ;qx4uL5R8=*ar4~`CaB$ZE>GjKut@{gYS z{3=4wc)r<+ph)-Gmz@J$qP0)10(4mwVA#VCa`rx-nOCkgP7;fjo-9G6fbUJfDx9@x zpPdX6A^F>S8Mi(k)8+B)bDA6|u3Q7R!xvCojBDO%Z%Efn`1i>Cz9+7xMIZd4 zn_>rMbH?Rz`RsgNH9Ii)exuf<3jduwnE$YX;v#kMix(nSS87N-FXSDM!P1>L1=l6V89PMv#!J?bppih z+)mrdE_Eg!R`@99hq>|X1UI*V_lY(M#Jyay@_5TQ3m%OI@eR)-@a|v8x>=T$z)Tp$ zb>S$s*XHMA*5Oy&DK&iBvFrT_#ix-T zl}rGx-Aj51<3`*Y9BASs6*6bpMiaz2(CewM58U3h-qApOif`}W#EAj3;DB4Jty4nf z<+Ng~bP>i|W4DsCu*1ubpyEZEd>WU)yq0-;B`|?LF5`?=*##bxGBgipvQ?@m*?pWf zH?iwX%5*#Mp2uS?UiB?+8H%PI1F`dpI7)xF>hv$KbqKqntnKS{l#c<|H|u@%gz|ayHWb`A4lLMxOLw0^Flat6=h<+B0G0NlhTZ(F zFzLSjnrH(Xl(!yKg%FwS91AOvitD2?ZyZx^HDB2*#etF4!)epEE(#KgoN9{IBv#{T zb!ct-QyJE-b$HAq6-d)bf=1PLGrI`tl%KOhkLKwtpc*xWJA88B-Dh2cy*e}cg+C*y zCa9zgx~=^=4;MZzA&!v!T-*Z?wP0q-eB3RcNCxIGXV^i@R9NfS2@)B3`gOqLzCTrD z63jIT5oj(x;C!Juvc-4>=svoSwc&7qMVTq*CYS7G;beZHkbo)b_hX9B+Bg0E)tUz- z?&ssJ?wQ9j2y!q)U5k-m;}DITLMX|mk}o7t-}F?)={uGw-?Ekk?vCKucUjy$Hp=O- z?-0E(G$Iu5X`W8aTB``gi<+Nx>%71H`_r{}4i$Ad*ehSS)@%)CFi{?p>vXV#eu65N z$3|OsexqhJTSL=5B2bmbc#gtdlRIK$bQGW3m_J!-z-8}8 zQAd|k-zY~R=$4^?r?ok0-J2>A7N(JCKY%X8B$+zChxWhUqH(v>8!JspvS%u-p0BGz z6&=?!7%XJ^*o{~6eStAxlRpnG=!*LxQGl#9N#bI8N6W8?(rZm|NQUPvc7NURx%ZPq z%pw{7*$Uk|B;u+aJQjm|^w*u&)b80~)^3tHsaU*p9Td~s-h|i7H`xgkH85X=6nGHc ziXP3+gomRSu@WCGHy7l)_p}rpv!9XLbPnY*%k-m`r!5uIpLhqVd7*>=L~R<$WWH-@R;W7L7h z*-kf5kpLydP>MxU5HRwco8`aj0Qsx`Cz#%Dn8{6xn4r6o>&D&fZd}h=2;v zxs=59_fNP0NNNIK%UESu+;%0&z$7{1E$-AY0$ z!WOZuvtpiG8xMuVbA^{ZjyVAU7Hu3;9k43-g{dw5F*7JnjNj~gw$n}hU94;00W1dE ztUYf-ATdLJ`*91kZh(dc)iC~)1(qPPeAVXtYtnK%XXK`d1pFPHd2yoL*2_G_hYjZx z1$Ifavij*MUPZ#aH>9hIIvdiU)=aiN$QDX}zZ0NLS#i=Q>zKu$>;s;uf=Ml?u@J^_ zYU*tmUmh-Z2Aqk@C_4-F98!V#n&}OMtOC$Mn<_o9n_|rx+~#`U*8=*5p~l*| zSgz>-xK-4Rs`tnBQ{0lz>)LTn=D8Ot8m&m7qvk(-t+c2;eDx)n=#u6Hb4xmD$UW;J z!h)PWj<11ewY<(7OI_MAPCgPr+fP?&)15hYa*Rb!vfRPMrEw~Y`$6ff@&rz_xNi5E&vwyCP*N{MwM^(!g&CNKML*Drq=z{Xsqzb@?Pox^TKccZFOY`-HB=tB3sa2xCTr{nCl6o1 z26e`90L`iCv_DPQV(m#;f%6P788+xtEnt9=Vb^cm#-W2Kn#Icnot3|H9o5{N971m# zHT{D|{OjWub5p<|(7S5XdWyzKL=L7S)@vaFT|s{9jbnu*U$Xx$aPdO`9sn>>l6bQcS_8Q{Jct|O*ud5Yf@=b-n(;!{K}l^UVANEkeA(f0|0UbO_Y@#&ZQ8ey6gD^`3emX*JR>b zT=8r=5xDbPUloQ0;b5H~{F!b2TR0gJTCFv$cG9p#(Qe^vMYIBdxORic9hPL{$?`G%h(NWO?0~FvY~4pOy3V1=A<&Dt7j-|vW2b+zsE2To z@^4Mhk}DrD*KTm8y3EsK&WVSY5Z1oP5;pLAn7l=j-}TgS5;b!t!NnENvLloZAuu_3 zK^P~NO_HpF0u~^glcKRZ|1N@a_v0yyXmz9aaC9&iZKn%TlWvei^D^ZJ{5Hm~p_(n_Pafi(fRSwI&8|xTcV3FcgC=PXI)mZ^j5Vq*Z`W2N zRExMu(^0scc8KM6^Rm9eD3MD^38QQXPWD1N>$xXdU!|!B#~`gjb$p7u-^g7;?x2&4 z`=^%2qOc&nB+F+hMs`g;I+K{t>d>pY3(dHLjIo6hkVJ(_=SkRk^B)&)18L^dI!$c& z7}k6a&`GpMpq> zF=Vx+oI4%A+|I>s0N9+@6E2{^acT$pc@Z+wHkdt0!=|djuQ5uz=*trBa1022K zl}c7&gqejJ%^c>w_-)iQlneUJL;)FqA57<4QJ4*$x!#eIY2&p7jh_j082A6!z3`cM zo|_KVE%`pSgWwAI)K2NE{Mp7W(`rB7i*LWuCPS@%XeMPL9WCj&KGO^rP!Z1)?PEE3 z%M!(0!z}!Jnqkd}PjXiq5Cq*&r^gipuy39ruMKnTo}oBL-J{Bjmc&0~9myiIfB|TM z>0>;&0{uen%9@$P#f)BGqfkT}nx`HoHYn~7Zg49eEj_v@p@8BM9>MetI?t1hD9V$} zGz{vG6k4S{UzLB^i72I@69;auqfvtbYU{Gz@T zO|5KB^EKKEVchV-BO5GUE<9ousw0d|b(Dy~k-rOj-?MglM# zc^WZ@%!}eem_mUr79I^^)djw}MKMl#k> zq|tqN0HkRx4fjR!-tF`AZE}FJU85o!EgB-g&Dp)StlSc8_nn$i-%p!-^&%W#GeS^N z!Sv813jpl=&O*>Dd*B*EEt@ENy2iE#oN5o-K1X|Gg7%&90l!Of3)%Y;u?o6MrBc^* zZEkpw0GU&WWtp&mo>b0A#exDfL%`{RJ8p%LF(P1^mqk%s9rR$MrKZV&D9XjaH>dN2 zUPc6f9c|{en>P&LcP`LN$^aH} zzpqx7cd$mJ9x`nE0^;xXVRb-)4P3pt^D?k4Cq|l;N1x>Tp`!BLZzTjbqe2PO7}rTk zCy@IQc+9vm#Jc!%=OtOpz(v}X z&^zD(I{i4>=`SmDH2GXpjoF&L{;Yizz@y1V0^%{UjuAC|#E1L@Ni-i|C_{YF|_bN{hizq}u z5s~${+jl6x{fu8$sPNnBlSQct-O`EV#N>2lqbb5a%uc%pb(G$k!OWmjAhB&RgU5Sy zDY|<|opBYviUHXXO5DI3wL@XB^kfg(6u^;m*=YK^F*!UpL=cs0Wwr(2>$ZS?tt*@< zUNp5^|2``|B3@VT+ed^zQJ1rHk7Z_$VyU!ImIIbDqQJU!C@w;?oyn%Nx)oO@beWF) zv2*@_z>Zkk6LxLkn~ITv>at+<$y1&`-X+c*WRRMQAoFLL9gL`J%1Iq4^obEHk0WV^ zD4yZ14stt6_b3nMYP#M0h&}I(=|sZ`egP(px)&+)+=uk;t+DPkOtRA#m&-P?7aTRm ze37-<&z)k$S4ac11q|77g7K<+%>yu2rwTLo=J?5HJ>H>i&=zRnRe6Eb9L6)$;?cNr z0pv(jRQ+?@xVAOTt)Us*oC5o_txk`NncG1(%d?C#eY8auRN6$n7{;mI52KLL-m$jL zV5F(jOC7I}(|xBs`ci}DEYlt8pR6!;_d$HoT)j5Qc6b1mWe%sd5-9Muyb;@QTVca0 zAxvPG?@?r99$zS+OqRWo=lLqjy9kAS55-<_9md6o+PG@=>C3@u*z_wRt%Jnyq;1(tEHZK09H<7 zy27i3xRihBY`&#Y`t3B1h6sB<)^A`3_4ZPHlebN0t&nc_=_OOdb}FFywW1-Xe|5Jo zcKBy^UG1w9nbynApCmm~vW&^SdMPF;bCaRf^)7YO?R|jd2r}JbL7G=HY#@u>V`6x& zmJw*LK0Wa;j1w9$jbkUH&Boe4n|FTsVk;#iogVr6$`KDw0VE4kDS^zddp+6iM}VJc z9+KmIJu**fl4w8eT%&M?>d?g+M5HZ@jEATB%aPFv!<01^(;lIe9wmUFaM3^5)Mdhj z6$RkBJ?Nnr_H4k}5mTRkKYbVI8wJK46n!x)V%7XG&EvRj#d#hf>~{nV4(uRQ!yAbv#Stu;aodD- z;H^u?C<*;lyI5V_SnN1OM1)ZMvw$Tvt`hFvFB#EMk8P2Yz3aqAF|DyMw=2oP6Q=t8 zMT1o%O$T(ZDcbcz(_-ZVU5Bs>QGqp#3XMe?xT2DKq!oCykP%9KXs0Y_l63~#La%BB z+`FrIR}{mkJUkqRFs_yTBjiYL7%M~vE7zYEYi;+w@`xld?T!%m!=X*J6iN_J3(1Uc zXfjj(=Cs^JM5|S?aD6G?jP^!dDP6}6uv_4JuV6PH`8b->cJFM3q5rsRdUlMF&~DrxD?w z`3x+}=MZA=Cb&WYXTRc!M_1?X8hL(Lip>-!G8027D}QKj;?_7yVJH{gKA7u0B#|Fx_n8m(VS4=?X@2M0(#8hl|r;Xd(y z7LtDcL)MFqm4`*d-8RiV{ilN$y>hw0C==g`Jn5qB>je>l?ecj`Pn(ud1Pf%y1!k;p zw#9ray-@bGr@>$(E@Yeez@~2`oVQIQz##RWTg5^j8zO}n2XjWM4L&sf<8U&_fod!8 z`>TyA^gAIR{;~YQD<%FiZ|eDBzJnaU%vf?lca!Ci&vo8wgGuj9*KWG|!nq!w31!FV z|F6fod%vcX7wm^!A-2IR;FP2@xK>P*YXfTB0b&m)E=7OdAQtoK29&G4Qb52#s!iDOE>Pjucwaxy}BL$8EL0d*N5~mXyV7 zyBDpX0`UDlm@A5%<^s@ll=A*vM=wTR)a`8CFv{G-wCX)bU3Kp1)lZ?Ie4p0?ju`TWUxN~Foq(gZTaR+ zkx2dS4KC^+HjHu^sa*G{+|Za4Bfn;N>#j7si8+iX?;IPx1vJbW`{4!ZEg`8=)tKz- z-TDXt(tvbfE>nO}Ne(meTq86+!pLurTzgk4QqR{kpQ4P_T3+vLsjLYBttLj>* zRz$~HQ_thvM!?96D94O}$I=gogxPDkJ(u7(7Q?-hpXy(^HA3U&9rC}5xIXNxrGYMM zi21+P$NQM5>4Ga0?SEz8{1>|ab%U{B{$Dd(3R0zMb;aq$adIP4=^NXsdVMvU@Q{xSjuxDPaGVf+4=`TY6byKXQpz{l89A=>=P}HQKBlz(J#L>1B+^O53ua zEyhawRWl3Xp|s8Wr6(gYk{BGIU1{-Yq}&O&m0^GV>b~I)q6l=ZI}fvTy8SHfm{xh& z^UGHqxYY_4e=8Rtr~9Ly>HhPh+Y0r6WzJYK^mlNC4dk=V^@UrJH@&EqMkK=`*TogH z`uDwJSJlUg3-3xJ36%>5Au~)F`p(O_{o12m^LkYM&*}%jMbP6kmEnNzzFgY7Q^StM z|8{!Qgd?!{$jh*;I2Uxi9}lGFih=>8CnEEVwZC#dmL)8UEzK>1_?wqjd^}@h7Mp9} zqq}-Xqbwo7)#+s;Cr!~lhM;O|jitwwEI=h{KtDDm=@-rriqQgA^Xj0L6rgiRak!05 z@Uo+)A(-g-z^E_nY;>#N;99f&i|sNijny??<%(O^7;X#Hb0a8}bJ%B?N63Y34}4>` z_rcbFzdkpw+|dA&h9xWEaLK5?u)Y%o{6sHCr% zM(hZdAIJn5tK~jLa3SE@)9O9y%WseUna=|isUO7^Tug1!z8dd9Z=j@)S-s23bcEfV zc%lMr+kVt5DbK^A`#k%kyd?ZMyR+a9gsl#^UIX0^e-*sykr)n0Hesb_uogWX2TeUR zF8Yw(cLy-1m({iDeO~+F*B@dB>LG0R+gvV6hCr?pD_KfVq!us{iR!ORBrrzJTw z0@sJk7rQQB6_t|vmGnG4dfe@dGCW##s^*%$n9z|-d<(#C+hvHlWk zoAS73m4muJQCCTt0swN$vPv`czVyax4+Oozexi(cJl58i5@|dZ0uvt(mmi!o^pZ>Z zP$a;WbUGT%kI`)ahM?|@rGmo2d$;Xx-ep4OeL>PE%?}ecH8vOa8A#C^j*Hs_b*tz% ziVBV-uVohN0fUCeIG-HdkJ%#CCDng&*sMB(K1NZP_NjYB@wipt$JI_s$Nl#r$!2`l z`Z__^buQ_)rj^d^Z0m(IBj6Ny8`BxQgj_$*kb$OS8YS34)X(bYDP|~Gt^p)S%Ki=a zOLkQ6_L4ZF6l(qd_{*?~8{CAk3n1#4E-E=Nvw0Gzg}Pa?Fwk87oG7q`y%YGUVDuy z-B7{mcM*`YX#51DsI(1AK3+6jIt+~bxpFLl2Z$L)E|8l8y{Xa!1oh*q5iS_5<1hed z^_A${_Mv4?!T}CP8hrhAb_*T>^5qM+JBkG?fm2^!E{_+V9hO@H6kU+ET@7x(4<>B0 zX6m;TnV5>nV!zV%*@8E^2@EFI^NBT-?k5%Q3M4kHbqxKll|iJVle-q--_{3u!@>?e zq-Ix!=p!i^nMPcm2I5i1>3rUv8~8wwsQwYV`H(`e%S(ubd^B9gK$tQ_8S&RN!veoJ z9p5W2>3FJL^0^MMdUpFubASFFB0m>x{cYZxmOKmOp=Hp2ad@C0U;3ehtbXI-0%|f= zZh#`1{n6@rG7)V$ol|ku_d?Uw=LWFN(!|La5^T)u=|l@C2J*ks9D(luEfwxDe|~8W zwXonD!v_X75B`|7FY|f~Qp-F3{|I~Qu(r17TePQ+l?I9wC%8j#Z%c4@hZctr+_ki{ z1TXGzpt!qBDelFBySo!0$V+I?@7;Ir{l3Rv?7i1szUCTp%&~UP`{*dC|0SPnZxj#C z4nnd9M88~bL>@qT^)Xmt4j_z^#vV?e|9N0rxjIz7DrPr*UVQs+ty}vXr#zr$ETqoi zqVo|fJ3gDJXf6GMH86iHD8v%ZTIp2uzBkjq$T=q938M6r&otTna6hr_sV)Tv8<~Ld zd=&ma5BS9SKJOe=cBy&$u)W$YhA35OpoRA_yzhGWGMOw*CJ#DBS6jk-zYZk7?0LqJ z>5V_L(pxZ2^P@71;q?mN8>;zth^_nVNZ`fc%(?m`=-nX(lp_brl67VR84aiF)o7{v zIDr;lBK7%fXGG(l!wIkE{j8#@`Tx@w_FHq(39abZe?lS9n;!4&CzO|$Jt_eoo zS14F~<}^R{tv0?rp@Q>^XHYfQbBoEQ<+&7YvIogFx$g*Uo}r)TKN>$1Uhet-c(D2o zrvE$Tk%HvU8NRLSBa(1gi3i1^A}I={RM$unEX@8m)(fR0??=6|^i$eTzp=GrQ68H8yb}!^)b4 zDvAwhxkdY%Vf#5V{QK56f}XzzMj_kT=I6XQNx~Hh1u<6IvMiN&0=bz#0F+-}8L5JP ze&YdjkEX1`C3{a)KUHR)p7`uJw-oEu9UM5*Ty$00mUxxaM-rs+_GLz(X-_?2pz)MB z&#Q)LJ8Gt$HASZFJK<2tclQjbM)@n|HOsL%dF1dA~}A3T{3Nsv)-c5le?ad z%tQNvsfTaP46J+R_1XBL(7-X1)%6Y>{+V9vZFLN%{Esx9?bA*J5t<=Ezh>6j9$LY? zek^|2DqfgygFXh7@f!|B0suWxE$=(Js4(yYp;CDo)8WM2ed9mObYqCbcMuJ-MZzys z*6~d82#Lzus9Lrc+M!Dog(Fu<1$H-5vOkfzexKuA3U`NlQ7ZeO_ zoLqX5g?FtS@uet)cd5E8|6uTX-?DIU;t|*0A?LN@910fD8YweU9aPuB9K0UJMrOe- zNI1xa@%6pm+n6&2_K)b!tK^o^=9N@Q36ZHD6k~*lS_F^0$!RX8$;dTjij#OMIx9tq_>FqVPR!Bx zZwjI`Gv9k#yrEwAMVuP^G3xR4`HO8mdWGZ}kYGxo$KqLkP1Lu z`g5B=P=$SnC0yewzkOv{dv>2J}7~@dG$xnC#e4kpCN0Uk1u}z z9tCxL0`dzx$iKH1A1v=nuXr4L{|>wC|J)E9#jVA6Qa|u2D<9{rRE<6EHg-o-y=i%h zg)p2neOcnY*!nQi*9qe0qi4$2f%*5kBjPt>fE%`s zVUAHLcW~^+fz$`%4CpLnJQ1n_F9F0ao`6e29jf1)_2O-nr+bG@doL{5O6#QMu#*+o zxb|>OiSJMq1cz_U=)ZxShy8NGlTAIJuEE|^teGOQ&ZOn{)b$C9q&ew{)MPb>Jo~y5 zQgU71&MtZqXlq_jylsx^nRu-Dhyb6jx`KLk3Oh8qcXzuAKwvB-aL_4VIdE z+|fKq(`-(-xG6O^OI0CK_^pwkAGu}KhNUM2QT&mR6oYmhAL6hflYB2c>QzA9EQ+>DfsX5 z1f9#P%hPW1s^LL$FOZdZKpR(u$2xsD8BX3a5q31R^{y;I#^Ac+Bw*-CMKe}OVbR?2 z$0xj{8Roz$O9tG#$>0?};Ic;{Bzrq3*5F%ha7xkK_OR`_c95a4S!$e$lX)T#RDr5o ztxqY4tF|AewN`WOBdVx-x^mY&p+KWA2-QovBNwf%-gR5sgSVQ^nBH zaV-AJCsN`nt=Io56}5yuv77UaGQUE9^6;Owjqube(khmia~6e${JX=n7PpEr!3%SD zp;WG;eR9#0y?%NiFkOx4x>FPnqmy}6fj&{FK;KACD=a^SYCniJH!i-BH3(THin*j9)gZ=m@4^HJ%8L00b&hNT z4U!{$XJUWV`Q4@coMLgN@m&}#^*RYtyTnvPZBmOKZ&ta=(Wd7e4{i_rvawtXWy5gL z#iNF#>-B70HE$wZu_s*J1L-&I+dhqJol9t|HY7oTxEizd&hC|;pxxtkrR^^rcc@X>sqD$rGlt1b=2v=;EbYTW2sdRw$tB>K~YVn>zpwGlkPh1NXVz5HzO=l54 zS?O(CAJ=;LYitIf_}>fimX(h3c%F&1)2le1pgTEikBGu0gI!`aRey|o^knt->h_Gs zCRxK|4F>WD#QRD^kc0ebXO3EdiVAqFZ_RgV)s}Agf@n8>$>CMPs8(Z(v`g2yB#t23SG2sMYo%a^5Un zb$(Mcb0WM`;^fCGE8c9-!6^q(D_Ji4vuFqo>sb|Xif7s=8{~TLom_-|EyDpCt@hRx zS{3WOXJ(?t?gEtMtHXt=KF5@Ts1;TEf<^b1pig6~@j=WPT7X_os+9s_{D;)$&o5Zsvqm=NFJ z#0mr&P5pd}2@v~yTWxD0hpfV<9UR#&)s;^*zWc>d`3^eAAP@^FM}xJW^orKiq?2UOz%b8T)dhsBY`)d}#&J3J zz$P^2r8CJw)94#64}UcY$hiUVH6UUovP!cM`tpQyZVogI0*S;m#Zjw_{aMdH*G9Xq zIDah7rZSM_1mpG^n=nW8d6f_DuJ92^QU?WQoQIJG_0a3BGkQD29c|TSq8u^e0u@`D z%;B$1mq;zqfyex$3eDEd@87T1nOy(2IH_%H0<~)sE4Gm(&{Tv-BOoLFHsb0;r+C3PLSJj{^oW5?)Z*CaZP3^Yl_W}lfhe8R@ zdeyf@y$`pC7=fm}{+~HPM1fw{+vA4mXXP!hMor-@XgvOPojAGoQ-Jb2!IQ zM)twWOus_NPpzrZgl*LK93MQ#;T%P|0LcHaV!KwJSOMhDh!Ps@yUqn2BFB~A-(DEk zHMEqD#kO2-8}<&>(T2%ME!^)~CZ(fHrWC*DPx@^S6mgz%$0~WWMJ6|-$!P?W-SjMo z!ZXzFTjY7Xx2!MJnhbz(*-LxU>wt%W=jm`O@%L?#g0t&G@KbWwMz z>mm*!uh@Fl!ub28a)`?o@Qy+C`wvv=2ak<)aw3jM_ReywvOr_%_9J$%WzxIz^QXZL zZ>gw(5g_{IqfY(jxFy(>-uJuYyAL^0ubszl&RT9)O5QDqut%m{-v&NChf`+SqGk%k z^QivmPUgFH@2^a_1X5q7KJ4t@HZHYI+#P%D5%^6!qB_cDBNycPyJ4$n0nw|+CX)LP z_O90^2o!)GAs*5Wk;~7p@AfOBcvp8hj-PR|ejL4r0goYz$nC5|c?V-c-b|mELT#a% z#`Oi(K;y9maJCw1QWA%MLPfQo`P_0?Z-Qe z2F&FuY#}X*aZ&g+M+MJ8jjrlr?*kW-g`3l11@-+eimTm^gvnI5h73whsBJy+m6!;b zHoF(gRxL+cj$KUKXcS_rO_OYWeee8r`feL5G6cPMeuxLEUWcGsqWN0ztGPc;-giYV zpFFl^yFq{1QgGkw1=j0r=xyBcW_(^TI8drW$XD_qF|Ih54jPxKOys&-PTjD{fVAdI zfc-iriwjN`+xX*?tQU{zwsT7$n;HJIEKeB9&^O+SB1`zW%Ndi!LUWU5C|tF;I>idt zD$s3aXXK!BjWtD>Y{xK-n2I4tsu0aB3z3x~iXVkE=Jq2k%Y$K(8U*B{H4P@yyQE*Y z7-NO@s%*)Br`c5SPfE!=Qn^po}-nNlgq}*cucN+xwW>K=gcOmX-bum zU0!2QTY71bZTnlxK`S3lk`J*sNQZ8YCF|C(hU33$#gAvV$&rD;u0zsIP8+iR))| zbYT*#Zq=-rp|j9rX=L;@C{dTw%NI&fcHY~|U(??^WbVRizAYWOQQnbGEcynJo6o)s z7a)a<4+$I2-O1EtZ1$WDx4#7RIK3v0G!{-i%FPll`ZKz!X; zs3OHnsfX#U3ik*KLAb0C>Dc7RQ@^YwxhQY<#PLZZ(^asl@z(pQ=1?kmom5tx_X*nE z&K+l1MFkm;!l_qRZRG#}Wii8-e#`T5o38O8v~+nICfNnAxJ2c3RrBvA zRp<|_Yu{$duysS@A`+Q92^8)95O}YX$cCPGxS|ZM9SxTDbeKBy!_^aXe`V>u3Qor; z);O)rYG=a~dofF&UKsb$jVFYL7n51h6c7Ody$8rrM@isByrnk_?B1Z+w#;V~{$R1Q zxdw%LQNKQStSp08ZRtd`TIAQT?Xpi<_?T%hM`U#^QN4+~-OPIfJidSuCXGuz1R4SH z(1$_q*eYBFg+WD1=Wwg) zx@`h66-B5*Y)iw-rDa!4ooU77zcdA_ft_T4krFb5I2IbBsU0YDu$PeGjs4%+1=2EZNzoa^+dBfqh+y?uE z=ChwZ?j@Micxkm_k+AoJtVUJTa78-oNdWf3FdkKBaalI8*^WV&jWhcrbS{RxH^yf@ zqhz$z6yondudv#)+$e#<`@-U6iHN$wP4RJg8!=@81)Iw=~~9Itm0nD#-U%L!Xnc>4DcNC!2%Q^ATCZQp&j8O4 zc+?K^0v8DTp@jm%+6Ky|xXiFD!(z>UCrfEsYBI~WZ)zB&GRHEl^*FXbZvYX@rn(=8 z=CQ37eC9R*z1%$s?s*PI^tO&Jh-RysR-6i22t=py5){{kgx@bbFp^PuQ30+jJLG5#`;B;t@rVJmR+FMO!{Y$UYq5ZEz4- z8_ytgzjJ;Zw9D2;!tuuszYUpx8T_U|1rf+fX0r9qdvT8=CZ5DTg*cGv`GY|-+-C#D z-h!rGp`wkX27f)$-7+pNazO<|2E;1s-&t63@J;$>lHe;?t<)3>6}u;UunxGT>jnL z+B%mr3fVHTiumIhQ*dw!-($v4zdu~{0sJrT0owd|C!FPc*W%T~!sHm6!>nD-F2RV0-m|yA zZ&Q;jJY!eB+!mg=_pa;pu;Sk_{;frXI4wa#d@ZZ-GTy0ffKiL11$3#?QO}j{6VH%s zTk&0;r?xc1l>g!2ql>nKfQJ>AJ=j z#*LoCMs<^}qwz#c1Y0wHK`mun=Zj4xzCGmhr? zGZB$M90(?6NU$*Nqcgf*g-jwueJ^tdga<=^J!kkconPu;vRRP9-3ru!K-2SVXB|Me zYuR}yx#-n}lqDlYYe{P^*Opu zKmSVZD?5@sr6rLJr|W2qhZe_{n3 zv7gzL7Dc>IL5QLxqtC(2A=>r}iW;-L$D!xA0hp=(N}M8Yq+oxn6Kzx#jq6^6ZQ6e7 z{HM8`1qPmaCBpk5dLNoDjTd)weG>;KqGOC^e^Fz9(05Rko_r7b{mD3|o(=AMpRXlS z)XctcEn8nRho`1YSDAUTz+`b z-<38r>NczhYHwigAM{N-kXD&`G9~uM=@l}cuO~aZvIOJ5-|+d-%%Yoxei{xaRd0bS$$RT!)5U^SDr$-+7zlypx|glS zc%dm8yglm$qnc~$bbU{nV|jflN*IARfwmd_30iP!7;Gt+4p5- zwbcWy5;+@?>BMD$!+^N}wwKClqoTG9Zq_r?Y%;#5EzXtJeX2DDCF|rU3sLMCB@k-; zt%TF8S%CGkP^hF!v$jiZr^!AJI4&#G>eWM_r14g9q`=PST}iUZWa7&yzor1pCJ-hQ zg+sj6j;ZAnuu5|xiEQ)WQ&nt$vbm}^fpn#`^s?V!>Uz2U!9+@24rDGdt)Nsrrcrga zKcZ>BN;u|ej>pbo5C#dxF>0NR)i>Q2$vqp>t zQEhHaQU$J7#wCL|d@V~hklI1ry3(rHt)CCs<_DS&WL4?I?W&4>T11)4tAAY-iC-#r zffczY$k<^x5fm~hQE`Uf>8-9ZI~0zS3%TT(^P2Gu&+GGgS7pXuB0*Y~ooaRvbXP!L zJE<l{yXOc$)U zfswQL8Lj4olG(H!_`JSmx!gK}(q(#aKVKNUIHm%ER(Hz0rMc3&ZSwLDUNMi+$aXvg zt_2MUj;zMnnshwc(E)}}S(HX0#incqa-eo^jb=l`yTGZa+}Cvf4$R9_1JjC@qI-za z6$~ljI83UXkzNjnEU9Qh62~(06CV&*QxgY;R=6r&9rB|_pddWuB6cU$zlxhM1SSFY z)cGvad2V2lXG5D<02?$lj$Af%?)(-$(4#%v)VZy~nWSFoz6Z_t@Fqn;*UB!!nZQnOB z;EURxK~RZaYNUYZZ(MN6@B#Pu>*VP%APR^f47^Mw{g^QyzNx@9bM+DUnN zZ<5YD3o`jn8Wc%+1+~N#5)%oN-UQ`VW9*=MXF;1E z%eXNO25XPYH^&N{wK+iN07@Xv2tgb-q5i9sSUf?XkI}r?R#$*Nj%XEz)uZO>byn~rRzSrXG9BEqz61vj^u%OiEEd-NQH>9#!^bymoCPz1K;5RZ2 zF{^dTQq;!kCzC|6ls>6{V%EX0Ejb?>Lt?&5LTn5&lj(Z4r|db@!*%^s*!t@q~08-1EzXW)~wa z))BAa*Vi4Q%@-$-yogakHk&qMw&vpvf;(ZhFwszYRHhH8*l*~3Sk)F}#^>#@y&SKAZ~4!kj~HI>oY2j!2r+409Xcv5kafB8wp^wy-1OC* zq}53?P$#;|o~wLx4)qMlc_?vypI-<~cOgVg#X)b;&*erm@iMQ*<~Ld(l>EnSQ27Cw z^6a)}%iXAXs`r&7wvAlSuBXNoUR9(b=vN2vu?@a{{unWmo8@9#TJP{OfdsI}HDBMj z>Y91nJA@OAw7G>v6s)WgQXr74nOxHH@c-P38A&fI)Iv_B*h(;fIDZ^8~WBV;AR%wA%Au z1o0E#&E9gpfhOgXg(i$8fwM>5R#+=m`Fv_#`2(#lIfBM!8y}{4X_*An9aq73bflRZ z-Z@s(mc&(PkTMHfmjl|$c`XiVy`6D%Yj)sQ@fipVqd;hG)A3e|)4I30qeuHV0tYoH zzetGH6vo(IJ%yDUI5g<__`Q9(>FVU$b9v(fjCdo#a|-Z@R#}4kzH9g1a(PpftT*i#Bw$| zcE7CK@7WX3F3EC(iwMp!Q#cTY?-r+jenzGc7xANRcd98X=&P>7Q(xug>Jd1&E+iwT zeAOv$KSp%Rk^@O;m&1buox(*T^Kk0>vpijzO5Bc<(6$ndv(8eUlnsN%bj-`y2Ic;6 zp℘Bfw0X*`ovko8J;qE}uEUAE(ALy+UeuR*pQ9l4ia=-7n*+Id(%1pn88p^5EW< zi+v-%%F>$P?A##7GwKW^pbc^sU+}gAXF#Ek8Re5pyR7JdMuBS53^K9Z6P6;1iAj}j zfI&(n^1&~dZwAbf-=U0Ur2g-X}8E@iGVFoY0Gh4%#WvK6Pp2l+D*4cWrop zpRrD5OdMjN&>d$FnqluGOu`5`xpjlMruC+rJ`pOQPV~(xW6qcM$iAA=$mbkqI1!^u zt3)rFuYX{(if(^g4Ku*8P>sYUo2V(#xFo{dzbFcxDmd&xS>R$y<|nFSFtDY_K{g*{ zgk2!3^y$0M^tFFdVxdNnHX-TLCqiT;l6N_xBrNH z-@GhNo>X?9uSypHPzKblF?g>K5G5r8N^Y8w#so;y05ZmAp9MR$;g@VX6`klC>oS@H z^$i|sRHFt(jN=tZSvP}hh0a^NVWg!xx~%ceWy}3p9ora5Q8nhQbZVb+)1x7SF>;aN zC0bX+Fz*7d%52bD@S~dKyY>%Dw5)?KUkE7>&_#E3YXRdfO;V=1?2FS8=!98j|8S>p z2tvCp8A>1+UVud6mApCyTRNZv*91}Wwi=dfp%iUsv^15eQEY}0_lSa6%DC9-R(`>o z1}HRsa|~qJbnEm?5@cd4RE_wTqx8}H1};BN^*EmLyu9s#i+d+jkN9)nG>)@cD*J3y zA|)j-0=lMOcrk~J<+-lXWV~~I5hQrHdpVMGz(yky5eF^VLGVvs;&z3sgb-?I>uNi! zC;p!T(p%HBe|14yJDR+W&Z{{?8jP>X_3 z6A?KHvhx?Ge>EVvozIQjv^ksmh3=$l4R_fseA9^cb6?o5&%^kD4w}2O#|6gw!!|*U z9JV_U-g>NOw;J<8+gShj9Y04Rhdq}DJ=TD>C5O6O0|UUSTEN$1_a@n8qwK@oF}LmW zyA8AsTx?UOlIicL(Vk#xOE61UqJR0EP$Z2snS``u&Y%q8ir1!yLF|Q%y}BVsTh! zs=k?T{l09q6UjeczvoOV2>zp0OSvqF!G~XeN`P^(rXZe|p?Mvj{p025bnTh%e?_9LzkmNK8?CKJR8*&a?`V_=x))@< zCH(N7ut3~!beF=xbu5{yR*dkTfuneC{oJ??Y6@3{ zG5X$@WG8PdX(rv(n`*G;Lv4eyMITfq*%iZ#cJ5z!9EdfvYT*mR*ZmX4mimuPZv8D6 z_wH>gYET|LNBd@0@5a(Qd(UV|VVXc5{i?%4Jz)<+Y5?By)!d`Z&ep-x$HiD-u<7OU z(X%w|JrZPyF@~pzf=wTnBNW;^_{ewCyH*qayJdrpV-)HreK#B2)lZTKo4spi?BIGR zAD2_LzqxUoj9F!3XRCQONWi4)9kJzV%Qg}Sg$gjG&8y36iz^m~rzQji+w_fANXi*>J(yt%%tNfDS`)#-C0 zq=>WnDjUzrL+>i6{81I;e0X7RI8HsGu0RmQQ`g>>YF4zjR_Rcu?^L+Zq2X}u>!jnp zRF?7bYV5$p8^8hB7jc_|5wsx4Kp% zrCF;x%(rd($2NOm2PP?^wJmJmKIgI6y&{V@h7M)rlSz)SxhiIzx2vUU2mER?zvsmO z!+A*Qm_8W`p$O+r-jzaY#_X@G^%O+tRkd{t<8M)kpBgvwV%%pC;bg61>4EurgPaf0 zWXRgHaCI&hojK~H5(UGUq%>xN3!V9kf#!VZDP41uPKOeBD$P~HDaY2ka`W4E3Y&(G zsslzx=kheqGvbug8cT4{&QEd|^5(ao7{$BBti>`2*i_7nAz0aMT9IHPQ#h4|{8*wS zt8rDUE^l-nmti>)oo6k3@Ne*XvQ+wJOS!2|GgBwEMjkSy>rkJk8T~z`#W+;wJ?K34 z5lvUYfQF#Bm5K(zT()W{C{C_}Cg#dfL$IsYhzo4n#qKlaRj_vZtojYqMWm5VdUpSoZ7+QY49KfCh}9^iT`TA*Tivl{ zKYIyq<{5X503}6JlRZB`p4>R|nR9oah811bq3f#m2zCsROrb*4mUj6yHf)SClww=A z%Mq4CF2?e71=2D~wA+#XJYp%Pji2T^g+0Tz_IewC4d|*;4Qa;g3d~EJ6ig!&>{I0H zfCuRfnlzlT$FB2?Wg#hsSpPrlQh+G+ZZasUs1;N@RFg*)H@xgH6!m*o=P)fm^ zcj@3e5Gt;IWz5RSrpvU;kw!nIzBka{r+^3NQdiT^2Li#Dx(B2->p2U`r*1x8wve9U zAO)a;p^l1=LbQ8Vb=N_k?3uO<_ITwL)D#NsKf_=9#uC1e7p2d>=dHNF(fK>-N=(W` zIdRhBE8&g~vd`H+Bm3O{NH_TSN7zKFRk84gLK@(^XaPF577FFDQ|aK8Reo*DL@gC> zmgZe&)tH``d?XarmRZV{!vjn?CzkU#ss>Y0b=Yt@UjQp&tsak!6Qpo@&zhWxuNU?x zXyURcLt7(N6%dv?nyxh(U#)mU> z87kGLevkqx`jIx0tV)8Q-4n)$NDGmO zITiH<2CZD#*q|q%Uc4mN%(Fd3(~d83s$>=*n>bewrl`^`N4kbc@4eHz`#g+ zSd6+7=wEiplA}5JPJelHz^yQww8ivI(#_Q{Imr>*?T8eb*u#PCu9GV7aYC)vvahn3 zW{a7eW^{&h^TWsra``kOR4Ttgp}TP&&{Yu6P8^6j_Ck`>Bghv8FrJfR9>_#&qu;LZ zvb7+;R$CJGF^4!9*u7I1L6){* zAB8uF^9N^kHB@_M5H6Zk{9Y+YYWWxZRw>`sHG*0N(1X(^;~$q+3e&`&s3KHQ({PQX z;1Q92v;BKs`i8QQ8rYHLzi>fg|)G#a+ZI69ZJLzp@lb4>Elt{ z>IU0YpNo~NGDBe1pO*B_JoDx<3^@8R%|?y(IuE%^P&cK)Qox+tGbYkKkMMj+i|9nk z?ee3?W!GPFoT!bkDezX;N#`r*=LIM2fNgnrH7B%%g3B>%ow$=N`A1&^*ldb+K5!fA zyR4AZJDsPErwwORn)W!9*CdPBrv}RoNCgIIHEJzw3&Dq_y~S@f<~Q3LXHA2tBkXw( zi&#RtZjXkKRI_>@HGEGa;Zj*L=`4nxTESxWcrGyMRLA6BPf8 zqn7>~pCdl5`G%l{L~8=+?Rp<#&s1su2{soqFn=xHEZk%wZa!HRE5LvL?3br**q#1C zf>-6w!N-YPzwZ4FJ1jKq*30fJ`1K(|H}=KNR&B%n;Zm$p=mU1k&(Q-diV0iN$YOtv z<3wf^Db*dP-+4HBC%b9gb>xp2lcxU>C46{4YB()1UwgUWs}(I0F1nmDbZ39@Bh|9& zp2&TUK4WMde8p3zkTK9{0=a92+k_L0NbPfyM|NX74cOP1iNtLD4i z`4a4fHF|QiM72Rj>bT2;tipqz7n7}P&!O~_E^3|UHtufsBF=k4 zJBdxo|489?uw=jR)IBv!?lY|*gnYR&E!eNM?{|iTZ_O=SAFJPdm2M~J{-Z}`e-ZmF zHatZ~(B`JoR4jaQ&-Lhsrtf*uGXBO|K=w=Wze<(PL!<_PUzf)Ne!e@9j zlXj55eW<{6>o$5nAe(KNp28YFPRY03A=m2p09!XUpX;me)QdFAo$0&|@+x1Xe*W(C zn)MOy=qRe|KP|ByRHaNupo5TyZc7IH5_y^P5!Xj?K43p|53>?!V5$#T<`@M+fh zQW4Wlv&V>p8lRJbmegjxvv@IIb)JN9$FFupbg~8o7Ax%$=<=UOCMLXl)UJK9ZZQ;o zmZC$}VL~bWddC$vyVYICky=P7JDzF?qq{!zbL!{^>NN`erv;EFMOJC?io>g9j~Z>1 zw>W$QyYa=VOGZn3MK?8Tt;Vh zG>CuSS%R-WHmvUGbr~~2x{@K!Q5%>cYbMqJ1b;>PJ=RVN)4#$bqGHs|w#cb31<``YW2)0Cr$`8ey853L7Wm-6Htx#aQ-@Hvj zNyVumTg>3{$`3PD+7~HN8)mv?oVc#{&K}! zR}lABbO_UMILkq8Uv^DK*)h^hcGoov&G3281Ml6ee3yM0Q!8^JFjHW#x`9=mIMiyI&0>E$yIVX|;!gp7|wA?M_0#EL4$ z+WmoMf3L{d$%N@r?$cb+(JanJrtpnoft`)68P zb?iRIQjGT>GxC4Y*~KG6U`wz+x~*nq1uBf^HGkr3M;ug~*-KM@#Bk)CZ;bzodmZT` zC)L0oMr(2U=Qne+G0|?hp?k8j80){H>>DtrisxShR{B^)^qkE=GM~+DmqLa796jCUnbq({&*D#lQ`cM3) ziGz(5*8pTaCOE2FNLrnW_Z`i3Sc`OdT%|11f%a>6mp-s>sjm_!h!2z}P%LpeUR;X}BNcVCrvq~;W6KxSR*;g-Y$ zL6@gaV6>M`c9<8+ViXZ!FrC85`n~{?bmAt| z`m0~wl>pz1MdbMSVNH(x(2#FqO%JIa7w{OVltpo|f+>UZ^9FH!XY)%xR4*zuEi841 z&(;Lf46S$V=W`MbYbnsdQ|zlJqw_-z29O(|G-Dn3-B^(O$e;7#{_~4jETSA79FHmS zcAD?5hsY9Kf7dE5ev@mA2fr6Upda&!PvtJb~dpqlWY4R!yT#}#tKe#O)ZD#XFdg2d?9@yR0 zXQeD1jhF!b49WAdFbsnG#%yq48X|v>BU|2WbfU%dDG2$GZi;WibBul zjxxuKyR@c;aPW2`;@R!MlE44sC@FS|b_*k1jA#|c`S;`bO0q@OIz@ApDc+@X^@BD$ z(+zXNb0s@A6P`PBIS?D?qUxjuux62lZeAAtSjJb4Xccs|c#!d1C^Dy1KKF|oz|WV@ zAA{aqxwl*ilte{27Vq?anTfM4K52r|Gwx3p<`u7yH~aP{C3t#!y;44Hr&jD}&OgyK zg`F317Lg|o+784su1I2e@r1njMZXSn+v>YAs~JjT=;%k1x}P|Je3hoTU?cF`529{@ zxhu(a>4l32#6IW2p)?XcewPrv$8_GbMO+_&NNsX>FN;r zH^jH3Zh#a0)&RL3e_G;>FD%+!PrJSfB)_$|Ik-dkIrY5V@ce(s`s%1Q)-T%Lwp5`M zC~hUVJCtH=3GNbHic4?{P7Sx>MN`~DaJN$2iv|r8cXxdQ_x{#;>%F!30~scnZzktE zXP>?I=?Ba``OMW;JK=Hu3|vyicsD%?Z5B8wwLiPvlr6(A`=QUmaJmH|&Qb zeN~^T;3t~A@40|4(>UOa9&$f&d#WdHHI-r-cZ`p>@CcTGQoh{c?-3m@V!U34g>Ciu z(3zL6AFn>2%5Q44L|rGn7`2AF7^Lp~{-rJ#DmXND-RJiY)aCXnN53tJ*P@BScC@&p zz51feuPJx1o4hxYo(m1~qM)r{aA}t+Ub;xx`F#y{xfNFMQ}8Qt@x=-_wl$#o&vdlUxAJdkNeN%sKUw^1P zF@cyS#MgU#nOz~sq|3i#r|#dVAiI%=WdNUa>34{uPH@xR&g|MK(#Uegmni#zMarb; z>%9FX_26lSIKM)2Ih$${so-u!1^#0@>l8=V=9my)#*}l%OU^+_7-MDq$x_@O(PuxV z%-I@gZ)M%czh2%1$G1a#fz#l}yjJfoo1Hg@xQFp&f34YOS(OTDO0?}UzAd;ZBW zd>2=F1;Y9mwjj~*iJ6b3b6IyWXqb2QYw@`%16Q#{#FPzjg z&*i$g))yH`qjC_UdTG~)lFG1*(|;atbySK;`WPv?ae6Ae|02~X5WE2$^EuWM@9#^> zc@mggS<6$ExSf)!#p&*4^eV^B(rayXul_i6fuFwTgLW{1CP|~av@kTKe%87nqh_4= zCev$L7u%+IkQ!%>}<20y{TqR)!gB_yqCc-!3vn9PUdTK-cKejgQ~UZR`|-F5?3zN=-{T5IBW^-7bKL zguFMgVU2SIIdmS)L*o#>shy+6J4;wa@hLm~#jg6MY!@9)2A2)YH&(1S9XEpKC-0yd z%45fwEiO%5K63{iFFVf-hMIe{0*Tqls>6TuxEWp5IIyD~yv=QSwPTXvDu#6&jm57L zyHHE^VWf?g11X$4;_|P9dNk-2CVmuI&?#H!%7O>+_$?5MJ`Ro(A8ce!tA>ZhwFTe1 z4F3{?-t_FLBB9p{TcM}#NZu%?)>HB4pS3KIDkx0k9W?4Wbf@<-^{YKhjg`h1t#R*n z6r?SEpwIjSwZtJqPFS{JJ%zt|TS+5{=;lKiVf$+4d6VesGDsHh3N>^ks*?J{j=du8 z3)d}9pL|4<_&-)tlX~?Ij0=zZ->3slY@$?_?gQ;ABSHKEIw6JNmEJ6oGe^jPCWm&+ z_=?+Arb2^lVbk9{JMzDRhxq(j+|f(F|B+m_WvzS?pSR$d%&3G&B!YMy*Y`LzR)_gs zn21N1yI;0yUjIV97(cTAK@%#n)#_}18~^=+tSdNyOvy=&?1oS7PqPNQ`|^#jTLaI2 zyZ?N5BX>%&{wzj>;_nw83I4s`_JaPV9_WZ#IVvH9U~`r)8V|^mm0n}YH@81AX-$De zhB&3HNGfiUrR-!-U(nmKCs#Mv&wHBsu9e+;7jxJ}9Nn+(-9S4Xg@GQMA9JWu4E>1C z4-r(n3`%>dZdU(kXWhQ$?KFX?uNSH;?wpPB<^$ z$=PAevQeZEf0U_(-(^s13RWTKoZ!y#xBF=v+OHS%ywtP1gnT;cgWJl+WCcP{{J$!^ zkCyi%p@C&qK$bXHXY^7_hhjjv)Vm{SmyvgmH=ZBni7^`&VwC>FfyMa1?Xfp)f!qG% zo;TQ%yl^9ee?0?VF-wZtlFn)VbZ@1<-aD=1eM93}wNxrIZQ{?)u(vnIc}U8!42)8u z_eOHgO;uOi0tu)Yw0aqOZcVuUnQ;<}GLCk7n&N%&Z8sG1k!pk;IKXmBt6QFe-DJUu z-ky?|2li-5*-I<*wQ?&V7mlthkB9_Ax!~dZ!5Z}X>oh50ui5)a9i*gwAA#Eaqg+ij zi57Tj*z)}3Sqx(@lE!=U2`ZLgXxoVICjI&XsNxAX3$jwEP`2ngObU48w| z^s{E!d+OJ?(@A*{eh8bWRj&PMV5ei6i;nx*j<$Hh!s!D&*`R3pnQeiCkrFfS$C2;? zVZE}-a2-BYflacAX2FH^A7oCn+Zuqd=@YYmR-^j;4Rh%9O@L@1+n;>vbO2r%;1$x{+ah>w zYE@Rb`ulRxP9*JYC8*zM1|8>))0CEwCfpVncZ*fcL7WyHNNBa59Fb*D=uN1W)+XQX5ZN><-DE z`lTn~(l!1l(jw@18Cg6FWu$YLMZ&H$W|y~we8v>fy`nkRq#xe1#@Os~@c}gxoi3N`*w?T~PbHhvj zkW=jTqzIVkdQp#t(qReDR*jBp8#>iT<&(@Gy%;`^3XYdc4hc*L7a#{Ndt4SSa(gi} z#_)LkNomrX<6UlV%wX33RP^BBAW$>~1(P_B#Ra+vDfSTh`d01_liKOHT_BPV8M%C5 zk5D}o$@y=uyQbhZ0Y8ee2IDJIsPJx<%DYx_-m^)KiD!;~hkNdqMTb6@Ap5URZUi(7b?3>05EZpvxuBQve8G_a;I&!Q8p4IDB8U-=q zKdiMj!^>=DWrInrNH1f$5?!JLoYd?YU6XB+@Cid8uE2-C{Rc&w&56mUmk-EbTA}o; z?Xq?`MGFrw0TD8-e(9cb5AC-~j@o)lp_5_8r_{o??0F(HVIMMVjlhrP4gaBH;lw>xFt&_KK_Me?^Vx8!SM zyy1pvjbE#G$J#-27=SH)w&;}Kj80cCpY6@g#kxr)%duoM{=Wr5weI*}G~O2L8L)k;(PsdLwA zgQF~ucf_I)nsN8z%iru96iV$yKZy8SN6F?K_s=XlCMx;ER#c3Q^`#PcphC;Hz+I>V zp$7GHBEO3aCg_xn!gRHO!@_YQi{A>OXf?^Hy~C`>NVTI)4p%~UoB>=*{d-RR^cTftL$9cO$gr}v_ zK9M*O0e-mmPLzm*cVgn76X5Z=ckjFz)9d!B05bJ^x3vOrDL7C5b^Qqact2W8@__GN z^c|Jwr>`9BY+Shx>s{U*QD^mk`cjGi_`Ajr1ry8CW@IDv@S#z+C;!!HBx%k!LYaB- zR|@;?MIpsMgl0uo?A;}n7mf? zd2_70YTNsn8P}EkiwzOaoujJb6vsmts~_C?4m{@O5=F0Paz34y0RPWv-da zfSZ-7h-n5=qkrG*ClO8_GI31sQ&neTezWYg7%m^wUU)cCgynpJ_OS@tTQ6O^?d0HJ zaL1_uioPU{OqHj%YjMxpXf3L=tkkko0Y1H@3YTXBJ>4axvh?-Ph zO+F^3;En~(zv`DHAANPtyInTa%^7Pm#J9h+8SSunzgC~!A6Gq@W!UyE)MzRKQ@SxE zA(SP=CwFMMbl6Tg3U2S^N6fvmOLLvR=GbzNk%}Ih0i#qQqSW>Dv|ZPbf;cFQQ379;$Img9cb^# zTxbRPH{ZepK)m@euu@hzHIUeA8@_OGHnXPf`p2(p(p@wnw~1mc%Bkve zHj)3@uDyR5T?7g^Il$hf3b@0aW9M-qI*f_@!;CW0(}}Xn)(Hixjh>W}`tBOsxUY=7 zv*=EEadX7)%f`7kOzC4%qo6vwDxvIbJk&4}SOH zyybD@-rnX&xyq^xotShxkG`x6tUnaj)e zc?pBLq4960{TE%KF7yb12i`jDG-Uc&%={?levnp)?L=F39Lti9!DW*j*@GitU9G9P zF{Qa%Wane=lb{X2x~9gx;G#aHBlfIkyia%bf34G3lX%KlAREZ8W*JEk7jHfEVg)>{LS1cz- zk14&losL|LKqcEqgDcLg%+rH>yjh6|_|^Eqf%&>g3QD`X>T-E0g7l&rb&U3ZRU!Uw zAbr#-VgCY#wx+_x8$4xP-&3CbQ7;TX;qy5~^(C(O@Oj?H*)v5gv(@qOXFeT{*Gcs~ zT960_7XIEnHaxnh=tBeeYO>?cIw#X`La7 zyNhRKXTNZZ+DR7RbJCa5eHE$X(sJ0PKYTlW-7OIAwvg`Wds+q;s%8i~J27ty2o_-* zo)QS2$60aF=it4nt98Da^1WDS60vi}vP2?gcTPMSQrTvkcCORPZ=c|Mvsm?YJB@-- z2dA~MO&3R86~!ARfIpT<(*>1QFx+>uBG^#2_t7&S_Xc!$_zUy+8A?Jdjk}Ho$1#|P z>T_UqEiCnBA;5*OmO>JvqoS3UQuNwR?(Xh=ihLCt7bg+=KoDya0j2b-Q-D+(z1^UcTjDdf(A z54JMO?{;8t_*M!YIqk(i-~JUjf&Iz*CY1CE|FhD1^gF!YI=6|Qq!F>T>eX<&JRA?H zCI)tt#`qG$qQdZk9u8)l(cbL=pDulxT1FkNzs&Tx*S3g18>wiRHpP+l{oct(q03iPfLR&n{o${byDc9gPDXv`AuIyFF|r^{?kDTJ5W{mz`IpEXDvTKc z&`!KXC~*MMi&3;ZBEnL&Ec)eq*GDIcu9a!S#o^3IyZ3vEJ?hil zO8g>Pq6gyI9vVgs4e7j#5!MHI-sb-?tdI4`3nIgo-`|~*p*g%iIkzc3lH$(vHq`aM zZWWP(18?bI(_QmxwWDpcQ{v|C{{5u<-vR&i+(L1BrS3w-y^n6M%kLP|ocI5iA^`%I zjYetcoOh$!<*BC6;>tDcPS_k))|e7lx2yB+ZFD!ii^ z|88wjy~q&JK@A&@B)>UXs2_j^}alm@|f63Za)xLNmf(ejZeHPwPm(Ti+gjIIK(4Mn8qljb=wpSrMr9Rw zvltN0oJdc1rLW8)IWAhYm?^YV_|lbA_U4@I^jUXoL^o;e8Y^4gU0R0lA>@MAj>>DC zr=0xcTXWSf=TikrG~pPB|KkEQq}mpZpIRxW1jsimbVMjL^->@4)*s9xRU{vpa}7-g zP-x}X_b#kO57;1(4271tP@bxaIsv1z4-UHZz>uz`UMb~gp2<+QiF4h^Ad>{eOCH4; z-5s&<3^y$APxnf?kty!V=I=K{Nb_a$>pR7u8bYG3{Kt}imOqv2v}itJMB z)P2jAObiH)3kEt<^iX6NRC1id=bh1v8V0f4bi$(sdRpE?N_ZWz8PG;S^M~tJG6P&Y zQuvbhUUEL0QF}j|!Szb`#7z9Ro~SR6@tbSCi0#;C0;;2eJNU6lLhn0-l3ON?iYtlM zWy52ZSZWWpodxzgfRN1Fvg`XfjPmA$(v{!!a8J&8f5_a&TW3ED#+hBh>9CJ}THnLQ zXS#NoUwdDyhY(KDsp(w+Iy{RTQk0bge;A#=eAN|8iDuwRrd0Z(PAh7{B?$0786cwv zH7~@jh_N}rB8qxq)bYrtPkRorZN;|9s*XaK|69VnQ4(@lg$DHM#u;Kj zEu#uA(kq`yZg-uNFTvmUSH}08yt#(2E-yflR%>F|NWC8ki8NtBbRa&7Y^juls^bz* zTS)0*nZ`CViyh_K;Qf2QV(}Bb*NQ%TAPRPmxN+5A6n=rc0$k3IRm%Be$pp0ZXGg3{ z1if1cW$@_oZ9BUY;X_xdmaA9542D#LMxBAYWg9n!5J3kwn6!;v+31=vt-~|D<;|=z zHDRY*TVrv{zk}y*qerFhyQkBcZ*S`4)WYnhwWr5+dOw0dmfQ22`zUPEqX3xNDn;LB zzuiR7b8M8$OM`?4tL*X%>!il?VnqJ3T++l}D)rYvvVXENS5`7F0<5VU@k0B#fwWH5{>s^<37so+FRv+t^ zyQ5m#AdfQIly{C(pa>q}Nl*u!+u6j&~<0ijc zN%jEF-ftP`)Zbc8V#ywGiJ7?{|Dwr~Cx}t2(K+;(@^asmw6x|J4;)do{UboSo=Cbe zB}FbYI6S0eP6aAahz7rU%d}FmHQ;6OBw6#|xRgY6fF)ALz@vChGo`VwujGEs2VU>~`nKUrsucnG3UOLUY>v+4d z*s*lfc0yOlk~)}xo*{~^WU)9Ql)fO89@>=XG=S&s-DgibU&bQa>QWur;cCNdVIREs z^jXcY5pNY=?9Qx9yUV~ZA^YKK2zo}-Xg=_i%g;k-g9EkW-C=JwXs!Ghr)2X}nHauS zfuofH11IVgIU>1|K@12KLJsz@!X(YM%c(NlAIR_*HnYw@yQEv=J4aR9ymF4@%F-^s zrW*wd>giH4uRMCs_gRyY z2-xKu0o(RAZ2pNDQ!UWGd$M`=&GB~gTU`3ic_ZC1f{>bRi$P{qbPi?rGg0PG5QFI6 zBCEMX%uysFIplqDg@PR&E;D^W_IT@vNxq8J&z-0=XJ1vZh@GL`xiVxTc9pHLnfXHI(`RXgqgH%l zzWd0v-`%6k6@*RU%iY4HCnHJTt?`U8R)%xjOg4Nm8m371*X)oHMeMPCnFo@s@Z<_9 z((4P>9^DJIWd=AK=DmCI52os#X!uV3U5)Bkz!9HZuy=lAv@Y{PeUd>!_+l@1qPw5z zA%&C8V0H?medsGKV2W~lr6Vc}HYu2K_$05hKQ}|{D1vjg8B1w9rDA9!psvhK&q)0z zG0(aK=QiN<3r8%|w!MrT(1(2-h`V~+B^G%#^P6d9d1cI&*|u=T`?au3WbmxvxQ-^2 zTIPp?tdE9F=rHA^M{bw&{h2RIP%~N#Bf5T-3-k?sOeOF?N_iUD*j&}7TK<9cefapx zOjv-3x-#Zq!g^mn?}Qp?vlMtJd_Mmq-~ zCKFplwTtXH-k7^;DDRH&mfM3br4vPZw03jMij<+p*Df3Mg_*rI+=qOn;r?Gh>Q#%) zu~%O4{yho%Z-PxY%Am9M_Gof12JDc)ybN18n2t4tm{IOk z9H_%ELcqWzjp+ssy$_3sA_izkbsdFJJ00K6#hHLrjV>tm@IcTf6GUlczONW10$VFb ze%FqP@kFr_o4_Q7Vh3!a&5F8E&R3uMySdBC<^wyetjmvKh6p;yd+>IxfA+TV^xC6_ zfYUA#J)XT$CSEZhC-6QAScT>bY|$BwqH_Hm#gckRxQz$b=XQpszH*DdvP#MBLPG*hfzOi$E!a zT$O$}Gm}FWo!61{ z5_o5mDaXHz>l(Y{z)^XLsmi517ZOK5@4vntac3TCTjY-4oIH+D;f{Pm?|a;~`LjdG zX;Q4!N>wbN7mgSW3iPsZ@i_VT7Srl|N-B4#ixo9xK475%0)1AFq(mr6<@Fzju$ zDpHJnO!;x~=|WH-S@`uVR-SEsa-ek%*33yTMm{BtoO0VsWrR!)Am@Vc!}JWfc-{p5 zs2<4^3tst=iRew8&C<-P?|@mJc9si7doG3=F9M?5n$7TEAxFek3bjG4wNOZ!6V?4T zN}=r9;lDRrPBp?JAPJ(cx3$XoZxGaT;)!kN5J57cB89=r$Jj=_md`j*B8eu<*@~K3 z{z*{(4+argK(gZhME$@Wl-~Nry))}lx+_So!RM2~s3#_`OLKi_G)An=G66{XoK-dl zqtB>3AxSWh$YK7QzACAfdwOW+U(Tw;peWEzQ4%*3uFC!>WDD@x5Wtl=5eIvdql6C9M7@RXX7Y{*Bm6?%W4eE|tCXBo~ zNA!J}F?f+@nQ3j3uZjk-3bn<{)hHa9A)PQwqOkZLF`w{{7%YI=#ywCIq@z<75;#42 zQPtr1deJDN?>#tmS)EyVwW<~`8|e4FYZ`Ahl?b2?BRM-anpx4yTATV|d8WuhXv>Ni zsv?%b2EOnkmGZ}|0P%UJGFFVU(S&{#r{6)?Ln=${uWBgvew;{6dyEs=F*g0m7X3Mg+G|pWA>1&~3;CQd&;#EX;8A{j98XLh&XYeY zY7f6=o55ypn3eslw9>~WqBvgsYhlR?EI0Qk@1A;U+zGgQGwwVw!{yw=JEO5LzlaH? z;SGs$T3I+t{41?_jI)hNYabLDcm^h;j{8<8+EAn^urJWyU8@@+F3vI1AJB5RjrF2H z22z$aO5y$WbI*u}0%@qoyrPO_oyW4GdfvojqM5gzq#1#6uIK_4?kbX4ERBrX;BxhA z1K~5`A9ATg@)Ge^p@VX&Eha!yX-+WoFII3U*gp83jAlrnjpt1 zYr_L+g|bm;a42A>V)F3mFc;x$$z~8-Ued5V9mMmV6%=L!!a%|A_Z&)c7)UF0f5-1YI9Tjo}xDey>tRfUn^(B_Z)EnwVRP;=ToMGslBL^dD+u3)&)TY9C$sSi6HD{j;7p13vjFMX@>66HDinKw9i@KH(L|&Rg|as*CT7H zVdf;%mpi~WM+W5M*ZXC@7t?QZDIQ3OKxKzQLuo`J%Nng=-jsQ-b&hf{fc%V)mpkh~ zLq(^Bo^pHQ)CW?80l`pFeuWdcgM08pWeLoQlW^o8N71ph)Ugr3z0*mTlaB$W@RpbF zT$D2R)=LQqgk;KZC3BHd;{rYv(_;&e3%M+ah6&bqX8=h`W+*kNsxi&{^+rB>9))%% zuN0R{;+IZyUx{QKED(9>(N;3EM zNy1{Rd}1=5s4Wx;7Mq`Feg3wGIh*|Oy@Z0t2OIaEt`?mLnxcfPRo%zUY88dWV-hsd z1O4kv%Rkkaj5^n?^G_GS-QDjRG$U&2fBx*H4x`#wx=9n=PwO_%>=NZn=);E-WP96{ z$h-qDS}~!|EP1KJgNngu1;*a022*gSd5+47na;LR0wzh0!a^$v=Kp zVw}o@z(5ApK31}$`~u$KV&XEc*a}k#)iY6%7|~jWtTG9|jJ(sU-%)geaEF770Y&a$ zot@OFT{C6*x|+oq{-ZT+#~i3jkfSt@fDN6u4a88|uQ7!|+hJp-%H*)B7zpX1?^&=K z|7_xq`?HAiJu9sQBj(2-J#Q;_&RRbf3aBYLF&w%FxgIAj%`gw+KCO@?wAw%yp(rOC z8`Y9uvg4PuRwU_6PLoB_n4;6mWm#YR(lBS2FPc&@En=Roy?!n}?>6SpKQbTHuO%{d z>|h?3K;!8p(P_{9Yp&rg)cfk3m=^GoXN43xU zNe$ZCx-uFn`N~+e%l2Q0@70+q%x2BFE^}{P4TpGMc*y{sekBu6zY<&h?yVPq)X8Ye z!|TtqwbDV6F8oQod}*#rU&a+()pf7`#KoX;X|f=de9SmW`O+`2Br+hiCix>eec)F) zGUV0gMb0v%KN2^WGwR0RF~MHJSx`b#-MG&NrL7Yu>^xUBKhv_(=V~TfWc<_?%lP?| zY$!lM%iCEK4{rJh<7<|w{%)U$uv$8jGGp5n3X$y#i7M1tOxV

)*7p;1^w1rVr53 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�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

=X=`CyXvnYLRPBcPY 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 s%*=sd6iJ27rE~#TCS=M2v#|58Uv4p8x;= diff --git a/docs/source/user_guide/argo_workflows.md b/docs/source/user_guide/argo_workflows.md deleted file mode 100644 index a5c3da996c..0000000000 --- a/docs/source/user_guide/argo_workflows.md +++ /dev/null @@ -1,32 +0,0 @@ -# Argo Workflows - -Argo Workflows is an open source container-native workflow engine for orchestrating parallel jobs on Kubernetes. Argo -workflows comes enabled by default with Nebari deployments. - -## Accessing Argo Server - -If Argo Workflows is enabled, users can access argo workflows server at: `your-nebari-domain.com/argo`. Log in via -Keycloak with your usual credentials. - -## Submitting a Workflow via Argo Server - -You can submit a workflow by clicking "SUBMIT NEW WORKFLOW" on the landing page assuming you have the appropriate -permissions. - -![Argo Server Landing Page](../images/argo-server-landing-page.png) - -## Submitting a workflow via Argo CLI - -You can submit or manage workflows via the Argo CLI. The Argo CLI can be downloaded from the -[Argo Releases](https://github.com/argoproj/argo-workflows/releases) page. After downloading the CLI, you can get your -token from the Argo Server UI by clicking on the user tab in the bottom left corner and then clicking "Copy To -Clipboard". You'll need to make a few edits to access to what was copied for Argo CLI to work correctly. The base href -should be `ARGO_BASE_HREF=/argo` in the default nebari installation and you need to set the namespace where Argo was -deployed (dev by default) `ARGO_NAMESPACE=dev`. After setting those variables and the others copied from the Argo Server -UI, you can check that things are working by running `argo list`. - -![Argo Workflows User Tab](../images/argo-workflows-user-tab.png) - -## Additional Argo Workflows Resources - -Refer to the [Argo documentation](https://argoproj.github.io/argo-workflows/) for further details on Argo Workflows. diff --git a/nebari/template/stages/07-kubernetes-services/modules/kubernetes/services/monitoring/dashboards/Main/cluster_information.json b/nebari/template/stages/07-kubernetes-services/modules/kubernetes/services/monitoring/dashboards/Main/cluster_information.json deleted file mode 100644 index d6730a7755..0000000000 --- a/nebari/template/stages/07-kubernetes-services/modules/kubernetes/services/monitoring/dashboards/Main/cluster_information.json +++ /dev/null @@ -1,978 +0,0 @@ -{ - "annotations": { - "list": [ - { - "builtIn": 1, - "datasource": "-- Grafana --", - "enable": true, - "hide": true, - "iconColor": "rgba(0, 211, 255, 1)", - "name": "Annotations & Alerts", - "target": { - "limit": 100, - "matchAny": false, - "tags": [], - "type": "dashboard" - }, - "type": "dashboard" - } - ] - }, - "editable": true, - "fiscalYearStartMonth": 0, - "graphTooltip": 0, - "iteration": 1681232789057, - "links": [], - "liveNow": false, - "panels": [ - { - "collapse": false, - "collapsed": false, - "gridPos": { - "h": 1, - "w": 24, - "x": 0, - "y": 0 - }, - "id": 2, - "panels": [], - "showTitle": true, - "title": "Cluster Stats", - "titleSize": "h6", - "type": "row" - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": { - "uid": "$PROMETHEUS_DS" - }, - "decimals": 0, - "description": "Count of running users, grouped by namespace\n", - "fill": 1, - "fillGradient": 0, - "gridPos": { - "h": 10, - "w": 24, - "x": 0, - "y": 1 - }, - "hiddenSeries": false, - "id": 3, - "legend": { - "alignAsTable": false, - "avg": false, - "current": false, - "max": false, - "min": false, - "rightSide": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "links": [], - "nullPointMode": "null", - "options": { - "alertThreshold": true - }, - "percentage": false, - "pluginVersion": "8.3.3", - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "stack": true, - "steppedLine": false, - "targets": [ - { - "expr": "# Sum up all running user pods by namespace\nsum(\n # Grab a list of all running pods.\n # The group aggregator always returns \"1\" for the number of times each\n # unique label appears in the time series. This is desirable for this\n # use case because we're merely identifying running pods by name,\n # not how many times they might be running.\n group(\n kube_pod_status_phase{phase=\"Running\"}\n ) by (pod)\n * on (pod) group_right() group(\n kube_pod_labels{label_app=\"jupyterhub\", label_component=\"singleuser-server\"}\n ) by (namespace, pod)\n) by (namespace)\n", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "{{namespace}}", - "refId": "A" - } - ], - "thresholds": [], - "timeRegions": [], - "title": "Running Users", - "tooltip": { - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "mode": "time", - "show": true, - "values": [] - }, - "yaxes": [ - { - "decimals": 0, - "format": "short", - "logBase": 1, - "min": 0, - "show": true - }, - { - "decimals": 0, - "format": "short", - "logBase": 1, - "min": 0, - "show": true - } - ], - "yaxis": { - "align": false - } - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": { - "uid": "$PROMETHEUS_DS" - }, - "description": "% of total memory in the cluster currently requested by to non-placeholder pods.\n\nIf autoscaling is efficient, this should be a fairly constant, high number (>70%).\n", - "fill": 1, - "fillGradient": 0, - "gridPos": { - "h": 10, - "w": 12, - "x": 0, - "y": 11 - }, - "hiddenSeries": false, - "id": 4, - "legend": { - "alignAsTable": false, - "avg": false, - "current": false, - "max": false, - "min": false, - "rightSide": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "links": [], - "nullPointMode": "null", - "options": { - "alertThreshold": true - }, - "percentage": false, - "pluginVersion": "8.3.3", - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "sum(\n # Get individual container memory requests\n kube_pod_container_resource_requests{resource=\"memory\"}\n # Add node pool name as label\n * on(node) group_left(label_cloud_google_com_gke_nodepool)\n # group aggregator ensures that node names are unique per\n # pool.\n group(\n kube_node_labels\n ) by (node, label_cloud_google_com_gke_nodepool)\n # Ignore containers from pods that aren't currently running or scheduled\n # FIXME: This isn't the best metric here, evaluate what is.\n and on (pod) kube_pod_status_scheduled{condition='true'}\n # Ignore user and node placeholder pods\n and on (pod) kube_pod_labels{label_component!~'user-placeholder|node-placeholder'}\n) by (label_cloud_google_com_gke_nodepool)\n/\nsum(\n # Total allocatable memory on a node\n kube_node_status_allocatable{resource=\"memory\"}\n # Add nodepool name as label\n * on(node) group_left(label_cloud_google_com_gke_nodepool)\n # group aggregator ensures that node names are unique per\n # pool.\n group(\n kube_node_labels\n ) by (node, label_cloud_google_com_gke_nodepool)\n) by (label_cloud_google_com_gke_nodepool)\n", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "{{label_cloud_google_com_gke_nodepool}}", - "refId": "A" - } - ], - "thresholds": [], - "timeRegions": [], - "title": "Memory commitment %", - "tooltip": { - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "mode": "time", - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "percentunit", - "logBase": 1, - "max": 1, - "min": 0, - "show": true - }, - { - "format": "short", - "logBase": 1, - "max": 1, - "min": 0, - "show": true - } - ], - "yaxis": { - "align": false - } - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": { - "uid": "$PROMETHEUS_DS" - }, - "description": "% of total CPU in the cluster currently requested by to non-placeholder pods.\n\nJupyterHub users mostly are capped by memory, so this is not super useful.\n", - "fill": 1, - "fillGradient": 0, - "gridPos": { - "h": 10, - "w": 12, - "x": 12, - "y": 11 - }, - "hiddenSeries": false, - "id": 5, - "legend": { - "alignAsTable": false, - "avg": false, - "current": false, - "max": false, - "min": false, - "rightSide": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "links": [], - "nullPointMode": "null", - "options": { - "alertThreshold": true - }, - "percentage": false, - "pluginVersion": "8.3.3", - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "sum(\n # Get individual container memory requests\n kube_pod_container_resource_requests{resource=\"cpu\"}\n # Add node pool name as label\n * on(node) group_left(label_cloud_google_com_gke_nodepool)\n # group aggregator ensures that node names are unique per\n # pool.\n group(\n kube_node_labels\n ) by (node, label_cloud_google_com_gke_nodepool)\n # Ignore containers from pods that aren't currently running or scheduled\n # FIXME: This isn't the best metric here, evaluate what is.\n and on (pod) kube_pod_status_scheduled{condition='true'}\n # Ignore user and node placeholder pods\n and on (pod) kube_pod_labels{label_component!~'user-placeholder|node-placeholder'}\n) by (label_cloud_google_com_gke_nodepool)\n/\nsum(\n # Total allocatable CPU on a node\n kube_node_status_allocatable{resource=\"cpu\"}\n # Add nodepool name as label\n * on(node) group_left(label_cloud_google_com_gke_nodepool)\n # group aggregator ensures that node names are unique per\n # pool.\n group(\n kube_node_labels\n ) by (node, label_cloud_google_com_gke_nodepool)\n) by (label_cloud_google_com_gke_nodepool)\n", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "{{label_cloud_google_com_gke_nodepool}}", - "refId": "A" - } - ], - "thresholds": [], - "timeRegions": [], - "title": "CPU commitment %", - "tooltip": { - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "mode": "time", - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "percentunit", - "logBase": 1, - "max": 1, - "min": 0, - "show": true - }, - { - "format": "short", - "logBase": 1, - "max": 1, - "min": 0, - "show": true - } - ], - "yaxis": { - "align": false - } - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": { - "uid": "$PROMETHEUS_DS" - }, - "decimals": 0, - "fill": 1, - "fillGradient": 0, - "gridPos": { - "h": 10, - "w": 12, - "x": 0, - "y": 21 - }, - "hiddenSeries": false, - "id": 6, - "legend": { - "alignAsTable": false, - "avg": false, - "current": false, - "max": false, - "min": false, - "rightSide": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "links": [], - "nullPointMode": "null", - "options": { - "alertThreshold": true - }, - "percentage": false, - "pluginVersion": "8.3.3", - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "# sum up all nodes by nodepool\nsum(\n # kube_pod_labels comes from\n # https://github.com/kubernetes/kube-state-metrics, and there is a particular\n # label (kubernetes_node) that lists the node on which the kube-state-metrics pod\n # s running! So that's totally irrelevant to these queries, but when a nodepool\n # is rotated it caused there to exist two metrics with the same node value (which\n # we care about) but different kubernetes_node values (because kube-state-metrics\n # was running in a different node, even though we don't care about that). This\n # group really just drops all labels except the two we care about to\n # avoid messing things up.\n group(\n kube_node_labels\n ) by (node, label_cloud_google_com_gke_nodepool)\n) by (label_cloud_google_com_gke_nodepool)\n", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "{{label_cloud_google_com_gke_nodepool}}", - "refId": "A" - } - ], - "thresholds": [], - "timeRegions": [], - "title": "Node Count", - "tooltip": { - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "mode": "time", - "show": true, - "values": [] - }, - "yaxes": [ - { - "decimals": 0, - "format": "short", - "logBase": 1, - "min": 0, - "show": true - }, - { - "decimals": 0, - "format": "short", - "logBase": 1, - "min": 0, - "show": true - } - ], - "yaxis": { - "align": false - } - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": { - "uid": "$PROMETHEUS_DS" - }, - "decimals": 0, - "description": "Pods in states other than 'Running'.\n\nIn a functional clusters, pods should not be in non-Running states for long.\n", - "fill": 1, - "fillGradient": 0, - "gridPos": { - "h": 10, - "w": 12, - "x": 12, - "y": 21 - }, - "hiddenSeries": false, - "id": 7, - "legend": { - "alignAsTable": false, - "avg": false, - "current": false, - "hideZero": true, - "max": false, - "min": false, - "rightSide": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "links": [], - "nullPointMode": "null", - "options": { - "alertThreshold": true - }, - "percentage": false, - "pluginVersion": "8.3.3", - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "sum(kube_pod_status_phase{phase!=\"Running\"}) by (phase)", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "{{phase}}", - "refId": "A" - } - ], - "thresholds": [], - "timeRegions": [], - "title": "Non Running Pods", - "tooltip": { - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "mode": "time", - "show": true, - "values": [] - }, - "yaxes": [ - { - "decimals": 0, - "format": "short", - "logBase": 1, - "min": 0, - "show": true - }, - { - "decimals": 0, - "format": "short", - "logBase": 1, - "min": 0, - "show": true - } - ], - "yaxis": { - "align": false - } - }, - { - "collapse": false, - "collapsed": false, - "gridPos": { - "h": 1, - "w": 24, - "x": 0, - "y": 31 - }, - "id": 8, - "panels": [], - "showTitle": true, - "title": "Node Stats", - "titleSize": "h6", - "type": "row" - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": { - "uid": "$PROMETHEUS_DS" - }, - "description": "% of available CPUs currently in use\n", - "fill": 1, - "fillGradient": 0, - "gridPos": { - "h": 10, - "w": 12, - "x": 0, - "y": 32 - }, - "id": 9, - "legend": { - "alignAsTable": false, - "avg": false, - "current": false, - "max": false, - "min": false, - "rightSide": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "links": [], - "nullPointMode": "null", - "percentage": false, - "pluginVersion": "8.3.3", - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "sum(rate(node_cpu_seconds_total{mode!=\"idle\"}[5m])) by (node)\n/\nsum(kube_node_status_capacity{resource=\"cpu\"}) by (node)\n", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "{{ node }}", - "refId": "A" - } - ], - "thresholds": [], - "title": "Node CPU Utilization %", - "tooltip": { - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "mode": "time", - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "percentunit", - "logBase": 1, - "max": 1, - "min": 0, - "show": true - }, - { - "format": "short", - "logBase": 1, - "max": 1, - "min": 0, - "show": true - } - ] - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": { - "uid": "$PROMETHEUS_DS" - }, - "description": "% of available Memory currently in use\n", - "fill": 1, - "fillGradient": 0, - "gridPos": { - "h": 10, - "w": 12, - "x": 12, - "y": 32 - }, - "id": 10, - "legend": { - "alignAsTable": false, - "avg": false, - "current": false, - "max": false, - "min": false, - "rightSide": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "links": [], - "nullPointMode": "null", - "percentage": false, - "pluginVersion": "8.3.3", - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "1 - (\n sum (\n # Memory that can be allocated to processes when they need\n node_memory_MemFree_bytes + # Unused bytes\n node_memory_Cached_bytes + # Shared memory + temporary disk cache\n node_memory_Buffers_bytes # Very temporary buffer memory cache for disk i/o\n ) by (node)\n /\n sum(node_memory_MemTotal_bytes) by (node)\n)\n", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "{{node}}", - "refId": "A" - } - ], - "thresholds": [], - "title": "Node Memory Utilization %", - "tooltip": { - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "mode": "time", - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "percentunit", - "logBase": 1, - "max": 1, - "min": 0, - "show": true - }, - { - "format": "short", - "logBase": 1, - "max": 1, - "min": 0, - "show": true - } - ] - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": { - "uid": "$PROMETHEUS_DS" - }, - "description": "% of each node guaranteed to pods on it\n", - "fill": 1, - "fillGradient": 0, - "gridPos": { - "h": 10, - "w": 12, - "x": 0, - "y": 42 - }, - "id": 11, - "legend": { - "alignAsTable": false, - "avg": false, - "current": false, - "max": false, - "min": false, - "rightSide": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "links": [], - "nullPointMode": "null", - "percentage": false, - "pluginVersion": "8.3.3", - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "sum(\n # Get individual container CPU limits\n kube_pod_container_resource_requests{resource=\"cpu\"}\n # Ignore containers from pods that aren't currently running or scheduled\n # FIXME: This isn't the best metric here, evaluate what is.\n and on (pod) kube_pod_status_scheduled{condition='true'}\n # Ignore user and node placeholder pods\n and on (pod) kube_pod_labels{label_component!~'user-placeholder|node-placeholder'}\n) by (node)\n/\nsum(\n # Get individual container CPU requests\n kube_node_status_allocatable{resource=\"cpu\"}\n) by (node)\n", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "{{node}}", - "refId": "A" - } - ], - "thresholds": [], - "title": "Node CPU Commit %", - "tooltip": { - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "mode": "time", - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "percentunit", - "logBase": 1, - "max": 1, - "min": 0, - "show": true - }, - { - "format": "short", - "logBase": 1, - "max": 1, - "min": 0, - "show": true - } - ] - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": { - "uid": "$PROMETHEUS_DS" - }, - "description": "% of each node guaranteed to pods on it\n", - "fill": 1, - "fillGradient": 0, - "gridPos": { - "h": 10, - "w": 12, - "x": 12, - "y": 42 - }, - "id": 12, - "legend": { - "alignAsTable": false, - "avg": false, - "current": false, - "max": false, - "min": false, - "rightSide": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "links": [], - "nullPointMode": "null", - "percentage": false, - "pluginVersion": "8.3.3", - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "sum(\n # Get individual container memory limits\n kube_pod_container_resource_requests{resource=\"memory\"}\n # Ignore containers from pods that aren't currently running or scheduled\n # FIXME: This isn't the best metric here, evaluate what is.\n and on (pod) kube_pod_status_scheduled{condition='true'}\n # Ignore user and node placeholder pods\n and on (pod) kube_pod_labels{label_component!~'user-placeholder|node-placeholder'}\n) by (node)\n/\nsum(\n # Get individual container memory requests\n kube_node_status_allocatable{resource=\"memory\"}\n) by (node)\n", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "{{node}}", - "refId": "A" - } - ], - "thresholds": [], - "title": "Node Memory Commit %", - "tooltip": { - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "mode": "time", - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "percentunit", - "logBase": 1, - "max": 1, - "min": 0, - "show": true - }, - { - "format": "short", - "logBase": 1, - "max": 1, - "min": 0, - "show": true - } - ] - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": { - "uid": "$PROMETHEUS_DS" - }, - "decimals": 0, - "description": "Number of Out of Memory (OOM) kills in a given node.\n\nWhen users use up more memory than they are allowed, the notebook kernel they\nwere running usually gets killed and restarted. This graph shows the number of times\nthat happens on any given node, and helps validate that a notebook kernel restart was\ninfact caused by an OOM\n", - "fill": 1, - "fillGradient": 0, - "gridPos": { - "h": 10, - "w": 12, - "x": 0, - "y": 52 - }, - "id": 13, - "legend": { - "alignAsTable": false, - "avg": false, - "current": false, - "hideZero": true, - "max": false, - "min": false, - "rightSide": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "links": [], - "nullPointMode": "null", - "percentage": false, - "pluginVersion": "8.3.3", - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "# We use [2m] here, as node_exporter usually scrapes things at 1min intervals\n# And oom kills are distinct events, so we want to see 'how many have just happened',\n# rather than average over time.\nincrease(node_vmstat_oom_kill[2m])\n", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "{{ node }}", - "refId": "A" - } - ], - "thresholds": [], - "title": "Out of Memory kill count", - "tooltip": { - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "mode": "time", - "show": true, - "values": [] - }, - "yaxes": [ - { - "decimals": 0, - "format": "short", - "logBase": 1, - "min": 0, - "show": true - }, - { - "decimals": 0, - "format": "short", - "logBase": 1, - "min": 0, - "show": true - } - ] - } - ], - "refresh": "5s", - "schemaVersion": 34, - "style": "dark", - "tags": [ - "jupyterhub", - "kubernetes" - ], - "templating": { - "list": [ - { - "current": { - "selected": false, - "text": "Prometheus", - "value": "Prometheus" - }, - "hide": 1, - "includeAll": false, - "multi": false, - "name": "PROMETHEUS_DS", - "options": [], - "query": "prometheus", - "refresh": 1, - "regex": "", - "skipUrlSync": false, - "type": "datasource" - } - ] - }, - "time": { - "from": "now-6h", - "to": "now" - }, - "timepicker": { - "refresh_intervals": [ - "5s", - "10s", - "30s", - "1m", - "5m", - "15m", - "30m", - "1h", - "2h", - "1d" - ], - "time_options": [ - "5m", - "15m", - "1h", - "6h", - "12h", - "24h", - "2d", - "7d", - "30d" - ] - }, - "timezone": "browser", - "title": "Cluster Information", - "uid": "-whBDuL4k", - "version": 1, - "weekStart": "" -} diff --git a/nebari/template/stages/07-kubernetes-services/modules/kubernetes/services/monitoring/dashboards/Main/conda_store.json b/nebari/template/stages/07-kubernetes-services/modules/kubernetes/services/monitoring/dashboards/Main/conda_store.json deleted file mode 100644 index 724b130bc0..0000000000 --- a/nebari/template/stages/07-kubernetes-services/modules/kubernetes/services/monitoring/dashboards/Main/conda_store.json +++ /dev/null @@ -1,721 +0,0 @@ -{ - "annotations": { - "list": [ - { - "builtIn": 1, - "datasource": "-- Grafana --", - "enable": true, - "hide": true, - "iconColor": "rgba(0, 211, 255, 1)", - "name": "Annotations & Alerts", - "target": { - "limit": 100, - "matchAny": false, - "tags": [], - "type": "dashboard" - }, - "type": "dashboard" - } - ] - }, - "description": "", - "editable": true, - "fiscalYearStartMonth": 0, - "graphTooltip": 0, - "links": [], - "liveNow": false, - "panels": [ - { - "collapsed": false, - "gridPos": { - "h": 1, - "w": 24, - "x": 0, - "y": 0 - }, - "id": 6, - "panels": [], - "title": "Environments", - "type": "row" - }, - { - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "drawStyle": "line", - "fillOpacity": 0, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "lineInterpolation": "linear", - "lineWidth": 1, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "auto", - "spanNulls": true, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - }, - "mappings": [], - "min": 0, - "noValue": "0", - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - } - }, - "overrides": [] - }, - "gridPos": { - "h": 7, - "w": 24, - "x": 0, - "y": 1 - }, - "id": 18, - "options": { - "legend": { - "calcs": [], - "displayMode": "list", - "placement": "bottom" - }, - "tooltip": { - "mode": "single" - } - }, - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "PBFA97CFB590B2093" - }, - "exemplar": true, - "expr": "conda_store_build_queued", - "interval": "", - "legendFormat": "conda_store_build_queued", - "refId": "Queued" - }, - { - "datasource": { - "type": "prometheus", - "uid": "PBFA97CFB590B2093" - }, - "exemplar": true, - "expr": "conda_store_build_building", - "hide": false, - "instant": false, - "interval": "", - "legendFormat": "conda_store_build_building", - "refId": "Building" - }, - { - "datasource": { - "type": "prometheus", - "uid": "PBFA97CFB590B2093" - }, - "exemplar": true, - "expr": "conda_store_build_completed", - "hide": false, - "instant": false, - "interval": "", - "legendFormat": "conda_store_build_completed", - "refId": "Completed" - }, - { - "datasource": { - "type": "prometheus", - "uid": "PBFA97CFB590B2093" - }, - "exemplar": true, - "expr": "conda_store_build_failed", - "hide": false, - "interval": "", - "legendFormat": "conda_store_build_failed", - "refId": "Failed" - } - ], - "title": "Builds", - "type": "timeseries" - }, - { - "datasource": { - "type": "prometheus", - "uid": "PBFA97CFB590B2093" - }, - "fieldConfig": { - "defaults": { - "color": { - "mode": "thresholds" - }, - "mappings": [], - "noValue": "0", - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - } - }, - "overrides": [] - }, - "gridPos": { - "h": 3, - "w": 3, - "x": 0, - "y": 8 - }, - "id": 8, - "options": { - "colorMode": "value", - "graphMode": "none", - "justifyMode": "auto", - "orientation": "auto", - "reduceOptions": { - "calcs": [ - "lastNotNull" - ], - "fields": "", - "values": false - }, - "textMode": "auto" - }, - "pluginVersion": "8.3.3", - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "PBFA97CFB590B2093" - }, - "exemplar": true, - "expr": "conda_store_environments", - "interval": "", - "legendFormat": "", - "refId": "A" - } - ], - "title": "Environments", - "type": "stat" - }, - { - "datasource": { - "type": "prometheus", - "uid": "PBFA97CFB590B2093" - }, - "fieldConfig": { - "defaults": { - "color": { - "mode": "thresholds" - }, - "mappings": [], - "noValue": "0", - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - } - }, - "overrides": [] - }, - "gridPos": { - "h": 3, - "w": 3, - "x": 3, - "y": 8 - }, - "id": 10, - "options": { - "colorMode": "value", - "graphMode": "area", - "justifyMode": "auto", - "orientation": "auto", - "reduceOptions": { - "calcs": [ - "lastNotNull" - ], - "fields": "", - "values": false - }, - "textMode": "auto" - }, - "pluginVersion": "8.3.3", - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "PBFA97CFB590B2093" - }, - "exemplar": true, - "expr": "conda_store_build_queued", - "interval": "", - "legendFormat": "", - "refId": "A" - } - ], - "title": "Queued", - "type": "stat" - }, - { - "datasource": { - "type": "prometheus", - "uid": "PBFA97CFB590B2093" - }, - "fieldConfig": { - "defaults": { - "color": { - "mode": "thresholds" - }, - "mappings": [], - "noValue": "0", - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - } - }, - "overrides": [] - }, - "gridPos": { - "h": 3, - "w": 3, - "x": 6, - "y": 8 - }, - "id": 12, - "options": { - "colorMode": "value", - "graphMode": "area", - "justifyMode": "auto", - "orientation": "auto", - "reduceOptions": { - "calcs": [ - "lastNotNull" - ], - "fields": "", - "values": false - }, - "textMode": "auto" - }, - "pluginVersion": "8.3.3", - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "PBFA97CFB590B2093" - }, - "exemplar": true, - "expr": "conda_store_build_building", - "interval": "", - "legendFormat": "", - "refId": "A" - } - ], - "title": "Buliding", - "type": "stat" - }, - { - "datasource": { - "type": "prometheus", - "uid": "PBFA97CFB590B2093" - }, - "fieldConfig": { - "defaults": { - "color": { - "mode": "thresholds" - }, - "mappings": [], - "noValue": "0", - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - } - }, - "overrides": [] - }, - "gridPos": { - "h": 3, - "w": 3, - "x": 9, - "y": 8 - }, - "id": 14, - "options": { - "colorMode": "value", - "graphMode": "area", - "justifyMode": "auto", - "orientation": "auto", - "reduceOptions": { - "calcs": [ - "lastNotNull" - ], - "fields": "", - "values": false - }, - "textMode": "auto" - }, - "pluginVersion": "8.3.3", - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "PBFA97CFB590B2093" - }, - "exemplar": true, - "expr": "conda_store_build_completed", - "interval": "", - "legendFormat": "", - "refId": "A" - } - ], - "title": "Completed", - "type": "stat" - }, - { - "datasource": { - "type": "prometheus", - "uid": "PBFA97CFB590B2093" - }, - "fieldConfig": { - "defaults": { - "color": { - "mode": "thresholds" - }, - "mappings": [], - "noValue": "0", - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - } - }, - "overrides": [] - }, - "gridPos": { - "h": 3, - "w": 3, - "x": 12, - "y": 8 - }, - "id": 16, - "options": { - "colorMode": "value", - "graphMode": "area", - "justifyMode": "auto", - "orientation": "auto", - "reduceOptions": { - "calcs": [ - "lastNotNull" - ], - "fields": "", - "values": false - }, - "textMode": "auto" - }, - "pluginVersion": "8.3.3", - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "PBFA97CFB590B2093" - }, - "exemplar": true, - "expr": "conda_store_build_failed", - "interval": "", - "legendFormat": "", - "refId": "A" - } - ], - "title": "Failed", - "type": "stat" - }, - { - "collapsed": false, - "gridPos": { - "h": 1, - "w": 24, - "x": 0, - "y": 11 - }, - "id": 4, - "panels": [], - "title": "Storage", - "type": "row" - }, - { - "datasource": { - "type": "prometheus", - "uid": "PBFA97CFB590B2093" - }, - "fieldConfig": { - "defaults": { - "color": { - "mode": "continuous-GrYlRd" - }, - "mappings": [], - "max": 1, - "min": 0, - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 0.8 - } - ] - }, - "unit": "percentunit" - }, - "overrides": [] - }, - "gridPos": { - "h": 6, - "w": 8, - "x": 0, - "y": 12 - }, - "id": 2, - "options": { - "orientation": "auto", - "reduceOptions": { - "calcs": [ - "lastNotNull" - ], - "fields": "", - "values": false - }, - "showThresholdLabels": false, - "showThresholdMarkers": true - }, - "pluginVersion": "8.3.3", - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "PBFA97CFB590B2093" - }, - "exemplar": true, - "expr": "conda_store_disk_usage / conda_store_disk_total", - "interval": "", - "legendFormat": "", - "refId": "A" - } - ], - "title": "Disk Usage", - "type": "gauge" - }, - { - "datasource": { - "type": "prometheus", - "uid": "PBFA97CFB590B2093" - }, - "fieldConfig": { - "defaults": { - "color": { - "mode": "thresholds" - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - } - ] - }, - "unit": "decgbytes" - }, - "overrides": [] - }, - "gridPos": { - "h": 6, - "w": 7, - "x": 8, - "y": 12 - }, - "id": 20, - "options": { - "colorMode": "value", - "graphMode": "area", - "justifyMode": "auto", - "orientation": "auto", - "reduceOptions": { - "calcs": [ - "lastNotNull" - ], - "fields": "", - "values": false - }, - "textMode": "auto" - }, - "pluginVersion": "8.3.3", - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "PBFA97CFB590B2093" - }, - "exemplar": true, - "expr": "conda_store_disk_total / (2.0^30)", - "instant": false, - "interval": "", - "legendFormat": "", - "refId": "A" - } - ], - "title": "Total Storage", - "type": "stat" - }, - { - "datasource": { - "type": "prometheus", - "uid": "PBFA97CFB590B2093" - }, - "fieldConfig": { - "defaults": { - "color": { - "mode": "thresholds" - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - }, - "unit": "decgbytes" - }, - "overrides": [] - }, - "gridPos": { - "h": 6, - "w": 7, - "x": 15, - "y": 12 - }, - "id": 22, - "options": { - "colorMode": "value", - "graphMode": "area", - "justifyMode": "auto", - "orientation": "auto", - "reduceOptions": { - "calcs": [ - "lastNotNull" - ], - "fields": "", - "values": false - }, - "textMode": "auto" - }, - "pluginVersion": "8.3.3", - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "PBFA97CFB590B2093" - }, - "exemplar": true, - "expr": "conda_store_disk_usage / (2^30)", - "interval": "", - "legendFormat": "", - "refId": "A" - } - ], - "title": "Disk Used", - "type": "stat" - } - ], - "refresh": "5s", - "schemaVersion": 34, - "style": "dark", - "tags": [], - "templating": { - "list": [] - }, - "time": { - "from": "now-6h", - "to": "now" - }, - "timepicker": {}, - "timezone": "", - "title": "Conda-Store", - "uid": "7lHPaT1nz", - "version": 1, - "weekStart": "" -} diff --git a/nebari/template/stages/07-kubernetes-services/modules/kubernetes/services/monitoring/dashboards/Main/jupyterhub_dashboard.json b/nebari/template/stages/07-kubernetes-services/modules/kubernetes/services/monitoring/dashboards/Main/jupyterhub_dashboard.json deleted file mode 100644 index 0bbcfad3d1..0000000000 --- a/nebari/template/stages/07-kubernetes-services/modules/kubernetes/services/monitoring/dashboards/Main/jupyterhub_dashboard.json +++ /dev/null @@ -1,1350 +0,0 @@ -{ - "annotations": { - "list": [ - { - "builtIn": 1, - "datasource": "-- Grafana --", - "enable": true, - "hide": true, - "iconColor": "rgba(0, 211, 255, 1)", - "name": "Annotations & Alerts", - "target": { - "limit": 100, - "matchAny": false, - "tags": [], - "type": "dashboard" - }, - "type": "dashboard" - } - ] - }, - "editable": true, - "fiscalYearStartMonth": 0, - "graphTooltip": 0, - "iteration": 1681169262003, - "links": [], - "liveNow": false, - "panels": [ - { - "collapse": false, - "collapsed": false, - "gridPos": { - "h": 1, - "w": 24, - "x": 0, - "y": 0 - }, - "id": 2, - "panels": [], - "showTitle": true, - "title": "Hub usage stats", - "titleSize": "h6", - "type": "row" - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": { - "uid": "$PROMETHEUS_DS" - }, - "decimals": 0, - "fill": 1, - "fillGradient": 0, - "gridPos": { - "h": 11, - "w": 24, - "x": 0, - "y": 1 - }, - "hiddenSeries": false, - "id": 3, - "legend": { - "alignAsTable": false, - "avg": false, - "current": false, - "max": false, - "min": false, - "rightSide": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "links": [], - "nullPointMode": "null", - "options": { - "alertThreshold": true - }, - "percentage": false, - "pluginVersion": "8.3.3", - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "stack": true, - "steppedLine": false, - "targets": [ - { - "expr": "sum(\n group(\n kube_pod_status_phase{phase=\"Running\"}\n ) by (label_component, pod, namespace)\n * on (namespace, pod) group_right() \n group(\n kube_pod_labels{label_app=\"jupyterhub\", label_component=\"singleuser-server\", namespace=~\"$hub\"}\n ) by (pod, namespace)\n) by (namespace)\n", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "{{namespace}}", - "refId": "A" - } - ], - "thresholds": [], - "timeRegions": [], - "title": "Currently Active Users", - "tooltip": { - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "mode": "time", - "show": true, - "values": [] - }, - "yaxes": [ - { - "decimals": 0, - "format": "short", - "logBase": 1, - "min": 0, - "show": true - }, - { - "decimals": 0, - "format": "short", - "logBase": 1, - "min": 0, - "show": true - } - ], - "yaxis": { - "align": false - } - }, - { - "collapse": false, - "collapsed": false, - "gridPos": { - "h": 1, - "w": 24, - "x": 0, - "y": 12 - }, - "id": 7, - "panels": [], - "showTitle": true, - "title": "User Resource Utilization stats", - "titleSize": "h6", - "type": "row" - }, - { - "cards": {}, - "color": { - "cardColor": "#b4ff00", - "colorScale": "sqrt", - "colorScheme": "interpolateViridis", - "exponent": 0.5, - "mode": "spectrum" - }, - "dataFormat": "timeseries", - "datasource": { - "type": "prometheus", - "uid": "$PROMETHEUS_DS" - }, - "gridPos": { - "h": 10, - "w": 12, - "x": 0, - "y": 13 - }, - "heatmap": {}, - "hideZeroBuckets": false, - "highlightCards": true, - "id": 8, - "legend": { - "show": false - }, - "reverseYBuckets": false, - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "PBFA97CFB590B2093" - }, - "exemplar": true, - "expr": "(\n time()\n - (\n kube_pod_created{job='kube-state-metrics'}\n * on (namespace, pod) group_left()\n group(\n kube_pod_labels{label_app=\"jupyterhub\", label_component=\"singleuser-server\", namespace=~\"$hub\"}\n ) by (pod, namespace)\n )\n)\n", - "format": "time_series", - "interval": "600s", - "intervalFactor": 1, - "legendFormat": "", - "refId": "A" - } - ], - "title": "User active age distribution", - "tooltip": { - "show": true, - "showHistogram": false - }, - "type": "heatmap", - "xAxis": { - "show": true - }, - "xBucketSize": "600s", - "yAxis": { - "format": "s", - "logBase": 1, - "min": 0, - "show": true - }, - "yBucketBound": "auto" - }, - { - "cards": {}, - "color": { - "cardColor": "#b4ff00", - "colorScale": "sqrt", - "colorScheme": "interpolateViridis", - "exponent": 0.5, - "mode": "spectrum" - }, - "dataFormat": "timeseries", - "datasource": { - "uid": "$PROMETHEUS_DS" - }, - "gridPos": { - "h": 10, - "w": 12, - "x": 12, - "y": 13 - }, - "heatmap": {}, - "hideZeroBuckets": false, - "highlightCards": true, - "id": 9, - "legend": { - "show": false - }, - "reverseYBuckets": false, - "targets": [ - { - "expr": "sum(\n # exclude name=\"\" because the same container can be reported\n # with both no name and `name=k8s_...`,\n # in which case sum() by (pod) reports double the actual metric\n irate(container_cpu_usage_seconds_total{name!=\"\"}[5m])\n * on (namespace, pod) group_left(container) \n group(\n kube_pod_labels{label_app=\"jupyterhub\", label_component=\"singleuser-server\", namespace=~\"$hub\"}\n ) by (pod, namespace)\n) by (pod)\n", - "format": "time_series", - "interval": "600s", - "intervalFactor": 1, - "legendFormat": "", - "refId": "A" - } - ], - "title": "User CPU usage distribution", - "tooltip": { - "show": true, - "showHistogram": false - }, - "type": "heatmap", - "xAxis": { - "show": true - }, - "xBucketSize": "600s", - "yAxis": { - "format": "percentunit", - "logBase": 1, - "min": 0, - "show": true - }, - "yBucketBound": "auto" - }, - { - "cards": {}, - "color": { - "cardColor": "#b4ff00", - "colorScale": "sqrt", - "colorScheme": "interpolateViridis", - "exponent": 0.5, - "mode": "spectrum" - }, - "dataFormat": "timeseries", - "datasource": { - "uid": "$PROMETHEUS_DS" - }, - "gridPos": { - "h": 10, - "w": 12, - "x": 0, - "y": 23 - }, - "heatmap": {}, - "hideZeroBuckets": false, - "highlightCards": true, - "id": 10, - "legend": { - "show": false - }, - "reverseYBuckets": false, - "targets": [ - { - "expr": "sum(\n # exclude name=\"\" because the same container can be reported\n # with both no name and `name=k8s_...`,\n # in which case sum() by (pod) reports double the actual metric\n container_memory_working_set_bytes{name!=\"\"}\n * on (namespace, pod) group_left(container) \n group(\n kube_pod_labels{label_app=\"jupyterhub\", label_component=\"singleuser-server\", namespace=~\"$hub\"}\n ) by (pod, namespace)\n) by (pod)\n", - "format": "time_series", - "interval": "600s", - "intervalFactor": 1, - "legendFormat": "", - "refId": "A" - } - ], - "title": "User memory usage distribution", - "tooltip": { - "show": true, - "showHistogram": false - }, - "type": "heatmap", - "xAxis": { - "show": true - }, - "xBucketSize": "600s", - "yAxis": { - "format": "bytes", - "logBase": 1, - "min": 0, - "show": true - }, - "yBucketBound": "auto" - }, - { - "collapse": false, - "collapsed": false, - "gridPos": { - "h": 1, - "w": 24, - "x": 0, - "y": 33 - }, - "id": 11, - "panels": [], - "showTitle": true, - "title": "Hub Diagnostics", - "titleSize": "h6", - "type": "row" - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": { - "type": "prometheus", - "uid": "$PROMETHEUS_DS" - }, - "fill": 1, - "fillGradient": 0, - "gridPos": { - "h": 10, - "w": 12, - "x": 0, - "y": 34 - }, - "hiddenSeries": false, - "id": 12, - "legend": { - "alignAsTable": false, - "avg": false, - "current": false, - "max": false, - "min": false, - "rightSide": false, - "show": true, - "total": false, - "values": false - }, - "lines": false, - "linewidth": 1, - "links": [], - "nullPointMode": "null", - "options": { - "alertThreshold": true - }, - "percentage": false, - "pluginVersion": "8.3.3", - "pointradius": 2, - "points": true, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "stack": false, - "steppedLine": false, - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "PBFA97CFB590B2093" - }, - "exemplar": true, - "expr": "histogram_quantile(0.99, sum(rate(jupyterhub_server_spawn_duration_seconds_bucket{}[5m])) by (le))", - "format": "time_series", - "interval": "", - "intervalFactor": 2, - "legendFormat": "99th percentile", - "refId": "A" - }, - { - "datasource": { - "type": "prometheus", - "uid": "PBFA97CFB590B2093" - }, - "exemplar": true, - "expr": "histogram_quantile(0.5, sum(rate(jupyterhub_server_spawn_duration_seconds_bucket{}[5m])) by (le))", - "format": "time_series", - "interval": "", - "intervalFactor": 2, - "legendFormat": "50th percentile", - "refId": "B" - } - ], - "thresholds": [], - "timeRegions": [], - "title": "Server Start Times", - "tooltip": { - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "mode": "time", - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "s", - "logBase": 1, - "min": 0, - "show": true - }, - { - "format": "short", - "logBase": 1, - "min": 0, - "show": true - } - ], - "yaxis": { - "align": false - } - }, - { - "aliasColors": {}, - "bars": true, - "dashLength": 10, - "dashes": false, - "datasource": { - "uid": "$PROMETHEUS_DS" - }, - "description": "Attempts by users to start servers that failed.\n", - "fill": 1, - "fillGradient": 0, - "gridPos": { - "h": 10, - "w": 12, - "x": 12, - "y": 34 - }, - "hiddenSeries": false, - "id": 13, - "legend": { - "alignAsTable": false, - "avg": false, - "current": false, - "hideZero": true, - "max": false, - "min": false, - "rightSide": false, - "show": true, - "total": false, - "values": false - }, - "lines": false, - "linewidth": 1, - "links": [], - "nullPointMode": "null", - "options": { - "alertThreshold": true - }, - "percentage": false, - "pluginVersion": "8.3.3", - "pointradius": 2, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "sum(increase(jupyterhub_server_spawn_duration_seconds_count{status!=\"success\"}[2m])) by (status)", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "{{status}}", - "refId": "A" - } - ], - "thresholds": [], - "timeRegions": [], - "title": "Server Start Failures", - "tooltip": { - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "mode": "time", - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "short", - "logBase": 1, - "min": 0, - "show": true - }, - { - "format": "short", - "logBase": 1, - "min": 0, - "show": true - } - ], - "yaxis": { - "align": false - } - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": { - "type": "prometheus", - "uid": "$PROMETHEUS_DS" - }, - "fill": 1, - "fillGradient": 0, - "gridPos": { - "h": 10, - "w": 12, - "x": 0, - "y": 44 - }, - "hiddenSeries": false, - "id": 14, - "legend": { - "alignAsTable": false, - "avg": false, - "current": false, - "max": false, - "min": false, - "rightSide": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "links": [], - "nullPointMode": "null", - "options": { - "alertThreshold": true - }, - "percentage": false, - "pluginVersion": "8.3.3", - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "stack": false, - "steppedLine": false, - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "PBFA97CFB590B2093" - }, - "exemplar": true, - "expr": "histogram_quantile(\n 0.99,\n sum(\n rate(\n jupyterhub_request_duration_seconds_bucket{\n # Ignore SpawnProgressAPIHandler, as it is a EventSource stream\n # and keeps long lived connections open\n handler!=\"jupyterhub.apihandlers.users.SpawnProgressAPIHandler\"\n }[5m]\n )\n ) by (le))\n", - "format": "time_series", - "interval": "", - "intervalFactor": 2, - "legendFormat": "99th percentile", - "refId": "A" - }, - { - "datasource": { - "type": "prometheus", - "uid": "PBFA97CFB590B2093" - }, - "expr": "histogram_quantile(\n 0.50,\n sum(\n rate(\n jupyterhub_request_duration_seconds_bucket{\n app=\"jupyterhub\",\n namespace=~\"$hub\",\n # Ignore SpawnProgressAPIHandler, as it is a EventSource stream\n # and keeps long lived connections open\n handler!=\"jupyterhub.apihandlers.users.SpawnProgressAPIHandler\"\n }[5m]\n )\n ) by (le))\n", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "50th percentile", - "refId": "B" - } - ], - "thresholds": [], - "timeRegions": [], - "title": "Hub response latency", - "tooltip": { - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "mode": "time", - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "s", - "logBase": 1, - "min": 0, - "show": true - }, - { - "format": "short", - "logBase": 1, - "min": 0, - "show": true - } - ], - "yaxis": { - "align": false - } - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "fill": 1, - "fillGradient": 0, - "gridPos": { - "h": 12, - "w": 12, - "x": 12, - "y": 44 - }, - "hiddenSeries": false, - "id": 15, - "legend": { - "alignAsTable": true, - "avg": true, - "current": true, - "hideZero": true, - "max": true, - "min": false, - "rightSide": false, - "show": true, - "total": false, - "values": true - }, - "lines": true, - "linewidth": 1, - "links": [], - "nullPointMode": "null", - "options": { - "alertThreshold": true - }, - "percentage": false, - "pluginVersion": "8.3.3", - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "sum(\n # exclude name=\"\" because the same container can be reported\n# with both no name and `name=k8s_...`,\n# in which case sum() reports double the actual metric\nirate(container_cpu_usage_seconds_total{name!=\"\"}[5m])\n\n * on (namespace, pod) group_left(container, label_component) \n group(\n kube_pod_labels{label_app=\"jupyterhub\", label_component!=\"singleuser-server\", namespace=~\"$hub\"}\n ) by (pod, namespace)\n) by (label_component)\n", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "{{ label_component }}", - "refId": "A" - } - ], - "thresholds": [], - "timeRegions": [], - "title": "All JupyterHub Components CPU", - "tooltip": { - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "mode": "time", - "show": true, - "values": [] - }, - "yaxes": [ - { - "decimals": 1, - "format": "percentunit", - "logBase": 1, - "min": 0, - "show": true - }, - { - "format": "short", - "logBase": 1, - "min": 0, - "show": true - } - ], - "yaxis": { - "align": false - } - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "fill": 1, - "fillGradient": 0, - "gridPos": { - "h": 12, - "w": 12, - "x": 0, - "y": 54 - }, - "hiddenSeries": false, - "id": 16, - "legend": { - "alignAsTable": true, - "avg": true, - "current": true, - "hideZero": true, - "max": true, - "min": false, - "rightSide": false, - "show": true, - "total": false, - "values": true - }, - "lines": true, - "linewidth": 1, - "links": [], - "nullPointMode": "null", - "options": { - "alertThreshold": true - }, - "percentage": false, - "pluginVersion": "8.3.3", - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "sum(\n # exclude name=\"\" because the same container can be reported\n# with both no name and `name=k8s_...`,\n# in which case sum() reports double the actual metric\ncontainer_memory_working_set_bytes{name!=\"\"}\n\n * on (namespace, pod) group_left(container, label_component) \n group(\n kube_pod_labels{label_app=\"jupyterhub\", label_component!=\"singleuser-server\", namespace=~\"$hub\"}\n ) by (pod, namespace)\n) by (label_component)\n", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "{{ label_component }}", - "refId": "A" - } - ], - "thresholds": [], - "timeRegions": [], - "title": "All JupyterHub Components Memory (Working Set)", - "tooltip": { - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "mode": "time", - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "bytes", - "logBase": 1, - "min": 0, - "show": true - }, - { - "format": "short", - "logBase": 1, - "min": 0, - "show": true - } - ], - "yaxis": { - "align": false - } - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": { - "uid": "$PROMETHEUS_DS" - }, - "decimals": 0, - "description": "% of disk space left in the disk storing the JupyterHub sqlite database. If goes to 0, the hub will fail.\n", - "fill": 1, - "fillGradient": 0, - "gridPos": { - "h": 10, - "w": 12, - "x": 12, - "y": 56 - }, - "hiddenSeries": false, - "id": 17, - "legend": { - "alignAsTable": false, - "avg": false, - "current": false, - "max": false, - "min": false, - "rightSide": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "links": [], - "nullPointMode": "null", - "options": { - "alertThreshold": true - }, - "percentage": false, - "pluginVersion": "8.3.3", - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "# Free bytes available on the hub db PVC\nsum(kubelet_volume_stats_available_bytes{persistentvolumeclaim=\"hub-db-dir\", namespace=~\"$hub\"}) by (namespace) /\n# Total number of bytes available on the hub db PVC\nsum(kubelet_volume_stats_capacity_bytes{persistentvolumeclaim=\"hub-db-dir\", namespace=~\"$hub\"}) by (namespace)\n", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "{{ $hub }}", - "refId": "A" - } - ], - "thresholds": [], - "timeRegions": [], - "title": "Hub DB Disk Space Availability %", - "tooltip": { - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "mode": "time", - "show": true, - "values": [] - }, - "yaxes": [ - { - "decimals": 0, - "format": "percentunit", - "logBase": 1, - "max": 1, - "min": 0, - "show": true - }, - { - "decimals": 0, - "format": "short", - "logBase": 1, - "max": 1, - "min": 0, - "show": true - } - ], - "yaxis": { - "align": false - } - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": { - "uid": "$PROMETHEUS_DS" - }, - "description": "Pods in a non-running state in the hub's namespace.\n\nPods stuck in non-running states often indicate an error condition\n", - "fill": 1, - "fillGradient": 0, - "gridPos": { - "h": 10, - "w": 12, - "x": 0, - "y": 66 - }, - "hiddenSeries": false, - "id": 18, - "legend": { - "alignAsTable": false, - "avg": false, - "current": false, - "max": false, - "min": false, - "rightSide": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "links": [], - "nullPointMode": "null", - "options": { - "alertThreshold": true - }, - "percentage": false, - "pluginVersion": "8.3.3", - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "stack": true, - "steppedLine": false, - "targets": [ - { - "expr": "sum(\n kube_pod_status_phase{phase!=\"Running\", namespace=~\"$hub\"}\n) by (phase)\n", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "{{phase}}", - "refId": "A" - } - ], - "thresholds": [], - "timeRegions": [], - "title": "Non Running Pods", - "tooltip": { - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "mode": "time", - "show": true, - "values": [] - }, - "yaxes": [ - { - "decimals": 0, - "format": "short", - "logBase": 1, - "min": 0, - "show": true - }, - { - "format": "short", - "logBase": 1, - "min": 0, - "show": true - } - ], - "yaxis": { - "align": false - } - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": { - "uid": "$PROMETHEUS_DS" - }, - "decimals": 0, - "fill": 1, - "fillGradient": 0, - "gridPos": { - "h": 10, - "w": 12, - "x": 12, - "y": 66 - }, - "hiddenSeries": false, - "id": 19, - "legend": { - "alignAsTable": false, - "avg": false, - "current": false, - "max": false, - "min": false, - "rightSide": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "links": [], - "nullPointMode": "null", - "options": { - "alertThreshold": true - }, - "percentage": false, - "pluginVersion": "8.3.3", - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "sum(\n # kube_pod_info.node identifies the pod node,\n # while kube_pod_labels.node is the metrics exporter's node\n kube_pod_info{node!=\"\"}\n * on (namespace, pod) group_left() \n group(\n kube_pod_labels{label_app=\"jupyterhub\", label_component=\"singleuser-server\", namespace=~\"$hub\"}\n ) by (pod, namespace)\n) by (node)\n", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "{{ node }}", - "refId": "A" - } - ], - "thresholds": [], - "timeRegions": [], - "title": "Users per node", - "tooltip": { - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "mode": "time", - "show": true, - "values": [] - }, - "yaxes": [ - { - "decimals": 0, - "format": "short", - "logBase": 1, - "min": 0, - "show": true - }, - { - "decimals": 0, - "format": "short", - "logBase": 1, - "min": 0, - "show": true - } - ], - "yaxis": { - "align": false - } - }, - { - "collapse": false, - "collapsed": false, - "gridPos": { - "h": 1, - "w": 24, - "x": 0, - "y": 76 - }, - "id": 21, - "panels": [], - "showTitle": true, - "title": "Anomalous user pods", - "titleSize": "h6", - "type": "row" - }, - { - "columns": [], - "datasource": { - "type": "prometheus", - "uid": "$PROMETHEUS_DS" - }, - "description": "User pods that have been running for a long time (>8h).\n\nThis often indicates problems with the idle culler\n", - "fontSize": "100%", - "gridPos": { - "h": 12, - "w": 12, - "x": 0, - "y": 77 - }, - "id": 22, - "links": [], - "showHeader": true, - "sort": { - "col": 2, - "desc": true - }, - "styles": [ - { - "alias": "Age", - "align": "auto", - "pattern": "Value", - "type": "number", - "unit": "s" - }, - { - "alias": "Time", - "align": "auto", - "pattern": "Time", - "type": "hidden" - } - ], - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "PBFA97CFB590B2093" - }, - "exemplar": false, - "expr": "(\n time() - (kube_pod_created * on (namespace, pod) group_left\n group(\n kube_pod_labels{label_app=\"jupyterhub\", label_component=\"singleuser-server\", namespace=~\"$hub\"}\n ) by (pod, namespace))\n) > (60 * 60 * 8) # 8 hours is our threshold\n", - "format": "time_series", - "instant": true, - "interval": "", - "intervalFactor": 2, - "legendFormat": "{{namespace}}/{{pod}}", - "refId": "A" - } - ], - "title": "Very old user pods", - "transform": "timeseries_to_rows", - "type": "table-old" - }, - { - "columns": [], - "datasource": { - "type": "prometheus", - "uid": "$PROMETHEUS_DS" - }, - "description": "User pods using a lot of CPU\n\nThis could indicate a runaway process consuming resources\nunnecessarily.\n", - "fontSize": "100%", - "gridPos": { - "h": 12, - "w": 12, - "x": 12, - "y": 77 - }, - "id": 23, - "links": [], - "showHeader": true, - "sort": { - "col": 2, - "desc": true - }, - "styles": [ - { - "alias": "CPU usage", - "align": "auto", - "pattern": "Value", - "type": "number", - "unit": "percentunit" - }, - { - "alias": "Time", - "align": "auto", - "pattern": "Time", - "type": "hidden" - } - ], - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "PBFA97CFB590B2093" - }, - "exemplar": false, - "expr": "max( # Ideally we just want 'current' value, so max will do\n irate(container_cpu_usage_seconds_total[5m])\n * on (namespace, pod) group_left() \n group(\n kube_pod_labels{label_app=\"jupyterhub\", label_component=\"singleuser-server\", namespace=~\"$hub\"}\n ) by (pod, namespace)\n) by (namespace, pod) > 0.5\n", - "format": "time_series", - "instant": true, - "interval": "", - "intervalFactor": 2, - "legendFormat": "{{namespace}}/{{pod}}", - "refId": "A" - } - ], - "title": "User Pods with high CPU usage (>0.5)", - "transform": "timeseries_to_rows", - "type": "table-old" - }, - { - "columns": [], - "datasource": { - "type": "prometheus", - "uid": "$PROMETHEUS_DS" - }, - "description": "User pods getting close to their memory limit\n\nOnce they hit their memory limit, user kernels will start dying.\n", - "fontSize": "100%", - "gridPos": { - "h": 12, - "w": 12, - "x": 0, - "y": 89 - }, - "id": 24, - "links": [], - "showHeader": true, - "sort": { - "col": 2, - "desc": true - }, - "styles": [ - { - "alias": "% of mem limit consumed", - "align": "auto", - "pattern": "Value", - "type": "number", - "unit": "percentunit" - }, - { - "alias": "Time", - "align": "auto", - "pattern": "Time", - "type": "hidden" - } - ], - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "PBFA97CFB590B2093" - }, - "exemplar": false, - "expr": "max( # Ideally we just want 'current', but max will do. This metric is a gauge, so sum is inappropriate\n container_memory_working_set_bytes\n * on (namespace, pod) group_left() \n group(\n kube_pod_labels{label_app=\"jupyterhub\", label_component=\"singleuser-server\", namespace=~\"$hub\"}\n ) by (pod, namespace)\n) by (namespace, pod)\n/\nsum(\n kube_pod_container_resource_limits{resource=\"memory\"}\n * on (namespace, pod) group_left() \n group(\n kube_pod_labels{label_app=\"jupyterhub\", label_component=\"singleuser-server\", namespace=~\"$hub\"}\n ) by (pod, namespace)\n) by (namespace, pod)\n> 0.8\n", - "format": "time_series", - "instant": true, - "interval": "", - "intervalFactor": 2, - "legendFormat": "{{namespace}}/{{pod}}", - "refId": "A" - } - ], - "title": "User pods with high memory usage (>80% of limit)", - "transform": "timeseries_to_rows", - "type": "table-old" - } - ], - "refresh": "5s", - "schemaVersion": 34, - "style": "dark", - "tags": [ - "jupyterhub" - ], - "templating": { - "list": [ - { - "current": { - "selected": false, - "text": "Prometheus", - "value": "Prometheus" - }, - "hide": 1, - "includeAll": false, - "multi": false, - "name": "PROMETHEUS_DS", - "options": [], - "query": "prometheus", - "refresh": 1, - "regex": "", - "skipUrlSync": false, - "type": "datasource" - }, - { - "current": { - "selected": true, - "text": [ - "dev" - ], - "value": [ - "dev" - ] - }, - "datasource": { - "uid": "$PROMETHEUS_DS" - }, - "definition": "", - "hide": 0, - "includeAll": true, - "multi": true, - "name": "hub", - "options": [], - "query": { - "query": "label_values(kube_service_labels{service=\"hub\"}, namespace)", - "refId": "Prometheus-hub-Variable-Query" - }, - "refresh": 1, - "regex": "", - "skipUrlSync": false, - "sort": 0, - "tagValuesQuery": "", - "tagsQuery": "", - "type": "query", - "useTags": false - } - ] - }, - "time": { - "from": "now-6h", - "to": "now" - }, - "timepicker": { - "refresh_intervals": [ - "5s", - "10s", - "30s", - "1m", - "5m", - "15m", - "30m", - "1h", - "2h", - "1d" - ], - "time_options": [ - "5m", - "15m", - "1h", - "6h", - "12h", - "24h", - "2d", - "7d", - "30d" - ] - }, - "timezone": "browser", - "title": "JupyterHub Dashboard", - "uid": "hub-dashboard", - "version": 1, - "weekStart": "" -} diff --git a/nebari/template/stages/07-kubernetes-services/modules/kubernetes/services/monitoring/dashboards/Main/keycloak.json b/nebari/template/stages/07-kubernetes-services/modules/kubernetes/services/monitoring/dashboards/Main/keycloak.json deleted file mode 100644 index 41fea2ad23..0000000000 --- a/nebari/template/stages/07-kubernetes-services/modules/kubernetes/services/monitoring/dashboards/Main/keycloak.json +++ /dev/null @@ -1,2165 +0,0 @@ -{ - "annotations": { - "list": [ - { - "builtIn": 1, - "datasource": "-- Grafana --", - "enable": true, - "hide": true, - "iconColor": "rgba(0, 211, 255, 1)", - "name": "Annotations & Alerts", - "target": { - "limit": 100, - "matchAny": false, - "tags": [], - "type": "dashboard" - }, - "type": "dashboard" - }, - { - "datasource": "-- Grafana --", - "enable": true, - "iconColor": "rgba(0, 211, 255, 1)", - "iconSize": 0, - "lineColor": "", - "name": "Annotations & Alerts", - "query": "", - "showLine": false, - "tagsField": "", - "target": { - "limit": 100, - "matchAny": false, - "tags": [], - "type": "dashboard" - }, - "textField": "", - "type": "dashboard" - } - ] - }, - "description": "An updated version of dashboard Keycloak metrics exported with Keycloak Metrics SPI\n\nhttps://github.com/aerogear/keycloak-metrics-spi", - "editable": true, - "fiscalYearStartMonth": 0, - "gnetId": 14607, - "graphTooltip": 1, - "iteration": 1642196323079, - "links": [], - "liveNow": false, - "panels": [ - { - "CustomPanel": { - "datasource": "$Datasource", - "description": "Memory currently being used by Keycloak.", - "fieldConfig": { - "defaults": { - "color": { - "mode": "thresholds" - }, - "custom": {}, - "mappings": [], - "max": 100, - "min": 0, - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green" - }, - { - "color": "#EAB839", - "value": 80 - }, - { - "color": "red", - "value": 90 - } - ] - }, - "unit": "percent" - }, - "overrides": [] - }, - "gridPos": { - "h": 7, - "w": 6, - "x": 0, - "y": 0 - }, - "hideTimeOverride": false, - "id": 5, - "links": [], - "options": { - "orientation": "auto", - "reduceOptions": { - "calcs": [ - "mean" - ], - "fields": "", - "values": false - }, - "showThresholdLabels": false, - "showThresholdMarkers": true - }, - "pluginVersion": "7.2.0", - "targets": [ - { - "expr": "sum(jvm_memory_bytes_used{instance=\"$instance\", area=\"heap\"})*100/sum(jvm_memory_bytes_max{instance=\"$instance\", area=\"heap\"})\n", - "format": "time_series", - "hide": false, - "instant": false, - "intervalFactor": 1, - "legendFormat": "", - "refId": "B" - } - ], - "title": "Current Memory HEAP", - "type": "gauge" - }, - "datasource": { - "uid": "$Datasource" - }, - "editable": false, - "error": false, - "fieldConfig": { - "defaults": { - "mappings": [], - "max": 100, - "min": 0, - "thresholds": { - "mode": "percentage", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "#EAB839", - "value": 80 - }, - { - "color": "red", - "value": 90 - } - ] - }, - "unit": "percent" - }, - "overrides": [] - }, - "gridPos": { - "h": 7, - "w": 6, - "x": 0, - "y": 0 - }, - "hideTimeOverride": false, - "id": 5, - "isNew": false, - "options": { - "orientation": "auto", - "reduceOptions": { - "calcs": [ - "mean" - ], - "fields": "", - "values": false - }, - "showThresholdLabels": false, - "showThresholdMarkers": true - }, - "pluginVersion": "8.3.3", - "span": 0, - "targets": [ - { - "expr": "sum(jvm_memory_bytes_used{pod=\"$instance\", area=\"heap\"})*100/sum(jvm_memory_bytes_max{pod=\"$instance\", area=\"heap\"})", - "interval": "", - "legendFormat": "", - "refId": "A" - } - ], - "title": "Current Memory HEAP", - "type": "gauge" - }, - { - "CustomPanel": { - "datasource": "$Datasource", - "description": "Memory currently being used by Keycloak.", - "fieldConfig": { - "defaults": { - "color": { - "mode": "thresholds" - }, - "custom": {}, - "mappings": [], - "max": 100, - "min": 0, - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green" - }, - { - "color": "#EAB839", - "value": 80 - }, - { - "color": "red", - "value": 90 - } - ] - }, - "unit": "percent" - }, - "overrides": [] - }, - "gridPos": { - "h": 7, - "w": 6, - "x": 6, - "y": 0 - }, - "hideTimeOverride": false, - "id": 23, - "links": [], - "options": { - "orientation": "auto", - "reduceOptions": { - "calcs": [ - "mean" - ], - "fields": "", - "values": false - }, - "showThresholdLabels": false, - "showThresholdMarkers": true - }, - "pluginVersion": "7.2.0", - "targets": [ - { - "expr": "sum(jvm_memory_bytes_used{instance=\"$instance\", area=\"nonheap\"})*100/sum(jvm_memory_bytes_max{instance=\"$instance\", area=\"nonheap\"})", - "format": "time_series", - "hide": false, - "instant": false, - "intervalFactor": 1, - "legendFormat": "", - "refId": "B" - } - ], - "title": "Current Memory nonHEAP", - "type": "gauge" - }, - "datasource": { - "uid": "$Datasource" - }, - "editable": false, - "error": false, - "fieldConfig": { - "defaults": { - "mappings": [], - "max": 100, - "min": 0, - "thresholds": { - "mode": "percentage", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "#EAB839", - "value": 80 - }, - { - "color": "red", - "value": 90 - } - ] - }, - "unit": "percent" - }, - "overrides": [] - }, - "gridPos": { - "h": 7, - "w": 6, - "x": 6, - "y": 0 - }, - "hideTimeOverride": false, - "id": 23, - "isNew": false, - "options": { - "orientation": "auto", - "reduceOptions": { - "calcs": [ - "mean" - ], - "fields": "", - "values": false - }, - "showThresholdLabels": false, - "showThresholdMarkers": true - }, - "pluginVersion": "8.3.3", - "span": 0, - "targets": [ - { - "expr": "sum(jvm_memory_bytes_used{pod=\"$instance\", area=\"nonheap\"})*100/sum(jvm_memory_bytes_max{pod=\"$instance\", area=\"nonheap\"})", - "interval": "", - "legendFormat": "", - "refId": "A" - } - ], - "title": "Current Memory nonHEAP", - "type": "gauge" - }, - { - "datasource": { - "uid": "$Datasource" - }, - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "drawStyle": "line", - "fillOpacity": 20, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "lineInterpolation": "linear", - "lineWidth": 1, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "never", - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - }, - "mappings": [], - "min": 0, - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - }, - "unit": "bytes" - }, - "overrides": [] - }, - "gridPos": { - "h": 7, - "w": 12, - "x": 12, - "y": 0 - }, - "hideTimeOverride": false, - "id": 12, - "options": { - "legend": { - "calcs": [], - "displayMode": "list", - "placement": "right" - }, - "tooltip": { - "mode": "single" - } - }, - "pluginVersion": "8.3.3", - "targets": [ - { - "expr": "sum(jvm_memory_bytes_max{pod=\"$instance\"})", - "format": "time_series", - "interval": "", - "intervalFactor": 1, - "legendFormat": "Max", - "refId": "A" - }, - { - "expr": "sum(jvm_memory_bytes_committed{pod=\"$instance\"})", - "format": "time_series", - "interval": "", - "intervalFactor": 1, - "legendFormat": "Comitted", - "refId": "C" - }, - { - "expr": "sum(jvm_memory_bytes_used{pod=\"$instance\"})", - "format": "time_series", - "interval": "", - "intervalFactor": 1, - "legendFormat": "Used", - "refId": "B" - } - ], - "title": "Memory Usage", - "type": "timeseries" - }, - { - "datasource": { - "type": "prometheus", - "uid": "$Datasource" - }, - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - } - }, - "decimals": 0, - "mappings": [], - "unit": "short" - }, - "overrides": [] - }, - "gridPos": { - "h": 7, - "w": 6, - "x": 0, - "y": 7 - }, - "hideTimeOverride": true, - "id": 16, - "links": [], - "options": { - "legend": { - "calcs": [], - "displayMode": "table", - "placement": "right", - "values": [ - "percent" - ] - }, - "pieType": "pie", - "reduceOptions": { - "calcs": [ - "lastNotNull" - ], - "fields": "", - "values": false - }, - "tooltip": { - "mode": "single" - } - }, - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "PBFA97CFB590B2093" - }, - "exemplar": true, - "expr": "sum by (realm)(increase(keycloak_logins[24h]))", - "interval": "", - "legendFormat": "{{realm}}", - "refId": "A" - } - ], - "title": "Logins Per REALM for past 24h", - "type": "piechart" - }, - { - "datasource": { - "type": "prometheus", - "uid": "$Datasource" - }, - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - } - }, - "decimals": 0, - "mappings": [], - "unit": "short" - }, - "overrides": [] - }, - "gridPos": { - "h": 7, - "w": 6, - "x": 6, - "y": 7 - }, - "id": 44, - "links": [], - "options": { - "legend": { - "calcs": [], - "displayMode": "table", - "placement": "right", - "values": [ - "percent" - ] - }, - "pieType": "pie", - "reduceOptions": { - "calcs": [ - "lastNotNull" - ], - "fields": "", - "values": false - }, - "tooltip": { - "mode": "single" - } - }, - "pluginVersion": "7.2.0", - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "PBFA97CFB590B2093" - }, - "exemplar": true, - "expr": "sum by (realm)(increase(keycloak_registrations[24h]))", - "interval": "", - "legendFormat": "{{realm}}", - "refId": "A" - } - ], - "title": "Registrations Per REALM for past 24h", - "type": "piechart" - }, - { - "datasource": { - "type": "prometheus", - "uid": "$Datasource" - }, - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - } - }, - "decimals": 0, - "mappings": [], - "unit": "short" - }, - "overrides": [] - }, - "gridPos": { - "h": 7, - "w": 6, - "x": 12, - "y": 7 - }, - "hideTimeOverride": true, - "id": 20, - "links": [], - "options": { - "legend": { - "calcs": [], - "displayMode": "table", - "placement": "right", - "values": [ - "percent" - ] - }, - "pieType": "pie", - "reduceOptions": { - "calcs": [ - "lastNotNull" - ], - "fields": "", - "values": false - }, - "tooltip": { - "mode": "single" - } - }, - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "PBFA97CFB590B2093" - }, - "exemplar": true, - "expr": "sum by (client_id)(increase(keycloak_logins[24h]))", - "interval": "", - "legendFormat": "{{client_id}}", - "refId": "A" - } - ], - "title": "Logins Per CLIENT for past 24h", - "type": "piechart" - }, - { - "datasource": { - "uid": "$Datasource" - }, - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - } - }, - "decimals": 0, - "mappings": [], - "unit": "short" - }, - "overrides": [] - }, - "gridPos": { - "h": 7, - "w": 6, - "x": 18, - "y": 7 - }, - "hideTimeOverride": true, - "id": 17, - "links": [], - "options": { - "legend": { - "calcs": [], - "displayMode": "table", - "placement": "right", - "values": [ - "percent" - ] - }, - "pieType": "pie", - "reduceOptions": { - "calcs": [ - "lastNotNull" - ], - "fields": "", - "values": false - }, - "tooltip": { - "mode": "single" - } - }, - "targets": [ - { - "expr": "sum by (client_id)(increase(keycloak_registrations[24h]))", - "interval": "", - "legendFormat": "{{client_id}}", - "refId": "A" - } - ], - "title": "Registrations Per CLIENT for past 24h", - "type": "piechart" - }, - { - "datasource": { - "uid": "$Datasource" - }, - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "drawStyle": "line", - "fillOpacity": 10, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "lineInterpolation": "linear", - "lineWidth": 1, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "never", - "spanNulls": true, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - }, - "unit": "short" - }, - "overrides": [] - }, - "gridPos": { - "h": 8, - "w": 12, - "x": 6, - "y": 14 - }, - "id": 46, - "options": { - "legend": { - "calcs": [], - "displayMode": "list", - "placement": "bottom" - }, - "tooltip": { - "mode": "single" - } - }, - "pluginVersion": "8.3.3", - "targets": [ - { - "expr": "sum by (code)(increase(keycloak_response_errors[30m]))", - "interval": "", - "legendFormat": "{{code}}", - "refId": "A" - } - ], - "title": "4xx and 5xx Responses", - "type": "timeseries" - }, - { - "datasource": { - "type": "prometheus", - "uid": "$Datasource" - }, - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "drawStyle": "line", - "fillOpacity": 10, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "lineInterpolation": "linear", - "lineWidth": 1, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "never", - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - }, - "mappings": [], - "min": 0, - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - }, - "unit": "none" - }, - "overrides": [] - }, - "gridPos": { - "h": 8, - "w": 12, - "x": 0, - "y": 22 - }, - "hideTimeOverride": false, - "id": 1, - "options": { - "legend": { - "calcs": [], - "displayMode": "table", - "placement": "right" - }, - "tooltip": { - "mode": "single" - } - }, - "pluginVersion": "8.3.3", - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "PBFA97CFB590B2093" - }, - "exemplar": true, - "expr": "sum by (realm)(increase(keycloak_logins[30m]))", - "format": "time_series", - "interval": "", - "intervalFactor": 1, - "legendFormat": "{{realm}}", - "refId": "A" - } - ], - "title": "Logins per REALM", - "type": "timeseries" - }, - { - "datasource": { - "uid": "$Datasource" - }, - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "drawStyle": "line", - "fillOpacity": 10, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "lineInterpolation": "linear", - "lineWidth": 1, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "never", - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - }, - "mappings": [], - "min": 0, - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - }, - "unit": "none" - }, - "overrides": [] - }, - "gridPos": { - "h": 8, - "w": 12, - "x": 12, - "y": 22 - }, - "hideTimeOverride": false, - "id": 7, - "options": { - "legend": { - "calcs": [ - "lastNotNull" - ], - "displayMode": "table", - "placement": "right" - }, - "tooltip": { - "mode": "single" - } - }, - "pluginVersion": "8.3.3", - "targets": [ - { - "expr": "sum by (error) (increase(keycloak_failed_login_attempts{provider=\"keycloak\",realm=\"$realm\"}[30m]))", - "format": "time_series", - "interval": "", - "intervalFactor": 1, - "legendFormat": "{{$realm }} {{error}}", - "refId": "A" - }, - { - "expr": "sum by (realm) (increase(keycloak_failed_login_attempts{provider=\"keycloak\",realm=\"dialog-test\"} [30m]))", - "interval": "", - "legendFormat": "{{sum by $realm}}", - "refId": "B" - } - ], - "title": "Login Errors on realm $realm", - "type": "timeseries" - }, - { - "datasource": { - "uid": "$Datasource" - }, - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "drawStyle": "line", - "fillOpacity": 10, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "lineInterpolation": "linear", - "lineWidth": 1, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "never", - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - }, - "mappings": [], - "min": 0, - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - }, - "unit": "none" - }, - "overrides": [] - }, - "gridPos": { - "h": 8, - "w": 12, - "x": 0, - "y": 30 - }, - "hideTimeOverride": false, - "id": 18, - "options": { - "legend": { - "calcs": [], - "displayMode": "table", - "placement": "right" - }, - "tooltip": { - "mode": "single" - } - }, - "pluginVersion": "8.3.3", - "targets": [ - { - "expr": "sum by (client_id)(increase(keycloak_logins{realm=\"$realm\",provider=\"keycloak\"}[30m]))", - "format": "time_series", - "interval": "", - "intervalFactor": 2, - "legendFormat": "{{client_id}}", - "refId": "A" - } - ], - "title": "Logins per CLIENT on realm $realm", - "type": "timeseries" - }, - { - "datasource": { - "uid": "$Datasource" - }, - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "drawStyle": "line", - "fillOpacity": 10, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "lineInterpolation": "linear", - "lineWidth": 1, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "never", - "spanNulls": true, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - }, - "unit": "short" - }, - "overrides": [] - }, - "gridPos": { - "h": 8, - "w": 12, - "x": 12, - "y": 30 - }, - "hideTimeOverride": false, - "id": 21, - "options": { - "legend": { - "calcs": [], - "displayMode": "table", - "placement": "right" - }, - "tooltip": { - "mode": "single" - } - }, - "pluginVersion": "8.3.3", - "targets": [ - { - "expr": "sum by (realm) (increase(keycloak_registrations_errors{provider=\"keycloak\",realm=\"$realm\"} [30m]))", - "format": "time_series", - "interval": "", - "intervalFactor": 2, - "legendFormat": "Sum by {{realm}}", - "refId": "A" - }, - { - "expr": "sum by (error) (increase(keycloak_registrations_errors{provider=\"keycloak\",realm=\"$realm\"} [30m]))", - "interval": "", - "legendFormat": "{{error}}", - "refId": "B" - } - ], - "title": "Registration Errors on realm $realm", - "type": "timeseries" - }, - { - "datasource": { - "uid": "$Datasource" - }, - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "drawStyle": "line", - "fillOpacity": 10, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "lineInterpolation": "linear", - "lineWidth": 1, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "never", - "spanNulls": true, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - }, - "mappings": [], - "min": 0, - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - }, - "unit": "short" - }, - "overrides": [] - }, - "gridPos": { - "h": 8, - "w": 12, - "x": 0, - "y": 38 - }, - "hideTimeOverride": false, - "id": 33, - "options": { - "legend": { - "calcs": [], - "displayMode": "table", - "placement": "right" - }, - "tooltip": { - "mode": "single" - } - }, - "pluginVersion": "8.3.3", - "targets": [ - { - "expr": "sum by (realm)(increase(keycloak_registrations[30m]))", - "format": "time_series", - "interval": "", - "intervalFactor": 1, - "legendFormat": "{{realm}}", - "refId": "A" - } - ], - "title": "Registrations per REALM", - "type": "timeseries" - }, - { - "datasource": { - "uid": "$Datasource" - }, - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "drawStyle": "line", - "fillOpacity": 10, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "lineInterpolation": "linear", - "lineWidth": 1, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "never", - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - }, - "mappings": [], - "min": 0, - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - }, - "unit": "none" - }, - "overrides": [] - }, - "gridPos": { - "h": 8, - "w": 12, - "x": 12, - "y": 38 - }, - "hideTimeOverride": false, - "id": 19, - "options": { - "legend": { - "calcs": [ - "lastNotNull" - ], - "displayMode": "table", - "placement": "right" - }, - "tooltip": { - "mode": "single" - } - }, - "pluginVersion": "8.3.3", - "targets": [ - { - "expr": "sum by (error) (increase(keycloak_failed_login_attempts{provider=\"keycloak\",realm=\"$realm\",client_id=\"$ClientId\"}[30m]))", - "format": "time_series", - "interval": "", - "intervalFactor": 2, - "legendFormat": "{{error}}", - "refId": "A" - } - ], - "title": "Login Errors for $ClientId", - "type": "timeseries" - }, - { - "datasource": { - "uid": "$Datasource" - }, - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "drawStyle": "line", - "fillOpacity": 10, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "lineInterpolation": "linear", - "lineWidth": 1, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "never", - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - }, - "mappings": [], - "min": 0, - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - }, - "unit": "none" - }, - "overrides": [] - }, - "gridPos": { - "h": 8, - "w": 12, - "x": 0, - "y": 46 - }, - "hideTimeOverride": false, - "id": 22, - "options": { - "legend": { - "calcs": [], - "displayMode": "table", - "placement": "right" - }, - "tooltip": { - "mode": "single" - } - }, - "pluginVersion": "8.3.3", - "targets": [ - { - "expr": "sum by (client_id)(increase(keycloak_registrations{realm=\"$realm\",provider=\"keycloak\"}[30m]))", - "format": "time_series", - "interval": "", - "intervalFactor": 2, - "legendFormat": "{{client_id}}", - "refId": "A" - }, - { - "expr": "sum by (realm)(increase(keycloak_registrations{provider=\"keycloak\",realm=\"$realm\"} [30m]))", - "interval": "", - "legendFormat": "Sum by {{realm}}", - "refId": "B" - } - ], - "title": "Registrations per CLIENT on Realm $realm", - "type": "timeseries" - }, - { - "datasource": { - "uid": "$Datasource" - }, - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "drawStyle": "line", - "fillOpacity": 10, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "lineInterpolation": "linear", - "lineWidth": 1, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "never", - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - }, - "mappings": [], - "min": 0, - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - }, - "unit": "none" - }, - "overrides": [] - }, - "gridPos": { - "h": 8, - "w": 12, - "x": 12, - "y": 46 - }, - "hideTimeOverride": false, - "id": 34, - "options": { - "legend": { - "calcs": [ - "lastNotNull" - ], - "displayMode": "table", - "placement": "right" - }, - "tooltip": { - "mode": "single" - } - }, - "pluginVersion": "8.3.3", - "targets": [ - { - "expr": "sum by (error) (increase(keycloak_registrations_errors{provider=\"keycloak\",realm=\"$realm\",client_id=\"$ClientId\"}[30m]))", - "format": "time_series", - "interval": "", - "intervalFactor": 2, - "legendFormat": "{{error}}", - "refId": "A" - } - ], - "title": "Registration Errors for $ClientId", - "type": "timeseries" - }, - { - "cards": {}, - "color": { - "cardColor": "#73BF69", - "colorScale": "sqrt", - "colorScheme": "interpolateGreens", - "exponent": 0.4, - "mode": "opacity" - }, - "dataFormat": "tsbuckets", - "datasource": { - "uid": "$Datasource" - }, - "description": "", - "gridPos": { - "h": 8, - "w": 12, - "x": 0, - "y": 54 - }, - "heatmap": {}, - "hideTimeOverride": false, - "hideZeroBuckets": true, - "highlightCards": true, - "id": 35, - "legend": { - "show": true - }, - "pluginVersion": "7.2.0", - "reverseYBuckets": false, - "targets": [ - { - "expr": "sum(increase(keycloak_request_duration_bucket{method=\"GET\"}[30m])) by (le)", - "format": "heatmap", - "interval": "", - "intervalFactor": 4, - "legendFormat": "{{ le }}", - "refId": "A" - } - ], - "title": "Request duration method = \"GET\" Heatmap", - "tooltip": { - "show": true, - "showHistogram": false - }, - "type": "heatmap", - "xAxis": { - "show": true - }, - "yAxis": { - "format": "ms", - "logBase": 1, - "show": true - }, - "yBucketBound": "auto" - }, - { - "datasource": { - "uid": "$Datasource" - }, - "description": "", - "fieldConfig": { - "defaults": { - "mappings": [], - "max": 100, - "min": 0, - "thresholds": { - "mode": "percentage", - "steps": [ - { - "color": "red", - "value": null - }, - { - "color": "red", - "value": 80 - }, - { - "color": "#EAB839", - "value": 90 - }, - { - "color": "green", - "value": 98 - } - ] - }, - "unit": "percent" - }, - "overrides": [] - }, - "gridPos": { - "h": 8, - "w": 12, - "x": 12, - "y": 54 - }, - "hideTimeOverride": false, - "id": 39, - "options": { - "orientation": "auto", - "reduceOptions": { - "calcs": [ - "mean" - ], - "fields": "", - "values": false - }, - "showThresholdLabels": false, - "showThresholdMarkers": true - }, - "pluginVersion": "8.3.3", - "targets": [ - { - "expr": "sum(rate(keycloak_request_duration_bucket{method=\"GET\", le=\"100.0\"}[30m])) / sum(rate(keycloak_request_duration_count{method=\"GET\"}[30m])) * 100", - "format": "time_series", - "interval": "", - "intervalFactor": 2, - "legendFormat": "", - "refId": "A" - } - ], - "title": "Percentage of requests \"GET\" method was served in 100ms or below", - "type": "gauge" - }, - { - "cards": {}, - "color": { - "cardColor": "#73BF69", - "colorScale": "sqrt", - "colorScheme": "interpolateGreens", - "exponent": 0.4, - "mode": "opacity" - }, - "dataFormat": "tsbuckets", - "datasource": { - "uid": "$Datasource" - }, - "description": "", - "gridPos": { - "h": 8, - "w": 12, - "x": 0, - "y": 62 - }, - "heatmap": {}, - "hideTimeOverride": false, - "hideZeroBuckets": true, - "highlightCards": true, - "id": 36, - "legend": { - "show": true - }, - "pluginVersion": "7.2.0", - "reverseYBuckets": false, - "targets": [ - { - "expr": "sum(increase(keycloak_request_duration_bucket{method=\"POST\"}[30m])) by (le)", - "format": "heatmap", - "interval": "", - "intervalFactor": 4, - "legendFormat": "{{ le }}", - "refId": "A" - } - ], - "title": "Request duration method = \"POST\" Heatmap", - "tooltip": { - "show": true, - "showHistogram": false - }, - "type": "heatmap", - "xAxis": { - "show": true - }, - "yAxis": { - "format": "ms", - "logBase": 1, - "show": true - }, - "yBucketBound": "auto" - }, - { - "datasource": { - "uid": "$Datasource" - }, - "description": "", - "fieldConfig": { - "defaults": { - "mappings": [], - "max": 100, - "min": 0, - "thresholds": { - "mode": "percentage", - "steps": [ - { - "color": "red", - "value": null - }, - { - "color": "red", - "value": 80 - }, - { - "color": "#EAB839", - "value": 90 - }, - { - "color": "green", - "value": 98 - } - ] - }, - "unit": "percent" - }, - "overrides": [] - }, - "gridPos": { - "h": 8, - "w": 12, - "x": 12, - "y": 62 - }, - "hideTimeOverride": false, - "id": 40, - "options": { - "orientation": "auto", - "reduceOptions": { - "calcs": [ - "mean" - ], - "fields": "", - "values": false - }, - "showThresholdLabels": false, - "showThresholdMarkers": true - }, - "pluginVersion": "8.3.3", - "targets": [ - { - "expr": "sum(rate(keycloak_request_duration_bucket{method=\"POST\", le=\"100.0\"}[30m])) / sum(rate(keycloak_request_duration_count{method=\"POST\"}[30m])) * 100", - "format": "time_series", - "interval": "", - "intervalFactor": 2, - "legendFormat": "", - "refId": "A" - } - ], - "title": "Percentage of requests \"POST\" method was served in 100ms or below", - "type": "gauge" - }, - { - "cards": {}, - "color": { - "cardColor": "#73BF69", - "colorScale": "sqrt", - "colorScheme": "interpolateGreens", - "exponent": 0.4, - "mode": "opacity" - }, - "dataFormat": "tsbuckets", - "datasource": { - "uid": "$Datasource" - }, - "description": "", - "gridPos": { - "h": 8, - "w": 12, - "x": 0, - "y": 70 - }, - "heatmap": {}, - "hideTimeOverride": false, - "hideZeroBuckets": true, - "highlightCards": true, - "id": 37, - "legend": { - "show": true - }, - "pluginVersion": "7.2.0", - "reverseYBuckets": false, - "targets": [ - { - "expr": "sum(increase(keycloak_request_duration_bucket{method=\"HEAD\"}[30m])) by (le)", - "format": "heatmap", - "interval": "", - "intervalFactor": 4, - "legendFormat": "{{ le }}", - "refId": "A" - } - ], - "title": "Request duration method = \"HEAD\" Heatmap", - "tooltip": { - "show": true, - "showHistogram": false - }, - "type": "heatmap", - "xAxis": { - "show": true - }, - "yAxis": { - "format": "ms", - "logBase": 1, - "show": true - }, - "yBucketBound": "auto" - }, - { - "datasource": { - "uid": "$Datasource" - }, - "description": "", - "fieldConfig": { - "defaults": { - "mappings": [], - "max": 100, - "min": 0, - "thresholds": { - "mode": "percentage", - "steps": [ - { - "color": "red", - "value": null - }, - { - "color": "red", - "value": 80 - }, - { - "color": "#EAB839", - "value": 90 - }, - { - "color": "green", - "value": 98 - } - ] - }, - "unit": "percent" - }, - "overrides": [] - }, - "gridPos": { - "h": 8, - "w": 12, - "x": 12, - "y": 70 - }, - "hideTimeOverride": false, - "id": 41, - "options": { - "orientation": "auto", - "reduceOptions": { - "calcs": [ - "mean" - ], - "fields": "", - "values": false - }, - "showThresholdLabels": false, - "showThresholdMarkers": true - }, - "pluginVersion": "8.3.3", - "targets": [ - { - "expr": "sum(rate(keycloak_request_duration_bucket{method=\"HEAD\", le=\"100.0\"}[30m])) / sum(rate(keycloak_request_duration_count{method=\"HEAD\"}[30m])) * 100", - "format": "time_series", - "interval": "", - "intervalFactor": 2, - "legendFormat": "", - "refId": "A" - } - ], - "title": "Percentage of requests \"HEAD\" method was served in 100ms or below", - "type": "gauge" - }, - { - "cards": {}, - "color": { - "cardColor": "#73BF69", - "colorScale": "sqrt", - "colorScheme": "interpolateGreens", - "exponent": 0.4, - "mode": "opacity" - }, - "dataFormat": "tsbuckets", - "datasource": { - "uid": "$Datasource" - }, - "description": "", - "gridPos": { - "h": 8, - "w": 12, - "x": 0, - "y": 78 - }, - "heatmap": {}, - "hideTimeOverride": false, - "hideZeroBuckets": true, - "highlightCards": true, - "id": 38, - "legend": { - "show": true - }, - "pluginVersion": "7.2.0", - "reverseYBuckets": false, - "targets": [ - { - "expr": "sum(increase(keycloak_request_duration_bucket{method=\"PUT\"}[30m])) by (le)", - "format": "heatmap", - "interval": "", - "intervalFactor": 4, - "legendFormat": "{{ le }}", - "refId": "A" - } - ], - "title": "Request duration method = \"PUT\" Heatmap", - "tooltip": { - "show": true, - "showHistogram": false - }, - "type": "heatmap", - "xAxis": { - "show": true - }, - "yAxis": { - "format": "ms", - "logBase": 1, - "show": true - }, - "yBucketBound": "auto" - }, - { - "datasource": { - "uid": "$Datasource" - }, - "description": "", - "fieldConfig": { - "defaults": { - "mappings": [], - "max": 100, - "min": 0, - "thresholds": { - "mode": "percentage", - "steps": [ - { - "color": "red", - "value": null - }, - { - "color": "red", - "value": 80 - }, - { - "color": "#EAB839", - "value": 90 - }, - { - "color": "green", - "value": 98 - } - ] - }, - "unit": "percent" - }, - "overrides": [] - }, - "gridPos": { - "h": 8, - "w": 12, - "x": 12, - "y": 78 - }, - "hideTimeOverride": false, - "id": 42, - "options": { - "orientation": "auto", - "reduceOptions": { - "calcs": [ - "mean" - ], - "fields": "", - "values": false - }, - "showThresholdLabels": false, - "showThresholdMarkers": true - }, - "pluginVersion": "8.3.3", - "targets": [ - { - "expr": "sum(rate(keycloak_request_duration_bucket{method=\"PUT\", le=\"100.0\"}[30m])) / sum(rate(keycloak_request_duration_count{method=\"PUT\"}[30m])) * 100", - "format": "time_series", - "interval": "", - "intervalFactor": 2, - "legendFormat": "", - "refId": "A" - } - ], - "title": "Percentage of requests \"PUT\" method was served in 100ms or below", - "type": "gauge" - } - ], - "refresh": false, - "schemaVersion": 34, - "style": "dark", - "tags": [], - "templating": { - "list": [ - { - "current": { - "selected": false, - "text": "Prometheus", - "value": "Prometheus" - }, - "hide": 0, - "includeAll": false, - "multi": false, - "name": "Datasource", - "options": [], - "query": "prometheus", - "queryValue": "", - "refresh": 1, - "regex": "", - "skipUrlSync": false, - "type": "datasource" - }, - { - "allFormat": "", - "allValue": "", - "current": { - "selected": false, - "text": "None", - "value": "" - }, - "datasource": { - "uid": "$Datasource" - }, - "definition": "label_values(keycloak_logins,pod)", - "hide": 0, - "includeAll": false, - "label": "Instance", - "multi": false, - "multiFormat": "", - "name": "instance", - "options": [], - "query": { - "query": "label_values(keycloak_logins,pod)", - "refId": "Prometheus-instance-Variable-Query" - }, - "refresh": 1, - "regex": "", - "skipUrlSync": false, - "sort": 0, - "tagValuesQuery": "", - "tagsQuery": "", - "type": "query", - "useTags": false - }, - { - "allFormat": "", - "allValue": "", - "current": { - "selected": true, - "text": "master", - "value": "master" - }, - "datasource": { - "uid": "$Datasource" - }, - "definition": "", - "hide": 0, - "includeAll": false, - "label": "Realm", - "multi": false, - "multiFormat": "", - "name": "realm", - "options": [], - "query": { - "query": "label_values(keycloak_logins{provider=\"keycloak\"},realm)", - "refId": "Prometheus-realm-Variable-Query" - }, - "refresh": 1, - "regex": "", - "skipUrlSync": false, - "sort": 0, - "tagValuesQuery": "", - "tagsQuery": "", - "type": "query", - "useTags": false - }, - { - "allFormat": "", - "allValue": "", - "current": { - "selected": false, - "text": "admin-cli", - "value": "admin-cli" - }, - "datasource": { - "uid": "$Datasource" - }, - "definition": "", - "hide": 0, - "includeAll": false, - "label": "ClientId", - "multi": false, - "multiFormat": "", - "name": "ClientId", - "options": [], - "query": { - "query": "label_values(keycloak_logins{provider=\"keycloak\",realm=\"$realm\"},client_id)", - "refId": "Prometheus-ClientId-Variable-Query" - }, - "refresh": 1, - "regex": "", - "skipUrlSync": false, - "sort": 0, - "tagValuesQuery": "", - "tagsQuery": "", - "type": "query", - "useTags": false - } - ] - }, - "time": { - "from": "now-30d", - "to": "now" - }, - "timepicker": { - "refresh_intervals": [ - "5s", - "10s", - "30s", - "1m", - "5m", - "15m", - "30m", - "1h", - "2h", - "1d" - ], - "time_options": [ - "5m", - "15m", - "1h", - "6h", - "12h", - "24h", - "2d", - "7d", - "30d" - ] - }, - "timezone": "", - "title": "Keycloak Metrics Dashboard", - "uid": "keycloak-dashboard", - "version": 2, - "weekStart": "" -} diff --git a/nebari/template/stages/07-kubernetes-services/modules/kubernetes/services/monitoring/dashboards/Main/traefik.json b/nebari/template/stages/07-kubernetes-services/modules/kubernetes/services/monitoring/dashboards/Main/traefik.json deleted file mode 100644 index 503b48af7c..0000000000 --- a/nebari/template/stages/07-kubernetes-services/modules/kubernetes/services/monitoring/dashboards/Main/traefik.json +++ /dev/null @@ -1,1254 +0,0 @@ -{ - "annotations": { - "list": [ - { - "builtIn": 1, - "datasource": "-- Grafana --", - "enable": true, - "hide": true, - "iconColor": "rgba(0, 211, 255, 1)", - "name": "Annotations & Alerts", - "target": { - "limit": 100, - "matchAny": false, - "tags": [], - "type": "dashboard" - }, - "type": "dashboard" - } - ] - }, - "description": "Traefik Metrics Overview", - "editable": true, - "fiscalYearStartMonth": 0, - "gnetId": 13165, - "graphTooltip": 1, - "iteration": 1681240333933, - "links": [], - "liveNow": false, - "panels": [ - { - "collapsed": false, - "datasource": { - "type": "prometheus", - "uid": "PBFA97CFB590B2093" - }, - "gridPos": { - "h": 1, - "w": 24, - "x": 0, - "y": 0 - }, - "id": 21, - "panels": [], - "title": "General", - "type": "row" - }, - { - "fieldConfig": { - "defaults": { - "color": { - "fixedColor": "rgb(31, 120, 193)", - "mode": "fixed" - }, - "mappings": [ - { - "options": { - "match": "null", - "result": { - "text": "N/A" - } - }, - "type": "special" - } - ], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - }, - "unit": "none" - }, - "overrides": [] - }, - "gridPos": { - "h": 7, - "w": 3, - "x": 0, - "y": 1 - }, - "id": 13, - "links": [], - "maxDataPoints": 100, - "options": { - "colorMode": "none", - "graphMode": "area", - "justifyMode": "auto", - "orientation": "horizontal", - "reduceOptions": { - "calcs": [ - "lastNotNull" - ], - "fields": "", - "values": false - }, - "text": {}, - "textMode": "auto" - }, - "pluginVersion": "8.3.3", - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "PBFA97CFB590B2093" - }, - "exemplar": true, - "expr": "count(kube_pod_status_ready{namespace=\"$namespace\",condition=\"true\",pod=~\"nebari-traefik-ingress-.*\", job=\"kube-state-metrics\"})", - "format": "time_series", - "hide": false, - "interval": "", - "intervalFactor": 1, - "legendFormat": "", - "refId": "A" - } - ], - "title": "Running instances", - "type": "stat" - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "fill": 1, - "fillGradient": 0, - "gridPos": { - "h": 7, - "w": 21, - "x": 3, - "y": 1 - }, - "hiddenSeries": false, - "id": 29, - "legend": { - "alignAsTable": true, - "avg": true, - "current": false, - "max": true, - "min": false, - "rightSide": true, - "show": true, - "total": false, - "values": true - }, - "lines": true, - "linewidth": 1, - "links": [], - "nullPointMode": "null", - "options": { - "alertThreshold": true - }, - "percentage": false, - "pluginVersion": "8.3.3", - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "stack": false, - "steppedLine": false, - "targets": [ - { - "exemplar": true, - "expr": "histogram_quantile(0.$percentiles, sum(rate(traefik_entrypoint_request_duration_seconds_bucket{code=~\"2..\"}[5m])) by (instance, le))", - "format": "time_series", - "interval": "", - "intervalFactor": 1, - "legendFormat": "{{ instance }}", - "refId": "A" - } - ], - "thresholds": [], - "timeRegions": [], - "title": "Per instance latency $percentiles th perc over 5 min", - "tooltip": { - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "mode": "time", - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "s", - "logBase": 1, - "min": "0", - "show": true - }, - { - "format": "short", - "logBase": 1, - "show": false - } - ], - "yaxis": { - "align": false - } - }, - { - "collapsed": false, - "datasource": { - "type": "prometheus", - "uid": "PBFA97CFB590B2093" - }, - "gridPos": { - "h": 1, - "w": 24, - "x": 0, - "y": 8 - }, - "id": 17, - "panels": [], - "title": "Entrypoints", - "type": "row" - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": { - "uid": "$Prometheus" - }, - "fill": 7, - "fillGradient": 0, - "gridPos": { - "h": 7, - "w": 12, - "x": 0, - "y": 9 - }, - "hiddenSeries": false, - "id": 19, - "legend": { - "alignAsTable": true, - "avg": true, - "current": true, - "hideZero": true, - "max": true, - "min": false, - "rightSide": true, - "show": true, - "sort": "avg", - "sortDesc": true, - "total": false, - "values": true - }, - "lines": true, - "linewidth": 1, - "links": [], - "nullPointMode": "null", - "options": { - "alertThreshold": true - }, - "percentage": false, - "pluginVersion": "8.3.3", - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "stack": true, - "steppedLine": false, - "targets": [ - { - "exemplar": true, - "expr": "sum(traefik_entrypoint_open_connections) by (method)", - "format": "time_series", - "interval": "", - "intervalFactor": 1, - "legendFormat": "{{ method }}", - "refId": "A" - } - ], - "thresholds": [], - "timeRegions": [], - "title": "Open Connections", - "tooltip": { - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "mode": "time", - "show": true, - "values": [] - }, - "yaxes": [ - { - "decimals": 0, - "format": "short", - "logBase": 1, - "min": "0", - "show": true - }, - { - "format": "short", - "logBase": 1, - "min": "0", - "show": false - } - ], - "yaxis": { - "align": false - } - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": { - "uid": "$Prometheus" - }, - "decimals": 2, - "fill": 1, - "fillGradient": 0, - "gridPos": { - "h": 7, - "w": 12, - "x": 12, - "y": 9 - }, - "hiddenSeries": false, - "id": 22, - "legend": { - "alignAsTable": true, - "avg": true, - "current": true, - "hideZero": true, - "max": false, - "min": false, - "rightSide": true, - "show": true, - "total": false, - "values": true - }, - "lines": true, - "linewidth": 1, - "links": [], - "nullPointMode": "null", - "options": { - "alertThreshold": true - }, - "percentage": false, - "pluginVersion": "8.3.3", - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "stack": false, - "steppedLine": false, - "targets": [ - { - "exemplar": true, - "expr": "(sum(rate(traefik_entrypoint_request_duration_seconds_bucket{le=\"0.1\",code=\"200\"}[5m])) by (job) + sum(rate(traefik_entrypoint_request_duration_seconds_bucket{le=\"0.3\",code=\"200\"}[5m])) by (job)) / 2 / sum(rate(traefik_entrypoint_request_duration_seconds_count{code=\"200\"}[5m])) by (job)", - "format": "time_series", - "interval": "", - "intervalFactor": 1, - "legendFormat": "Code 200", - "refId": "A" - } - ], - "thresholds": [], - "timeRegions": [], - "title": "Apdex score (over 5 min)", - "tooltip": { - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "mode": "time", - "show": true, - "values": [] - }, - "yaxes": [ - { - "decimals": 2, - "format": "short", - "label": "", - "logBase": 1, - "min": "0", - "show": true - }, - { - "format": "short", - "logBase": 1, - "min": "0", - "show": false - } - ], - "yaxis": { - "align": false - } - }, - { - "aliasColors": {}, - "bars": true, - "dashLength": 10, - "dashes": false, - "decimals": 2, - "description": "", - "fill": 1, - "fillGradient": 0, - "gridPos": { - "h": 10, - "w": 24, - "x": 0, - "y": 16 - }, - "hiddenSeries": false, - "id": 3, - "legend": { - "alignAsTable": true, - "avg": true, - "current": true, - "hideZero": true, - "max": true, - "min": false, - "rightSide": true, - "show": true, - "sort": "avg", - "sortDesc": true, - "total": false, - "values": true - }, - "lines": false, - "linewidth": 1, - "links": [], - "nullPointMode": "null", - "options": { - "alertThreshold": true - }, - "percentage": false, - "pluginVersion": "8.3.3", - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "stack": false, - "steppedLine": false, - "targets": [ - { - "exemplar": true, - "expr": "sum(rate(traefik_entrypoint_requests_total[1m])) by (entrypoint)", - "format": "time_series", - "interval": "", - "intervalFactor": 2, - "legendFormat": "{{ entrypoint }}", - "refId": "A" - } - ], - "thresholds": [], - "timeRegions": [], - "title": "Requests/min per entrypoint", - "tooltip": { - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "mode": "time", - "show": true, - "values": [] - }, - "yaxes": [ - { - "decimals": 2, - "format": "short", - "label": "", - "logBase": 1, - "min": "0", - "show": true - }, - { - "decimals": 2, - "format": "short", - "label": "", - "logBase": 1, - "min": "0", - "show": true - } - ], - "yaxis": { - "align": false - } - }, - { - "collapsed": false, - "datasource": { - "type": "prometheus", - "uid": "PBFA97CFB590B2093" - }, - "gridPos": { - "h": 1, - "w": 24, - "x": 0, - "y": 26 - }, - "id": 24, - "panels": [], - "title": "Services", - "type": "row" - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": { - "uid": "$Prometheus" - }, - "decimals": 0, - "fill": 7, - "fillGradient": 0, - "gridPos": { - "h": 7, - "w": 12, - "x": 0, - "y": 27 - }, - "hiddenSeries": false, - "id": 25, - "legend": { - "alignAsTable": true, - "avg": true, - "current": true, - "hideZero": true, - "max": true, - "min": false, - "rightSide": true, - "show": true, - "sort": "avg", - "sortDesc": true, - "total": false, - "values": true - }, - "lines": true, - "linewidth": 1, - "links": [], - "nullPointMode": "null", - "options": { - "alertThreshold": true - }, - "percentage": false, - "pluginVersion": "8.3.3", - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "stack": true, - "steppedLine": false, - "targets": [ - { - "exemplar": true, - "expr": "sum(traefik_service_open_connections) by (method)", - "format": "time_series", - "interval": "", - "intervalFactor": 1, - "legendFormat": "{{ method }}", - "refId": "A" - } - ], - "thresholds": [], - "timeRegions": [], - "title": "Open Connections", - "tooltip": { - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "mode": "time", - "show": true, - "values": [] - }, - "yaxes": [ - { - "decimals": 0, - "format": "short", - "label": "", - "logBase": 1, - "min": "0", - "show": true - }, - { - "format": "short", - "logBase": 1, - "min": "0", - "show": false - } - ], - "yaxis": { - "align": false - } - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "decimals": 2, - "fill": 1, - "fillGradient": 0, - "gridPos": { - "h": 7, - "w": 12, - "x": 12, - "y": 27 - }, - "hiddenSeries": false, - "id": 26, - "legend": { - "alignAsTable": true, - "avg": true, - "current": true, - "max": true, - "min": true, - "rightSide": false, - "show": true, - "total": false, - "values": true - }, - "lines": true, - "linewidth": 1, - "links": [], - "nullPointMode": "null", - "options": { - "alertThreshold": true - }, - "percentage": false, - "pluginVersion": "8.3.3", - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "stack": false, - "steppedLine": false, - "targets": [ - { - "exemplar": true, - "expr": "(sum(rate(traefik_service_request_duration_seconds_bucket{le=\"0.1\",code=\"200\"}[5m])) by (job) + sum(rate(traefik_service_request_duration_seconds_bucket{le=\"0.3\",code=\"200\"}[5m])) by (job)) / 2 / sum(rate(traefik_service_request_duration_seconds_count{code=\"200\"}[5m])) by (job)", - "format": "time_series", - "interval": "", - "intervalFactor": 1, - "legendFormat": "200", - "refId": "A" - }, - { - "exemplar": true, - "expr": "traefik_service_request_duration_seconds_bucket{le=\"0.1\",code=\"200\"}", - "hide": false, - "interval": "", - "legendFormat": "", - "refId": "B" - } - ], - "thresholds": [], - "timeRegions": [], - "title": "Apdex score (over 5 min)", - "tooltip": { - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "mode": "time", - "show": true, - "values": [] - }, - "yaxes": [ - { - "decimals": 2, - "format": "short", - "logBase": 1, - "min": "0", - "show": true - }, - { - "format": "short", - "logBase": 1, - "min": "0", - "show": false - } - ], - "yaxis": { - "align": false - } - }, - { - "aliasColors": {}, - "bars": true, - "dashLength": 10, - "dashes": false, - "decimals": 2, - "description": "", - "fill": 1, - "fillGradient": 0, - "gridPos": { - "h": 10, - "w": 24, - "x": 0, - "y": 34 - }, - "hiddenSeries": false, - "id": 4, - "legend": { - "alignAsTable": true, - "avg": true, - "current": true, - "hideZero": true, - "max": true, - "min": false, - "rightSide": true, - "show": true, - "sort": "avg", - "sortDesc": true, - "total": false, - "values": true - }, - "lines": false, - "linewidth": 1, - "links": [], - "nullPointMode": "null", - "options": { - "alertThreshold": true - }, - "percentage": false, - "pluginVersion": "8.3.3", - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "stack": false, - "steppedLine": false, - "targets": [ - { - "exemplar": true, - "expr": "sum(rate(traefik_service_requests_total[1m])) by (service)", - "format": "time_series", - "interval": "", - "intervalFactor": 2, - "legendFormat": "{{ service }}", - "refId": "A" - } - ], - "thresholds": [], - "timeRegions": [], - "title": "Requests/min per service", - "tooltip": { - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "mode": "time", - "show": true, - "values": [] - }, - "yaxes": [ - { - "decimals": 2, - "format": "short", - "label": "", - "logBase": 1, - "min": "0", - "show": true - }, - { - "decimals": 2, - "format": "short", - "label": "", - "logBase": 1, - "min": "0", - "show": true - } - ], - "yaxis": { - "align": false - } - }, - { - "collapsed": false, - "datasource": { - "type": "prometheus", - "uid": "PBFA97CFB590B2093" - }, - "gridPos": { - "h": 1, - "w": 24, - "x": 0, - "y": 44 - }, - "id": 15, - "panels": [], - "title": "HTTP Codes stats", - "type": "row" - }, - { - "aliasColors": {}, - "bars": true, - "dashLength": 10, - "dashes": false, - "datasource": { - "uid": "$Prometheus" - }, - "decimals": 0, - "description": "", - "fill": 1, - "fillGradient": 0, - "gridPos": { - "h": 9, - "w": 12, - "x": 0, - "y": 45 - }, - "hiddenSeries": false, - "id": 5, - "legend": { - "alignAsTable": true, - "avg": false, - "current": false, - "hideEmpty": false, - "hideZero": true, - "max": false, - "min": false, - "rightSide": true, - "show": true, - "total": true, - "values": true - }, - "lines": false, - "linewidth": 1, - "links": [], - "nullPointMode": "null", - "options": { - "alertThreshold": true - }, - "percentage": false, - "pluginVersion": "8.3.3", - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "stack": true, - "steppedLine": false, - "targets": [ - { - "exemplar": true, - "expr": "count(rate(traefik_service_requests_total{code=~\"[2|3|4|5]..\"}[5m])) by (method, code)", - "format": "time_series", - "interval": "1", - "intervalFactor": 2, - "legendFormat": "{{method}} : {{code}}", - "refId": "A" - } - ], - "thresholds": [], - "timeRegions": [], - "title": "Status method/codes over 5min", - "tooltip": { - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "mode": "time", - "show": true, - "values": [] - }, - "yaxes": [ - { - "decimals": 2, - "format": "short", - "logBase": 1, - "min": "0", - "show": true - }, - { - "decimals": 2, - "format": "short", - "logBase": 1, - "min": "0", - "show": true - } - ], - "yaxis": { - "align": false - } - }, - { - "collapsed": false, - "datasource": { - "type": "prometheus", - "uid": "PBFA97CFB590B2093" - }, - "gridPos": { - "h": 1, - "w": 24, - "x": 0, - "y": 54 - }, - "id": 35, - "panels": [], - "title": "Pods resources", - "type": "row" - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "fill": 1, - "fillGradient": 0, - "gridPos": { - "h": 9, - "w": 12, - "x": 0, - "y": 55 - }, - "hiddenSeries": false, - "id": 31, - "legend": { - "alignAsTable": true, - "avg": true, - "current": true, - "max": true, - "min": false, - "rightSide": false, - "show": true, - "total": false, - "values": true - }, - "lines": true, - "linewidth": 1, - "links": [], - "nullPointMode": "null", - "options": { - "alertThreshold": true - }, - "percentage": false, - "pluginVersion": "8.3.3", - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "stack": false, - "steppedLine": false, - "targets": [ - { - "exemplar": true, - "expr": "sum(container_memory_usage_bytes{namespace=\"$namespace\",pod=~\".*traefik.*\"})", - "format": "time_series", - "interval": "", - "intervalFactor": 1, - "legendFormat": "Memory used", - "refId": "A" - }, - { - "exemplar": true, - "expr": "sum(kube_pod_container_resource_requests_memory_bytes{namespace=\"$namespace\",pod=~\".*traefik.*\"})", - "format": "time_series", - "interval": "", - "intervalFactor": 1, - "legendFormat": "Requested memory", - "refId": "B" - }, - { - "exemplar": true, - "expr": "sum(kube_pod_container_resource_limits_memory_bytes{namespace=\"$namespace\",pod=~\".*traefik.*\"})", - "format": "time_series", - "interval": "", - "intervalFactor": 1, - "legendFormat": "Limit memory usage", - "refId": "C" - } - ], - "thresholds": [], - "timeRegions": [], - "title": "Traefik memory usage", - "tooltip": { - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "mode": "time", - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "bytes", - "logBase": 1, - "show": true - }, - { - "format": "short", - "logBase": 1, - "show": false - } - ], - "yaxis": { - "align": false - } - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": { - "uid": "$Prometheus" - }, - "fill": 1, - "fillGradient": 0, - "gridPos": { - "h": 9, - "w": 12, - "x": 12, - "y": 55 - }, - "hiddenSeries": false, - "id": 33, - "legend": { - "alignAsTable": true, - "avg": true, - "current": true, - "max": true, - "min": false, - "show": true, - "total": false, - "values": true - }, - "lines": true, - "linewidth": 1, - "links": [], - "nullPointMode": "null", - "options": { - "alertThreshold": true - }, - "percentage": false, - "pluginVersion": "8.3.3", - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "stack": false, - "steppedLine": false, - "targets": [ - { - "exemplar": true, - "expr": "sum(rate(container_cpu_usage_seconds_total{namespace=\"$namespace\",pod=~\".*traefik.*\"}[2m]))", - "format": "time_series", - "interval": "", - "intervalFactor": 1, - "legendFormat": "Cpu used", - "refId": "A" - }, - { - "exemplar": true, - "expr": "sum(kube_pod_container_resource_requests_cpu_cores{namespace=\"$namespace\",pod=\".*traefik.*\"})", - "format": "time_series", - "interval": "", - "intervalFactor": 1, - "legendFormat": "Requested cpu", - "refId": "B" - }, - { - "exemplar": true, - "expr": "sum(kube_pod_container_resource_limits_cpu_cores{namespace=\"$namespace\",pod=\".*traefik.*\"})", - "format": "time_series", - "interval": "", - "intervalFactor": 1, - "legendFormat": "Limit cpu usage", - "refId": "C" - } - ], - "thresholds": [], - "timeRegions": [], - "title": "Traefik CPU usage", - "tooltip": { - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "mode": "time", - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "short", - "logBase": 1, - "show": true - }, - { - "format": "short", - "logBase": 1, - "show": true - } - ], - "yaxis": { - "align": false - } - } - ], - "refresh": "10s", - "schemaVersion": 34, - "style": "dark", - "tags": [], - "templating": { - "list": [ - { - "current": { - "selected": false, - "text": "Prometheus", - "value": "Prometheus" - }, - "hide": 0, - "includeAll": false, - "label": "Datasource", - "multi": false, - "name": "Prometheus", - "options": [], - "query": "prometheus", - "queryValue": "", - "refresh": 1, - "regex": "", - "skipUrlSync": false, - "type": "datasource" - }, - { - "current": { - "selected": true, - "text": "dev", - "value": "dev" - }, - "datasource": { - "type": "prometheus", - "uid": "PBFA97CFB590B2093" - }, - "definition": "label_values(kube_pod_container_info{pod=~\".*traefik.*\"}, namespace)", - "hide": 0, - "includeAll": false, - "label": "Namespace", - "multi": false, - "name": "namespace", - "options": [], - "query": { - "query": "label_values(kube_pod_container_info{pod=~\".*traefik.*\"}, namespace)", - "refId": "StandardVariableQuery" - }, - "refresh": 1, - "regex": "", - "skipUrlSync": false, - "sort": 1, - "tagValuesQuery": "", - "tagsQuery": "", - "type": "query", - "useTags": false - }, - { - "current": { - "selected": true, - "text": "95", - "value": "95" - }, - "hide": 0, - "includeAll": false, - "label": "Percentiles", - "multi": false, - "name": "percentiles", - "options": [ - { - "selected": true, - "text": "95", - "value": "95" - }, - { - "selected": false, - "text": "99", - "value": "99" - } - ], - "query": "95,99", - "queryValue": "", - "skipUrlSync": false, - "type": "custom" - } - ] - }, - "time": { - "from": "now-6h", - "to": "now" - }, - "timepicker": { - "refresh_intervals": [ - "10s", - "30s", - "1m", - "5m", - "15m", - "30m", - "1h" - ], - "time_options": [ - "5m", - "15m", - "1h", - "6h", - "12h", - "24h", - "2d", - "7d", - "30d" - ] - }, - "timezone": "", - "title": "Traefik", - "uid": "2p6nlgS7z", - "version": 1, - "weekStart": "" -} diff --git a/nebari/template/stages/07-kubernetes-services/modules/kubernetes/services/monitoring/dashboards/Main/usage_report.json b/nebari/template/stages/07-kubernetes-services/modules/kubernetes/services/monitoring/dashboards/Main/usage_report.json deleted file mode 100644 index 6bef780268..0000000000 --- a/nebari/template/stages/07-kubernetes-services/modules/kubernetes/services/monitoring/dashboards/Main/usage_report.json +++ /dev/null @@ -1,296 +0,0 @@ -{ - "annotations": { - "list": [ - { - "builtIn": 1, - "datasource": "-- Grafana --", - "enable": true, - "hide": true, - "iconColor": "rgba(0, 211, 255, 1)", - "name": "Annotations & Alerts", - "target": { - "limit": 100, - "matchAny": false, - "tags": [], - "type": "dashboard" - }, - "type": "dashboard" - } - ] - }, - "editable": true, - "fiscalYearStartMonth": 0, - "graphTooltip": 0, - "iteration": 1681169345054, - "links": [], - "liveNow": false, - "panels": [ - { - "datasource": { - "type": "prometheus", - "uid": "$PROMETHEUS_DS" - }, - "fieldConfig": { - "defaults": { - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - } - ] - }, - "unit": "bytes" - }, - "overrides": [] - }, - "gridPos": { - "h": 10, - "w": 24, - "x": 0, - "y": 0 - }, - "id": 2, - "options": { - "displayMode": "gradient", - "orientation": "auto", - "reduceOptions": { - "calcs": [ - "lastNotNull" - ], - "fields": "", - "values": false - }, - "showUnfilled": true - }, - "pluginVersion": "8.3.3", - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "PBFA97CFB590B2093" - }, - "exemplar": true, - "expr": "kube_pod_labels{\n label_app=\"jupyterhub\",\n label_component=\"singleuser-server\",\n namespace=~\"$hub\",\n job=\"kube-state-metrics\"\n}\n* on (namespace, pod) group_left()\nsum(\n container_memory_working_set_bytes{\n namespace=~\"$hub\",\n container=\"notebook\",\n name!=\"\",\n }\n) by (namespace, pod)\n", - "format": "time_series", - "interval": "", - "intervalFactor": 2, - "legendFormat": "{{label_hub_jupyter_org_username}} ({{namespace}})", - "refId": "A" - } - ], - "title": "User pod memory usage", - "type": "bargauge" - }, - { - "datasource": { - "type": "prometheus", - "uid": "$PROMETHEUS_DS" - }, - "fieldConfig": { - "defaults": { - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - } - ] - }, - "unit": "bytes" - }, - "overrides": [] - }, - "gridPos": { - "h": 10, - "w": 24, - "x": 0, - "y": 10 - }, - "id": 3, - "options": { - "displayMode": "gradient", - "orientation": "auto", - "reduceOptions": { - "calcs": [ - "lastNotNull" - ], - "fields": "", - "values": false - }, - "showUnfilled": true - }, - "pluginVersion": "8.3.3", - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "PBFA97CFB590B2093" - }, - "exemplar": true, - "expr": "sum(\n kube_pod_labels{\n namespace=~\"$hub\",\n label_app_kubernetes_io_component=\"dask-worker\",\n }\n * on (namespace, pod) group_left()\n sum(\n container_memory_working_set_bytes{\n namespace=~\"$hub\",\n container=\"dask-worker\",\n name!=\"\",\n }\n ) by (namespace, pod)\n) by (label_gateway_dask_org_cluster)\n", - "format": "time_series", - "interval": "", - "intervalFactor": 2, - "legendFormat": "{{label_hub_jupyter_org_username}}-{{label_gateway_dask_org_cluster}}", - "refId": "A" - } - ], - "title": "Dask-gateway worker pod memory usage", - "type": "bargauge" - }, - { - "datasource": { - "type": "prometheus", - "uid": "$PROMETHEUS_DS" - }, - "fieldConfig": { - "defaults": { - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - } - ] - }, - "unit": "bytes" - }, - "overrides": [] - }, - "gridPos": { - "h": 10, - "w": 24, - "x": 0, - "y": 20 - }, - "id": 4, - "options": { - "displayMode": "gradient", - "orientation": "auto", - "reduceOptions": { - "calcs": [ - "lastNotNull" - ], - "fields": "", - "values": false - }, - "showUnfilled": true - }, - "pluginVersion": "8.3.3", - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "PBFA97CFB590B2093" - }, - "exemplar": true, - "expr": "sum(\n kube_pod_labels{\n namespace=~\"$hub\",\n label_app_kubernetes_io_component=\"dask-scheduler\",\n }\n * on (namespace, pod) group_left()\n sum(\n container_memory_working_set_bytes{\n namespace=~\"$hub\",\n container=\"dask-scheduler\",\n name!=\"\",\n }\n ) by (namespace, pod)\n) by (label_gateway_dask_org_cluster)\n", - "format": "time_series", - "interval": "", - "intervalFactor": 2, - "legendFormat": "{{label_hub_jupyter_org_username}}-{{label_gateway_dask_org_cluster}}", - "refId": "A" - } - ], - "title": "Dask-gateway scheduler pod memory usage", - "type": "bargauge" - } - ], - "refresh": "5s", - "schemaVersion": 34, - "style": "dark", - "tags": [ - "jupyterhub", - "dask" - ], - "templating": { - "list": [ - { - "current": { - "selected": false, - "text": "Prometheus", - "value": "Prometheus" - }, - "hide": 1, - "includeAll": false, - "multi": false, - "name": "PROMETHEUS_DS", - "options": [], - "query": "prometheus", - "refresh": 1, - "regex": "", - "skipUrlSync": false, - "type": "datasource" - }, - { - "current": { - "selected": false, - "text": "dev", - "value": "dev" - }, - "datasource": { - "uid": "$PROMETHEUS_DS" - }, - "definition": "", - "hide": 0, - "includeAll": true, - "multi": false, - "name": "hub", - "options": [], - "query": { - "query": "label_values(kube_service_labels{service=\"hub\"}, namespace)", - "refId": "Prometheus-hub-Variable-Query" - }, - "refresh": 1, - "regex": "", - "skipUrlSync": false, - "sort": 0, - "tagValuesQuery": "", - "tagsQuery": "", - "type": "query", - "useTags": false - } - ] - }, - "time": { - "from": "now-6h", - "to": "now" - }, - "timepicker": { - "refresh_intervals": [ - "5s", - "10s", - "30s", - "1m", - "5m", - "15m", - "30m", - "1h", - "2h", - "1d" - ], - "time_options": [ - "5m", - "15m", - "1h", - "6h", - "12h", - "24h", - "2d", - "7d", - "30d" - ] - }, - "timezone": "browser", - "title": "Usage Report", - "uid": "usage-report", - "version": 1, - "weekStart": "" -} From 33f3dab580a8f68bedccff1a8e26cc899dda9888 Mon Sep 17 00:00:00 2001 From: iameskild Date: Wed, 25 Oct 2023 09:01:30 -0700 Subject: [PATCH 2/2] Update conftest.py --- tests/conftest.py | 93 +---------------------------------------------- 1 file changed, 1 insertion(+), 92 deletions(-) diff --git a/tests/conftest.py b/tests/conftest.py index cbcef549f1..9a98c74d1d 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -1,92 +1 @@ -from functools import partial -from unittest.mock import Mock - -import pytest - -from _nebari.initialize import render_config - -INIT_INPUTS = [ - # project, namespace, domain, cloud_provider, ci_provider, auth_provider - ("pytestdo", "dev", "do.nebari.dev", "do", "github-actions", "github"), - ("pytestaws", "dev", "aws.nebari.dev", "aws", "github-actions", "github"), - ("pytestgcp", "dev", "gcp.nebari.dev", "gcp", "github-actions", "github"), - ("pytestazure", "dev", "azure.nebari.dev", "azure", "github-actions", "github"), -] - -NEBARI_CONFIG_FN = "nebari-config.yaml" -PRESERVED_DIR = "preserved_dir" -DEFAULT_GH_REPO = "github.com/test/test" -DEFAULT_TERRAFORM_STATE = "remote" - - -# use this partial function for all tests that need to call `render_config` -render_config_partial = partial( - render_config, - repository=DEFAULT_GH_REPO, - repository_auto_provision=False, - auth_auto_provision=False, - terraform_state=DEFAULT_TERRAFORM_STATE, - disable_prompt=True, -) - - -@pytest.fixture(params=INIT_INPUTS) -def setup_fixture(request, monkeypatch, tmp_path): - """This fixture helps simplify writing tests by: - - parametrizing the different cloud provider inputs in a single place - - creating a tmp directory (and file) for the `nebari-config.yaml` to be save to - - monkeypatching functions that call out to external APIs. - """ - render_config_inputs = request.param - ( - project, - namespace, - domain, - cloud_provider, - ci_provider, - auth_provider, - ) = render_config_inputs - - def _mock_kubernetes_versions(grab_latest_version=False): - # template for all `kubernetes_versions` calls - # monkeypatched to avoid making outbound API calls in CI - k8s_versions = ["1.18", "1.19", "1.20"] - m = Mock() - m.return_value = k8s_versions - if grab_latest_version: - m.return_value = k8s_versions[-1] - return m - - if cloud_provider == "aws": - monkeypatch.setattr( - "_nebari.utils.amazon_web_services.kubernetes_versions", - _mock_kubernetes_versions(), - ) - elif cloud_provider == "azure": - monkeypatch.setattr( - "_nebari.utils.azure_cloud.kubernetes_versions", - _mock_kubernetes_versions(), - ) - elif cloud_provider == "do": - monkeypatch.setattr( - "_nebari.utils.digital_ocean.kubernetes_versions", - _mock_kubernetes_versions(), - ) - elif cloud_provider == "gcp": - monkeypatch.setattr( - "_nebari.utils.google_cloud.kubernetes_versions", - _mock_kubernetes_versions(), - ) - - output_directory = tmp_path / f"{cloud_provider}_output_dir" - output_directory.mkdir() - nebari_config_loc = output_directory / NEBARI_CONFIG_FN - - # data that should NOT be deleted when `nebari render` is called - # see test_render.py::test_remove_existing_renders - preserved_directory = output_directory / PRESERVED_DIR - preserved_directory.mkdir() - preserved_filename = preserved_directory / "file.txt" - preserved_filename.write_text("This is a test...") - - yield (nebari_config_loc, render_config_inputs) +pytest_plugins = ["tests.common.playwright_fixtures"]