monocle-apptrace 0.1.1__tar.gz → 0.3.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of monocle-apptrace might be problematic. Click here for more details.

Files changed (107) hide show
  1. {monocle_apptrace-0.1.1 → monocle_apptrace-0.3.0}/.gitignore +2 -1
  2. monocle_apptrace-0.3.0/CHANGELOG.md +75 -0
  3. {monocle_apptrace-0.1.1 → monocle_apptrace-0.3.0}/Monocle_User_Guide.md +31 -4
  4. {monocle_apptrace-0.1.1 → monocle_apptrace-0.3.0}/Monocle_committer_guide.md +31 -1
  5. {monocle_apptrace-0.1.1 → monocle_apptrace-0.3.0}/PKG-INFO +23 -2
  6. {monocle_apptrace-0.1.1 → monocle_apptrace-0.3.0}/pyproject.toml +40 -3
  7. monocle_apptrace-0.3.0/src/monocle_apptrace/__init__.py +1 -0
  8. monocle_apptrace-0.3.0/src/monocle_apptrace/__main__.py +19 -0
  9. monocle_apptrace-0.3.0/src/monocle_apptrace/exporters/aws/s3_exporter.py +181 -0
  10. monocle_apptrace-0.3.0/src/monocle_apptrace/exporters/aws/s3_exporter_opendal.py +137 -0
  11. monocle_apptrace-0.3.0/src/monocle_apptrace/exporters/azure/blob_exporter.py +146 -0
  12. monocle_apptrace-0.3.0/src/monocle_apptrace/exporters/azure/blob_exporter_opendal.py +162 -0
  13. monocle_apptrace-0.3.0/src/monocle_apptrace/exporters/base_exporter.py +48 -0
  14. monocle_apptrace-0.3.0/src/monocle_apptrace/exporters/exporter_processor.py +144 -0
  15. {monocle_apptrace-0.1.1 → monocle_apptrace-0.3.0}/src/monocle_apptrace/exporters/file_exporter.py +16 -0
  16. monocle_apptrace-0.3.0/src/monocle_apptrace/exporters/monocle_exporters.py +55 -0
  17. monocle_apptrace-0.3.0/src/monocle_apptrace/exporters/okahu/okahu_exporter.py +117 -0
  18. monocle_apptrace-0.3.0/src/monocle_apptrace/instrumentation/__init__.py +1 -0
  19. monocle_apptrace-0.3.0/src/monocle_apptrace/instrumentation/common/__init__.py +2 -0
  20. monocle_apptrace-0.3.0/src/monocle_apptrace/instrumentation/common/constants.py +70 -0
  21. monocle_apptrace-0.3.0/src/monocle_apptrace/instrumentation/common/instrumentor.py +362 -0
  22. monocle_apptrace-0.3.0/src/monocle_apptrace/instrumentation/common/span_handler.py +220 -0
  23. monocle_apptrace-0.3.0/src/monocle_apptrace/instrumentation/common/utils.py +356 -0
  24. monocle_apptrace-0.3.0/src/monocle_apptrace/instrumentation/common/wrapper.py +92 -0
  25. monocle_apptrace-0.3.0/src/monocle_apptrace/instrumentation/common/wrapper_method.py +72 -0
  26. monocle_apptrace-0.3.0/src/monocle_apptrace/instrumentation/metamodel/botocore/__init__.py +0 -0
  27. monocle_apptrace-0.3.0/src/monocle_apptrace/instrumentation/metamodel/botocore/_helper.py +95 -0
  28. monocle_apptrace-0.3.0/src/monocle_apptrace/instrumentation/metamodel/botocore/entities/__init__.py +0 -0
  29. monocle_apptrace-0.3.0/src/monocle_apptrace/instrumentation/metamodel/botocore/entities/inference.py +65 -0
  30. monocle_apptrace-0.3.0/src/monocle_apptrace/instrumentation/metamodel/botocore/handlers/botocore_span_handler.py +26 -0
  31. monocle_apptrace-0.3.0/src/monocle_apptrace/instrumentation/metamodel/botocore/methods.py +16 -0
  32. monocle_apptrace-0.3.0/src/monocle_apptrace/instrumentation/metamodel/flask/__init__.py +0 -0
  33. monocle_apptrace-0.3.0/src/monocle_apptrace/instrumentation/metamodel/flask/_helper.py +29 -0
  34. monocle_apptrace-0.3.0/src/monocle_apptrace/instrumentation/metamodel/flask/methods.py +13 -0
  35. monocle_apptrace-0.3.0/src/monocle_apptrace/instrumentation/metamodel/haystack/__init__.py +0 -0
  36. monocle_apptrace-0.3.0/src/monocle_apptrace/instrumentation/metamodel/haystack/_helper.py +127 -0
  37. monocle_apptrace-0.3.0/src/monocle_apptrace/instrumentation/metamodel/haystack/entities/__init__.py +0 -0
  38. monocle_apptrace-0.3.0/src/monocle_apptrace/instrumentation/metamodel/haystack/entities/inference.py +76 -0
  39. monocle_apptrace-0.3.0/src/monocle_apptrace/instrumentation/metamodel/haystack/entities/retrieval.py +61 -0
  40. monocle_apptrace-0.3.0/src/monocle_apptrace/instrumentation/metamodel/haystack/methods.py +43 -0
  41. monocle_apptrace-0.3.0/src/monocle_apptrace/instrumentation/metamodel/langchain/__init__.py +0 -0
  42. monocle_apptrace-0.3.0/src/monocle_apptrace/instrumentation/metamodel/langchain/_helper.py +127 -0
  43. monocle_apptrace-0.3.0/src/monocle_apptrace/instrumentation/metamodel/langchain/entities/__init__.py +0 -0
  44. monocle_apptrace-0.3.0/src/monocle_apptrace/instrumentation/metamodel/langchain/entities/inference.py +72 -0
  45. monocle_apptrace-0.3.0/src/monocle_apptrace/instrumentation/metamodel/langchain/entities/retrieval.py +58 -0
  46. monocle_apptrace-0.1.1/src/monocle_apptrace/metamodel/maps/lang_chain_methods.json → monocle_apptrace-0.3.0/src/monocle_apptrace/instrumentation/metamodel/langchain/methods.py +48 -43
  47. monocle_apptrace-0.3.0/src/monocle_apptrace/instrumentation/metamodel/langgraph/__init__.py +0 -0
  48. monocle_apptrace-0.3.0/src/monocle_apptrace/instrumentation/metamodel/langgraph/_helper.py +48 -0
  49. monocle_apptrace-0.3.0/src/monocle_apptrace/instrumentation/metamodel/langgraph/entities/__init__.py +0 -0
  50. monocle_apptrace-0.3.0/src/monocle_apptrace/instrumentation/metamodel/langgraph/entities/inference.py +56 -0
  51. monocle_apptrace-0.3.0/src/monocle_apptrace/instrumentation/metamodel/langgraph/methods.py +14 -0
  52. monocle_apptrace-0.3.0/src/monocle_apptrace/instrumentation/metamodel/llamaindex/__init__.py +0 -0
  53. monocle_apptrace-0.3.0/src/monocle_apptrace/instrumentation/metamodel/llamaindex/_helper.py +172 -0
  54. monocle_apptrace-0.3.0/src/monocle_apptrace/instrumentation/metamodel/llamaindex/entities/__init__.py +0 -0
  55. monocle_apptrace-0.3.0/src/monocle_apptrace/instrumentation/metamodel/llamaindex/entities/agent.py +47 -0
  56. monocle_apptrace-0.3.0/src/monocle_apptrace/instrumentation/metamodel/llamaindex/entities/inference.py +73 -0
  57. monocle_apptrace-0.3.0/src/monocle_apptrace/instrumentation/metamodel/llamaindex/entities/retrieval.py +57 -0
  58. monocle_apptrace-0.3.0/src/monocle_apptrace/instrumentation/metamodel/llamaindex/methods.py +101 -0
  59. monocle_apptrace-0.3.0/src/monocle_apptrace/instrumentation/metamodel/openai/__init__.py +0 -0
  60. monocle_apptrace-0.3.0/src/monocle_apptrace/instrumentation/metamodel/openai/_helper.py +112 -0
  61. monocle_apptrace-0.3.0/src/monocle_apptrace/instrumentation/metamodel/openai/entities/__init__.py +0 -0
  62. monocle_apptrace-0.3.0/src/monocle_apptrace/instrumentation/metamodel/openai/entities/inference.py +71 -0
  63. monocle_apptrace-0.3.0/src/monocle_apptrace/instrumentation/metamodel/openai/entities/retrieval.py +43 -0
  64. monocle_apptrace-0.3.0/src/monocle_apptrace/instrumentation/metamodel/openai/methods.py +45 -0
  65. monocle_apptrace-0.3.0/src/monocle_apptrace/instrumentation/metamodel/requests/__init__.py +4 -0
  66. monocle_apptrace-0.3.0/src/monocle_apptrace/instrumentation/metamodel/requests/_helper.py +31 -0
  67. monocle_apptrace-0.3.0/src/monocle_apptrace/instrumentation/metamodel/requests/methods.py +12 -0
  68. monocle_apptrace-0.1.1/CHANGELOG.md +0 -17
  69. monocle_apptrace-0.1.1/Pipfile.lock +0 -340
  70. monocle_apptrace-0.1.1/src/monocle_apptrace/constants.py +0 -22
  71. monocle_apptrace-0.1.1/src/monocle_apptrace/haystack/__init__.py +0 -9
  72. monocle_apptrace-0.1.1/src/monocle_apptrace/haystack/wrap_node.py +0 -27
  73. monocle_apptrace-0.1.1/src/monocle_apptrace/haystack/wrap_openai.py +0 -44
  74. monocle_apptrace-0.1.1/src/monocle_apptrace/haystack/wrap_pipeline.py +0 -62
  75. monocle_apptrace-0.1.1/src/monocle_apptrace/instrumentor.py +0 -124
  76. monocle_apptrace-0.1.1/src/monocle_apptrace/langchain/__init__.py +0 -6
  77. monocle_apptrace-0.1.1/src/monocle_apptrace/llamaindex/__init__.py +0 -15
  78. monocle_apptrace-0.1.1/src/monocle_apptrace/metamodel/README.md +0 -47
  79. monocle_apptrace-0.1.1/src/monocle_apptrace/metamodel/entities/README.md +0 -54
  80. monocle_apptrace-0.1.1/src/monocle_apptrace/metamodel/entities/entity_types.json +0 -157
  81. monocle_apptrace-0.1.1/src/monocle_apptrace/metamodel/entities/entity_types.py +0 -51
  82. monocle_apptrace-0.1.1/src/monocle_apptrace/metamodel/maps/haystack_methods.json +0 -25
  83. monocle_apptrace-0.1.1/src/monocle_apptrace/metamodel/maps/llama_index_methods.json +0 -70
  84. monocle_apptrace-0.1.1/src/monocle_apptrace/metamodel/spans/README.md +0 -121
  85. monocle_apptrace-0.1.1/src/monocle_apptrace/metamodel/spans/span_example.json +0 -140
  86. monocle_apptrace-0.1.1/src/monocle_apptrace/metamodel/spans/span_format.json +0 -55
  87. monocle_apptrace-0.1.1/src/monocle_apptrace/utils.py +0 -93
  88. monocle_apptrace-0.1.1/src/monocle_apptrace/wrap_common.py +0 -311
  89. monocle_apptrace-0.1.1/src/monocle_apptrace/wrapper.py +0 -24
  90. monocle_apptrace-0.1.1/storage/default__vector_store.json +0 -1
  91. monocle_apptrace-0.1.1/storage/docstore.json +0 -1
  92. monocle_apptrace-0.1.1/storage/graph_store.json +0 -1
  93. monocle_apptrace-0.1.1/storage/image__vector_store.json +0 -1
  94. monocle_apptrace-0.1.1/storage/index_store.json +0 -1
  95. {monocle_apptrace-0.1.1 → monocle_apptrace-0.3.0}/CODEOWNERS.md +0 -0
  96. {monocle_apptrace-0.1.1 → monocle_apptrace-0.3.0}/CODE_OF_CONDUCT.md +0 -0
  97. {monocle_apptrace-0.1.1 → monocle_apptrace-0.3.0}/CONTRIBUTING.md +0 -0
  98. {monocle_apptrace-0.1.1 → monocle_apptrace-0.3.0}/COPYRIGHT.template +0 -0
  99. {monocle_apptrace-0.1.1 → monocle_apptrace-0.3.0}/LICENSE +0 -0
  100. {monocle_apptrace-0.1.1 → monocle_apptrace-0.3.0}/MAINTAINER.md +0 -0
  101. {monocle_apptrace-0.1.1 → monocle_apptrace-0.3.0}/Monocle_contributor_guide.md +0 -0
  102. {monocle_apptrace-0.1.1 → monocle_apptrace-0.3.0}/NOTICE +0 -0
  103. {monocle_apptrace-0.1.1 → monocle_apptrace-0.3.0}/README.md +0 -0
  104. {monocle_apptrace-0.1.1 → monocle_apptrace-0.3.0}/SECURITY.md +0 -0
  105. {monocle_apptrace-0.1.1 → monocle_apptrace-0.3.0}/src/monocle_apptrace/README.md +0 -0
  106. {monocle_apptrace-0.1.1/src/monocle_apptrace → monocle_apptrace-0.3.0/src/monocle_apptrace/instrumentation/metamodel}/__init__.py +0 -0
  107. {monocle_apptrace-0.1.1 → monocle_apptrace-0.3.0}/tox.ini +0 -0
@@ -12,4 +12,5 @@ traces.txt
12
12
  dist
13
13
  .tox
14
14
  .DS_Store
15
- Pipfile**
15
+ Pipfile**
16
+ launch.json
@@ -0,0 +1,75 @@
1
+ ## Version 0.3.0 (2024-12-10)
2
+
3
+ - Fixed issue with passing context in async case ([#150](https://github.com/monocle2ai/monocle/pull/150))
4
+ - Added lambda processor ([#148](https://github.com/monocle2ai/monocle/pull/148))
5
+ - Setup package level init scripts to make the monocle import simpler ([#147](https://github.com/monocle2ai/monocle/pull/147))
6
+ - Boto attributes and test cleanup ([#146](https://github.com/monocle2ai/monocle/pull/146))
7
+ - Openai workflow ([#142](https://github.com/monocle2ai/monocle/pull/142))
8
+ - Add input/output for openai embedding ([#141](https://github.com/monocle2ai/monocle/pull/141))
9
+ - Async method and scope fix ([#140](https://github.com/monocle2ai/monocle/pull/140))
10
+ - Bug fix for helper langchain and langgraph ([#137](https://github.com/monocle2ai/monocle/pull/137))
11
+ - Package main script to run any app with monocle instrumentation ([#132](https://github.com/monocle2ai/monocle/pull/132))
12
+ - Add openai api metamodel ([#131](https://github.com/monocle2ai/monocle/pull/131))
13
+ - Support notion of scopes to group traces/snaps into logical constructs ([#130](https://github.com/monocle2ai/monocle/pull/130))
14
+ - Add Llamaindex ReAct agent ([#127](https://github.com/monocle2ai/monocle/pull/127))
15
+ - Langhcain input fix and s3 exporter prefix support ([#126](https://github.com/monocle2ai/monocle/pull/126))
16
+ - Use standard AWS credential envs ([#123](https://github.com/monocle2ai/monocle/pull/123))
17
+ - Check additional attributes for Azure OpenAI model and consolidate common method in utils ([#122](https://github.com/monocle2ai/monocle/pull/122))
18
+ - Bug fix for accessor ([#121](https://github.com/monocle2ai/monocle/pull/121))
19
+ - Bug fix for empty response ([#120](https://github.com/monocle2ai/monocle/pull/120))
20
+ - Bug fix for inference endpoint ([#119](https://github.com/monocle2ai/monocle/pull/119))
21
+ - Opendal exporter for S3 and Blob ([#117](https://github.com/monocle2ai/monocle/pull/117))
22
+ - Handle specific ModuleNotFoundError exceptions gracefully ([#115](https://github.com/monocle2ai/monocle/pull/115))
23
+ - Adding support for console and memory exporter to list of monocle exporters ([#113](https://github.com/monocle2ai/monocle/pull/113))
24
+ - Add trace id propogation for constant trace id and from request ([#111](https://github.com/monocle2ai/monocle/pull/111))
25
+ - Restructure of monoocle code for easy extensibility ([#109](https://github.com/monocle2ai/monocle/pull/109))
26
+ - S3 update filename prefix ([#98](https://github.com/monocle2ai/monocle/pull/98))
27
+ - Update inference span for botocore sagemaker ([#93](https://github.com/monocle2ai/monocle/pull/93))
28
+ - Capturing inference output and token metadata for bedrock ([#82](https://github.com/monocle2ai/monocle/pull/82))
29
+ - Add dev dependency for Mistral AI integration ([#81](https://github.com/monocle2ai/monocle/pull/81))
30
+ - Add VectorStore deployment URL capture support ([#80](https://github.com/monocle2ai/monocle/pull/80))
31
+ - Clean up cloud exporter implementation ([#79](https://github.com/monocle2ai/monocle/pull/79))
32
+ - Capture inference span input/output events attributes ([#77](https://github.com/monocle2ai/monocle/pull/77))
33
+ - Add release automation workflows ([#76](https://github.com/monocle2ai/monocle/pull/76))
34
+ - Fix gaps in Monocle SDK implementation ([#72](https://github.com/monocle2ai/monocle/pull/72))
35
+ - Add kwargs and return value handling in Accessor ([#71](https://github.com/monocle2ai/monocle/pull/71))
36
+ - Update workflow name formatting ([#69](https://github.com/monocle2ai/monocle/pull/69))
37
+ - Implement Haystack metamodel support ([#68](https://github.com/monocle2ai/monocle/pull/68))
38
+
39
+ ## Version 0.2.0 (2024-12-05)
40
+
41
+ ## 0.2.0 (Oct 22, 2024)
42
+
43
+ - Ndjson format for S3 and Blob exporters ([#61](https://github.com/monocle2ai/monocle/pull/61))
44
+ - Set monocle exporter from env setting ([#60](https://github.com/monocle2ai/monocle/pull/60))
45
+ - Update workflow name and type with new format ([#59](https://github.com/monocle2ai/monocle/pull/59))
46
+ - Updated async and custom output processor testcase for metamodel([#58](https://github.com/monocle2ai/monocle/pull/58))
47
+ - Build okahu exporter and added test cases for okahu exporte ([#56](https://github.com/monocle2ai/monocle/pull/56))
48
+ - Handle exception in span wrappers([#52](https://github.com/monocle2ai/monocle/pull/52))
49
+ - Metamodel entity changes ([#51](https://github.com/monocle2ai/monocle/pull/51)), ([#54](https://github.com/monocle2ai/monocle/pull/54))
50
+ - Error handling for llm_endpoint and tags ([#50](https://github.com/monocle2ai/monocle/pull/50))
51
+ - Context_output for vector store retriever ([#48](https://github.com/monocle2ai/monocle/pull/48))
52
+ - Direct exporter - AWS S3 ([#42](https://github.com/monocle2ai/monocle/pull/42))
53
+ - Direct Exporter - Blob store ([#41](https://github.com/monocle2ai/monocle/pull/41))
54
+ - Initial metamodel definition ([#39](https://github.com/monocle2ai/monocle/pull/39))
55
+ - Improvement in vectorstore traces ([#38](https://github.com/monocle2ai/monocle/pull/38))
56
+ - Update key for session context field in attributes ([#34](https://github.com/monocle2ai/monocle/pull/34))
57
+
58
+
59
+ ## 0.1.0 (Aug 27, 2024)
60
+
61
+ - Fixed LlamaIndex tracing bugs ([#32](https://github.com/monocle2ai/monocle/pull/32))
62
+ - Added support to add AWS cloud infra attributes ([#29](https://github.com/monocle2ai/monocle/pull/29))
63
+ - Added support to add Azure cloud infra attributes ([#23](https://github.com/monocle2ai/monocle/pull/23))
64
+ - Added support for adding provider name in LLM span in traces ([#22](https://github.com/monocle2ai/monocle/pull/22))
65
+ - Added a default file span exporter ([#21](https://github.com/monocle2ai/monocle/pull/21))
66
+ - Moved input and output context and prompts from attributes to events ([#15](https://github.com/monocle2ai/monocle/pull/15))
67
+
68
+
69
+
70
+
71
+
72
+
73
+ ## 0.0.1 (Jul 17, 2024)
74
+
75
+ - First monocle release
@@ -1,4 +1,4 @@
1
- #Monocle User Guide
1
+ # Monocle User Guide
2
2
 
3
3
  ## Monocle Concepts
4
4
  ### Traces
@@ -13,21 +13,42 @@ It’s typically the workflow code components of an application that generate th
13
13
  ```
14
14
  > pip install monocle_apptrace
15
15
  ```
16
+
17
+ - For Azure support (to upload traces to Azure), install with the azure extra:
18
+ ```
19
+ > pip install monocle_apptrace[azure]
20
+ ```
21
+
22
+ - For AWS support (to upload traces to AWS), install with the aws extra:
23
+ ```
24
+ > pip install monocle_apptrace[aws]
25
+ ```
26
+
16
27
  - You can locally build and install Monocle library from source
17
28
  ```
18
- > pip install .
29
+ > pip install .
19
30
  ```
20
31
  - Install the optional test dependencies listed against dev in pyproject.toml in editable mode
21
32
  ```
22
- > pip install -e ".[dev]"
33
+ > pip install -e ".[dev]"
23
34
  ```
24
35
 
36
+
25
37
  ## Using Monocle with your application to generate traces
26
38
  ### Enable Monocle tracing
27
39
  You need to import monocle package and invoke the API ``setup_monocle_telemetry(workflow=<workflow-name>)`` to enable the tracing. The 'workflow-name' is what you define to identify the give application workflow, for example "customer-chatbot". Monocle trace will include this name in every trace. The trace output will include a list of spans in the traces. You can print the output on the console or send it to an HTTP endpoint.
28
40
 
29
41
  ### Using Monocle's out of box support of genAI technology components
30
42
  Monocle community has done the hard work of figuring out what to trace and how to extract relevant details from multiple genAI technology components. For example, if you have a python app coded using LlamaIndex and using models hostsed in OpenAI, Monocle can seamlessly trace your app. All you need to do enable Monocle tracing.
43
+
44
+ ### Using Monocle's Support for Adding Custom Attributes
45
+ Monocle provides users with the ability to add custom attributes to various spans, such as inference and retrieval spans, by utilizing the output processor within its metamodel. This feature allows for dynamic attribute assignment through lambda functions, which operate on an arguments dictionary.
46
+ The arguments dictionary contains key-value pairs that can be used to compute custom attributes. The dictionary includes the following components:
47
+ ```python
48
+ arguments = {"instance":instance, "args":args, "kwargs":kwargs, "output":return_value}
49
+ ```
50
+ By leveraging this dictionary, users can define custom attributes for spans, enabling the integration of additional context and information into the tracing process. The lambda functions used in the attributes field can access and process these values to enrich the span with relevant custom data.
51
+
31
52
  #### Example - Enable Monocle tracing in your application
32
53
  ```python
33
54
  from monocle_apptrace.instrumentor import setup_monocle_telemetry
@@ -48,7 +69,7 @@ chain.invoke({"number":2})
48
69
  # Request callbacks: Finally, let's use the request `callbacks` to achieve the same result
49
70
  chain = LLMChain(llm=llm, prompt=prompt)
50
71
  chain.invoke({"number":2}, {"callbacks":[handler]})
51
-
72
+
52
73
  ```
53
74
 
54
75
  ### Accessing monocle trace
@@ -63,6 +84,12 @@ setup_monocle_telemetry(workflow_name = "simple_math_app",
63
84
  ```
64
85
  To print the trace on the console, use ```ConsoleSpanExporter()``` instead of ```FileSpanExporter()```
65
86
 
87
+ For Azure:
88
+ Install the Azure support as shown in the setup section, then use ```AzureBlobSpanExporter()``` to upload the traces to Azure.
89
+
90
+ For AWS:
91
+ Install the AWS support as shown in the setup section, then use ```S3SpanExporter()``` to upload the traces to an S3 bucket.
92
+
66
93
  ### Leveraging Monocle's extensibility to handle customization
67
94
  When the out of box features from app frameworks are not sufficent, the app developers have to add custom code. For example, if you are extending a LLM class in LlamaIndex to use a model hosted in NVIDIA Triton. This new class is not know to Monocle. You can specify this new class method part of Monocle enabling API and it will be able to trace it.
68
95
 
@@ -22,5 +22,35 @@ After setup of credentials, follow the commands below to publish the package to
22
22
 
23
23
  ```
24
24
  > python3 -m pip install pipenv
25
- > pipenv install monocle-observability
25
+ > pipenv install monocle-apptrace
26
26
  ```
27
+ ### Running the testcases
28
+
29
+
30
+ ##### Activate the virtual environment
31
+ ```
32
+ cd monocle
33
+ monocle% python -m pip install pipenv
34
+ monocle% pipenv --python 3.11.9
35
+ monocle% source $(pipenv --venv)/bin/activate
36
+
37
+ ```
38
+ ##### Install the dependencies
39
+ ```
40
+ monocle% pip install -e '.[dev]'
41
+ ```
42
+
43
+ ##### Run the unit tests
44
+ ```
45
+ monocle% pytest tests/unit/*_test.py
46
+ ```
47
+
48
+ ##### Run the integration tests
49
+ ```
50
+ monocle% pytest -m integration
51
+ ```
52
+
53
+ ###### Run the integration test individually
54
+ ```
55
+ monocle% pytest tests/integration/test_langchain_rag_l_to_m.py
56
+ ```
@@ -1,6 +1,6 @@
1
- Metadata-Version: 2.3
1
+ Metadata-Version: 2.4
2
2
  Name: monocle_apptrace
3
- Version: 0.1.1
3
+ Version: 0.3.0
4
4
  Summary: package with monocle genAI tracing
5
5
  Project-URL: Homepage, https://github.com/monocle2ai/monocle
6
6
  Project-URL: Issues, https://github.com/monocle2ai/monocle/issues
@@ -15,20 +15,41 @@ Requires-Dist: opentelemetry-instrumentation
15
15
  Requires-Dist: opentelemetry-sdk>=1.21.0
16
16
  Requires-Dist: requests
17
17
  Requires-Dist: wrapt>=1.14.0
18
+ Provides-Extra: aws
19
+ Requires-Dist: boto3==1.35.19; extra == 'aws'
20
+ Provides-Extra: azure
21
+ Requires-Dist: azure-storage-blob==12.22.0; extra == 'azure'
18
22
  Provides-Extra: dev
23
+ Requires-Dist: azure-storage-blob==12.22.0; extra == 'dev'
24
+ Requires-Dist: boto3==1.34.131; extra == 'dev'
25
+ Requires-Dist: chromadb==0.4.22; extra == 'dev'
19
26
  Requires-Dist: datasets==2.20.0; extra == 'dev'
20
27
  Requires-Dist: faiss-cpu==1.8.0; extra == 'dev'
28
+ Requires-Dist: flask; extra == 'dev'
29
+ Requires-Dist: haystack-ai==2.3.0; extra == 'dev'
21
30
  Requires-Dist: instructorembedding==1.0.1; extra == 'dev'
31
+ Requires-Dist: langchain-aws==0.1.10; extra == 'dev'
22
32
  Requires-Dist: langchain-chroma==0.1.1; extra == 'dev'
23
33
  Requires-Dist: langchain-community==0.2.5; extra == 'dev'
34
+ Requires-Dist: langchain-mistralai==0.1.13; extra == 'dev'
24
35
  Requires-Dist: langchain-openai==0.1.8; extra == 'dev'
25
36
  Requires-Dist: langchain==0.2.5; extra == 'dev'
37
+ Requires-Dist: langchainhub==0.1.21; extra == 'dev'
38
+ Requires-Dist: langgraph==0.2.68; extra == 'dev'
26
39
  Requires-Dist: llama-index-embeddings-huggingface==0.2.0; extra == 'dev'
40
+ Requires-Dist: llama-index-llms-azure-openai==0.1.9; extra == 'dev'
41
+ Requires-Dist: llama-index-llms-mistralai==0.1.20; extra == 'dev'
27
42
  Requires-Dist: llama-index-vector-stores-chroma==0.1.9; extra == 'dev'
43
+ Requires-Dist: llama-index-vector-stores-opensearch==0.1.10; extra == 'dev'
28
44
  Requires-Dist: llama-index==0.10.30; extra == 'dev'
45
+ Requires-Dist: mistral-haystack==0.0.2; extra == 'dev'
29
46
  Requires-Dist: numpy==1.26.4; extra == 'dev'
47
+ Requires-Dist: opendal==0.45.14; extra == 'dev'
48
+ Requires-Dist: opensearch-haystack==1.2.0; extra == 'dev'
49
+ Requires-Dist: opentelemetry-instrumentation-flask; extra == 'dev'
30
50
  Requires-Dist: parameterized==0.9.0; extra == 'dev'
31
51
  Requires-Dist: pytest==8.0.0; extra == 'dev'
52
+ Requires-Dist: requests-aws4auth==1.2.3; extra == 'dev'
32
53
  Requires-Dist: sentence-transformers==2.6.1; extra == 'dev'
33
54
  Requires-Dist: types-requests==2.31.0.20240106; extra == 'dev'
34
55
  Description-Content-Type: text/markdown
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "monocle_apptrace"
7
- version = "0.1.1"
7
+ version = "0.3.0"
8
8
  authors = []
9
9
  description = "package with monocle genAI tracing"
10
10
  readme = "README.md"
@@ -23,8 +23,20 @@ dependencies = [
23
23
  ]
24
24
 
25
25
  [tool.pytest.ini_options]
26
+ #log_cli = true
27
+ #log_cli_level = "INFO"
28
+ # Enable file logging
29
+ log_file = "traces.log"
30
+ log_file_level = "INFO"
31
+ log_format = "%(asctime)s %(levelname)s %(pathname)s:%(lineno)d %(message)s"
32
+ log_date_format = "%Y-%m-%d %H:%M:%S"
33
+
26
34
  pythonpath = [
27
- "src"
35
+ "src",
36
+ "tests"
37
+ ]
38
+ markers = [
39
+ "integration"
28
40
  ]
29
41
 
30
42
  [project.optional-dependencies]
@@ -43,7 +55,32 @@ dev = [
43
55
  'llama-index==0.10.30',
44
56
  'llama-index-embeddings-huggingface==0.2.0',
45
57
  'llama-index-vector-stores-chroma==0.1.9',
46
- 'parameterized==0.9.0'
58
+ 'parameterized==0.9.0',
59
+ 'llama-index-llms-mistralai==0.1.20',
60
+ 'langchain-mistralai==0.1.13',
61
+ 'mistral-haystack==0.0.2',
62
+ 'langchain-aws==0.1.10',
63
+ 'azure-storage-blob==12.22.0', # this is for blob exporter
64
+ 'boto3==1.34.131', # this is for aws exporter
65
+ 'llama-index-vector-stores-opensearch==0.1.10',
66
+ 'haystack-ai==2.3.0',
67
+ 'llama-index-llms-azure-openai==0.1.9',
68
+ 'requests-aws4auth==1.2.3',
69
+ 'opensearch-haystack==1.2.0',
70
+ 'langchainhub==0.1.21',
71
+ 'chromadb==0.4.22',
72
+ 'flask',
73
+ 'opentelemetry-instrumentation-flask',
74
+ 'langgraph==0.2.68',
75
+ 'opendal==0.45.14'
76
+ ]
77
+
78
+ azure = [
79
+ 'azure-storage-blob==12.22.0',
80
+ ]
81
+
82
+ aws = [
83
+ 'boto3==1.35.19',
47
84
  ]
48
85
 
49
86
  [project.urls]
@@ -0,0 +1 @@
1
+ from .instrumentation import *
@@ -0,0 +1,19 @@
1
+ import sys, os
2
+ import runpy
3
+ from monocle_apptrace.instrumentation.common.instrumentor import setup_monocle_telemetry
4
+
5
+ def main():
6
+ if len(sys.argv) < 2 or not sys.argv[1].endswith(".py"):
7
+ print("Usage: python -m monocle_apptrace <your-main-module-file> <args>")
8
+ sys.exit(1)
9
+ file_name = os.path.basename(sys.argv[1])
10
+ workflow_name = file_name[:-3]
11
+ setup_monocle_telemetry(workflow_name=workflow_name)
12
+ sys.argv.pop(0)
13
+
14
+ try:
15
+ runpy.run_path(path_name=sys.argv[0], run_name="__main__")
16
+ except Exception as e:
17
+ print(e)
18
+ if __name__ == "__main__":
19
+ main()
@@ -0,0 +1,181 @@
1
+ import os
2
+ import time
3
+ import random
4
+ import datetime
5
+ import logging
6
+ import asyncio
7
+ import boto3
8
+ from botocore.exceptions import ClientError
9
+ from botocore.exceptions import (
10
+ BotoCoreError,
11
+ ConnectionClosedError,
12
+ ConnectTimeoutError,
13
+ EndpointConnectionError,
14
+ ReadTimeoutError,
15
+ )
16
+ from opentelemetry.sdk.trace import ReadableSpan
17
+ from opentelemetry.sdk.trace.export import SpanExporter, SpanExportResult
18
+ from monocle_apptrace.exporters.base_exporter import SpanExporterBase
19
+ from monocle_apptrace.exporters.exporter_processor import ExportTaskProcessor
20
+ from typing import Sequence, Optional
21
+ import json
22
+ logger = logging.getLogger(__name__)
23
+
24
+ class S3SpanExporter(SpanExporterBase):
25
+ def __init__(self, bucket_name=None, region_name=None, task_processor: Optional[ExportTaskProcessor] = None):
26
+ super().__init__()
27
+ # Use environment variables if credentials are not provided
28
+ DEFAULT_FILE_PREFIX = "monocle_trace_"
29
+ DEFAULT_TIME_FORMAT = "%Y-%m-%d__%H.%M.%S"
30
+ self.max_batch_size = 500
31
+ self.export_interval = 1
32
+ if(os.getenv('MONOCLE_AWS_ACCESS_KEY_ID') and os.getenv('MONOCLE_AWS_SECRET_ACCESS_KEY')):
33
+ self.s3_client = boto3.client(
34
+ 's3',
35
+ aws_access_key_id=os.getenv('MONOCLE_AWS_ACCESS_KEY_ID'),
36
+ aws_secret_access_key=os.getenv('MONOCLE_AWS_SECRET_ACCESS_KEY'),
37
+ region_name=region_name,
38
+ )
39
+ else:
40
+ self.s3_client = boto3.client(
41
+ 's3',
42
+ aws_access_key_id=os.getenv('AWS_ACCESS_KEY_ID'),
43
+ aws_secret_access_key=os.getenv('AWS_SECRET_ACCESS_KEY'),
44
+ region_name=region_name,
45
+ )
46
+ self.bucket_name = bucket_name or os.getenv('MONOCLE_S3_BUCKET_NAME','default-bucket')
47
+ self.file_prefix = os.getenv('MONOCLE_S3_KEY_PREFIX', DEFAULT_FILE_PREFIX)
48
+ self.time_format = DEFAULT_TIME_FORMAT
49
+ self.export_queue = []
50
+ self.last_export_time = time.time()
51
+ self.task_processor = task_processor
52
+ if self.task_processor is not None:
53
+ self.task_processor.start()
54
+
55
+ # Check if bucket exists or create it
56
+ if not self.__bucket_exists(self.bucket_name):
57
+ try:
58
+ self.s3_client.create_bucket(
59
+ Bucket=self.bucket_name,
60
+ CreateBucketConfiguration={'LocationConstraint': region_name}
61
+ )
62
+ logger.info(f"Bucket {self.bucket_name} created successfully.")
63
+ except ClientError as e:
64
+ logger.error(f"Error creating bucket {self.bucket_name}: {e}")
65
+ raise e
66
+
67
+ def __bucket_exists(self, bucket_name):
68
+ try:
69
+ # Check if the bucket exists by calling head_bucket
70
+ self.s3_client.head_bucket(Bucket=bucket_name)
71
+ return True
72
+ except ClientError as e:
73
+ error_code = e.response['Error']['Code']
74
+ if error_code == '404':
75
+ # Bucket not found
76
+ logger.error(f"Bucket {bucket_name} does not exist (404).")
77
+ return False
78
+ elif error_code == '403':
79
+ # Permission denied
80
+ logger.error(f"Access to bucket {bucket_name} is forbidden (403).")
81
+ raise PermissionError(f"Access to bucket {bucket_name} is forbidden.")
82
+ elif error_code == '400':
83
+ # Bad request or malformed input
84
+ logger.error(f"Bad request for bucket {bucket_name} (400).")
85
+ raise ValueError(f"Bad request for bucket {bucket_name}.")
86
+ else:
87
+ # Other client errors
88
+ logger.error(f"Unexpected error when accessing bucket {bucket_name}: {e}")
89
+ raise e
90
+ except TypeError as e:
91
+ # Handle TypeError separately
92
+ logger.error(f"Type error while checking bucket existence: {e}")
93
+ raise e
94
+
95
+ def export(self, spans: Sequence[ReadableSpan]) -> SpanExportResult:
96
+ """Synchronous export method that internally handles async logic."""
97
+ try:
98
+ # Run the asynchronous export logic in an event loop
99
+ logger.info(f"Exporting {len(spans)} spans to S3.")
100
+ asyncio.run(self.__export_async(spans))
101
+ return SpanExportResult.SUCCESS
102
+ except Exception as e:
103
+ logger.error(f"Error exporting spans: {e}")
104
+ return SpanExportResult.FAILURE
105
+
106
+ async def __export_async(self, spans: Sequence[ReadableSpan]) -> SpanExportResult:
107
+ try:
108
+ logger.info(f"__export_async {len(spans)} spans to S3.")
109
+ # Add spans to the export queue
110
+ for span in spans:
111
+ self.export_queue.append(span)
112
+ # If the queue reaches MAX_BATCH_SIZE, export the spans
113
+ if len(self.export_queue) >= self.max_batch_size:
114
+ await self.__export_spans()
115
+
116
+ # Check if it's time to force a flush
117
+ current_time = time.time()
118
+ if current_time - self.last_export_time >= self.export_interval:
119
+ await self.__export_spans() # Export spans if time interval has passed
120
+ self.last_export_time = current_time # Reset the last export time
121
+
122
+ return SpanExportResult.SUCCESS
123
+ except Exception as e:
124
+ logger.error(f"Error exporting spans: {e}")
125
+ return SpanExportResult.FAILURE
126
+
127
+ def __serialize_spans(self, spans: Sequence[ReadableSpan]) -> str:
128
+ try:
129
+ # Serialize spans to JSON or any other format you prefer
130
+ valid_json_list = []
131
+ for span in spans:
132
+ try:
133
+ valid_json_list.append(span.to_json(indent=0).replace("\n", ""))
134
+ except json.JSONDecodeError as e:
135
+ logger.warning(f"Invalid JSON format in span data: {span.context.span_id}. Error: {e}")
136
+ continue
137
+ ndjson_data = "\n".join(valid_json_list) + "\n"
138
+ return ndjson_data
139
+ except Exception as e:
140
+ logger.warning(f"Error serializing spans: {e}")
141
+
142
+
143
+ async def __export_spans(self):
144
+ if len(self.export_queue) == 0:
145
+ return
146
+
147
+ # Take a batch of spans from the queue
148
+ batch_to_export = self.export_queue[:self.max_batch_size]
149
+ serialized_data = self.__serialize_spans(batch_to_export)
150
+ self.export_queue = self.export_queue[self.max_batch_size:]
151
+ # to calculate is_root_span loop over each span in batch_to_export and check if parent id is none or null
152
+ is_root_span = any(not span.parent for span in batch_to_export)
153
+ logger.info(f"Exporting {len(batch_to_export)} spans to S3 is_root_span : {is_root_span}.")
154
+ if self.task_processor is not None and callable(getattr(self.task_processor, 'queue_task', None)):
155
+ self.task_processor.queue_task(self.__upload_to_s3, serialized_data, is_root_span)
156
+ else:
157
+ try:
158
+ self.__upload_to_s3(serialized_data)
159
+ except Exception as e:
160
+ logger.error(f"Failed to upload span batch: {e}")
161
+
162
+ @SpanExporterBase.retry_with_backoff(exceptions=(EndpointConnectionError, ConnectionClosedError, ReadTimeoutError, ConnectTimeoutError))
163
+ def __upload_to_s3(self, span_data_batch: str):
164
+ current_time = datetime.datetime.now().strftime(self.time_format)
165
+ prefix = self.file_prefix + os.environ.get('MONOCLE_S3_KEY_PREFIX_CURRENT', '')
166
+ file_name = f"{prefix}{current_time}.ndjson"
167
+ self.s3_client.put_object(
168
+ Bucket=self.bucket_name,
169
+ Key=file_name,
170
+ Body=span_data_batch
171
+ )
172
+ logger.info(f"Span batch uploaded to AWS S3 as {file_name}.")
173
+
174
+ async def force_flush(self, timeout_millis: int = 30000) -> bool:
175
+ await self.__export_spans() # Export any remaining spans in the queue
176
+ return True
177
+
178
+ def shutdown(self) -> None:
179
+ if hasattr(self, 'task_processor') and self.task_processor is not None:
180
+ self.task_processor.stop()
181
+ logger.info("S3SpanExporter has been shut down.")
@@ -0,0 +1,137 @@
1
+ import os
2
+ import time
3
+ import datetime
4
+ import logging
5
+ import asyncio
6
+ from typing import Sequence, Optional
7
+ from opentelemetry.sdk.trace import ReadableSpan
8
+ from opentelemetry.sdk.trace.export import SpanExportResult
9
+ from monocle_apptrace.exporters.base_exporter import SpanExporterBase
10
+ from monocle_apptrace.exporters.exporter_processor import ExportTaskProcessor
11
+ from opendal import Operator
12
+ from opendal.exceptions import PermissionDenied, ConfigInvalid, Unexpected
13
+
14
+ import json
15
+
16
+ logger = logging.getLogger(__name__)
17
+ class OpenDALS3Exporter(SpanExporterBase):
18
+ def __init__(self, bucket_name=None, region_name=None, task_processor: Optional[ExportTaskProcessor] = None):
19
+ super().__init__()
20
+ DEFAULT_FILE_PREFIX = "monocle_trace_"
21
+ DEFAULT_TIME_FORMAT = "%Y-%m-%d__%H.%M.%S"
22
+ self.max_batch_size = 500
23
+ self.export_interval = 1
24
+ self.file_prefix = DEFAULT_FILE_PREFIX
25
+ self.time_format = DEFAULT_TIME_FORMAT
26
+ self.export_queue = []
27
+ self.last_export_time = time.time()
28
+ self.bucket_name = bucket_name or os.getenv("MONOCLE_S3_BUCKET_NAME", "default-bucket")
29
+
30
+ # Initialize OpenDAL S3 operator
31
+ self.op = Operator(
32
+ "s3",
33
+ root = "/",
34
+ region=os.getenv("AWS_REGION", region_name),
35
+ bucket=self.bucket_name,
36
+ access_key_id=os.getenv("AWS_ACCESS_KEY_ID"),
37
+ secret_access_key=os.getenv("AWS_SECRET_ACCESS_KEY"),
38
+ )
39
+
40
+ self.task_processor = task_processor
41
+ if self.task_processor is not None:
42
+ self.task_processor.start()
43
+
44
+ def export(self, spans: Sequence[ReadableSpan]) -> SpanExportResult:
45
+ """Synchronous export method that internally handles async logic."""
46
+ try:
47
+ # Run the asynchronous export logic in an event loop
48
+ asyncio.run(self.__export_async(spans))
49
+ return SpanExportResult.SUCCESS
50
+ except Exception as e:
51
+ logger.error(f"Error exporting spans: {e}")
52
+ return SpanExportResult.FAILURE
53
+
54
+ async def __export_async(self, spans: Sequence[ReadableSpan]) -> SpanExportResult:
55
+ try:
56
+ # Add spans to the export queue
57
+ for span in spans:
58
+ self.export_queue.append(span)
59
+ if len(self.export_queue) >= self.max_batch_size:
60
+ await self.__export_spans()
61
+
62
+ # Check if it's time to force a flush
63
+ current_time = time.time()
64
+ if current_time - self.last_export_time >= self.export_interval:
65
+ await self.__export_spans()
66
+ self.last_export_time = current_time
67
+
68
+ return SpanExportResult.SUCCESS
69
+ except Exception as e:
70
+ logger.error(f"Error exporting spans: {e}")
71
+ return SpanExportResult.FAILURE
72
+
73
+ def __serialize_spans(self, spans: Sequence[ReadableSpan]) -> str:
74
+ try:
75
+ # Serialize spans to JSON or any other format you prefer
76
+ valid_json_list = []
77
+ for span in spans:
78
+ try:
79
+ valid_json_list.append(span.to_json(indent=0).replace("\n", ""))
80
+ except json.JSONDecodeError as e:
81
+ logger.warning(f"Invalid JSON format in span data: {span.context.span_id}. Error: {e}")
82
+ continue
83
+ return "\n".join(valid_json_list) + "\n"
84
+ except Exception as e:
85
+ logger.warning(f"Error serializing spans: {e}")
86
+
87
+ async def __export_spans(self):
88
+ if not self.export_queue:
89
+ return
90
+ # Take a batch of spans from the queue
91
+ batch_to_export = self.export_queue[:self.max_batch_size]
92
+ serialized_data = self.__serialize_spans(batch_to_export)
93
+ self.export_queue = self.export_queue[self.max_batch_size:]
94
+
95
+ # Calculate is_root_span by checking if any span has no parent
96
+ is_root_span = any(not span.parent for span in batch_to_export)
97
+
98
+ if self.task_processor is not None and callable(getattr(self.task_processor, 'queue_task', None)):
99
+ self.task_processor.queue_task(self.__upload_to_s3, serialized_data, is_root_span)
100
+ else:
101
+ try:
102
+ self.__upload_to_s3(serialized_data, is_root_span)
103
+ except Exception as e:
104
+ logger.error(f"Failed to upload span batch: {e}")
105
+
106
+ @SpanExporterBase.retry_with_backoff(exceptions=(Unexpected))
107
+ def __upload_to_s3(self, span_data_batch: str, is_root_span: bool = False):
108
+ current_time = datetime.datetime.now().strftime(self.time_format)
109
+ file_name = f"{self.file_prefix}{current_time}.ndjson"
110
+ try:
111
+ # Attempt to write the span data batch to S3
112
+ self.op.write(file_name, span_data_batch.encode("utf-8"))
113
+ logger.info(f"Span batch uploaded to S3 as {file_name}. Is root span: {is_root_span}")
114
+
115
+ except PermissionDenied as e:
116
+ # S3 bucket is forbidden.
117
+ logger.error(f"Access to bucket {self.bucket_name} is forbidden (403).")
118
+ raise PermissionError(f"Access to bucket {self.bucket_name} is forbidden.")
119
+
120
+ except ConfigInvalid as e:
121
+ # Bucket does not exist.
122
+ if "404" in str(e):
123
+ logger.error("Bucket does not exist. Please check the bucket name and region.")
124
+ raise Exception(f"Bucket does not exist. Error: {e}")
125
+ else:
126
+ logger.error(f"Unexpected error when accessing bucket {self.bucket_name}: {e}")
127
+ raise e
128
+
129
+
130
+ async def force_flush(self, timeout_millis: int = 30000) -> bool:
131
+ await self.__export_spans()
132
+ return True
133
+
134
+ def shutdown(self) -> None:
135
+ if hasattr(self, 'task_processor') and self.task_processor is not None:
136
+ self.task_processor.stop()
137
+ logger.info("S3SpanExporter has been shut down.")