-
Notifications
You must be signed in to change notification settings - Fork 17
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
initial commit for instrumentation using monkey patching and open telemetry formatting and linting Do not install dependencies for opentelemetry by default version locking make changes for async client feat: instrumentation for litellm and openai revert log changes langgraph instrumentation remove openai instrumentation fix missing import formatting minor changes minor fixes fixes per comments
- Loading branch information
Showing
24 changed files
with
682 additions
and
4 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
import importlib | ||
from opentelemetry import trace | ||
from opentelemetry.sdk.trace import TracerProvider | ||
from opentelemetry.sdk.trace.export import BatchSpanProcessor | ||
from opentelemetry.instrumentation.instrumentor import BaseInstrumentor # type: ignore [attr-defined] | ||
|
||
from .crewai import CrewAIInstrumentor | ||
from .litellm import LitellmInstrumentor | ||
from .portkey_span_exporter import PortkeySpanExporter | ||
from .langgraph import LanggraphInstrumentor | ||
|
||
__all__ = ["initialize_instrumentation"] | ||
|
||
package_instrumentor_map: dict[str, BaseInstrumentor] = { | ||
"crewai": CrewAIInstrumentor, | ||
"litellm": LitellmInstrumentor, | ||
"langgraph": LanggraphInstrumentor, | ||
} | ||
|
||
|
||
def initialize_instrumentation(api_key: str, base_url: str): | ||
tracer_provider = TracerProvider() | ||
exporter = PortkeySpanExporter(api_key=api_key, base_url=base_url) | ||
trace.set_tracer_provider(tracer_provider) | ||
tracer_provider.add_span_processor(BatchSpanProcessor(exporter)) | ||
for package, instrumentor in package_instrumentor_map.items(): | ||
if importlib.util.find_spec(package): | ||
instrumentor().instrument() | ||
print(f"Portkey: {package} Instrumentation initialized") |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
from .instrumentation import CrewAIInstrumentor | ||
|
||
__all__ = ["CrewAIInstrumentor"] |
68 changes: 68 additions & 0 deletions
68
portkey_ai/api_resources/instrumentation/crewai/instrumentation.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,68 @@ | ||
import importlib.metadata | ||
from typing import Any, Collection | ||
from opentelemetry.instrumentation.instrumentor import BaseInstrumentor # type: ignore [attr-defined] | ||
from opentelemetry.trace import get_tracer | ||
from wrapt import wrap_function_wrapper | ||
|
||
from portkey_ai.api_resources.instrumentation.crewai.patch import patch_crew | ||
|
||
|
||
class CrewAIInstrumentor(BaseInstrumentor): | ||
methods_to_patch = [ | ||
{ | ||
"module": "crewai.crew", | ||
"method": "Crew.kickoff", | ||
}, | ||
{ | ||
"module": "crewai.crew", | ||
"method": "Crew.kickoff_for_each", | ||
}, | ||
{ | ||
"module": "crewai.crew", | ||
"method": "Crew.kickoff_async", | ||
}, | ||
{ | ||
"module": "crewai.crew", | ||
"method": "Crew.kickoff_for_each_async", | ||
}, | ||
{ | ||
"module": "crewai.agent", | ||
"method": "Agent.execute_task", | ||
}, | ||
{ | ||
"module": "crewai.task", | ||
"method": "Task.execute_sync", | ||
}, | ||
{ | ||
"module": "crewai.memory.storage.rag_storage", | ||
"method": "RAGStorage.save", | ||
}, | ||
{ | ||
"module": "crewai.memory.storage.rag_storage", | ||
"method": "RAGStorage.search", | ||
}, | ||
{ | ||
"module": "crewai.memory.storage.rag_storage", | ||
"method": "RAGStorage.reset", | ||
}, | ||
] | ||
|
||
def instrumentation_dependencies(self) -> Collection[str]: | ||
return ["crewai >= 0.32.0"] | ||
|
||
def _instrument(self, **kwargs: Any) -> None: | ||
version = importlib.metadata.version("crewai") | ||
tracer_provider = kwargs.get("tracer_provider") | ||
tracer = get_tracer(__name__, "", tracer_provider) | ||
try: | ||
for method in self.methods_to_patch: | ||
wrap_function_wrapper( | ||
module=method["module"], | ||
name=method["method"], | ||
wrapper=patch_crew(method["method"], version, tracer), | ||
) | ||
except Exception as e: | ||
print(f"Failed to instrument CrewAI: {e}") | ||
|
||
def _uninstrument(self, **kwargs: Any) -> None: | ||
pass |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,50 @@ | ||
from opentelemetry import trace | ||
from opentelemetry.trace import SpanKind, Status, StatusCode | ||
|
||
from portkey_ai.utils.json_utils import serialize_args, serialize_kwargs | ||
from portkey_ai.api_resources.instrumentation.utils import ( | ||
set_members, | ||
set_span_attribute, | ||
) | ||
|
||
|
||
def patch_crew(operation_name: str, version: str, tracer: trace.Tracer): | ||
def traced_func(wrapped, instance, args, kwargs): | ||
with tracer.start_as_current_span( | ||
name=operation_name, kind=SpanKind.CLIENT | ||
) as span: | ||
try: | ||
module_name = instance.__module__ | ||
class_name = instance.__class__.__name__ | ||
|
||
span.set_attribute("_source", "crewai") | ||
span.set_attribute("_source_type", "agent framework") | ||
span.set_attribute("framework.version", version) | ||
span.set_attribute("module", module_name) | ||
span.set_attribute("method", operation_name) | ||
span.set_attribute("args", serialize_args(*args)) | ||
span.set_attribute("kwargs", serialize_kwargs(**kwargs)) | ||
|
||
result = wrapped(*args, **kwargs) | ||
span.set_status(Status(StatusCode.OK)) | ||
|
||
try: | ||
set_members(span, instance, module_name, class_name) | ||
except Exception as e: | ||
span.record_exception(e) | ||
|
||
set_span_attribute(span, "result", result) | ||
|
||
if class_name == "Crew": | ||
for attr in ["tasks_output", "token_usage", "usage_metrics"]: | ||
if hasattr(result, attr): | ||
span.set_attribute( | ||
f"crewai.crew.{attr}", str(getattr(result, attr)) | ||
) | ||
except Exception as e: | ||
span.record_exception(e) | ||
span.set_status(Status(StatusCode.ERROR, str(e))) | ||
raise | ||
return result | ||
|
||
return traced_func |
5 changes: 5 additions & 0 deletions
5
portkey_ai/api_resources/instrumentation/langgraph/__init__.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
from portkey_ai.api_resources.instrumentation.langgraph.instrumentation import ( | ||
LanggraphInstrumentor, | ||
) | ||
|
||
__all__ = ["LanggraphInstrumentor"] |
52 changes: 52 additions & 0 deletions
52
portkey_ai/api_resources/instrumentation/langgraph/instrumentation.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,52 @@ | ||
import importlib.metadata | ||
from typing import Any, Collection | ||
from opentelemetry.instrumentation.instrumentor import BaseInstrumentor # type: ignore [attr-defined] | ||
from opentelemetry.trace import get_tracer | ||
from wrapt import wrap_function_wrapper | ||
|
||
from portkey_ai.api_resources.instrumentation.langgraph.patch import patch_langgraph | ||
|
||
|
||
class LanggraphInstrumentor(BaseInstrumentor): | ||
methods_to_patch = [ | ||
{ | ||
"module": "langgraph.graph.state", | ||
"method": "StateGraph.add_node", | ||
}, | ||
{ | ||
"module": "langgraph.graph.state", | ||
"method": "StateGraph.add_edge", | ||
}, | ||
{ | ||
"module": "langgraph.graph.state", | ||
"method": "StateGraph.set_entry_point", | ||
}, | ||
{ | ||
"module": "langgraph.graph.state", | ||
"method": "StateGraph.set_finish_point", | ||
}, | ||
{ | ||
"module": "langgraph.graph.state", | ||
"method": "StateGraph.add_conditional_edges", | ||
}, | ||
] | ||
|
||
def instrumentation_dependencies(self) -> Collection[str]: | ||
return ["langgraph >= 0.2.0"] | ||
|
||
def _instrument(self, **kwargs: Any) -> None: | ||
version = importlib.metadata.version("langgraph") | ||
tracer_provider = kwargs.get("tracer_provider") | ||
tracer = get_tracer(__name__, "", tracer_provider) | ||
try: | ||
for method in self.methods_to_patch: | ||
wrap_function_wrapper( | ||
module=method["module"], | ||
name=method["method"], | ||
wrapper=patch_langgraph(method["method"], version, tracer), | ||
) | ||
except Exception as e: | ||
print(f"Failed to instrument Langgraph: {e}") | ||
|
||
def _uninstrument(self, **kwargs: Any) -> None: | ||
pass |
Oops, something went wrong.