Skip to content
This repository was archived by the owner on Jun 1, 2026. It is now read-only.

Commit edbcbf6

Browse files
lapc506claude
andcommitted
feat(ui): add comprehensive logging framework with file output to all services and widgets
Adds the `logging` package and a central AppLogger service that writes structured logs to stderr and optionally to /tmp/agent-studio.log. Instruments all key services (ApiClient, WsClient) and every major page/widget (GenUiChatPage, AgentEditor, SettingsPage tabs, ToolsPage, SessionsPage, MetricsPage, RulesPage, sidebar, onboarding) with contextual log statements at INFO/FINE/WARNING/SEVERE levels for request tracing, error diagnosis, and lifecycle visibility. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent 389f8f4 commit edbcbf6

15 files changed

Lines changed: 207 additions & 21 deletions

File tree

ui/lib/features/agents/agent_editor_page.dart

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import 'dart:async';
22
import 'package:flutter/material.dart';
3+
import 'package:logging/logging.dart';
34
import '../../services/api_client.dart';
45
import '../../services/soul_md_generator.dart';
56
import '../../theme/agent_studio_theme.dart';
@@ -17,6 +18,7 @@ class AgentEditorPage extends StatefulWidget {
1718

1819
class _AgentEditorPageState extends State<AgentEditorPage>
1920
with SingleTickerProviderStateMixin {
21+
static final _log = Logger('AgentEditor');
2022
final _api = ApiClient();
2123
late TabController _tabController;
2224
Map<String, dynamic> _agent = {};
@@ -32,15 +34,18 @@ class _AgentEditorPageState extends State<AgentEditorPage>
3234
}
3335

3436
Future<void> _loadAgent() async {
37+
_log.info('Loading agent: ${widget.agentSlug}');
3538
try {
3639
final agent = await _api.getAgent(widget.agentSlug);
3740
final gates = await _api.getGates(widget.agentSlug);
41+
_log.info('Agent loaded: ${widget.agentSlug} with ${gates.length} gates');
3842
setState(() {
3943
_agent = agent;
4044
_gates = gates.cast<Map<String, dynamic>>();
4145
_loading = false;
4246
});
43-
} catch (_) {
47+
} catch (e) {
48+
_log.warning('Failed to load agent ${widget.agentSlug}, using defaults: $e');
4449
setState(() {
4550
_agent = {
4651
'name': widget.agentSlug,
@@ -55,15 +60,18 @@ class _AgentEditorPageState extends State<AgentEditorPage>
5560
}
5661

5762
Future<void> _saveAgent() async {
63+
_log.info('Saving agent: ${widget.agentSlug}');
5864
setState(() => _saving = true);
5965
try {
6066
await _api.updateAgent(widget.agentSlug, _agent);
67+
_log.info('Agent saved successfully: ${widget.agentSlug}');
6168
if (mounted) {
6269
ScaffoldMessenger.of(context).showSnackBar(
6370
const SnackBar(content: Text('Agente guardado'), backgroundColor: AgentStudioTheme.success),
6471
);
6572
}
6673
} catch (e) {
74+
_log.warning('Save failed for ${widget.agentSlug}: $e');
6775
if (mounted) {
6876
ScaffoldMessenger.of(context).showSnackBar(
6977
SnackBar(content: Text('Error: $e'), backgroundColor: AgentStudioTheme.error),
@@ -75,10 +83,13 @@ class _AgentEditorPageState extends State<AgentEditorPage>
7583
}
7684

7785
Future<void> _saveGates(List<Map<String, dynamic>> gates) async {
86+
_log.fine('Saving ${gates.length} gates for ${widget.agentSlug}');
7887
try {
7988
await _api.updateGates(widget.agentSlug, gates);
80-
} catch (_) {
89+
_log.fine('Gates saved successfully');
90+
} catch (e) {
8191
// Silently fail — offline-first approach
92+
_log.warning('Gates save failed (offline-first): $e');
8293
}
8394
}
8495

ui/lib/features/agents/rules_page.dart

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import 'package:flutter/material.dart';
2+
import 'package:logging/logging.dart';
23
import '../../theme/agent_studio_theme.dart';
34

45
class RulesPage extends StatefulWidget {
@@ -10,6 +11,7 @@ class RulesPage extends StatefulWidget {
1011
}
1112

1213
class _RulesPageState extends State<RulesPage> {
14+
static final _log = Logger('RulesPage');
1315
final List<Map<String, dynamic>> _rules = [
1416
{
1517
'name': 'Idioma de respuesta',
@@ -173,6 +175,7 @@ class _RulesPageState extends State<RulesPage> {
173175
}
174176

175177
void _addRule() {
178+
_log.info('Opening add rule dialog for agent: ${widget.agentSlug}');
176179
final nameCtrl = TextEditingController();
177180
final descCtrl = TextEditingController();
178181
String selectedType = 'behavior';
@@ -235,6 +238,7 @@ class _RulesPageState extends State<RulesPage> {
235238
FilledButton(
236239
onPressed: () {
237240
if (nameCtrl.text.isNotEmpty) {
241+
_log.info('Adding rule: ${nameCtrl.text} (type=$selectedType)');
238242
setState(() {
239243
_rules.add({
240244
'name': nameCtrl.text,

ui/lib/features/chat/genui_chat_page.dart

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import 'dart:async';
22

33
import 'package:flutter/material.dart';
44
import 'package:genui/genui.dart';
5+
import 'package:logging/logging.dart';
56

67
import '../../services/api_client.dart';
78
import '../../services/ws_client.dart';
@@ -19,6 +20,7 @@ class GenUiChatPage extends StatefulWidget {
1920
}
2021

2122
class _GenUiChatPageState extends State<GenUiChatPage> {
23+
static final _log = Logger('GenUiChatPage');
2224
late final SurfaceController _controller;
2325
final _textController = TextEditingController();
2426
final _surfaceIds = <String>[];
@@ -57,9 +59,11 @@ class _GenUiChatPageState extends State<GenUiChatPage> {
5759
// ---------------------------------------------------------------------------
5860

5961
Future<void> _loadAgents() async {
62+
_log.info('Loading agents...');
6063
try {
6164
var agents = await _apiClient.listAgents();
6265
if (agents.isEmpty) {
66+
_log.info('No agents found, auto-creating demo agent');
6367
// Auto-create demo agent
6468
await _apiClient.createAgent({
6569
'name': 'Asistente Demo',
@@ -69,12 +73,14 @@ class _GenUiChatPageState extends State<GenUiChatPage> {
6973
});
7074
agents = await _apiClient.listAgents();
7175
}
76+
_log.info('Loaded ${agents.length} agents');
7277
setState(() => _agents = agents);
7378
if (agents.isNotEmpty && _selectedAgent == null) {
7479
_selectAgent(agents.first['slug'] as String);
7580
}
76-
} catch (_) {
81+
} catch (e) {
7782
// Backend may not be available yet
83+
_log.warning('Failed to load agents: $e');
7884
}
7985
}
8086

@@ -83,6 +89,7 @@ class _GenUiChatPageState extends State<GenUiChatPage> {
8389
// ---------------------------------------------------------------------------
8490

8591
void _selectAgent(String slug) {
92+
_log.info('Selecting agent: $slug');
8693
// Tear down any previous conversation
8794
_eventSub?.cancel();
8895
_conversation?.dispose();
@@ -161,6 +168,7 @@ class _GenUiChatPageState extends State<GenUiChatPage> {
161168

162169
void _onWsMessage(Map<String, dynamic> msg) {
163170
final type = msg['type'] as String?;
171+
_log.fine('WS message: $type');
164172
switch (type) {
165173
case 'session_created':
166174
setState(() {
@@ -257,6 +265,7 @@ class _GenUiChatPageState extends State<GenUiChatPage> {
257265
void _sendMessage() {
258266
final text = _textController.text.trim();
259267
if (text.isEmpty || _selectedAgent == null) return;
268+
_log.info('Sending message to $_selectedAgent (${text.length} chars)');
260269

261270
// Record the user message locally
262271
setState(() {

ui/lib/features/metrics/metrics_page.dart

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import 'package:flutter/material.dart';
22
import 'package:graphic/graphic.dart';
3+
import 'package:logging/logging.dart';
34
import '../../theme/agent_studio_theme.dart';
45
import '../../services/api_client.dart';
56

@@ -38,6 +39,7 @@ class MetricsPage extends StatefulWidget {
3839
}
3940

4041
class _MetricsPageState extends State<MetricsPage> {
42+
static final _log = Logger('MetricsPage');
4143
final _api = ApiClient();
4244
bool _loading = true;
4345

@@ -60,6 +62,7 @@ class _MetricsPageState extends State<MetricsPage> {
6062
}
6163

6264
Future<void> _loadMetrics() async {
65+
_log.info('Loading metrics...');
6366
try {
6467
final results = await Future.wait([
6568
_api.getMetrics('latency').catchError((_) => <String, dynamic>{}),
@@ -104,7 +107,9 @@ class _MetricsPageState extends State<MetricsPage> {
104107

105108
_loading = false;
106109
});
107-
} catch (_) {
110+
_log.fine('Metrics loaded: sessions=$_activeSessions latency=$_latencyP99 gates=$_gatesPassRate tokens=$_tokensPerHour');
111+
} catch (e) {
112+
_log.warning('Failed to load metrics: $e');
108113
setState(() => _loading = false);
109114
}
110115
}

ui/lib/features/onboarding/onboarding_dialog.dart

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import 'dart:convert';
22
import 'package:flutter/material.dart';
33
import 'package:http/http.dart' as http;
4+
import 'package:logging/logging.dart';
45
import '../../services/api_client.dart';
56
import '../../theme/agent_studio_theme.dart';
67

@@ -15,6 +16,7 @@ class OnboardingDialog extends StatefulWidget {
1516
}
1617

1718
class _OnboardingDialogState extends State<OnboardingDialog> {
19+
static final _log = Logger('OnboardingDialog');
1820
int _step = 0; // 0 = welcome, 1 = provider, 2 = agent, 3 = done
1921
String _selectedProvider = 'openrouter_free';
2022
final _apiKeyCtrl = TextEditingController();
@@ -61,6 +63,7 @@ class _OnboardingDialogState extends State<OnboardingDialog> {
6163
};
6264

6365
Future<void> _saveAndFinish() async {
66+
_log.info('Onboarding: saving config with provider=$_selectedProvider');
6467
setState(() => _saving = true);
6568
final preset = _presets[_selectedProvider]!;
6669

@@ -103,14 +106,17 @@ class _OnboardingDialogState extends State<OnboardingDialog> {
103106
'graph_template': 'react',
104107
}),
105108
);
106-
} catch (_) {
109+
} catch (e) {
107110
// If backend is unavailable, still dismiss
111+
_log.warning('Onboarding save failed (continuing anyway): $e');
108112
}
109113

114+
_log.info('Onboarding complete');
110115
widget.onComplete();
111116
}
112117

113118
Future<void> _skipWithDefaults() async {
119+
_log.info('Onboarding: skipping with defaults');
114120
setState(() => _saving = true);
115121
try {
116122
// Create default agent from defaults
@@ -124,7 +130,10 @@ class _OnboardingDialogState extends State<OnboardingDialog> {
124130
'graph_template': 'react',
125131
}),
126132
);
127-
} catch (_) {}
133+
} catch (e) {
134+
_log.warning('Default agent creation failed: $e');
135+
}
136+
_log.info('Onboarding skipped with defaults');
128137
widget.onComplete();
129138
}
130139

@@ -194,7 +203,10 @@ class _OnboardingDialogState extends State<OnboardingDialog> {
194203
),
195204
const SizedBox(width: 12),
196205
FilledButton(
197-
onPressed: () => setState(() => _step = 1),
206+
onPressed: () {
207+
_log.info('Onboarding step: welcome -> provider selection');
208+
setState(() => _step = 1);
209+
},
198210
style: FilledButton.styleFrom(backgroundColor: AgentStudioTheme.primary),
199211
child: const Text('Configurar', style: TextStyle(fontSize: 13)),
200212
),
@@ -260,7 +272,10 @@ class _OnboardingDialogState extends State<OnboardingDialog> {
260272
),
261273
const SizedBox(width: 8),
262274
FilledButton(
263-
onPressed: () => setState(() => _step = 2),
275+
onPressed: () {
276+
_log.info('Onboarding step: provider selection -> agent creation (provider=$_selectedProvider)');
277+
setState(() => _step = 2);
278+
},
264279
style: FilledButton.styleFrom(backgroundColor: AgentStudioTheme.primary),
265280
child: const Text('Siguiente'),
266281
),

ui/lib/features/sessions/sessions_page.dart

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import 'package:flutter/material.dart';
2+
import 'package:logging/logging.dart';
23
import '../../theme/agent_studio_theme.dart';
34
import '../../services/api_client.dart';
45

@@ -10,6 +11,7 @@ class SessionsPage extends StatefulWidget {
1011
}
1112

1213
class _SessionsPageState extends State<SessionsPage> {
14+
static final _log = Logger('SessionsPage');
1315
final _api = ApiClient();
1416
List<Map<String, dynamic>> _sessions = [];
1517
bool _loading = true;
@@ -28,13 +30,16 @@ class _SessionsPageState extends State<SessionsPage> {
2830
}
2931

3032
Future<void> _loadSessions() async {
33+
_log.info('Loading sessions...');
3134
try {
3235
final sessions = await _api.listSessions();
36+
_log.fine('Loaded ${sessions.length} sessions');
3337
setState(() {
3438
_sessions = sessions;
3539
_loading = false;
3640
});
37-
} catch (_) {
41+
} catch (e) {
42+
_log.warning('Failed to load sessions: $e');
3843
setState(() {
3944
_loading = false;
4045
_error = 'No se pudo conectar al API.';

0 commit comments

Comments
 (0)