diff --git a/src/oci-compute-mcp-server/uv.lock b/src/oci-compute-mcp-server/uv.lock index 4bc8620..7eb1105 100644 --- a/src/oci-compute-mcp-server/uv.lock +++ b/src/oci-compute-mcp-server/uv.lock @@ -582,11 +582,12 @@ wheels = [ [[package]] name = "oracle-oci-compute-mcp-server" -version = "1.0.1" +version = "1.0.2" source = { editable = "." } dependencies = [ { name = "fastmcp" }, { name = "oci" }, + { name = "pydantic" }, ] [package.dev-dependencies] @@ -599,6 +600,7 @@ dev = [ requires-dist = [ { name = "fastmcp", specifier = "==2.12.2" }, { name = "oci", specifier = "==2.160.0" }, + { name = "pydantic", specifier = "==2.12.3" }, ] [package.metadata.requires-dev] @@ -654,7 +656,7 @@ wheels = [ [[package]] name = "pydantic" -version = "2.11.9" +version = "2.12.3" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "annotated-types" }, @@ -662,9 +664,9 @@ dependencies = [ { name = "typing-extensions" }, { name = "typing-inspection" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/ff/5d/09a551ba512d7ca404d785072700d3f6727a02f6f3c24ecfd081c7cf0aa8/pydantic-2.11.9.tar.gz", hash = "sha256:6b8ffda597a14812a7975c90b82a8a2e777d9257aba3453f973acd3c032a18e2", size = 788495, upload-time = "2025-09-13T11:26:39.325Z" } +sdist = { url = "https://files.pythonhosted.org/packages/f3/1e/4f0a3233767010308f2fd6bd0814597e3f63f1dc98304a9112b8759df4ff/pydantic-2.12.3.tar.gz", hash = "sha256:1da1c82b0fc140bb0103bc1441ffe062154c8d38491189751ee00fd8ca65ce74", size = 819383, upload-time = "2025-10-17T15:04:21.222Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/3e/d3/108f2006987c58e76691d5ae5d200dd3e0f532cb4e5fa3560751c3a1feba/pydantic-2.11.9-py3-none-any.whl", hash = "sha256:c42dd626f5cfc1c6950ce6205ea58c93efa406da65f479dcb4029d5934857da2", size = 444855, upload-time = "2025-09-13T11:26:36.909Z" }, + { url = "https://files.pythonhosted.org/packages/a1/6b/83661fa77dcefa195ad5f8cd9af3d1a7450fd57cc883ad04d65446ac2029/pydantic-2.12.3-py3-none-any.whl", hash = "sha256:6986454a854bc3bc6e5443e1369e06a3a456af9d339eda45510f517d9ea5c6bf", size = 462431, upload-time = "2025-10-17T15:04:19.346Z" }, ] [package.optional-dependencies] @@ -674,30 +676,51 @@ email = [ [[package]] name = "pydantic-core" -version = "2.33.2" +version = "2.41.4" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "typing-extensions" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/ad/88/5f2260bdfae97aabf98f1778d43f69574390ad787afb646292a638c923d4/pydantic_core-2.33.2.tar.gz", hash = "sha256:7cb8bc3605c29176e1b105350d2e6474142d7c1bd1d9327c4a9bdb46bf827acc", size = 435195, upload-time = "2025-04-23T18:33:52.104Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/46/8c/99040727b41f56616573a28771b1bfa08a3d3fe74d3d513f01251f79f172/pydantic_core-2.33.2-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:1082dd3e2d7109ad8b7da48e1d4710c8d06c253cbc4a27c1cff4fbcaa97a9e3f", size = 2015688, upload-time = "2025-04-23T18:31:53.175Z" }, - { url = "https://files.pythonhosted.org/packages/3a/cc/5999d1eb705a6cefc31f0b4a90e9f7fc400539b1a1030529700cc1b51838/pydantic_core-2.33.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:f517ca031dfc037a9c07e748cefd8d96235088b83b4f4ba8939105d20fa1dcd6", size = 1844808, upload-time = "2025-04-23T18:31:54.79Z" }, - { url = "https://files.pythonhosted.org/packages/6f/5e/a0a7b8885c98889a18b6e376f344da1ef323d270b44edf8174d6bce4d622/pydantic_core-2.33.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0a9f2c9dd19656823cb8250b0724ee9c60a82f3cdf68a080979d13092a3b0fef", size = 1885580, upload-time = "2025-04-23T18:31:57.393Z" }, - { url = "https://files.pythonhosted.org/packages/3b/2a/953581f343c7d11a304581156618c3f592435523dd9d79865903272c256a/pydantic_core-2.33.2-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:2b0a451c263b01acebe51895bfb0e1cc842a5c666efe06cdf13846c7418caa9a", size = 1973859, upload-time = "2025-04-23T18:31:59.065Z" }, - { url = "https://files.pythonhosted.org/packages/e6/55/f1a813904771c03a3f97f676c62cca0c0a4138654107c1b61f19c644868b/pydantic_core-2.33.2-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1ea40a64d23faa25e62a70ad163571c0b342b8bf66d5fa612ac0dec4f069d916", size = 2120810, upload-time = "2025-04-23T18:32:00.78Z" }, - { url = "https://files.pythonhosted.org/packages/aa/c3/053389835a996e18853ba107a63caae0b9deb4a276c6b472931ea9ae6e48/pydantic_core-2.33.2-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:0fb2d542b4d66f9470e8065c5469ec676978d625a8b7a363f07d9a501a9cb36a", size = 2676498, upload-time = "2025-04-23T18:32:02.418Z" }, - { url = "https://files.pythonhosted.org/packages/eb/3c/f4abd740877a35abade05e437245b192f9d0ffb48bbbbd708df33d3cda37/pydantic_core-2.33.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9fdac5d6ffa1b5a83bca06ffe7583f5576555e6c8b3a91fbd25ea7780f825f7d", size = 2000611, upload-time = "2025-04-23T18:32:04.152Z" }, - { url = "https://files.pythonhosted.org/packages/59/a7/63ef2fed1837d1121a894d0ce88439fe3e3b3e48c7543b2a4479eb99c2bd/pydantic_core-2.33.2-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:04a1a413977ab517154eebb2d326da71638271477d6ad87a769102f7c2488c56", size = 2107924, upload-time = "2025-04-23T18:32:06.129Z" }, - { url = "https://files.pythonhosted.org/packages/04/8f/2551964ef045669801675f1cfc3b0d74147f4901c3ffa42be2ddb1f0efc4/pydantic_core-2.33.2-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:c8e7af2f4e0194c22b5b37205bfb293d166a7344a5b0d0eaccebc376546d77d5", size = 2063196, upload-time = "2025-04-23T18:32:08.178Z" }, - { url = "https://files.pythonhosted.org/packages/26/bd/d9602777e77fc6dbb0c7db9ad356e9a985825547dce5ad1d30ee04903918/pydantic_core-2.33.2-cp313-cp313-musllinux_1_1_armv7l.whl", hash = "sha256:5c92edd15cd58b3c2d34873597a1e20f13094f59cf88068adb18947df5455b4e", size = 2236389, upload-time = "2025-04-23T18:32:10.242Z" }, - { url = "https://files.pythonhosted.org/packages/42/db/0e950daa7e2230423ab342ae918a794964b053bec24ba8af013fc7c94846/pydantic_core-2.33.2-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:65132b7b4a1c0beded5e057324b7e16e10910c106d43675d9bd87d4f38dde162", size = 2239223, upload-time = "2025-04-23T18:32:12.382Z" }, - { url = "https://files.pythonhosted.org/packages/58/4d/4f937099c545a8a17eb52cb67fe0447fd9a373b348ccfa9a87f141eeb00f/pydantic_core-2.33.2-cp313-cp313-win32.whl", hash = "sha256:52fb90784e0a242bb96ec53f42196a17278855b0f31ac7c3cc6f5c1ec4811849", size = 1900473, upload-time = "2025-04-23T18:32:14.034Z" }, - { url = "https://files.pythonhosted.org/packages/a0/75/4a0a9bac998d78d889def5e4ef2b065acba8cae8c93696906c3a91f310ca/pydantic_core-2.33.2-cp313-cp313-win_amd64.whl", hash = "sha256:c083a3bdd5a93dfe480f1125926afcdbf2917ae714bdb80b36d34318b2bec5d9", size = 1955269, upload-time = "2025-04-23T18:32:15.783Z" }, - { url = "https://files.pythonhosted.org/packages/f9/86/1beda0576969592f1497b4ce8e7bc8cbdf614c352426271b1b10d5f0aa64/pydantic_core-2.33.2-cp313-cp313-win_arm64.whl", hash = "sha256:e80b087132752f6b3d714f041ccf74403799d3b23a72722ea2e6ba2e892555b9", size = 1893921, upload-time = "2025-04-23T18:32:18.473Z" }, - { url = "https://files.pythonhosted.org/packages/a4/7d/e09391c2eebeab681df2b74bfe6c43422fffede8dc74187b2b0bf6fd7571/pydantic_core-2.33.2-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:61c18fba8e5e9db3ab908620af374db0ac1baa69f0f32df4f61ae23f15e586ac", size = 1806162, upload-time = "2025-04-23T18:32:20.188Z" }, - { url = "https://files.pythonhosted.org/packages/f1/3d/847b6b1fed9f8ed3bb95a9ad04fbd0b212e832d4f0f50ff4d9ee5a9f15cf/pydantic_core-2.33.2-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:95237e53bb015f67b63c91af7518a62a8660376a6a0db19b89acc77a4d6199f5", size = 1981560, upload-time = "2025-04-23T18:32:22.354Z" }, - { url = "https://files.pythonhosted.org/packages/6f/9a/e73262f6c6656262b5fdd723ad90f518f579b7bc8622e43a942eec53c938/pydantic_core-2.33.2-cp313-cp313t-win_amd64.whl", hash = "sha256:c2fc0a768ef76c15ab9238afa6da7f69895bb5d1ee83aeea2e3509af4472d0b9", size = 1935777, upload-time = "2025-04-23T18:32:25.088Z" }, +sdist = { url = "https://files.pythonhosted.org/packages/df/18/d0944e8eaaa3efd0a91b0f1fc537d3be55ad35091b6a87638211ba691964/pydantic_core-2.41.4.tar.gz", hash = "sha256:70e47929a9d4a1905a67e4b687d5946026390568a8e952b92824118063cee4d5", size = 457557, upload-time = "2025-10-14T10:23:47.909Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/13/d0/c20adabd181a029a970738dfe23710b52a31f1258f591874fcdec7359845/pydantic_core-2.41.4-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:85e050ad9e5f6fe1004eec65c914332e52f429bc0ae12d6fa2092407a462c746", size = 2105688, upload-time = "2025-10-14T10:20:54.448Z" }, + { url = "https://files.pythonhosted.org/packages/00/b6/0ce5c03cec5ae94cca220dfecddc453c077d71363b98a4bbdb3c0b22c783/pydantic_core-2.41.4-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:e7393f1d64792763a48924ba31d1e44c2cfbc05e3b1c2c9abb4ceeadd912cced", size = 1910807, upload-time = "2025-10-14T10:20:56.115Z" }, + { url = "https://files.pythonhosted.org/packages/68/3e/800d3d02c8beb0b5c069c870cbb83799d085debf43499c897bb4b4aaff0d/pydantic_core-2.41.4-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:94dab0940b0d1fb28bcab847adf887c66a27a40291eedf0b473be58761c9799a", size = 1956669, upload-time = "2025-10-14T10:20:57.874Z" }, + { url = "https://files.pythonhosted.org/packages/60/a4/24271cc71a17f64589be49ab8bd0751f6a0a03046c690df60989f2f95c2c/pydantic_core-2.41.4-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:de7c42f897e689ee6f9e93c4bec72b99ae3b32a2ade1c7e4798e690ff5246e02", size = 2051629, upload-time = "2025-10-14T10:21:00.006Z" }, + { url = "https://files.pythonhosted.org/packages/68/de/45af3ca2f175d91b96bfb62e1f2d2f1f9f3b14a734afe0bfeff079f78181/pydantic_core-2.41.4-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:664b3199193262277b8b3cd1e754fb07f2c6023289c815a1e1e8fb415cb247b1", size = 2224049, upload-time = "2025-10-14T10:21:01.801Z" }, + { url = "https://files.pythonhosted.org/packages/af/8f/ae4e1ff84672bf869d0a77af24fd78387850e9497753c432875066b5d622/pydantic_core-2.41.4-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d95b253b88f7d308b1c0b417c4624f44553ba4762816f94e6986819b9c273fb2", size = 2342409, upload-time = "2025-10-14T10:21:03.556Z" }, + { url = "https://files.pythonhosted.org/packages/18/62/273dd70b0026a085c7b74b000394e1ef95719ea579c76ea2f0cc8893736d/pydantic_core-2.41.4-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a1351f5bbdbbabc689727cb91649a00cb9ee7203e0a6e54e9f5ba9e22e384b84", size = 2069635, upload-time = "2025-10-14T10:21:05.385Z" }, + { url = "https://files.pythonhosted.org/packages/30/03/cf485fff699b4cdaea469bc481719d3e49f023241b4abb656f8d422189fc/pydantic_core-2.41.4-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:1affa4798520b148d7182da0615d648e752de4ab1a9566b7471bc803d88a062d", size = 2194284, upload-time = "2025-10-14T10:21:07.122Z" }, + { url = "https://files.pythonhosted.org/packages/f9/7e/c8e713db32405dfd97211f2fc0a15d6bf8adb7640f3d18544c1f39526619/pydantic_core-2.41.4-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:7b74e18052fea4aa8dea2fb7dbc23d15439695da6cbe6cfc1b694af1115df09d", size = 2137566, upload-time = "2025-10-14T10:21:08.981Z" }, + { url = "https://files.pythonhosted.org/packages/04/f7/db71fd4cdccc8b75990f79ccafbbd66757e19f6d5ee724a6252414483fb4/pydantic_core-2.41.4-cp313-cp313-musllinux_1_1_armv7l.whl", hash = "sha256:285b643d75c0e30abda9dc1077395624f314a37e3c09ca402d4015ef5979f1a2", size = 2316809, upload-time = "2025-10-14T10:21:10.805Z" }, + { url = "https://files.pythonhosted.org/packages/76/63/a54973ddb945f1bca56742b48b144d85c9fc22f819ddeb9f861c249d5464/pydantic_core-2.41.4-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:f52679ff4218d713b3b33f88c89ccbf3a5c2c12ba665fb80ccc4192b4608dbab", size = 2311119, upload-time = "2025-10-14T10:21:12.583Z" }, + { url = "https://files.pythonhosted.org/packages/f8/03/5d12891e93c19218af74843a27e32b94922195ded2386f7b55382f904d2f/pydantic_core-2.41.4-cp313-cp313-win32.whl", hash = "sha256:ecde6dedd6fff127c273c76821bb754d793be1024bc33314a120f83a3c69460c", size = 1981398, upload-time = "2025-10-14T10:21:14.584Z" }, + { url = "https://files.pythonhosted.org/packages/be/d8/fd0de71f39db91135b7a26996160de71c073d8635edfce8b3c3681be0d6d/pydantic_core-2.41.4-cp313-cp313-win_amd64.whl", hash = "sha256:d081a1f3800f05409ed868ebb2d74ac39dd0c1ff6c035b5162356d76030736d4", size = 2030735, upload-time = "2025-10-14T10:21:16.432Z" }, + { url = "https://files.pythonhosted.org/packages/72/86/c99921c1cf6650023c08bfab6fe2d7057a5142628ef7ccfa9921f2dda1d5/pydantic_core-2.41.4-cp313-cp313-win_arm64.whl", hash = "sha256:f8e49c9c364a7edcbe2a310f12733aad95b022495ef2a8d653f645e5d20c1564", size = 1973209, upload-time = "2025-10-14T10:21:18.213Z" }, + { url = "https://files.pythonhosted.org/packages/36/0d/b5706cacb70a8414396efdda3d72ae0542e050b591119e458e2490baf035/pydantic_core-2.41.4-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:ed97fd56a561f5eb5706cebe94f1ad7c13b84d98312a05546f2ad036bafe87f4", size = 1877324, upload-time = "2025-10-14T10:21:20.363Z" }, + { url = "https://files.pythonhosted.org/packages/de/2d/cba1fa02cfdea72dfb3a9babb067c83b9dff0bbcb198368e000a6b756ea7/pydantic_core-2.41.4-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a870c307bf1ee91fc58a9a61338ff780d01bfae45922624816878dce784095d2", size = 1884515, upload-time = "2025-10-14T10:21:22.339Z" }, + { url = "https://files.pythonhosted.org/packages/07/ea/3df927c4384ed9b503c9cc2d076cf983b4f2adb0c754578dfb1245c51e46/pydantic_core-2.41.4-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d25e97bc1f5f8f7985bdc2335ef9e73843bb561eb1fa6831fdfc295c1c2061cf", size = 2042819, upload-time = "2025-10-14T10:21:26.683Z" }, + { url = "https://files.pythonhosted.org/packages/6a/ee/df8e871f07074250270a3b1b82aad4cd0026b588acd5d7d3eb2fcb1471a3/pydantic_core-2.41.4-cp313-cp313t-win_amd64.whl", hash = "sha256:d405d14bea042f166512add3091c1af40437c2e7f86988f3915fabd27b1e9cd2", size = 1995866, upload-time = "2025-10-14T10:21:28.951Z" }, + { url = "https://files.pythonhosted.org/packages/fc/de/b20f4ab954d6d399499c33ec4fafc46d9551e11dc1858fb7f5dca0748ceb/pydantic_core-2.41.4-cp313-cp313t-win_arm64.whl", hash = "sha256:19f3684868309db5263a11bace3c45d93f6f24afa2ffe75a647583df22a2ff89", size = 1970034, upload-time = "2025-10-14T10:21:30.869Z" }, + { url = "https://files.pythonhosted.org/packages/54/28/d3325da57d413b9819365546eb9a6e8b7cbd9373d9380efd5f74326143e6/pydantic_core-2.41.4-cp314-cp314-macosx_10_12_x86_64.whl", hash = "sha256:e9205d97ed08a82ebb9a307e92914bb30e18cdf6f6b12ca4bedadb1588a0bfe1", size = 2102022, upload-time = "2025-10-14T10:21:32.809Z" }, + { url = "https://files.pythonhosted.org/packages/9e/24/b58a1bc0d834bf1acc4361e61233ee217169a42efbdc15a60296e13ce438/pydantic_core-2.41.4-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:82df1f432b37d832709fbcc0e24394bba04a01b6ecf1ee87578145c19cde12ac", size = 1905495, upload-time = "2025-10-14T10:21:34.812Z" }, + { url = "https://files.pythonhosted.org/packages/fb/a4/71f759cc41b7043e8ecdaab81b985a9b6cad7cec077e0b92cff8b71ecf6b/pydantic_core-2.41.4-cp314-cp314-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fc3b4cc4539e055cfa39a3763c939f9d409eb40e85813257dcd761985a108554", size = 1956131, upload-time = "2025-10-14T10:21:36.924Z" }, + { url = "https://files.pythonhosted.org/packages/b0/64/1e79ac7aa51f1eec7c4cda8cbe456d5d09f05fdd68b32776d72168d54275/pydantic_core-2.41.4-cp314-cp314-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:b1eb1754fce47c63d2ff57fdb88c351a6c0150995890088b33767a10218eaa4e", size = 2052236, upload-time = "2025-10-14T10:21:38.927Z" }, + { url = "https://files.pythonhosted.org/packages/e9/e3/a3ffc363bd4287b80f1d43dc1c28ba64831f8dfc237d6fec8f2661138d48/pydantic_core-2.41.4-cp314-cp314-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e6ab5ab30ef325b443f379ddb575a34969c333004fca5a1daa0133a6ffaad616", size = 2223573, upload-time = "2025-10-14T10:21:41.574Z" }, + { url = "https://files.pythonhosted.org/packages/28/27/78814089b4d2e684a9088ede3790763c64693c3d1408ddc0a248bc789126/pydantic_core-2.41.4-cp314-cp314-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:31a41030b1d9ca497634092b46481b937ff9397a86f9f51bd41c4767b6fc04af", size = 2342467, upload-time = "2025-10-14T10:21:44.018Z" }, + { url = "https://files.pythonhosted.org/packages/92/97/4de0e2a1159cb85ad737e03306717637842c88c7fd6d97973172fb183149/pydantic_core-2.41.4-cp314-cp314-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a44ac1738591472c3d020f61c6df1e4015180d6262ebd39bf2aeb52571b60f12", size = 2063754, upload-time = "2025-10-14T10:21:46.466Z" }, + { url = "https://files.pythonhosted.org/packages/0f/50/8cb90ce4b9efcf7ae78130afeb99fd1c86125ccdf9906ef64b9d42f37c25/pydantic_core-2.41.4-cp314-cp314-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:d72f2b5e6e82ab8f94ea7d0d42f83c487dc159c5240d8f83beae684472864e2d", size = 2196754, upload-time = "2025-10-14T10:21:48.486Z" }, + { url = "https://files.pythonhosted.org/packages/34/3b/ccdc77af9cd5082723574a1cc1bcae7a6acacc829d7c0a06201f7886a109/pydantic_core-2.41.4-cp314-cp314-musllinux_1_1_aarch64.whl", hash = "sha256:c4d1e854aaf044487d31143f541f7aafe7b482ae72a022c664b2de2e466ed0ad", size = 2137115, upload-time = "2025-10-14T10:21:50.63Z" }, + { url = "https://files.pythonhosted.org/packages/ca/ba/e7c7a02651a8f7c52dc2cff2b64a30c313e3b57c7d93703cecea76c09b71/pydantic_core-2.41.4-cp314-cp314-musllinux_1_1_armv7l.whl", hash = "sha256:b568af94267729d76e6ee5ececda4e283d07bbb28e8148bb17adad93d025d25a", size = 2317400, upload-time = "2025-10-14T10:21:52.959Z" }, + { url = "https://files.pythonhosted.org/packages/2c/ba/6c533a4ee8aec6b812c643c49bb3bd88d3f01e3cebe451bb85512d37f00f/pydantic_core-2.41.4-cp314-cp314-musllinux_1_1_x86_64.whl", hash = "sha256:6d55fb8b1e8929b341cc313a81a26e0d48aa3b519c1dbaadec3a6a2b4fcad025", size = 2312070, upload-time = "2025-10-14T10:21:55.419Z" }, + { url = "https://files.pythonhosted.org/packages/22/ae/f10524fcc0ab8d7f96cf9a74c880243576fd3e72bd8ce4f81e43d22bcab7/pydantic_core-2.41.4-cp314-cp314-win32.whl", hash = "sha256:5b66584e549e2e32a1398df11da2e0a7eff45d5c2d9db9d5667c5e6ac764d77e", size = 1982277, upload-time = "2025-10-14T10:21:57.474Z" }, + { url = "https://files.pythonhosted.org/packages/b4/dc/e5aa27aea1ad4638f0c3fb41132f7eb583bd7420ee63204e2d4333a3bbf9/pydantic_core-2.41.4-cp314-cp314-win_amd64.whl", hash = "sha256:557a0aab88664cc552285316809cab897716a372afaf8efdbef756f8b890e894", size = 2024608, upload-time = "2025-10-14T10:21:59.557Z" }, + { url = "https://files.pythonhosted.org/packages/3e/61/51d89cc2612bd147198e120a13f150afbf0bcb4615cddb049ab10b81b79e/pydantic_core-2.41.4-cp314-cp314-win_arm64.whl", hash = "sha256:3f1ea6f48a045745d0d9f325989d8abd3f1eaf47dd00485912d1a3a63c623a8d", size = 1967614, upload-time = "2025-10-14T10:22:01.847Z" }, + { url = "https://files.pythonhosted.org/packages/0d/c2/472f2e31b95eff099961fa050c376ab7156a81da194f9edb9f710f68787b/pydantic_core-2.41.4-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:6c1fe4c5404c448b13188dd8bd2ebc2bdd7e6727fa61ff481bcc2cca894018da", size = 1876904, upload-time = "2025-10-14T10:22:04.062Z" }, + { url = "https://files.pythonhosted.org/packages/4a/07/ea8eeb91173807ecdae4f4a5f4b150a520085b35454350fc219ba79e66a3/pydantic_core-2.41.4-cp314-cp314t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:523e7da4d43b113bf8e7b49fa4ec0c35bf4fe66b2230bfc5c13cc498f12c6c3e", size = 1882538, upload-time = "2025-10-14T10:22:06.39Z" }, + { url = "https://files.pythonhosted.org/packages/1e/29/b53a9ca6cd366bfc928823679c6a76c7a4c69f8201c0ba7903ad18ebae2f/pydantic_core-2.41.4-cp314-cp314t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5729225de81fb65b70fdb1907fcf08c75d498f4a6f15af005aabb1fdadc19dfa", size = 2041183, upload-time = "2025-10-14T10:22:08.812Z" }, + { url = "https://files.pythonhosted.org/packages/c7/3d/f8c1a371ceebcaf94d6dd2d77c6cf4b1c078e13a5837aee83f760b4f7cfd/pydantic_core-2.41.4-cp314-cp314t-win_amd64.whl", hash = "sha256:de2cfbb09e88f0f795fd90cf955858fc2c691df65b1f21f0aa00b99f3fbc661d", size = 1993542, upload-time = "2025-10-14T10:22:11.332Z" }, + { url = "https://files.pythonhosted.org/packages/8a/ac/9fc61b4f9d079482a290afe8d206b8f490e9fd32d4fc03ed4fc698214e01/pydantic_core-2.41.4-cp314-cp314t-win_arm64.whl", hash = "sha256:d34f950ae05a83e0ede899c595f312ca976023ea1db100cd5aa188f7005e3ab0", size = 1973897, upload-time = "2025-10-14T10:22:13.444Z" }, ] [[package]] @@ -1026,14 +1049,14 @@ wheels = [ [[package]] name = "typing-inspection" -version = "0.4.1" +version = "0.4.2" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "typing-extensions" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/f8/b1/0c11f5058406b3af7609f121aaa6b609744687f1d158b3c3a5bf4cc94238/typing_inspection-0.4.1.tar.gz", hash = "sha256:6ae134cc0203c33377d43188d4064e9b357dba58cff3185f22924610e70a9d28", size = 75726, upload-time = "2025-05-21T18:55:23.885Z" } +sdist = { url = "https://files.pythonhosted.org/packages/55/e3/70399cb7dd41c10ac53367ae42139cf4b1ca5f36bb3dc6c9d33acdb43655/typing_inspection-0.4.2.tar.gz", hash = "sha256:ba561c48a67c5958007083d386c3295464928b01faa735ab8547c5692e87f464", size = 75949, upload-time = "2025-10-01T02:14:41.687Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/17/69/cd203477f944c353c31bade965f880aa1061fd6bf05ded0726ca845b6ff7/typing_inspection-0.4.1-py3-none-any.whl", hash = "sha256:389055682238f53b04f7badcb49b989835495a96700ced5dab2d8feae4b26f51", size = 14552, upload-time = "2025-05-21T18:55:22.152Z" }, + { url = "https://files.pythonhosted.org/packages/dc/9b/47798a6c91d8bdb567fe2698fe81e0c6b7cb7ef4d13da4114b41d239f65d/typing_inspection-0.4.2-py3-none-any.whl", hash = "sha256:4ed1cacbdc298c220f1bd249ed5287caa16f34d44ef4e9c3d0cbad5b521545e7", size = 14611, upload-time = "2025-10-01T02:14:40.154Z" }, ] [[package]] diff --git a/src/oci-logging-mcp-server/oracle/oci_logging_mcp_server/__init__.py b/src/oci-logging-mcp-server/oracle/oci_logging_mcp_server/__init__.py index 1bf9657..1724cda 100644 --- a/src/oci-logging-mcp-server/oracle/oci_logging_mcp_server/__init__.py +++ b/src/oci-logging-mcp-server/oracle/oci_logging_mcp_server/__init__.py @@ -5,4 +5,4 @@ """ __project__ = "oracle.oci-logging-mcp-server" -__version__ = "1.0.1" +__version__ = "1.1.0" diff --git a/src/oci-logging-mcp-server/oracle/oci_logging_mcp_server/models.py b/src/oci-logging-mcp-server/oracle/oci_logging_mcp_server/models.py new file mode 100644 index 0000000..8429fad --- /dev/null +++ b/src/oci-logging-mcp-server/oracle/oci_logging_mcp_server/models.py @@ -0,0 +1,548 @@ +""" +Copyright (c) 2025, Oracle and/or its affiliates. +Licensed under the Universal Permissive License v1.0 as shown at +https://oss.oracle.com/licenses/upl. +""" + +from datetime import datetime +from typing import Any, Dict, List, Literal, Optional + +import oci +from pydantic import BaseModel, Field + + +def _oci_to_dict(obj): + """Best-effort conversion of OCI SDK model objects to plain dicts.""" + if obj is None: + return None + try: + from oci.util import to_dict as oci_to_dict + + return oci_to_dict(obj) + except Exception: + pass + if isinstance(obj, dict): + return obj + if hasattr(obj, "__dict__"): + return {k: v for k, v in obj.__dict__.items() if not k.startswith("_")} + return None + + +# region LogGroupSummary + + +class LogGroupSummary(BaseModel): + """ + Pydantic model mirroring the fields of oci.logging.models.LogGroupSummary. + Note: This OCI model does not contain nested types; all fields are primitives or mappings. + """ + + id: Optional[str] = Field(None, description="The OCID of the log group resource.") + compartment_id: Optional[str] = Field( + None, description="The OCID of the compartment that the resource belongs to." + ) + display_name: Optional[str] = Field( + None, + description=( + "The user-friendly display name. This must be unique within the enclosing resource, " + "and it's changeable. Avoid entering confidential information." + ), + ) + description: Optional[str] = Field( + None, description="Description for this resource." + ) + defined_tags: Optional[Dict[str, Dict[str, Any]]] = Field( + None, + description=( + "Defined tags for this resource. Each key is predefined and scoped to a namespace." + ), + ) + freeform_tags: Optional[Dict[str, str]] = Field( + None, + description=( + "Free-form tags for this resource. Each tag is a simple key-value pair with no predefined name, " + "type, or namespace." + ), + ) + time_created: Optional[datetime] = Field( + None, description="Time the resource was created (RFC3339)." + ) + time_last_modified: Optional[datetime] = Field( + None, description="Time the resource was last modified (RFC3339)." + ) + lifecycle_state: Optional[ + Literal[ + "CREATING", + "ACTIVE", + "UPDATING", + "INACTIVE", + "DELETING", + "FAILED", + "UNKNOWN_ENUM_VALUE", + ] + ] = Field(None, description="The log group object state.") + + +def map_log_group_summary( + log_group: oci.logging.models.LogGroupSummary, +) -> LogGroupSummary | None: + """ + Convert an oci.logging.models.LogGroupSummary to + oracle.oci_logging_mcp_server.models.LogGroupSummary. + """ + if log_group is None: + return None + + # Best-effort dict extraction (not strictly required here, but consistent with other servers) + _ = _oci_to_dict(log_group) # noqa: F841 + + return LogGroupSummary( + id=getattr(log_group, "id", None), + compartment_id=getattr(log_group, "compartment_id", None), + display_name=getattr(log_group, "display_name", None), + description=getattr(log_group, "description", None), + defined_tags=getattr(log_group, "defined_tags", None), + freeform_tags=getattr(log_group, "freeform_tags", None), + time_created=getattr(log_group, "time_created", None), + time_last_modified=getattr(log_group, "time_last_modified", None), + lifecycle_state=getattr(log_group, "lifecycle_state", None), + ) + + +# endregion + +# region LogGroup + + +class LogGroup(BaseModel): + """ + Pydantic model mirroring the fields of oci.logging.models.LogGroup. + Note: This OCI model does not contain nested types; all fields are primitives or mappings. + """ + + id: Optional[str] = Field(None, description="The OCID of the resource.") + compartment_id: Optional[str] = Field( + None, description="The OCID of the compartment that the resource belongs to." + ) + display_name: Optional[str] = Field( + None, + description=( + "The user-friendly display name. This must be unique within the enclosing resource, " + "and it's changeable. Avoid entering confidential information." + ), + ) + description: Optional[str] = Field( + None, description="Description for this resource." + ) + lifecycle_state: Optional[ + Literal[ + "CREATING", + "ACTIVE", + "UPDATING", + "INACTIVE", + "DELETING", + "FAILED", + "UNKNOWN_ENUM_VALUE", + ] + ] = Field(None, description="The log group object state.") + defined_tags: Optional[Dict[str, Dict[str, Any]]] = Field( + None, + description=( + "Defined tags for this resource. Each key is predefined and scoped to a namespace." + ), + ) + freeform_tags: Optional[Dict[str, str]] = Field( + None, + description=( + "Free-form tags for this resource. Each tag is a simple key-value pair with no predefined name, " + "type, or namespace." + ), + ) + time_created: Optional[datetime] = Field( + None, description="Time the resource was created (RFC3339)." + ) + time_last_modified: Optional[datetime] = Field( + None, description="Time the resource was last modified (RFC3339)." + ) + + +def map_log_group( + log_group: oci.logging.models.LogGroup, +) -> LogGroup | None: + """ + Convert an oci.logging.models.LogGroup to + oracle.oci_logging_mcp_server.models.LogGroup. + """ + if log_group is None: + return None + + return LogGroup( + id=getattr(log_group, "id", None), + compartment_id=getattr(log_group, "compartment_id", None), + display_name=getattr(log_group, "display_name", None), + description=getattr(log_group, "description", None), + lifecycle_state=getattr(log_group, "lifecycle_state", None), + defined_tags=getattr(log_group, "defined_tags", None), + freeform_tags=getattr(log_group, "freeform_tags", None), + time_created=getattr(log_group, "time_created", None), + time_last_modified=getattr(log_group, "time_last_modified", None), + ) + + +# endregion + +# region LogSummary + + +class Archiving(BaseModel): + """Log archiving configuration.""" + + is_enabled: Optional[bool] = Field( + None, + description="True if archiving is enabled. Deprecated; prefer Service Connector Hub.", + ) + + +class Source(BaseModel): + """ + Base model for log source. + Mirrors oci.logging.models.Source discriminator. + """ + + source_type: Optional[Literal["OCISERVICE", "UNKNOWN_ENUM_VALUE"]] = Field( + None, description="The log source type." + ) + + +class OciService(Source): + """ + OCI service logging configuration (subtype of Source). + Mirrors oci.logging.models.OciService. + """ + + service: Optional[str] = Field(None, description="Service generating the log.") + resource: Optional[str] = Field( + None, description="Unique identifier of the resource emitting the log." + ) + category: Optional[str] = Field(None, description="Log object category.") + parameters: Optional[Dict[str, str]] = Field( + None, description="Log category parameters." + ) + + +class Configuration(BaseModel): + """ + Log object configuration. + Mirrors oci.logging.models.Configuration. + """ + + compartment_id: Optional[str] = Field( + None, description="The OCID of the compartment that the resource belongs to." + ) + source: Optional[Source] = Field( + None, description="The source the log object comes from." + ) + archiving: Optional[Archiving] = Field( + None, description="Log archiving configuration." + ) + + +class LogSummary(BaseModel): + """ + Pydantic model mirroring the fields of oci.logging.models.LogSummary. + Includes nested types: Configuration -> (Source|OciService, Archiving). + """ + + id: Optional[str] = Field(None, description="The OCID of the resource.") + log_group_id: Optional[str] = Field(None, description="Log group OCID.") + display_name: Optional[str] = Field( + None, + description=( + "The user-friendly display name. This must be unique within the enclosing resource, " + "and it's changeable. Avoid entering confidential information." + ), + ) + is_enabled: Optional[bool] = Field( + None, description="Whether or not this resource is currently enabled." + ) + lifecycle_state: Optional[ + Literal[ + "CREATING", + "ACTIVE", + "UPDATING", + "INACTIVE", + "DELETING", + "FAILED", + "UNKNOWN_ENUM_VALUE", + ] + ] = Field(None, description="The pipeline state.") + log_type: Optional[Literal["CUSTOM", "SERVICE", "UNKNOWN_ENUM_VALUE"]] = Field( + None, + description="The logType that the log object is for, whether custom or service.", + ) + configuration: Optional[Configuration] = Field( + None, description="Log object configuration." + ) + defined_tags: Optional[Dict[str, Dict[str, Any]]] = Field( + None, + description="Defined tags for this resource. Each key is predefined and scoped to a namespace.", + ) + freeform_tags: Optional[Dict[str, str]] = Field( + None, + description="Free-form tags for this resource as simple key/value pairs without predefined names.", + ) + time_created: Optional[datetime] = Field( + None, description="Time the resource was created (RFC3339)." + ) + time_last_modified: Optional[datetime] = Field( + None, description="Time the resource was last modified (RFC3339)." + ) + retention_duration: Optional[int] = Field( + None, + description="Log retention duration in 30-day increments (30, 60, 90, ... up to 180).", + ) + compartment_id: Optional[str] = Field( + None, description="The OCID of the compartment that the resource belongs to." + ) + + +def map_archiving(arch) -> Archiving | None: + if not arch: + return None + return Archiving(is_enabled=getattr(arch, "is_enabled", None)) + + +def map_source(src) -> Source | None: + if not src: + return None + # Prefer explicit subtype mapping when possible + try: + if isinstance(src, oci.logging.models.OciService): + return OciService( + source_type=getattr(src, "source_type", None), + service=getattr(src, "service", None), + resource=getattr(src, "resource", None), + category=getattr(src, "category", None), + parameters=getattr(src, "parameters", None), + ) + except Exception: + # If SDK classes are not importable in this environment, fall through to generic mapping + pass + return Source(source_type=getattr(src, "source_type", None)) + + +def map_configuration(cfg) -> Configuration | None: + if not cfg: + return None + return Configuration( + compartment_id=getattr(cfg, "compartment_id", None), + source=map_source(getattr(cfg, "source", None)), + archiving=map_archiving(getattr(cfg, "archiving", None)), + ) + + +def map_log_summary(log: oci.logging.models.LogSummary) -> LogSummary | None: + """ + Convert an oci.logging.models.LogSummary to + oracle.oci_logging_mcp_server.models.LogSummary, including nested types. + """ + if log is None: + return None + + return LogSummary( + id=getattr(log, "id", None), + log_group_id=getattr(log, "log_group_id", None), + display_name=getattr(log, "display_name", None), + is_enabled=getattr(log, "is_enabled", None), + lifecycle_state=getattr(log, "lifecycle_state", None), + log_type=getattr(log, "log_type", None), + configuration=map_configuration(getattr(log, "configuration", None)), + defined_tags=getattr(log, "defined_tags", None), + freeform_tags=getattr(log, "freeform_tags", None), + time_created=getattr(log, "time_created", None), + time_last_modified=getattr(log, "time_last_modified", None), + retention_duration=getattr(log, "retention_duration", None), + compartment_id=getattr(log, "compartment_id", None), + ) + + +# endregion + +# region Log + + +class Log(BaseModel): + """ + Pydantic model mirroring the fields of oci.logging.models.Log. + Includes nested types: Configuration -> (Source|OciService, Archiving). + """ + + id: Optional[str] = Field(None, description="The OCID of the resource.") + tenancy_id: Optional[str] = Field(None, description="The OCID of the tenancy.") + log_group_id: Optional[str] = Field(None, description="Log group OCID.") + display_name: Optional[str] = Field( + None, + description=( + "The user-friendly display name. This must be unique within the enclosing resource, " + "and it's changeable. Avoid entering confidential information." + ), + ) + log_type: Optional[Literal["CUSTOM", "SERVICE", "UNKNOWN_ENUM_VALUE"]] = Field( + None, + description="The logType that the log object is for, whether custom or service.", + ) + is_enabled: Optional[bool] = Field( + None, description="Whether or not this resource is currently enabled." + ) + defined_tags: Optional[Dict[str, Dict[str, Any]]] = Field( + None, + description="Defined tags for this resource. Each key is predefined and scoped to a namespace.", + ) + freeform_tags: Optional[Dict[str, str]] = Field( + None, + description="Free-form tags for this resource as simple key/value pairs without predefined names.", + ) + configuration: Optional[Configuration] = Field( + None, description="Log object configuration." + ) + lifecycle_state: Optional[ + Literal[ + "CREATING", + "ACTIVE", + "UPDATING", + "INACTIVE", + "DELETING", + "FAILED", + "UNKNOWN_ENUM_VALUE", + ] + ] = Field(None, description="The pipeline state.") + time_created: Optional[datetime] = Field( + None, description="Time the resource was created (RFC3339)." + ) + time_last_modified: Optional[datetime] = Field( + None, description="Time the resource was last modified (RFC3339)." + ) + retention_duration: Optional[int] = Field( + None, + description="Log retention duration in 30-day increments (30, 60, 90, ... up to 180).", + ) + compartment_id: Optional[str] = Field( + None, description="The OCID of the compartment that the resource belongs to." + ) + + +def map_log(log: oci.logging.models.Log) -> Log | None: + """ + Convert an oci.logging.models.Log to + oracle.oci_logging_mcp_server.models.Log, including nested types. + """ + if log is None: + return None + + return Log( + id=getattr(log, "id", None), + tenancy_id=getattr(log, "tenancy_id", None), + log_group_id=getattr(log, "log_group_id", None), + display_name=getattr(log, "display_name", None), + log_type=getattr(log, "log_type", None), + is_enabled=getattr(log, "is_enabled", None), + defined_tags=getattr(log, "defined_tags", None), + freeform_tags=getattr(log, "freeform_tags", None), + configuration=map_configuration(getattr(log, "configuration", None)), + lifecycle_state=getattr(log, "lifecycle_state", None), + time_created=getattr(log, "time_created", None), + time_last_modified=getattr(log, "time_last_modified", None), + retention_duration=getattr(log, "retention_duration", None), + compartment_id=getattr(log, "compartment_id", None), + ) + + +# endregion + +# region SearchResponse + + +class FieldInfo(BaseModel): + """Contains field schema information.""" + + field_name: Optional[str] = Field(None, description="Field name") + field_type: Optional[Literal["STRING", "NUMBER", "BOOLEAN", "ARRAY"]] = Field( + None, + description="Field type - STRING: A sequence of characters. " + "NUMBER: Numeric type which can be an integer or floating point. " + "BOOLEAN: Either true or false. " + "ARRAY: An ordered collection of values.", + ) + + +class SearchResult(BaseModel): + """A log search result entry.""" + + data: Optional[Dict[str, Any]] = Field( + None, + description="JSON blob containing the search entry with the projected fields.", + ) + + +class SearchResultSummary(BaseModel): + """Summary of results.""" + + result_count: Optional[int] = Field( + None, description="Total number of search results." + ) + field_count: Optional[int] = Field( + None, description="Total number of field schema information." + ) + + +class SearchResponse(BaseModel): + """Search response object.""" + + results: Optional[List[SearchResult]] = Field( + None, description="List of search results" + ) + fields: Optional[List[FieldInfo]] = Field( + None, description="List of log field schema information." + ) + summary: Optional[SearchResultSummary] = Field( + None, description="Summary of results." + ) + + +def map_field_info(fi) -> FieldInfo | None: + if not fi: + return None + return FieldInfo( + field_name=getattr(fi, "field_name", None), + field_type=getattr(fi, "field_type", None), + ) + + +def map_search_result(sr) -> SearchResult | None: + if not sr: + return None + return SearchResult(data=_oci_to_dict(getattr(sr, "data", None))) + + +def map_search_result_summary(srs) -> SearchResultSummary | None: + if not srs: + return None + return SearchResultSummary( + result_count=getattr(srs, "result_count", None), + field_count=getattr(srs, "field_count", None), + ) + + +def map_search_response( + sr: oci.loggingsearch.models.SearchResponse, +) -> SearchResponse | None: + if not sr: + return None + return SearchResponse( + results=[map_search_result(r) for r in getattr(sr, "results", None) or []], + fields=[map_field_info(f) for f in getattr(sr, "fields", None) or []], + summary=map_search_result_summary(getattr(sr, "summary", None)), + ) + + +# endregion diff --git a/src/oci-logging-mcp-server/oracle/oci_logging_mcp_server/scripts.py b/src/oci-logging-mcp-server/oracle/oci_logging_mcp_server/scripts.py new file mode 100644 index 0000000..65aff55 --- /dev/null +++ b/src/oci-logging-mcp-server/oracle/oci_logging_mcp_server/scripts.py @@ -0,0 +1,18 @@ +""" +Copyright (c) 2025, Oracle and/or its affiliates. +Licensed under the Universal Permissive License v1.0 as shown at +https://oss.oracle.com/licenses/upl. +""" + +from pathlib import Path + +SCRIPTS_DIRECTORY = Path(__file__).parent / "scripts" + +SEARCH_LOG_SCRIPT = "SEARCH_LOG.md" +SEARCH_LOG_EVENT_TYPES_SCRIPT = "SEARCH_LOG_EVENT_TYPES.md" + + +def get_script_content(script_name: str) -> str: + file_path = SCRIPTS_DIRECTORY / script_name + with open(file_path, "r") as f: + return f.read() diff --git a/src/oci-logging-mcp-server/oracle/oci_logging_mcp_server/scripts/SEARCH_LOG.md b/src/oci-logging-mcp-server/oracle/oci_logging_mcp_server/scripts/SEARCH_LOG.md new file mode 100644 index 0000000..69e9da9 --- /dev/null +++ b/src/oci-logging-mcp-server/oracle/oci_logging_mcp_server/scripts/SEARCH_LOG.md @@ -0,0 +1,466 @@ +# Logging Query Language Specification + +Use query syntax components with Advanced mode custom searches on the Logging Search page. + +Markdown gathered from [here](https://docs.oracle.com/en-us/iaas/Content/Logging/Reference/query_language_specification.htm). + +## Query Components + +The logging query language processing is based on a data flow model. Each query can reference one or more logs, and produces a table dataset as a result. The query language provides several operators for searching, filtering, and aggregating structured and unstructured logs. + +A logging query includes the following components: + +- Log streams +- Fields +- Data types +- Stream expressions +- Pipe expressions +- Operators + +## Log Streams + +To begin your search, you must first define the set of logs you want to search. You can choose to search specific log objects, log groups, or compartments. You can mix and match as many logs as you need. The search scope is defined using the following pattern: + +`search (,? )*` + +The query language fetches log entries from the scope you provide, and constructs a log stream that you can filter, aggregate, and visualize. + +Log stream: + +` := " ( / ( / )? )?"` + +Examples: + +`search "compartmentOcid/logGroupNameOrOcid/logNameOrOcid"` + +`search "compartmentOcid/logGroupNameOrOcid"` + +`search "compartmentOcid"` + +`search "compartmentOcid/logGroupNameOrOcid/logNameOrOcid", "compartmentOcid_2/logGroupNameOrOcid_2", "compartmentOcid_3"` + +## Fields + +All fields in log streams are case-sensitive. Although actual logs have indexed fields in lower case only, you can also create new fields in the query with mixed case: + +``` +search "..." + | select event as EventName +``` + +Fields are in JSON notation, therefore, special characters must be in quotes. + +`Fields: := (DOT )*` + +For Identifier: + +` := a-zA-Z_[a-zA-Z_0-9]* | ('"' (~'"' | '""')* '"')` + +Examples: + +- type +- data.message +- data.request.URL +- "type" +- "data"."message" +- "data.message" (not the same as "data"."message") +- data."$event" +- data."first name" +- data."an example of escaped ("") double quotes" + +## Data Types + +The following key data types are supported by the query language. These are (long and double) 8 bytes. + +For details about the representation of the values of the corresponding types, see Literals. + +- Strings +- Numbers (integer, float-point) +- Arrays +- Booleans +- Timestamps +- Intervals + +## Stream Expressions + +- Tabular operators +- Aggregate operators + +## Pipe Expressions + +A pipe (|) applies an operator on the left side to a stream expression on the right side. The pipe expression is a stream expression. + +The operator on the right side of a pipe must consume only one stream (for example, aggregate operations, filters). + +The left side becomes the "current stream" for the right side expression, making all fields in the current stream available according to short names. For example: +``` +search "application" + | where level = 'ERROR' + +>> +{"timestamp": "2019-01-03T00:04:01", "level":"ERROR", "host":"host1", "message":"download failed...", "impact":2} +{"timestamp": "2019-01-03T00:06:39", "level":"ERROR", "host":"host2", "message":"reached 90% file size limit... ", "impact":4} +{"timestamp": "2019-01-03T00:06:59", "level":"ERROR", "host":"host2", "message":"reached 95% file size limit... ", "impact":5} +``` + +## Operators + +The following are supported when performing advanced queries: + +- Tabular operators +- Scalar operators +- Aggregate operators + +## Tabular Operators + +A tabular operator creates or modifies a log stream by filtering out or changing log entries. Also refer to BNF syntax notation. The following are tabular operators: + +- search +- where +- top +- sort +- dedup +- select +- extend + +### `search` + +Constructs a log stream from actual log objects. Also see Log Streams for details, and Using the CLI for additional examples. + +`search "compartmentOCID/loggroup1/logname1" "compartmentOCID/loggroup2/logname2" "compartmentOCID/loggroup3/logname3"` + +### `where` + +Filters the current log stream using a Boolean expression. + +``` +search "application" + | where level = 'ERROR' +>> +{"timestamp": "2019-01-03T00:04:01", "level":"ERROR", "host":"host1", "message":"download failed...", "impact":2} +{"timestamp": "2019-01-03T00:06:39", "level":"ERROR", "host":"host2", "message":"reached 90% file size limit... ", "impact":4} +{"timestamp": "2019-01-03T00:06:59", "level":"ERROR", "host":"host2", "message":"reached 95% file size limit... ", "impact":5} +``` + +`where` is optional: + +``` +search "application" + | level = 'ERROR' +``` + +Some example comparisons with numbers and Boolean field comparisons are the following: + +`| data.statusCode = 200` + +`| data.isPar` + +If somebody passes in a resource to show the logs for, pass in the OCID with this format, SPECIFICALLY using `data.resourceId` + +`| data.resourceId = 'ocid1.instance.oc1.iad...'` + +You can perform a full text search by specifying a filter on the entire content of the log. A search on `logContent` returns any log line where a value matches your string. This functionality supports wildcards. For example: + +``` +search "application" + | where logContent = 'ERROR' -- returns log lines with a value matching "ERROR" +``` + +``` +search "application" + | where logContent = '*ERROR*' -- returns log lines with a value containing "ERROR" +``` + +### `top` + +Fetches only a specified number of rows from the current log stream, sorted based on some expression. + +` := top [0-9]+ by ` + +Examples: + +- `top 3 by datetime` +- `top 3 by *` +- `top 3 by (a + b)` + +A number of rows must be a constant positive integer, and a sorting expression must be provided. + +``` +search "application" + | top 3 by impact +>> +{"timestamp": "2019-01-03T00:06:59", "level":"ERROR", "host":"host2", "message":"reached 95% file size limit... ", "impact":5} +{"timestamp": "2019-01-03T00:06:39", "level":"ERROR", "host":"host2", "message":"reached 90% file size limit... ", "impact":4} +{"timestamp": "2019-01-03T00:04:01", "level":"ERROR", "host":"host1", "message":"download failed...", "impact":2} +``` + +### `sort` + +Sorts the current log stream by the specified columns, in either ascending (default) or descending order. The operator uses the "DESC" and "ASC" keywords to specify the type of the order. The default sort order is `asc`. + +``` + := sort by (, )* + := (asc | desc)? +``` + +Example: + +``` +search "application" + | sort by impact desc +>> +{"timestamp": "2019-01-03T00:06:59", "level":"ERROR", "host":"host2", "message":"reached 95% file size limit... ", "impact":5} +{"timestamp": "2019-01-03T00:06:39", "level":"ERROR", "host":"host2", "message":"reached 90% file size limit... ", "impact":4} +{"timestamp": "2019-01-03T00:04:01", "level":"ERROR", "host":"host1", "message":"download failed...", "impact":2} +{"timestamp": "2019-01-03T00:05:33", "level":"WARNING", "host":"host2", "message":"reached 70% file size limit... ", "impact":1} +{"timestamp": "2019-01-03T00:04:05", "level":"INFO", "host":" host1", "message":"host list updated..."} +{"timestamp": "2019-01-03T00:06:59", "level":"INFO", "host":" host2", "message":"fs clean up started..."} +``` + +More than one column can be used to specify the order: + +``` +search "application" + | sort by host, impact desc +>> +{"timestamp": "2019-01-03T00:06:59", "level":"ERROR", "host":"host2", "message":"reached 95% file size limit... ", "impact":5} +{"timestamp": "2019-01-03T00:06:39", "level":"ERROR", "host":"host2", "message":"reached 90% file size limit... ", "impact":4} +{"timestamp": "2019-01-03T00:05:33", "level":"WARNING", "host":"host2", "message":"reached 70% file size limit... ", "impact":1} +{"timestamp": "2019-01-03T00:06:59", "level":"INFO", "host":" host2", "message":"fs clean up started..."} +{"timestamp": "2019-01-03T00:04:01", "level":"ERROR", "host":"host1", "message":"download failed...", "impact":2} +{"timestamp": "2019-01-03T00:04:05", "level":"INFO", "host":" host1", "message":"host list updated..."} +``` + +### `dedup` + +Processes the current log stream by filtering out all duplicates by specified columns. If more than one column is specified, all columns have to be delimited by commas. + +` := dedup (, )` + +Examples + +``` +search "application" + | dedup host +>> +{"timestamp": "2019-01-03T00:04:01", "level":"ERROR", "host":"host1", "message":"download failed...", "impact":2} +{"timestamp": "2019-01-03T00:05:33", "level":"WARNING", "host":"host2", "message":"reached 70% file size limit... ", "impact":1} +``` + +``` +search "application" + | dedup host, impact +{"timestamp": "2019-01-03T00:04:01", "level":"ERROR", "host":"host1", "message":"download failed...", "impact":2} +{"timestamp": "2019-01-03T00:05:33", "level":"WARNING", "host":"host2", "message":"reached 70% file size limit... ", "impact":1} +{"timestamp": "2019-01-03T00:06:39", "level":"ERROR", "host":"host2", "message":"reached 90% file size limit... ", "impact":4} +{"timestamp": "2019-01-03T00:06:59", "level":"ERROR", "host":"host2", "message":"reached 95% file size limit... ", "impact":5} +``` + +### `select` + +Applies a series of named scalar expressions to the current log stream. See summarize for an aggregation version of select. + +``` +