Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add Prometheus & Grafana Monitoring for LLMs Using OpenTelemetry #427

Open
wants to merge 10 commits into
base: main
Choose a base branch
from

Conversation

akotyla
Copy link
Collaborator

@akotyla akotyla commented Mar 19, 2025

No description provided.

@akotyla akotyla force-pushed the 414-feat-add-prometheus-grafana-monitoring-for-llms-using-opentelemetry branch from bb1433f to db9da5f Compare March 20, 2025 06:58
Copy link
Contributor

github-actions bot commented Mar 20, 2025

badge

Code Coverage Summary

Filename                                                                                                        Stmts    Miss  Cover    Missing
------------------------------------------------------------------------------------------------------------  -------  ------  -------  ---------------------------------------------------------------
packages/ragbits-cli/src/ragbits/cli/__init__.py                                                                   31       4  87.10%   73-74, 81-82
packages/ragbits-cli/src/ragbits/cli/_utils.py                                                                     23       4  82.61%   47, 65-67
packages/ragbits-cli/src/ragbits/cli/state.py                                                                      79       3  96.20%   50-51, 61
packages/ragbits-cli/tests/unit/test_state.py                                                                      72       2  97.22%   103-104
packages/ragbits-conversations/src/ragbits/conversations/__init__.py                                                0       0  100.00%
packages/ragbits-conversations/src/ragbits/conversations/history/__init__.py                                        0       0  100.00%
packages/ragbits-conversations/src/ragbits/conversations/history/compressors/__init__.py                            3       0  100.00%
packages/ragbits-conversations/src/ragbits/conversations/history/compressors/base.py                               10       0  100.00%
packages/ragbits-conversations/src/ragbits/conversations/history/compressors/llm.py                                29       1  96.55%   79
packages/ragbits-conversations/src/ragbits/conversations/history/stores/__init__.py                                 3       0  100.00%
packages/ragbits-conversations/src/ragbits/conversations/history/stores/base.py                                    17       0  100.00%
packages/ragbits-conversations/src/ragbits/conversations/history/stores/sql.py                                     66       1  98.48%   128
packages/ragbits-conversations/tests/unit/history/test_llm_compressor.py                                           64       0  100.00%
packages/ragbits-conversations/tests/unit/history/test_sql_store.py                                                48       2  95.83%   29-30
packages/ragbits-core/src/ragbits/core/__init__.py                                                                  6       2  66.67%   8-9
packages/ragbits-core/src/ragbits/core/cli.py                                                                       6       0  100.00%
packages/ragbits-core/src/ragbits/core/config.py                                                                   17       0  100.00%
packages/ragbits-core/src/ragbits/core/options.py                                                                  17       0  100.00%
packages/ragbits-core/src/ragbits/core/types.py                                                                     9       0  100.00%
packages/ragbits-core/src/ragbits/core/audit/__init__.py                                                           83       8  90.36%   42-43, 56, 80-83, 90-92
packages/ragbits-core/src/ragbits/core/audit/otel_metric_handler.py                                                 9       4  55.56%   10-11, 17, 44
packages/ragbits-core/src/ragbits/core/audit/trace_handlers/__init__.py                                             0       0  100.00%
packages/ragbits-core/src/ragbits/core/audit/trace_handlers/base.py                                               183      35  80.87%   156-165, 249, 256, 262-264, 271-274, 335, 337, 341-345, 390-409
packages/ragbits-core/src/ragbits/core/audit/trace_handlers/cli.py                                                132       2  98.48%   91-92
packages/ragbits-core/src/ragbits/core/embeddings/__init__.py                                                       5       0  100.00%
packages/ragbits-core/src/ragbits/core/embeddings/base.py                                                          16       2  87.50%   40, 53
packages/ragbits-core/src/ragbits/core/embeddings/exceptions.py                                                    17       7  58.82%   7-8, 17, 26-27, 36, 45
packages/ragbits-core/src/ragbits/core/embeddings/litellm.py                                                       38      18  52.63%   78-112
packages/ragbits-core/src/ragbits/core/embeddings/noop.py                                                          29       1  96.55%   89
packages/ragbits-core/src/ragbits/core/embeddings/sparse.py                                                        58      29  50.00%   24-25, 28, 67-97
packages/ragbits-core/src/ragbits/core/llms/__init__.py                                                             4       0  100.00%
packages/ragbits-core/src/ragbits/core/llms/base.py                                                                80       2  97.50%   67, 79
packages/ragbits-core/src/ragbits/core/llms/exceptions.py                                                          20       5  75.00%   17, 26-27, 36, 45
packages/ragbits-core/src/ragbits/core/llms/factory.py                                                             12       2  83.33%   30, 51
packages/ragbits-core/src/ragbits/core/llms/litellm.py                                                            111      40  63.96%   94, 135, 144, 152, 187-239, 261-266, 277
packages/ragbits-core/src/ragbits/core/llms/local.py                                                               80      50  37.50%   10-13, 69-77, 89-90, 111-131, 152-193
packages/ragbits-core/src/ragbits/core/llms/mock.py                                                                30       3  90.00%   70-73
packages/ragbits-core/src/ragbits/core/prompt/__init__.py                                                           2       0  100.00%
packages/ragbits-core/src/ragbits/core/prompt/_cli.py                                                              44      21  52.27%   25-33, 47-49, 63-65, 73-75, 89-97
packages/ragbits-core/src/ragbits/core/prompt/base.py                                                              28       0  100.00%
packages/ragbits-core/src/ragbits/core/prompt/exceptions.py                                                         7       0  100.00%
packages/ragbits-core/src/ragbits/core/prompt/parsers.py                                                           35       0  100.00%
packages/ragbits-core/src/ragbits/core/prompt/prompt.py                                                           143       1  99.30%   201
packages/ragbits-core/src/ragbits/core/prompt/discovery/__init__.py                                                 2       0  100.00%
packages/ragbits-core/src/ragbits/core/prompt/discovery/prompt_discovery.py                                        36       2  94.44%   55-56
packages/ragbits-core/src/ragbits/core/utils/__init__.py                                                            0       0  100.00%
packages/ragbits-core/src/ragbits/core/utils/_pyproject.py                                                         38       1  97.37%   113
packages/ragbits-core/src/ragbits/core/utils/config_handling.py                                                    72       8  88.89%   16, 54-55, 62-63, 152-154
packages/ragbits-core/src/ragbits/core/utils/decorators.py                                                         29       0  100.00%
packages/ragbits-core/src/ragbits/core/utils/dict_transformations.py                                               72       3  95.83%   24, 27, 108
packages/ragbits-core/src/ragbits/core/utils/pydantic.py                                                           13       2  84.62%   13, 16
packages/ragbits-core/src/ragbits/core/vector_stores/__init__.py                                                    3       0  100.00%
packages/ragbits-core/src/ragbits/core/vector_stores/_cli.py                                                       50       4  92.00%   67, 89, 95, 119
packages/ragbits-core/src/ragbits/core/vector_stores/base.py                                                       75       2  97.33%   41, 192
packages/ragbits-core/src/ragbits/core/vector_stores/chroma.py                                                     99       3  96.97%   67, 108, 180
packages/ragbits-core/src/ragbits/core/vector_stores/in_memory.py                                                  54       2  96.30%   86, 93
packages/ragbits-core/src/ragbits/core/vector_stores/pgvector.py                                                  143      31  78.32%   101, 203-211, 241-242, 255-257, 330-370
packages/ragbits-core/src/ragbits/core/vector_stores/qdrant.py                                                     94       7  92.55%   68-85, 123, 146, 199, 206
packages/ragbits-core/tests/cli/__init__.py                                                                         0       0  100.00%
packages/ragbits-core/tests/cli/test_cli_trace_handler.py                                                          48       3  93.75%   30, 43, 56
packages/ragbits-core/tests/cli/test_vector_store.py                                                              115       0  100.00%
packages/ragbits-core/tests/integration/vector_stores/test_vector_store.py                                         82       0  100.00%
packages/ragbits-core/tests/unit/__init__.py                                                                        0       0  100.00%
packages/ragbits-core/tests/unit/test_options.py                                                                   21       0  100.00%
packages/ragbits-core/tests/unit/audit/__init__.py                                                                  0       0  100.00%
packages/ragbits-core/tests/unit/audit/test_cli.py                                                                107       0  100.00%
packages/ragbits-core/tests/unit/audit/test_trace.py                                                               97       3  96.91%   16, 19, 22
packages/ragbits-core/tests/unit/embeddings/__init__.py                                                             0       0  100.00%
packages/ragbits-core/tests/unit/embeddings/test_from_config.py                                                    20       0  100.00%
packages/ragbits-core/tests/unit/llms/__init__.py                                                                   0       0  100.00%
packages/ragbits-core/tests/unit/llms/test_base.py                                                                 98       0  100.00%
packages/ragbits-core/tests/unit/llms/test_from_config.py                                                          16       0  100.00%
packages/ragbits-core/tests/unit/llms/test_litellm.py                                                              80       0  100.00%
packages/ragbits-core/tests/unit/llms/factory/__init__.py                                                           0       0  100.00%
packages/ragbits-core/tests/unit/llms/factory/test_get_preferred_llm.py                                            12       0  100.00%
packages/ragbits-core/tests/unit/prompts/__init__.py                                                                0       0  100.00%
packages/ragbits-core/tests/unit/prompts/test_parsers.py                                                           65       0  100.00%
packages/ragbits-core/tests/unit/prompts/test_prompt.py                                                           191       0  100.00%
packages/ragbits-core/tests/unit/prompts/discovery/__init__.py                                                      0       0  100.00%
packages/ragbits-core/tests/unit/prompts/discovery/prompt_classes_for_tests.py                                     30       0  100.00%
packages/ragbits-core/tests/unit/prompts/discovery/test_prompt_discovery.py                                        18       0  100.00%
packages/ragbits-core/tests/unit/prompts/discovery/ragbits_tests_pkg_with_prompts/__init__.py                       2       1  50.00%   3
packages/ragbits-core/tests/unit/prompts/discovery/ragbits_tests_pkg_with_prompts/prompts/__init__.py               3       2  33.33%   2-4
packages/ragbits-core/tests/unit/prompts/discovery/ragbits_tests_pkg_with_prompts/prompts/temp_prompt1.py          14       0  100.00%
packages/ragbits-core/tests/unit/prompts/discovery/ragbits_tests_pkg_with_prompts/prompts/temp_prompt2.py          14       0  100.00%
packages/ragbits-core/tests/unit/utils/__init__.py                                                                  0       0  100.00%
packages/ragbits-core/tests/unit/utils/test_config_handling.py                                                     64       2  96.88%   27-28
packages/ragbits-core/tests/unit/utils/test_decorators.py                                                          26       2  92.31%   17, 39
packages/ragbits-core/tests/unit/utils/test_dict_transformations.py                                                69       0  100.00%
packages/ragbits-core/tests/unit/utils/pyproject/test_find.py                                                      13       0  100.00%
packages/ragbits-core/tests/unit/utils/pyproject/test_get_config.py                                                 9       0  100.00%
packages/ragbits-core/tests/unit/utils/pyproject/test_get_instace.py                                               37       0  100.00%
packages/ragbits-core/tests/unit/vector_stores/__init__.py                                                          0       0  100.00%
packages/ragbits-core/tests/unit/vector_stores/test_chroma.py                                                      65       0  100.00%
packages/ragbits-core/tests/unit/vector_stores/test_from_config.py                                                 40       0  100.00%
packages/ragbits-core/tests/unit/vector_stores/test_in_memory.py                                                   85       0  100.00%
packages/ragbits-core/tests/unit/vector_stores/test_pgvector.py                                                   164       0  100.00%
packages/ragbits-core/tests/unit/vector_stores/test_qdrant.py                                                      81       0  100.00%
packages/ragbits-document-search/src/ragbits/document_search/__init__.py                                            2       0  100.00%
packages/ragbits-document-search/src/ragbits/document_search/_main.py                                              98       0  100.00%
packages/ragbits-document-search/src/ragbits/document_search/cli.py                                                39       2  94.87%   85, 104
packages/ragbits-document-search/src/ragbits/document_search/documents/__init__.py                                  0       0  100.00%
packages/ragbits-document-search/src/ragbits/document_search/documents/document.py                                 62       2  96.77%   100, 147
packages/ragbits-document-search/src/ragbits/document_search/documents/element.py                                  91      14  84.62%   117, 134, 195-202, 212, 221-223
packages/ragbits-document-search/src/ragbits/document_search/documents/exceptions.py                               22       0  100.00%
packages/ragbits-document-search/src/ragbits/document_search/documents/sources/__init__.py                          8       0  100.00%
packages/ragbits-document-search/src/ragbits/document_search/documents/sources/azure.py                            97      13  86.60%   73-74, 109-110, 181-192
packages/ragbits-document-search/src/ragbits/document_search/documents/sources/base.py                             64       4  93.75%   166-167, 170-171
packages/ragbits-document-search/src/ragbits/document_search/documents/sources/gcs.py                              65       1  98.46%   45
packages/ragbits-document-search/src/ragbits/document_search/documents/sources/hf.py                               60      12  80.00%   55-58, 62-63, 94, 101-102, 117-119
packages/ragbits-document-search/src/ragbits/document_search/documents/sources/local.py                            40       2  95.00%   40, 80
packages/ragbits-document-search/src/ragbits/document_search/documents/sources/s3.py                              105      49  53.33%   51-58, 72-96, 116-132, 164, 181
packages/ragbits-document-search/src/ragbits/document_search/documents/sources/web.py                              45       2  95.56%   62, 79
packages/ragbits-document-search/src/ragbits/document_search/ingestion/__init__.py                                  0       0  100.00%
packages/ragbits-document-search/src/ragbits/document_search/ingestion/document_processor.py                       33       0  100.00%
packages/ragbits-document-search/src/ragbits/document_search/ingestion/intermediate_handlers/__init__.py            3       0  100.00%
packages/ragbits-document-search/src/ragbits/document_search/ingestion/intermediate_handlers/base.py                5       0  100.00%
packages/ragbits-document-search/src/ragbits/document_search/ingestion/intermediate_handlers/images.py             36       2  94.44%   71, 101
packages/ragbits-document-search/src/ragbits/document_search/ingestion/providers/__init__.py                        3       0  100.00%
packages/ragbits-document-search/src/ragbits/document_search/ingestion/providers/base.py                           20       0  100.00%
packages/ragbits-document-search/src/ragbits/document_search/ingestion/providers/dummy.py                          21       7  66.67%   35, 56-62
packages/ragbits-document-search/src/ragbits/document_search/ingestion/providers/unstructured/__init__.py           4       0  100.00%
packages/ragbits-document-search/src/ragbits/document_search/ingestion/providers/unstructured/default.py           48       4  91.67%   99, 104-105, 144
packages/ragbits-document-search/src/ragbits/document_search/ingestion/providers/unstructured/images.py            34      14  58.82%   54-63, 70-77, 88, 101
packages/ragbits-document-search/src/ragbits/document_search/ingestion/providers/unstructured/pdf.py               19       6  68.42%   23, 35-43
packages/ragbits-document-search/src/ragbits/document_search/ingestion/providers/unstructured/utils.py             28       7  75.00%   68, 79-80, 95-98
packages/ragbits-document-search/src/ragbits/document_search/ingestion/strategies/__init__.py                       5       0  100.00%
packages/ragbits-document-search/src/ragbits/document_search/ingestion/strategies/base.py                          69       9  86.96%   110-118, 162-163
packages/ragbits-document-search/src/ragbits/document_search/ingestion/strategies/batched.py                       54       2  96.30%   229-230
packages/ragbits-document-search/src/ragbits/document_search/ingestion/strategies/ray.py                           35       0  100.00%
packages/ragbits-document-search/src/ragbits/document_search/ingestion/strategies/sequential.py                    23       2  91.30%   69-70
packages/ragbits-document-search/src/ragbits/document_search/retrieval/__init__.py                                  0       0  100.00%
packages/ragbits-document-search/src/ragbits/document_search/retrieval/rephrasers/__init__.py                       6       0  100.00%
packages/ragbits-document-search/src/ragbits/document_search/retrieval/rephrasers/base.py                           9       0  100.00%
packages/ragbits-document-search/src/ragbits/document_search/retrieval/rephrasers/llm.py                           25       4  84.00%   47-50
packages/ragbits-document-search/src/ragbits/document_search/retrieval/rephrasers/multi.py                         27       4  85.19%   51-54
packages/ragbits-document-search/src/ragbits/document_search/retrieval/rephrasers/noop.py                           6       0  100.00%
packages/ragbits-document-search/src/ragbits/document_search/retrieval/rephrasers/prompts.py                       26       2  92.31%   65, 87
packages/ragbits-document-search/src/ragbits/document_search/retrieval/rerankers/__init__.py                        3       0  100.00%
packages/ragbits-document-search/src/ragbits/document_search/retrieval/rerankers/base.py                           17       0  100.00%
packages/ragbits-document-search/src/ragbits/document_search/retrieval/rerankers/litellm.py                        18       0  100.00%
packages/ragbits-document-search/src/ragbits/document_search/retrieval/rerankers/noop.py                           11       0  100.00%
packages/ragbits-document-search/src/ragbits/document_search/retrieval/rerankers/reciprocal_ranked_fusion.py       22       2  90.91%   50, 60
packages/ragbits-document-search/src/ragbits/document_search/retrieval/rerankers/rerankers_answerdotai.py          22       0  100.00%
packages/ragbits-document-search/tests/__init__.py                                                                  0       0  100.00%
packages/ragbits-document-search/tests/helpers.py                                                                   3       0  100.00%
packages/ragbits-document-search/tests/cli/test_ingest.py                                                          21       0  100.00%
packages/ragbits-document-search/tests/cli/test_search.py                                                          71       0  100.00%
packages/ragbits-document-search/tests/integration/__init__.py                                                      0       0  100.00%
packages/ragbits-document-search/tests/integration/test_rerankers.py                                               26       6  76.92%   21-43
packages/ragbits-document-search/tests/integration/test_sources.py                                                 24      10  58.33%   23-33, 41-46
packages/ragbits-document-search/tests/integration/test_unstructured.py                                            48      10  79.17%   52-58, 71-77
packages/ragbits-document-search/tests/unit/test_aws_source.py                                                     24       0  100.00%
packages/ragbits-document-search/tests/unit/test_azure_blob_source.py                                              76       0  100.00%
packages/ragbits-document-search/tests/unit/test_config.py                                                         63       0  100.00%
packages/ragbits-document-search/tests/unit/test_document_processor.py                                             17       0  100.00%
packages/ragbits-document-search/tests/unit/test_document_search.py                                               219       1  99.54%   430
packages/ragbits-document-search/tests/unit/test_documents.py                                                      13       0  100.00%
packages/ragbits-document-search/tests/unit/test_elements.py                                                       20       0  100.00%
packages/ragbits-document-search/tests/unit/test_gcs_hf_sources.py                                                 53       8  84.91%   17-18, 53-58
packages/ragbits-document-search/tests/unit/test_ingest_strategies.py                                              22       0  100.00%
packages/ragbits-document-search/tests/unit/test_intermediate_handlers.py                                          33       0  100.00%
packages/ragbits-document-search/tests/unit/test_local_file_source.py                                              13       0  100.00%
packages/ragbits-document-search/tests/unit/test_providers.py                                                      41       0  100.00%
packages/ragbits-document-search/tests/unit/test_rephrasers.py                                                     40       0  100.00%
packages/ragbits-document-search/tests/unit/test_rerankers.py                                                      81       1  98.77%   25
packages/ragbits-document-search/tests/unit/test_source_discriminator.py                                           36       0  100.00%
packages/ragbits-document-search/tests/unit/test_source_exceptions.py                                              56       0  100.00%
packages/ragbits-document-search/tests/unit/test_web_source.py                                                     43       0  100.00%
packages/ragbits-document-search/tests/unit/testprojects/project_with_instance_factory/__init__.py                  0       0  100.00%
packages/ragbits-document-search/tests/unit/testprojects/project_with_instance_factory/factories.py                22       0  100.00%
packages/ragbits-evaluate/src/ragbits/evaluate/__init__.py                                                          0       0  100.00%
packages/ragbits-evaluate/src/ragbits/evaluate/cli.py                                                              45      16  64.44%   109-119, 130-149
packages/ragbits-evaluate/src/ragbits/evaluate/config.py                                                            6       0  100.00%
packages/ragbits-evaluate/src/ragbits/evaluate/evaluator.py                                                        51      25  50.98%   43-48, 71-78, 99-109, 122, 136, 151-155
packages/ragbits-evaluate/src/ragbits/evaluate/dataloaders/__init__.py                                              7       2  71.43%   20-21
packages/ragbits-evaluate/src/ragbits/evaluate/dataloaders/base.py                                                  7       0  100.00%
packages/ragbits-evaluate/src/ragbits/evaluate/metrics/__init__.py                                                  2       0  100.00%
packages/ragbits-evaluate/src/ragbits/evaluate/metrics/base.py                                                     21       5  76.19%   24-25, 54, 67, 79
packages/ragbits-evaluate/src/ragbits/evaluate/pipelines/__init__.py                                               11       4  63.64%   23-26
packages/ragbits-evaluate/src/ragbits/evaluate/pipelines/base.py                                                   14       2  85.71%   23, 41
packages/ragbits-evaluate/src/ragbits/evaluate/pipelines/document_search.py                                        29      12  58.62%   35-36, 52-55, 61-68, 80-82
packages/ragbits-guardrails/src/ragbits/guardrails/__init__.py                                                      0       0  100.00%
packages/ragbits-guardrails/src/ragbits/guardrails/base.py                                                         15       0  100.00%
packages/ragbits-guardrails/src/ragbits/guardrails/openai_moderation.py                                            19       5  73.68%   29-33
packages/ragbits-guardrails/tests/unit/test_openai_moderation.py                                                   35       0  100.00%
TOTAL                                                                                                            6889     600  91.29%

Diff against main

Filename                                                                   Stmts    Miss  Cover
-----------------------------------------------------------------------  -------  ------  --------
packages/ragbits-core/src/ragbits/core/audit/__init__.py                      +9      +3  -2.88%
packages/ragbits-core/src/ragbits/core/audit/otel_metric_handler.py           +9      +4  +55.56%
packages/ragbits-core/src/ragbits/core/audit/trace_handlers/__init__.py        0       0  +100.00%
packages/ragbits-core/src/ragbits/core/audit/trace_handlers/base.py         +183     +35  +80.87%
packages/ragbits-core/src/ragbits/core/audit/trace_handlers/cli.py          +132      +2  +98.48%
packages/ragbits-core/src/ragbits/core/llms/litellm.py                       +28     +18  -9.53%
packages/ragbits-core/src/ragbits/core/llms/local.py                         +25     +23  -13.41%
TOTAL                                                                       +386     +85  -0.61%

Results for commit: 6749b76

Minimum allowed coverage is 60%

♻️ This comment has been updated with latest results

Copy link
Contributor

github-actions bot commented Mar 20, 2025

Trivy scanning results.

Report Summary

┌─────────┬──────┬─────────────────┬─────────┐
│ Target │ Type │ Vulnerabilities │ Secrets │
├─────────┼──────┼─────────────────┼─────────┤
│ uv.lock │ uv │ 21 │ - │
└─────────┴──────┴─────────────────┴─────────┘
Legend:

  • '-': Not scanned
  • '0': Clean (no security findings detected)

For OSS Maintainers: VEX Notice

If you're an OSS maintainer and Trivy has detected vulnerabilities in your project that you believe are not actually exploitable, consider issuing a VEX (Vulnerability Exploitability eXchange) statement.
VEX allows you to communicate the actual status of vulnerabilities in your project, improving security transparency and reducing false positives for your users.
Learn more and start using VEX: https://trivy.dev/v0.60/docs/supply-chain/vex/repo#publishing-vex-documents

To disable this notice, set the TRIVY_DISABLE_VEX_NOTICE environment variable.

uv.lock (uv)

Total: 21 (MEDIUM: 11, HIGH: 9, CRITICAL: 1)

┌──────────────────┬────────────────┬──────────┬────────┬───────────────────┬───────────────┬──────────────────────────────────────────────────────────────┐
│ Library │ Vulnerability │ Severity │ Status │ Installed Version │ Fixed Version │ Title │
├──────────────────┼────────────────┼──────────┼────────┼───────────────────┼───────────────┼──────────────────────────────────────────────────────────────┤
│ aiohttp │ CVE-2024-52303 │ MEDIUM │ fixed │ 3.10.8 │ 3.10.11 │ aiohttp: aiohttp memory leak when middleware is enabled when │
│ │ │ │ │ │ │ requesting a resource... │
│ │ │ │ │ │ │ https://avd.aquasec.com/nvd/cve-2024-52303
│ ├────────────────┤ │ │ │ ├──────────────────────────────────────────────────────────────┤
│ │ CVE-2024-52304 │ │ │ │ │ aiohttp: aiohttp vulnerable to request smuggling due to │
│ │ │ │ │ │ │ incorrect parsing of chunk... │
│ │ │ │ │ │ │ https://avd.aquasec.com/nvd/cve-2024-52304
├──────────────────┼────────────────┼──────────┤ ├───────────────────┼───────────────┼──────────────────────────────────────────────────────────────┤
│ gradio │ CVE-2025-23042 │ CRITICAL │ │ 4.44.1 │ 5.11.0 │ Gradio Blocked Path ACL Bypass Vulnerability │
│ │ │ │ │ │ │ https://avd.aquasec.com/nvd/cve-2025-23042
│ ├────────────────┼──────────┤ │ ├───────────────┼──────────────────────────────────────────────────────────────┤
│ │ CVE-2024-47867 │ HIGH │ │ │ 5.0.0 │ Gradio lacks integrity checking on the downloaded FRP client │
│ │ │ │ │ │ │ https://avd.aquasec.com/nvd/cve-2024-47867
│ ├────────────────┤ │ │ │ ├──────────────────────────────────────────────────────────────┤
│ │ CVE-2024-47870 │ │ │ │ │ Gradio has a race condition in update_root_in_config may │
│ │ │ │ │ │ │ redirect user traffic │
│ │ │ │ │ │ │ https://avd.aquasec.com/nvd/cve-2024-47870
│ ├────────────────┤ │ │ │ ├──────────────────────────────────────────────────────────────┤
│ │ CVE-2024-47871 │ │ │ │ │ Gradio uses insecure communication between the FRP client │
│ │ │ │ │ │ │ and server │
│ │ │ │ │ │ │ https://avd.aquasec.com/nvd/cve-2024-47871
│ ├────────────────┼──────────┤ │ │ ├──────────────────────────────────────────────────────────────┤
│ │ CVE-2024-47164 │ MEDIUM │ │ │ │ Gradio's is_in_or_equal function may be bypassed │
│ │ │ │ │ │ │ https://avd.aquasec.com/nvd/cve-2024-47164
│ ├────────────────┤ │ │ │ ├──────────────────────────────────────────────────────────────┤
│ │ CVE-2024-47165 │ │ │ │ │ Gradio's CORS origin validation accepts the null origin │
│ │ │ │ │ │ │ https://avd.aquasec.com/nvd/cve-2024-47165
│ ├────────────────┤ │ │ │ ├──────────────────────────────────────────────────────────────┤
│ │ CVE-2024-47167 │ │ │ │ │ Gradio vulnerable to SSRF in the path parameter of │
│ │ │ │ │ │ │ /queue/join │
│ │ │ │ │ │ │ https://avd.aquasec.com/nvd/cve-2024-47167
│ ├────────────────┤ │ │ │ ├──────────────────────────────────────────────────────────────┤
│ │ CVE-2024-47868 │ │ │ │ │ Gradio has several components with post-process steps allow │
│ │ │ │ │ │ │ arbitrary file leaks │
│ │ │ │ │ │ │ https://avd.aquasec.com/nvd/cve-2024-47868
│ ├────────────────┤ │ │ │ ├──────────────────────────────────────────────────────────────┤
│ │ CVE-2024-47872 │ │ │ │ │ Gradio has an XSS on every Gradio server via upload of │
│ │ │ │ │ │ │ HTML... │
│ │ │ │ │ │ │ https://avd.aquasec.com/nvd/cve-2024-47872
├──────────────────┼────────────────┤ │ ├───────────────────┼───────────────┼──────────────────────────────────────────────────────────────┤
│ jinja2 │ CVE-2024-56201 │ │ │ 3.1.4 │ 3.1.5 │ jinja2: Jinja has a sandbox breakout through malicious │
│ │ │ │ │ │ │ filenames │
│ │ │ │ │ │ │ https://avd.aquasec.com/nvd/cve-2024-56201
│ ├────────────────┤ │ │ │ ├──────────────────────────────────────────────────────────────┤
│ │ CVE-2024-56326 │ │ │ │ │ jinja2: Jinja has a sandbox breakout through indirect │
│ │ │ │ │ │ │ reference to format method... │
│ │ │ │ │ │ │ https://avd.aquasec.com/nvd/cve-2024-56326
│ ├────────────────┤ │ │ ├───────────────┼──────────────────────────────────────────────────────────────┤
│ │ CVE-2025-27516 │ │ │ │ 3.1.6 │ jinja2: Jinja sandbox breakout through attr filter selecting │
│ │ │ │ │ │ │ format method │
│ │ │ │ │ │ │ https://avd.aquasec.com/nvd/cve-2025-27516
├──────────────────┼────────────────┼──────────┤ ├───────────────────┼───────────────┼──────────────────────────────────────────────────────────────┤
│ litellm │ CVE-2025-0628 │ HIGH │ │ 1.55.0 │ 1.61.15 │ LiteLLM Has an Improper Authorization Vulnerability │
│ │ │ │ │ │ │ https://avd.aquasec.com/nvd/cve-2025-0628
├──────────────────┼────────────────┤ │ ├───────────────────┼───────────────┼──────────────────────────────────────────────────────────────┤
│ python-multipart │ CVE-2024-53981 │ │ │ 0.0.12 │ 0.0.18 │ python-multipart: python-multipart has a DoS via deformation │
│ │ │ │ │ │ │ multipart/form-data boundary │
│ │ │ │ │ │ │ https://avd.aquasec.com/nvd/cve-2024-53981
├──────────────────┼────────────────┤ │ ├───────────────────┼───────────────┼──────────────────────────────────────────────────────────────┤
│ starlette │ CVE-2024-47874 │ │ │ 0.38.6 │ 0.40.0 │ starlette: Starlette Denial of service (DoS) via │
│ │ │ │ │ │ │ multipart/form-data │
│ │ │ │ │ │ │ https://avd.aquasec.com/nvd/cve-2024-47874
├──────────────────┼────────────────┤ │ ├───────────────────┼───────────────┼──────────────────────────────────────────────────────────────┤
│ transformers │ CVE-2024-11392 │ │ │ 4.44.2 │ 4.48.0 │ transformers: Hugging Face Transformers MobileViTV2 │
│ │ │ │ │ │ │ Deserialization of Untrusted Data Remote Code Execution... │
│ │ │ │ │ │ │ https://avd.aquasec.com/nvd/cve-2024-11392
│ ├────────────────┤ │ │ │ ├──────────────────────────────────────────────────────────────┤
│ │ CVE-2024-11393 │ │ │ │ │ transformers: Hugging Face Transformers MaskFormer Model │
│ │ │ │ │ │ │ Deserialization of Untrusted Data Remote Code... │
│ │ │ │ │ │ │ https://avd.aquasec.com/nvd/cve-2024-11393
│ ├────────────────┤ │ │ │ ├──────────────────────────────────────────────────────────────┤
│ │ CVE-2024-11394 │ │ │ │ │ transformers: Hugging Face Transformers Trax Model │
│ │ │ │ │ │ │ Deserialization of Untrusted Data Remote Code... │
│ │ │ │ │ │ │ https://avd.aquasec.com/nvd/cve-2024-11394
│ ├────────────────┼──────────┤ │ │ ├──────────────────────────────────────────────────────────────┤
│ │ CVE-2024-12720 │ MEDIUM │ │ │ │ Transformers Regular Expression Denial of Service (ReDoS) │
│ │ │ │ │ │ │ vulnerability │
│ │ │ │ │ │ │ https://avd.aquasec.com/nvd/cve-2024-12720
└──────────────────┴────────────────┴──────────┴────────┴───────────────────┴───────────────┴──────────────────────────────────────────────────────────────┘

@akotyla akotyla marked this pull request as ready for review March 20, 2025 11:41
@akotyla akotyla force-pushed the 414-feat-add-prometheus-grafana-monitoring-for-llms-using-opentelemetry branch from 6e7a967 to 12eb8ad Compare March 23, 2025 15:43
),
}

def record(self, metric_name: str, value: float, attributes: dict | None = None) -> None:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we should have some enum for metrics, passing string directly is error-prone.


Handler = str | TraceHandler

P = ParamSpec("P")
R = TypeVar("R")


def set_metric_handler(meter: Meter) -> None:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It should be configurable to add some sort of prefix to all metrics. For example input_tokens -> ragbits_input_tokens


1. Open your browser and navigate to http://localhost:3000.
2. Use the default credentials to log in (username: `admin`, password: `admin`).
3. Once logged in, you can either navigate to the Explore section to query and visualize metrics directly or create a new dashboard to build custom visualizations tailored to your needs.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we should provide some prebuilt dashboard :D

@mhordynski mhordynski requested a review from Copilot March 27, 2025 16:27
Copy link

@Copilot Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

This PR adds Prometheus and Grafana monitoring for LLM interactions using OpenTelemetry.

  • Updates import paths in audit trace and CLI modules
  • Adds metric recording in LLM call functions and introduces a new metric handler using OpenTelemetry
  • Provides accompanying documentation and CHANGELOG updates

Reviewed Changes

Copilot reviewed 13 out of 13 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
packages/ragbits-core/tests/unit/audit/test_trace.py Updated import path for trace handlers
packages/ragbits-core/tests/unit/audit/test_cli.py Updated import path for CLI trace handlers
packages/ragbits-core/src/ragbits/core/llms/local.py Instrumented LLM calls with metric recording
packages/ragbits-core/src/ragbits/core/llms/litellm.py Enhanced metric recording in LLM calls and streaming; duplicate error check observed
packages/ragbits-core/src/ragbits/core/audit/trace_handlers/otel.py Updated import path for trace handlers
packages/ragbits-core/src/ragbits/core/audit/trace_handlers/cli.py Updated import path for CLI trace handlers
packages/ragbits-core/src/ragbits/core/audit/otel_metric_handler.py New module for handling OTEL metrics
packages/ragbits-core/src/ragbits/core/audit/init.py Added global metric handler setup and record_metric interface
packages/ragbits-core/CHANGELOG.md Documented monitoring feature addition
mkdocs.yml Updated navigation to include metrics documentation
docs/how-to/project/use_metrics.md Added guide for setting up metrics with Ragbits

Comment on lines +143 to +145
if not response.choices: # type: ignore
raise LLMEmptyResponseError()

Copy link
Preview

Copilot AI Mar 27, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The check for response.choices is repeated after already being checked earlier. Consider removing the duplicate check to avoid redundant error handling.

Suggested change
if not response.choices: # type: ignore
raise LLMEmptyResponseError()

Copilot is powered by AI, so mistakes are possible. Review output carefully before use.

Provide additional feedback

Please help us improve GitHub Copilot by sharing more details about this comment.

Comment on lines +55 to +56
Each metric is tagged with the following **labels** (attributes) for better filtering and analysis: the class name of the prompt being processed (`promp`) and the name of the LLM being used (`model`).

Copy link
Preview

Copilot AI Mar 27, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is a typo in the label name 'promp'. It should likely be corrected to 'prompt' for clarity.

Suggested change
Each metric is tagged with the following **labels** (attributes) for better filtering and analysis: the class name of the prompt being processed (`promp`) and the name of the LLM being used (`model`).
Each metric is tagged with the following **labels** (attributes) for better filtering and analysis: the class name of the prompt being processed (`prompt`) and the name of the LLM being used (`model`).

Copilot is powered by AI, so mistakes are possible. Review output carefully before use.

Provide additional feedback

Please help us improve GitHub Copilot by sharing more details about this comment.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

feat: add Prometheus & Grafana Monitoring for LLMs Using OpenTelemetry
2 participants