flock-core 0.2.2__py3-none-any.whl → 0.2.3__py3-none-any.whl
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 flock-core might be problematic. Click here for more details.
- flock/__init__.py +4 -0
- flock/config.py +29 -0
- flock/core/__init__.py +5 -0
- flock/core/flock.py +1 -2
- flock/core/logging/telemetry.py +102 -14
- flock/core/logging/telemetry_exporter/file_span.py +37 -0
- flock/core/logging/telemetry_exporter/sqllite_span.py +68 -0
- flock/workflow/activities.py +1 -1
- {flock_core-0.2.2.dist-info → flock_core-0.2.3.dist-info}/METADATA +2 -1
- {flock_core-0.2.2.dist-info → flock_core-0.2.3.dist-info}/RECORD +12 -9
- {flock_core-0.2.2.dist-info → flock_core-0.2.3.dist-info}/WHEEL +0 -0
- {flock_core-0.2.2.dist-info → flock_core-0.2.3.dist-info}/licenses/LICENSE +0 -0
flock/__init__.py
CHANGED
flock/config.py
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
# flock/config.py
|
|
2
|
+
import os
|
|
3
|
+
|
|
4
|
+
from flock.core.logging.telemetry import TelemetryConfig
|
|
5
|
+
|
|
6
|
+
# -- Connection and External Service Configurations --
|
|
7
|
+
TEMPORAL_SERVER_URL = os.getenv("TEMPORAL_SERVER_URL", "localhost:7233")
|
|
8
|
+
DEFAULT_MODEL = os.getenv("DEFAULT_MODEL", "openai/gpt-4o")
|
|
9
|
+
|
|
10
|
+
# API Keys and related settings
|
|
11
|
+
TAVILY_API_KEY = os.getenv("TAVILY_API_KEY", "")
|
|
12
|
+
GITHUB_PAT = os.getenv("GITHUB_PAT", "")
|
|
13
|
+
GITHUB_REPO = os.getenv("GITHUB_REPO", "")
|
|
14
|
+
GITHUB_USERNAME = os.getenv("GITHUB_USERNAME", "")
|
|
15
|
+
|
|
16
|
+
# -- Debugging and Logging Configurations --
|
|
17
|
+
LOCAL_DEBUG = os.getenv("LOCAL_DEBUG", "0") == "1"
|
|
18
|
+
LOG_LEVEL = os.getenv("LOG_LEVEL", "DEBUG")
|
|
19
|
+
|
|
20
|
+
OTL_SERVICE_NAME = os.getenv("OTL_SERVICE_NAME", "otel-flock")
|
|
21
|
+
JAEGER_ENDPOINT = os.getenv(
|
|
22
|
+
"JAEGER_ENDPOINT", "http://localhost:14268/api/traces"
|
|
23
|
+
) # Default gRPC endpoint for Jaeger
|
|
24
|
+
JAEGER_TRANSPORT = os.getenv(
|
|
25
|
+
"JAEGER_TRANSPORT", "http"
|
|
26
|
+
).lower() # Options: "grpc" or "http"
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
TELEMETRY = TelemetryConfig(OTL_SERVICE_NAME, JAEGER_ENDPOINT, JAEGER_TRANSPORT)
|
flock/core/__init__.py
CHANGED
flock/core/flock.py
CHANGED
|
@@ -15,14 +15,13 @@ from flock.core.flock_agent import FlockAgent
|
|
|
15
15
|
from flock.core.logging.formatters.base_formatter import FormatterOptions
|
|
16
16
|
from flock.core.logging.formatters.pprint_formatter import PrettyPrintFormatter
|
|
17
17
|
from flock.core.logging.logging import get_logger
|
|
18
|
-
from flock.core.logging.telemetry import setup_tracing
|
|
19
18
|
from flock.core.registry.agent_registry import Registry
|
|
20
19
|
from flock.core.util.cli_helper import display_banner
|
|
21
20
|
from flock.core.util.input_resolver import top_level_to_keys
|
|
22
21
|
|
|
23
22
|
T = TypeVar("T", bound=FlockAgent)
|
|
24
23
|
logger = get_logger("flock")
|
|
25
|
-
|
|
24
|
+
|
|
26
25
|
tracer = trace.get_tracer(__name__)
|
|
27
26
|
|
|
28
27
|
|
flock/core/logging/telemetry.py
CHANGED
|
@@ -1,21 +1,109 @@
|
|
|
1
|
+
"""This module sets up OpenTelemetry tracing for a service."""
|
|
2
|
+
|
|
1
3
|
from opentelemetry import trace
|
|
2
|
-
from opentelemetry.exporter.jaeger.thrift import JaegerExporter
|
|
3
4
|
from opentelemetry.sdk.resources import Resource
|
|
4
5
|
from opentelemetry.sdk.trace import TracerProvider
|
|
5
|
-
from opentelemetry.sdk.trace.export import
|
|
6
|
+
from opentelemetry.sdk.trace.export import (
|
|
7
|
+
BatchSpanProcessor,
|
|
8
|
+
)
|
|
9
|
+
|
|
10
|
+
from flock.core.logging.telemetry_exporter.file_span import FileSpanExporter
|
|
11
|
+
from flock.core.logging.telemetry_exporter.sqllite_span import (
|
|
12
|
+
SQLiteSpanExporter,
|
|
13
|
+
)
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
class TelemetryConfig:
|
|
17
|
+
"""This configuration class sets up OpenTelemetry tracing.
|
|
18
|
+
|
|
19
|
+
- Export spans to a Jaeger collector using gRPC.
|
|
20
|
+
- Write spans to a file.
|
|
21
|
+
- Save spans in a SQLite database.
|
|
22
|
+
|
|
23
|
+
Only exporters with a non-None configuration will be activated.
|
|
24
|
+
"""
|
|
25
|
+
|
|
26
|
+
def __init__(
|
|
27
|
+
self,
|
|
28
|
+
service_name: str,
|
|
29
|
+
jaeger_endpoint: str = None,
|
|
30
|
+
jaeger_transport: str = "grpc",
|
|
31
|
+
file_export_path: str = None,
|
|
32
|
+
sqlite_db_path: str = None,
|
|
33
|
+
batch_processor_options: dict = None,
|
|
34
|
+
):
|
|
35
|
+
""":param service_name: Name of your service.
|
|
36
|
+
|
|
37
|
+
:param jaeger_endpoint: The Jaeger collector gRPC endpoint (e.g., "localhost:14250").
|
|
38
|
+
:param file_export_path: If provided, spans will be written to this file.
|
|
39
|
+
:param sqlite_db_path: If provided, spans will be stored in this SQLite DB.
|
|
40
|
+
:param batch_processor_options: Dict of options for BatchSpanProcessor (e.g., {"max_export_batch_size": 10}).
|
|
41
|
+
"""
|
|
42
|
+
self.service_name = service_name
|
|
43
|
+
self.jaeger_endpoint = jaeger_endpoint
|
|
44
|
+
self.jaeger_transport = jaeger_transport
|
|
45
|
+
self.file_export_path = file_export_path
|
|
46
|
+
self.sqlite_db_path = sqlite_db_path
|
|
47
|
+
self.batch_processor_options = batch_processor_options or {}
|
|
48
|
+
|
|
49
|
+
def setup_tracing(self):
|
|
50
|
+
# Create a Resource with the service name.
|
|
51
|
+
resource = Resource(attributes={"service.name": self.service_name})
|
|
52
|
+
provider = TracerProvider(resource=resource)
|
|
53
|
+
trace.set_tracer_provider(provider)
|
|
54
|
+
|
|
55
|
+
# List to collect our span processors.
|
|
56
|
+
span_processors = []
|
|
57
|
+
|
|
58
|
+
# If a Jaeger endpoint is specified, add the Jaeger gRPC exporter.
|
|
59
|
+
if self.jaeger_endpoint:
|
|
60
|
+
if self.jaeger_transport == "grpc":
|
|
61
|
+
from opentelemetry.exporter.jaeger.proto.grpc import (
|
|
62
|
+
JaegerExporter,
|
|
63
|
+
)
|
|
64
|
+
|
|
65
|
+
jaeger_exporter = JaegerExporter(
|
|
66
|
+
endpoint=self.jaeger_endpoint,
|
|
67
|
+
insecure=True,
|
|
68
|
+
)
|
|
69
|
+
elif self.jaeger_transport == "http":
|
|
70
|
+
from opentelemetry.exporter.jaeger.thrift import JaegerExporter
|
|
71
|
+
|
|
72
|
+
jaeger_exporter = JaegerExporter(
|
|
73
|
+
collector_endpoint=self.jaeger_endpoint,
|
|
74
|
+
)
|
|
75
|
+
else:
|
|
76
|
+
raise ValueError(
|
|
77
|
+
"Invalid JAEGER_TRANSPORT specified. Use 'grpc' or 'http'."
|
|
78
|
+
)
|
|
79
|
+
|
|
80
|
+
span_processors.append(
|
|
81
|
+
BatchSpanProcessor(
|
|
82
|
+
jaeger_exporter, **self.batch_processor_options
|
|
83
|
+
)
|
|
84
|
+
)
|
|
6
85
|
|
|
86
|
+
# If a file path is provided, add the custom file exporter.
|
|
87
|
+
if self.file_export_path:
|
|
88
|
+
file_exporter = FileSpanExporter(self.file_export_path)
|
|
89
|
+
span_processors.append(
|
|
90
|
+
BatchSpanProcessor(
|
|
91
|
+
file_exporter, **self.batch_processor_options
|
|
92
|
+
)
|
|
93
|
+
)
|
|
7
94
|
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
95
|
+
# If a SQLite database path is provided, add the custom SQLite exporter.
|
|
96
|
+
if self.sqlite_db_path:
|
|
97
|
+
sqlite_exporter = SQLiteSpanExporter(self.sqlite_db_path)
|
|
98
|
+
span_processors.append(
|
|
99
|
+
BatchSpanProcessor(
|
|
100
|
+
sqlite_exporter, **self.batch_processor_options
|
|
101
|
+
)
|
|
102
|
+
)
|
|
12
103
|
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
agent_port=6831, # default Jaeger agent port
|
|
17
|
-
)
|
|
104
|
+
# Register all span processors with the provider.
|
|
105
|
+
for processor in span_processors:
|
|
106
|
+
provider.add_span_processor(processor)
|
|
18
107
|
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
return tracer
|
|
108
|
+
# Return a tracer instance.
|
|
109
|
+
return trace.get_tracer(__name__)
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import json
|
|
2
|
+
|
|
3
|
+
from opentelemetry.sdk.trace.export import (
|
|
4
|
+
SpanExporter,
|
|
5
|
+
SpanExportResult,
|
|
6
|
+
)
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class FileSpanExporter(SpanExporter):
|
|
10
|
+
"""A simple exporter that writes span data as JSON lines into a file."""
|
|
11
|
+
|
|
12
|
+
def __init__(self, file_path: str):
|
|
13
|
+
self.file_path = file_path
|
|
14
|
+
|
|
15
|
+
def export(self, spans) -> SpanExportResult:
|
|
16
|
+
try:
|
|
17
|
+
with open(self.file_path, "a") as f:
|
|
18
|
+
for span in spans:
|
|
19
|
+
# Create a dictionary representation of the span.
|
|
20
|
+
span_dict = {
|
|
21
|
+
"name": span.name,
|
|
22
|
+
"trace_id": format(span.context.trace_id, "032x"),
|
|
23
|
+
"span_id": format(span.context.span_id, "016x"),
|
|
24
|
+
"start_time": span.start_time,
|
|
25
|
+
"end_time": span.end_time,
|
|
26
|
+
"attributes": span.attributes,
|
|
27
|
+
"status": str(span.status),
|
|
28
|
+
}
|
|
29
|
+
f.write(json.dumps(span_dict) + "\n")
|
|
30
|
+
return SpanExportResult.SUCCESS
|
|
31
|
+
except Exception as e:
|
|
32
|
+
print("Error exporting spans to file:", e)
|
|
33
|
+
return SpanExportResult.FAILURE
|
|
34
|
+
|
|
35
|
+
def shutdown(self) -> None:
|
|
36
|
+
# Nothing special needed on shutdown.
|
|
37
|
+
pass
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import json
|
|
2
|
+
import sqlite3
|
|
3
|
+
|
|
4
|
+
from opentelemetry.sdk.trace.export import (
|
|
5
|
+
SpanExporter,
|
|
6
|
+
SpanExportResult,
|
|
7
|
+
)
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
class SQLiteSpanExporter(SpanExporter):
|
|
11
|
+
"""A custom exporter that writes span data into a SQLite database."""
|
|
12
|
+
|
|
13
|
+
def __init__(self, sqlite_db_path: str):
|
|
14
|
+
self.sqlite_db_path = sqlite_db_path
|
|
15
|
+
self.conn = sqlite3.connect(
|
|
16
|
+
self.sqlite_db_path, check_same_thread=False
|
|
17
|
+
)
|
|
18
|
+
self._create_table()
|
|
19
|
+
|
|
20
|
+
def _create_table(self):
|
|
21
|
+
cursor = self.conn.cursor()
|
|
22
|
+
cursor.execute(
|
|
23
|
+
"""
|
|
24
|
+
CREATE TABLE IF NOT EXISTS spans (
|
|
25
|
+
id TEXT PRIMARY KEY,
|
|
26
|
+
name TEXT,
|
|
27
|
+
trace_id TEXT,
|
|
28
|
+
span_id TEXT,
|
|
29
|
+
start_time INTEGER,
|
|
30
|
+
end_time INTEGER,
|
|
31
|
+
attributes TEXT,
|
|
32
|
+
status TEXT
|
|
33
|
+
)
|
|
34
|
+
"""
|
|
35
|
+
)
|
|
36
|
+
self.conn.commit()
|
|
37
|
+
|
|
38
|
+
def export(self, spans) -> SpanExportResult:
|
|
39
|
+
try:
|
|
40
|
+
cursor = self.conn.cursor()
|
|
41
|
+
for span in spans:
|
|
42
|
+
span_id = format(span.context.span_id, "016x")
|
|
43
|
+
trace_id = format(span.context.trace_id, "032x")
|
|
44
|
+
cursor.execute(
|
|
45
|
+
"""
|
|
46
|
+
INSERT OR REPLACE INTO spans
|
|
47
|
+
(id, name, trace_id, span_id, start_time, end_time, attributes, status)
|
|
48
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?)
|
|
49
|
+
""",
|
|
50
|
+
(
|
|
51
|
+
span_id,
|
|
52
|
+
span.name,
|
|
53
|
+
trace_id,
|
|
54
|
+
span_id,
|
|
55
|
+
span.start_time,
|
|
56
|
+
span.end_time,
|
|
57
|
+
json.dumps(span.attributes),
|
|
58
|
+
str(span.status),
|
|
59
|
+
),
|
|
60
|
+
)
|
|
61
|
+
self.conn.commit()
|
|
62
|
+
return SpanExportResult.SUCCESS
|
|
63
|
+
except Exception as e:
|
|
64
|
+
print("Error exporting spans to SQLite:", e)
|
|
65
|
+
return SpanExportResult.FAILURE
|
|
66
|
+
|
|
67
|
+
def shutdown(self) -> None:
|
|
68
|
+
self.conn.close()
|
flock/workflow/activities.py
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: flock-core
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.3
|
|
4
4
|
Summary: Declarative LLM Orchestration at Scale
|
|
5
5
|
Author-email: Andre Ratzenberger <andre.ratzenberger@whiteduck.de>
|
|
6
6
|
License-File: LICENSE
|
|
@@ -15,6 +15,7 @@ Requires-Dist: httpx>=0.28.1
|
|
|
15
15
|
Requires-Dist: loguru>=0.7.3
|
|
16
16
|
Requires-Dist: msgpack>=1.1.0
|
|
17
17
|
Requires-Dist: opentelemetry-api>=1.30.0
|
|
18
|
+
Requires-Dist: opentelemetry-exporter-jaeger-proto-grpc>=1.21.0
|
|
18
19
|
Requires-Dist: opentelemetry-exporter-jaeger>=1.21.0
|
|
19
20
|
Requires-Dist: opentelemetry-exporter-otlp>=1.30.0
|
|
20
21
|
Requires-Dist: opentelemetry-instrumentation-logging>=0.51b0
|
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
flock/__init__.py,sha256=
|
|
2
|
-
flock/
|
|
3
|
-
flock/core/
|
|
1
|
+
flock/__init__.py,sha256=uJxXAxt0def69cccAAdLjBxQOFXVRO72RE82hJnODSw,108
|
|
2
|
+
flock/config.py,sha256=hul_Vmgl8w5a_4YNfg3Mvll3iVEkjiR5At9D0WsVesw,1006
|
|
3
|
+
flock/core/__init__.py,sha256=0Xq_txurlxxjKGXjRn6GNJusGTiBcd7zw2eF0L7JyuU,183
|
|
4
|
+
flock/core/flock.py,sha256=Iw7Frmz2aZheApxi2KSjsX7gA8ZcemzXhfKXeQdtY0w,9438
|
|
4
5
|
flock/core/flock_agent.py,sha256=59qQ7ohOy2lc1KjI6SV7IcrqYL86ofAhq32pZGgk6eA,27761
|
|
5
6
|
flock/core/context/context.py,sha256=jH06w4C_O5CEL-YxjX_x_dmgLe9Rcllnn1Ebs0dvwaE,6171
|
|
6
7
|
flock/core/context/context_manager.py,sha256=qMySVny_dbTNLh21RHK_YT0mNKIOrqJDZpi9ZVdBsxU,1103
|
|
@@ -9,7 +10,7 @@ flock/core/execution/local_executor.py,sha256=O_dgQ_HJPCp97ghdEoDSNDIiaYkogrUS0G
|
|
|
9
10
|
flock/core/execution/temporal_executor.py,sha256=ai6ikr9rEiN2Kc-208OalxtfqL_FTt_UaH6a--oEkJM,2010
|
|
10
11
|
flock/core/logging/__init__.py,sha256=Q8hp9-1ilPIUIV0jLgJ3_cP7COrea32cVwL7dicPnlM,82
|
|
11
12
|
flock/core/logging/logging.py,sha256=F-FDz9etBXmAIT-fjx3pUfvNXsckgR6ONCMaFZIc4Kw,4619
|
|
12
|
-
flock/core/logging/telemetry.py,sha256=
|
|
13
|
+
flock/core/logging/telemetry.py,sha256=T2CRSiqOWvOsXe-WRsObkkOkrrd6z-BwEYLaBUU2AAM,4017
|
|
13
14
|
flock/core/logging/trace_and_logged.py,sha256=h4YH8s0KjK4tiBdrEZdCLd4fDzMB5-NKwqzrtkWhQw4,1999
|
|
14
15
|
flock/core/logging/formatters/base_formatter.py,sha256=CyG-X2NWq8sqEhFEO2aG7Mey5tVkIzoWiihW301_VIo,1023
|
|
15
16
|
flock/core/logging/formatters/formatter_factory.py,sha256=hmH-NpCESHkioX0GBQ5CuQR4axyIXnSRWwAZCHylx6Q,1283
|
|
@@ -17,6 +18,8 @@ flock/core/logging/formatters/pprint_formatter.py,sha256=2CZoMbfzJB9Xp9WaItxnXY3
|
|
|
17
18
|
flock/core/logging/formatters/rich_formatters.py,sha256=h1FD0_cIdQBQ8P2x05XhgD1cmmP80IBNVT5jb3cAV9M,4776
|
|
18
19
|
flock/core/logging/formatters/theme_builder.py,sha256=1RUEwPIDfCjwTapbK1liasA5SdukOn7YwbZ4H4j1WkI,17364
|
|
19
20
|
flock/core/logging/formatters/themed_formatter.py,sha256=CbxmqUC7zkLzyIxngk-3dcpQ6vxPR6zaDNA2TAMitCI,16714
|
|
21
|
+
flock/core/logging/telemetry_exporter/file_span.py,sha256=e4hr4D7tC9j4KT7JZBuZU0YxQCdHKADpXNeUNEwggN4,1294
|
|
22
|
+
flock/core/logging/telemetry_exporter/sqllite_span.py,sha256=9bqxHt1mDQGyhKxA9dON5xDi_6FMOfBSdrU_zWV0xv4,2107
|
|
20
23
|
flock/core/mixin/dspy_integration.py,sha256=oT5YfXxPhHkMCuwhXoppBAYBGePUAKse7KebGSM-bq0,6880
|
|
21
24
|
flock/core/mixin/prompt_parser.py,sha256=eOqI-FK3y17gVqpc_y5GF-WmK1Jv8mFlkZxTcgweoxI,5121
|
|
22
25
|
flock/core/registry/agent_registry.py,sha256=QHdr3Cb-32PEdz8jFCIZSH9OlfpRwAJMtSRpHCWJDq4,4889
|
|
@@ -362,11 +365,11 @@ flock/themes/zenburned.toml,sha256=UEmquBbcAO3Zj652XKUwCsNoC2iQSlIh-q5c6DH-7Kc,1
|
|
|
362
365
|
flock/themes/zenwritten-dark.toml,sha256=To5l6520_3UqAGiEumpzGWsHhXxqu9ThrMildXKgIO0,1669
|
|
363
366
|
flock/themes/zenwritten-light.toml,sha256=G1iEheCPfBNsMTGaVpEVpDzYBHA_T-MV27rolUYolmE,1666
|
|
364
367
|
flock/workflow/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
365
|
-
flock/workflow/activities.py,sha256=
|
|
368
|
+
flock/workflow/activities.py,sha256=YEg-Gr8kzVsxWsmsZguIVhX2XwMRvhZ2OlnsJoG5g_A,7646
|
|
366
369
|
flock/workflow/agent_activities.py,sha256=NhBZscflEf2IMfSRa_pBM_TRP7uVEF_O0ROvWZ33eDc,963
|
|
367
370
|
flock/workflow/temporal_setup.py,sha256=VWBgmBgfTBjwM5ruS_dVpA5AVxx6EZ7oFPGw4j3m0l0,1091
|
|
368
371
|
flock/workflow/workflow.py,sha256=I9MryXW_bqYVTHx-nl2epbTqeRy27CAWHHA7ZZA0nAk,1696
|
|
369
|
-
flock_core-0.2.
|
|
370
|
-
flock_core-0.2.
|
|
371
|
-
flock_core-0.2.
|
|
372
|
-
flock_core-0.2.
|
|
372
|
+
flock_core-0.2.3.dist-info/METADATA,sha256=cgqdCwNfYyRzXuhttnph9L7L87YOolVUDh6PYRHCbJ4,11129
|
|
373
|
+
flock_core-0.2.3.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
|
374
|
+
flock_core-0.2.3.dist-info/licenses/LICENSE,sha256=iYEqWy0wjULzM9GAERaybP4LBiPeu7Z1NEliLUdJKSc,1072
|
|
375
|
+
flock_core-0.2.3.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|