Skip to content

Commit 889a0ff

Browse files
author
Christian Quintino De Luca
committed
feat(lsp): indicizzazione globale, goto definition cross-file e rename multi-file
1 parent 1658479 commit 889a0ff

File tree

5 files changed

+594
-1
lines changed

5 files changed

+594
-1
lines changed

README.md

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,39 @@ python aspera_cli.py run --aspera aspera/lang/examples/empathetic.aspera --signa
108108
python aspera_cli.py validate ast.json
109109
```
110110

111+
### LSP (Language Server) Setup
112+
113+
Per abilitare diagnostica in editor e completamento base:
114+
115+
```powershell
116+
# Avvio server LSP (stdin/stdout)
117+
python -m aspera.tools.lsp_server
118+
# oppure, se installato come script
119+
aspera-lsp
120+
```
121+
122+
In VS Code, configura un client LSP generico puntando al comando sopra. Aggiungi anche `.vscode/settings.json` con:
123+
124+
```json
125+
{
126+
"ltex.language": "it-IT",
127+
"python.analysis.diagnosticMode": "openFilesOnly"
128+
}
129+
```
130+
131+
Funzionalità attuali: diagnostica parser in tempo reale, completion basica (`concept.`, `signals.`, `state.`, `threshold(`).
132+
133+
### Telemetry (OpenTelemetry)
134+
135+
ASPERA emette traces/metrics OTLP (HTTP) per observe/step/decide. Per provare in locale:
136+
137+
```powershell
138+
$env:OTEL_EXPORTER_OTLP_ENDPOINT="http://localhost:4318"
139+
python aspera_cli.py run --aspera agents\enterprise\ecommerce_conversion_optimizer\conversion_optimizer.aspera --signals examples\signals_ecommerce.json --mode mock
140+
```
141+
142+
Metriche principali: `aspera_observe_total`, `aspera_step_total`, `aspera_decide_total`. Configura il tuo collector OTLP (es. OpenTelemetry Collector) e visualizza in Grafana/Tempo.
143+
111144
### Smoke test con Groq (tutti gli agent)
112145

113146
```powershell

aspera/runtime/engine.py

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,8 @@
2727
retry_with_backoff,
2828
log_error_structured,
2929
)
30+
from aspera.runtime.otel import init_otel
31+
from opentelemetry import trace, metrics
3032

3133
logger = logging.getLogger(__name__)
3234

@@ -115,6 +117,20 @@ def __init__(
115117
}
116118

117119
logger.info("CognitiveEngine initialized")
120+
# OpenTelemetry (best effort)
121+
try:
122+
init_otel()
123+
self._tracer = trace.get_tracer("aspera.engine")
124+
self._meter = metrics.get_meter("aspera.engine")
125+
self._obs_step = self._meter.create_counter("aspera_observe_total")
126+
self._step_counter = self._meter.create_counter("aspera_step_total")
127+
self._decide_counter = self._meter.create_counter("aspera_decide_total")
128+
except Exception:
129+
self._tracer = None
130+
self._meter = None
131+
self._obs_step = None
132+
self._step_counter = None
133+
self._decide_counter = None
118134

119135
def load_ast(self, ast: Dict[str, Any]):
120136
"""
@@ -186,6 +202,11 @@ def observe(self, signals: Dict[str, Any], context: Dict[str, Any] = None):
186202
)
187203

188204
logger.info(f"Observed signals: {list(signals.keys())}")
205+
try:
206+
if self._obs_step:
207+
self._obs_step.add(1)
208+
except Exception:
209+
pass
189210
self.metrics["durations"]["observe"] = round((time.perf_counter() - t0) * 1000, 2)
190211

191212
def step(self) -> Dict[str, Any]:
@@ -295,6 +316,11 @@ def step(self) -> Dict[str, Any]:
295316
})
296317

297318
self.metrics["durations"]["step"] = round((time.perf_counter() - t0) * 1000, 2)
319+
try:
320+
if self._step_counter:
321+
self._step_counter.add(1)
322+
except Exception:
323+
pass
298324
logger.info(f"Step completed: {len(applied_inferences)} inferences applied, {len(all_changes)} changes")
299325
return step_result
300326

@@ -321,6 +347,11 @@ def decide(self) -> List[Dict[str, Any]]:
321347
})
322348

323349
self.metrics["counts"]["actions"] = len(actions)
350+
try:
351+
if self._decide_counter:
352+
self._decide_counter.add(1)
353+
except Exception:
354+
pass
324355
logger.info(f"Decision completed: {len(actions)} actions selected")
325356
return actions
326357

aspera/runtime/otel.py

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
"""
2+
OpenTelemetry setup per ASPERA Runtime (traces + metrics OTLP).
3+
"""
4+
5+
from __future__ import annotations
6+
7+
import os
8+
from typing import Optional
9+
10+
from opentelemetry import trace, metrics
11+
from opentelemetry.sdk.resources import Resource
12+
from opentelemetry.sdk.trace import TracerProvider
13+
from opentelemetry.sdk.trace.export import BatchSpanProcessor
14+
from opentelemetry.exporter.otlp.proto.http.trace_exporter import OTLPSpanExporter
15+
from opentelemetry.sdk.metrics import MeterProvider
16+
from opentelemetry.exporter.otlp.proto.http.metric_exporter import OTLPMetricExporter
17+
from opentelemetry.sdk.metrics.export import PeriodicExportingMetricReader
18+
19+
20+
def init_otel(service_name: str = "aspera-runtime", endpoint: Optional[str] = None) -> None:
21+
endpoint = endpoint or os.getenv("OTEL_EXPORTER_OTLP_ENDPOINT", "http://localhost:4318")
22+
resource = Resource.create({"service.name": service_name})
23+
24+
# Traces
25+
tracer_provider = TracerProvider(resource=resource)
26+
trace.set_tracer_provider(tracer_provider)
27+
span_exporter = OTLPSpanExporter(endpoint=f"{endpoint}/v1/traces")
28+
tracer_provider.add_span_processor(BatchSpanProcessor(span_exporter))
29+
30+
# Metrics
31+
metric_exporter = OTLPMetricExporter(endpoint=f"{endpoint}/v1/metrics")
32+
reader = PeriodicExportingMetricReader(metric_exporter)
33+
meter_provider = MeterProvider(resource=resource, metric_readers=[reader])
34+
metrics.set_meter_provider(meter_provider)
35+
36+
37+

0 commit comments

Comments
 (0)