Skip to content

Commit bb49fb0

Browse files
committed
feat: Add create_span function for observability and examples parameter to module decorator.
1 parent 3d43f8d commit bb49fb0

File tree

9 files changed

+38
-3
lines changed

9 files changed

+38
-3
lines changed

src/apcore/__init__.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,7 @@
129129
SpanExporter,
130130
StdoutExporter,
131131
TracingMiddleware,
132+
create_span,
132133
)
133134

134135
# Trace Context
@@ -258,6 +259,7 @@
258259
"InMemoryExporter",
259260
"OTLPExporter",
260261
"SpanExporter",
262+
"create_span",
261263
# Trace Context
262264
"TraceContext",
263265
"TraceParent",

src/apcore/acl.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,7 @@ def __init__(
8585
self._audit_logger: Callable[[AuditEntry], None] | None = audit_logger
8686
self._logger: logging.Logger = logging.getLogger(__name__)
8787
self._lock = threading.Lock()
88+
self.debug: bool = False
8889

8990
@classmethod
9091
def load(cls, yaml_path: str) -> ACL:

src/apcore/decorator.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
from apcore._docstrings import parse_docstring
1414
from apcore.context import Context
1515
from apcore.errors import FuncMissingReturnTypeError, FuncMissingTypeHintError
16+
from apcore.module import ModuleExample
1617

1718

1819
def _has_explicit_field_description(annotation: Any) -> bool:
@@ -175,6 +176,7 @@ def __init__(
175176
version: str = "1.0.0",
176177
annotations: dict[str, Any] | None = None,
177178
metadata: dict[str, Any] | None = None,
179+
examples: list[ModuleExample] | None = None,
178180
input_schema: type[BaseModel] | None = None,
179181
output_schema: type[BaseModel] | None = None,
180182
) -> None:
@@ -202,6 +204,7 @@ def __init__(
202204
self.version = version
203205
self.annotations = annotations
204206
self.metadata = metadata
207+
self.examples = examples
205208

206209
# Create execute closures — two separate defs required so that
207210
# inspect.iscoroutinefunction returns the correct value.
@@ -249,6 +252,7 @@ def module(
249252
tags: list[str] | None = None,
250253
version: str = "1.0.0",
251254
metadata: dict[str, Any] | None = None,
255+
examples: list[ModuleExample] | None = None,
252256
registry: Any = None,
253257
) -> Any:
254258
"""Wrap a Python function as an apcore module.
@@ -267,6 +271,7 @@ def _wrap(func: Callable, *, return_module: bool = False) -> Any:
267271
tags=tags,
268272
version=version,
269273
metadata=metadata,
274+
examples=examples,
270275
)
271276
if registry is not None:
272277
registry.register(fm.module_id, fm)

src/apcore/observability/__init__.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
SpanExporter,
2424
StdoutExporter,
2525
TracingMiddleware,
26+
create_span,
2627
)
2728

2829
__all__ = [
@@ -36,4 +37,5 @@
3637
"SpanExporter",
3738
"StdoutExporter",
3839
"TracingMiddleware",
40+
"create_span",
3941
]

src/apcore/observability/context_logger.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,14 +28,16 @@ class ContextLogger:
2828

2929
def __init__(
3030
self,
31-
name: str,
31+
name: str = "apcore",
32+
*,
33+
format: str | None = None,
3234
output_format: str = "json",
3335
level: str = "info",
3436
redact_sensitive: bool = True,
3537
output: Any = None,
3638
) -> None:
3739
self._name = name
38-
self._output_format = output_format
40+
self._output_format = format if format is not None else output_format
3941
self._level = level
4042
self._level_value = _LEVELS.get(level, 20)
4143
self._redact_sensitive = redact_sensitive

src/apcore/observability/tracing.py

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,26 @@ class Span:
3232
events: list[dict[str, Any]] = field(default_factory=list)
3333

3434

35+
def create_span(
36+
*,
37+
trace_id: str,
38+
name: str,
39+
start_time: float,
40+
span_id: str | None = None,
41+
parent_span_id: str | None = None,
42+
attributes: dict[str, Any] | None = None,
43+
) -> Span:
44+
"""Factory function to create a Span with sensible defaults."""
45+
return Span(
46+
trace_id=trace_id,
47+
name=name,
48+
start_time=start_time,
49+
span_id=span_id if span_id is not None else os.urandom(8).hex(),
50+
parent_span_id=parent_span_id,
51+
attributes=attributes if attributes is not None else {},
52+
)
53+
54+
3555
@runtime_checkable
3656
class SpanExporter(Protocol):
3757
"""Protocol for span export destinations."""
@@ -293,6 +313,7 @@ def on_error(self, module_id: str, inputs: dict[str, Any], error: Exception, con
293313

294314
__all__ = [
295315
"Span",
316+
"create_span",
296317
"SpanExporter",
297318
"StdoutExporter",
298319
"InMemoryExporter",

src/apcore/schema/exporter.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ def export_mcp(
5252
"destructiveHint": annotations.destructive if annotations else False,
5353
"idempotentHint": annotations.idempotent if annotations else False,
5454
"openWorldHint": annotations.open_world if annotations else True,
55-
"streaming": getattr(annotations, "streaming", False) if annotations else False,
55+
"streaming": annotations.streaming if annotations else False,
5656
},
5757
}
5858

tests/observability/test_observability_package.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,7 @@ def test_all_contains_all_public_names(self):
8080
"SpanExporter",
8181
"StdoutExporter",
8282
"TracingMiddleware",
83+
"create_span",
8384
}
8485
assert set(obs.__all__) == expected
8586

tests/test_public_api.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -440,6 +440,7 @@ class TestPublicAPIAll:
440440
"SpanExporter",
441441
"StdoutExporter",
442442
"InMemoryExporter",
443+
"create_span",
443444
"OTLPExporter",
444445
# Trace Context
445446
"TraceContext",

0 commit comments

Comments
 (0)