mcp-code-indexer 4.2.17__py3-none-any.whl → 4.2.18__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.
@@ -409,14 +409,30 @@ class DatabaseManager:
409
409
  operation_name: Name of the operation for monitoring
410
410
  timeout_seconds: Transaction timeout in seconds
411
411
  """
412
+ import time
413
+ acquire_start = time.monotonic()
412
414
  async with self.get_write_connection_with_retry(operation_name) as conn:
415
+ write_lock_time = time.monotonic() - acquire_start
416
+ logger.debug(
417
+ f"[{operation_name}] Write lock acquired in {write_lock_time*1000:.1f}ms"
418
+ )
413
419
  try:
414
420
  # Start immediate transaction with timeout
421
+ begin_start = time.monotonic()
415
422
  await asyncio.wait_for(
416
423
  conn.execute("BEGIN IMMEDIATE"), timeout=timeout_seconds
417
424
  )
425
+ begin_time = time.monotonic() - begin_start
426
+ logger.debug(
427
+ f"[{operation_name}] BEGIN IMMEDIATE completed in {begin_time*1000:.1f}ms"
428
+ )
418
429
  yield conn
430
+ commit_start = time.monotonic()
419
431
  await conn.commit()
432
+ commit_time = time.monotonic() - commit_start
433
+ logger.debug(
434
+ f"[{operation_name}] COMMIT completed in {commit_time*1000:.1f}ms"
435
+ )
420
436
  except asyncio.TimeoutError:
421
437
  logger.warning(
422
438
  (
@@ -476,13 +492,34 @@ class DatabaseManager:
476
492
 
477
493
  async def execute_transaction() -> Any:
478
494
  """Inner function to execute transaction - retried by executor."""
495
+ import time
496
+ start_time = time.monotonic()
497
+ logger.debug(
498
+ f"[{operation_name}] Starting transaction "
499
+ f"(timeout={timeout_seconds}s, pool_size={len(self._connection_pool)})"
500
+ )
479
501
  try:
480
502
  async with self.get_immediate_transaction(
481
503
  operation_name, timeout_seconds
482
504
  ) as conn:
505
+ lock_acquired_time = time.monotonic()
506
+ logger.debug(
507
+ f"[{operation_name}] Lock acquired in "
508
+ f"{(lock_acquired_time - start_time)*1000:.1f}ms"
509
+ )
483
510
  result = await operation_func(conn)
511
+ exec_time = time.monotonic()
512
+ logger.debug(
513
+ f"[{operation_name}] Operation executed in "
514
+ f"{(exec_time - lock_acquired_time)*1000:.1f}ms"
515
+ )
484
516
 
485
517
  # Record successful operation metrics
518
+ total_time = time.monotonic() - start_time
519
+ logger.debug(
520
+ f"[{operation_name}] Transaction completed successfully "
521
+ f"in {total_time*1000:.1f}ms"
522
+ )
486
523
  if self._metrics_collector:
487
524
  self._metrics_collector.record_operation(
488
525
  operation_name,
@@ -494,17 +531,26 @@ class DatabaseManager:
494
531
  return result
495
532
 
496
533
  except aiosqlite.OperationalError as e:
497
- # Record locking event for metrics
534
+ elapsed = time.monotonic() - start_time
498
535
  error_msg = str(e).lower()
536
+ logger.debug(
537
+ f"[{operation_name}] OperationalError after {elapsed*1000:.1f}ms: {e}"
538
+ )
499
539
  if self._metrics_collector and "locked" in error_msg:
500
540
  self._metrics_collector.record_locking_event(operation_name, str(e))
501
541
 
502
542
  # For retryable errors (locked/busy), re-raise the ORIGINAL error
503
543
  # so tenacity can retry. Only classify non-retryable errors.
504
544
  if "locked" in error_msg or "busy" in error_msg:
545
+ logger.debug(
546
+ f"[{operation_name}] Retryable error, will retry: {e}"
547
+ )
505
548
  raise # Let tenacity retry this
506
549
 
507
550
  # Non-retryable OperationalError - classify and raise
551
+ logger.warning(
552
+ f"[{operation_name}] Non-retryable OperationalError: {e}"
553
+ )
508
554
  classified_error = classify_sqlite_error(e, operation_name)
509
555
  if self._metrics_collector:
510
556
  self._metrics_collector.record_operation(
@@ -516,7 +562,11 @@ class DatabaseManager:
516
562
  raise classified_error
517
563
 
518
564
  except asyncio.TimeoutError as e:
519
- # Timeout on BEGIN IMMEDIATE - this is retryable
565
+ elapsed = time.monotonic() - start_time
566
+ logger.warning(
567
+ f"[{operation_name}] Timeout after {elapsed*1000:.1f}ms "
568
+ f"waiting for database lock (timeout={timeout_seconds}s)"
569
+ )
520
570
  if self._metrics_collector:
521
571
  self._metrics_collector.record_locking_event(
522
572
  operation_name, "timeout waiting for lock"
@@ -81,22 +81,29 @@ def setup_logging(
81
81
  root_logger.warning(f"Failed to set up file logging: {e}")
82
82
 
83
83
  # Configure specific loggers
84
+ effective_level = getattr(logging, log_level.upper())
84
85
 
85
- # Quiet down noisy libraries
86
+ # Quiet down noisy libraries (always WARNING+)
86
87
  logging.getLogger("aiosqlite").setLevel(logging.WARNING)
87
88
  logging.getLogger("tiktoken").setLevel(logging.WARNING)
88
89
 
89
- # MCP specific loggers
90
+ # MCP specific loggers - respect the configured log level
90
91
  mcp_logger = logging.getLogger("mcp")
91
- mcp_logger.setLevel(logging.INFO)
92
+ mcp_logger.setLevel(effective_level)
92
93
 
93
- # Database logger
94
- db_logger = logging.getLogger("src.database")
95
- db_logger.setLevel(logging.INFO)
94
+ # Database logger - respect the configured log level
95
+ db_logger = logging.getLogger("mcp_code_indexer.database")
96
+ db_logger.setLevel(effective_level)
96
97
 
97
- # Server logger
98
- server_logger = logging.getLogger("src.server")
99
- server_logger.setLevel(logging.INFO)
98
+ # Also set the old logger names for backwards compatibility
99
+ logging.getLogger("src.database").setLevel(effective_level)
100
+
101
+ # Server logger - respect the configured log level
102
+ server_logger = logging.getLogger("mcp_code_indexer.server")
103
+ server_logger.setLevel(effective_level)
104
+
105
+ # Also set the old logger names for backwards compatibility
106
+ logging.getLogger("src.server").setLevel(effective_level)
100
107
 
101
108
  return root_logger
102
109
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: mcp-code-indexer
3
- Version: 4.2.17
3
+ Version: 4.2.18
4
4
  Summary: MCP server that tracks file descriptions across codebases, enabling AI agents to efficiently navigate and understand code through searchable summaries and token-aware overviews.
5
5
  License: MIT
6
6
  License-File: LICENSE
@@ -49,8 +49,8 @@ Description-Content-Type: text/markdown
49
49
 
50
50
  # MCP Code Indexer 🚀
51
51
 
52
- [![PyPI version](https://badge.fury.io/py/mcp-code-indexer.svg?64)](https://badge.fury.io/py/mcp-code-indexer)
53
- [![Python](https://img.shields.io/pypi/pyversions/mcp-code-indexer.svg?64)](https://pypi.org/project/mcp-code-indexer/)
52
+ [![PyPI version](https://badge.fury.io/py/mcp-code-indexer.svg?65)](https://badge.fury.io/py/mcp-code-indexer)
53
+ [![Python](https://img.shields.io/pypi/pyversions/mcp-code-indexer.svg?65)](https://pypi.org/project/mcp-code-indexer/)
54
54
  [![License](https://img.shields.io/badge/License-MIT-blue.svg)](https://opensource.org/licenses/MIT)
55
55
 
56
56
  A production-ready **Model Context Protocol (MCP) server** that revolutionizes how AI agents navigate and understand codebases. Built for high-concurrency environments with advanced database resilience, the server provides instant access to intelligent descriptions, semantic search, and context-aware recommendations while maintaining 800+ writes/sec throughput.
@@ -8,7 +8,7 @@ mcp_code_indexer/commands/makelocal.py,sha256=T_44so96jcs1FNlft9E3nAq0LlOzQLhjLd
8
8
  mcp_code_indexer/data/stop_words_english.txt,sha256=feRGP8WG5hQPo-wZN5ralJiSv1CGw4h3010NBJnJ0Z8,6344
9
9
  mcp_code_indexer/database/__init__.py,sha256=aPq_aaRp0aSwOBIq9GkuMNjmLxA411zg2vhdrAuHm-w,38
10
10
  mcp_code_indexer/database/connection_health.py,sha256=jZr3tCbfjUJujdXe_uxtm1N4c31dMV4euiSY4ulamOE,25497
11
- mcp_code_indexer/database/database.py,sha256=GcXI6p99E4_fo9oMbbZXHIMpYm4Z7y2TdQJgSnZNvMI,57986
11
+ mcp_code_indexer/database/database.py,sha256=uDtghexmwJjqq_H8H4MG8VZyJpGIySqkdrgGWQ7FVzA,60327
12
12
  mcp_code_indexer/database/database_factory.py,sha256=VMw0tlutGgZoTI7Q_PCuFy5zAimq2xuMtDFAlF_FKtc,4316
13
13
  mcp_code_indexer/database/exceptions.py,sha256=zciu7fDwF8y0Z4tkzTBFPPvXCvdnEJiA-Wd-cBLZBWw,10473
14
14
  mcp_code_indexer/database/models.py,sha256=w1U9zMGNt0LQeCiifYeXKW_Cia9BKV5uPChbOve-FZY,13467
@@ -18,7 +18,7 @@ mcp_code_indexer/deepask_handler.py,sha256=qI9h_Me5WQAbt3hzzDG8XDBMZlnvx-I9R7Osm
18
18
  mcp_code_indexer/error_handler.py,sha256=ylciEM-cR7E8Gmd8cfh5olcllJm0FnaYBGH86yayFic,12530
19
19
  mcp_code_indexer/file_scanner.py,sha256=OCLnzPTneIiMtGcV3NB5qvnZrO3zxCqPEZXtCk75dfA,15178
20
20
  mcp_code_indexer/git_hook_handler.py,sha256=sTtZV3-Yy1Evt06R5NZclELeepM4Ia9OQoR2O6BK3Hk,45517
21
- mcp_code_indexer/logging_config.py,sha256=M5eVZ5PwfTROib7ISTQ522n2hUSc4hJ_wUgsrJKsTTg,10030
21
+ mcp_code_indexer/logging_config.py,sha256=NNB5iKCc-Hdognf-UdjuEKB9H_e4UIp3QTVnf69Rc2k,10504
22
22
  mcp_code_indexer/main.py,sha256=byM0Y9EwDa0616dEkx2p_1rUdJmDNeKAG41o5_AJago,41084
23
23
  mcp_code_indexer/middleware/__init__.py,sha256=UCEPzOlZldlqFzYEfrXw1HvCDvY1jpLvyaDGUzVr2aw,368
24
24
  mcp_code_indexer/middleware/auth.py,sha256=4HkHMDZBNsyPA1VE8qF7pRNKbqG4xIDZjllENbgynxI,7258
@@ -65,8 +65,8 @@ mcp_code_indexer/vector_mode/services/vector_mode_tools_service.py,sha256=K1_STy
65
65
  mcp_code_indexer/vector_mode/services/vector_storage_service.py,sha256=JI3VUc2mG8xZ_YqOvfKJivuMi4imeBLr2UFVrWgDWhk,21193
66
66
  mcp_code_indexer/vector_mode/types.py,sha256=M4lUF43FzjiVUezoRqozx_u0g1-xrX9qcRcRn-u65yw,1222
67
67
  mcp_code_indexer/vector_mode/utils.py,sha256=XtHrpOw0QJ0EjdzJ85jrbkmHy8Slkq_t7hz-q4RP-10,1283
68
- mcp_code_indexer-4.2.17.dist-info/METADATA,sha256=hlxYys7f-3mK2L00ZbP7UHyVxBa5AQO1xDw8t5HZ3jo,27689
69
- mcp_code_indexer-4.2.17.dist-info/WHEEL,sha256=kJCRJT_g0adfAJzTx2GUMmS80rTJIVHRCfG0DQgLq3o,88
70
- mcp_code_indexer-4.2.17.dist-info/entry_points.txt,sha256=UABj7HZ0mC6rvF22gxaz2LLNLGQShTrFmp5u00iUtvo,67
71
- mcp_code_indexer-4.2.17.dist-info/licenses/LICENSE,sha256=JN9dyPPgYwH9C-UjYM7FLNZjQ6BF7kAzpF3_4PwY4rY,1086
72
- mcp_code_indexer-4.2.17.dist-info/RECORD,,
68
+ mcp_code_indexer-4.2.18.dist-info/METADATA,sha256=KSfwzQpXfijIn6qqogm57T7r5mINsTeVhr0wpD7YL_E,27689
69
+ mcp_code_indexer-4.2.18.dist-info/WHEEL,sha256=kJCRJT_g0adfAJzTx2GUMmS80rTJIVHRCfG0DQgLq3o,88
70
+ mcp_code_indexer-4.2.18.dist-info/entry_points.txt,sha256=UABj7HZ0mC6rvF22gxaz2LLNLGQShTrFmp5u00iUtvo,67
71
+ mcp_code_indexer-4.2.18.dist-info/licenses/LICENSE,sha256=JN9dyPPgYwH9C-UjYM7FLNZjQ6BF7kAzpF3_4PwY4rY,1086
72
+ mcp_code_indexer-4.2.18.dist-info/RECORD,,