Metadata-Version: 2.4
Name: apm-component
Version: 1.0.1
Summary: Component testing application for external service integrations
Requires-Python: >=3.10
Description-Content-Type: text/markdown
Requires-Dist: mysql-connector-python
Requires-Dist: PyMySQL
Requires-Dist: mysqlclient
Requires-Dist: SQLAlchemy
Requires-Dist: aiomysql
Requires-Dist: DBUtils
Requires-Dist: cryptography
Requires-Dist: pymssql
Requires-Dist: pyodbc
Requires-Dist: requests
Requires-Dist: httpx
Requires-Dist: aiohttp
Requires-Dist: urllib3
Requires-Dist: httplib2
Requires-Dist: redis
Requires-Dist: aredis
Requires-Dist: pymemcache
Requires-Dist: python-memcached
Requires-Dist: pika
Requires-Dist: aio-pika
Requires-Dist: cassandra-driver
Requires-Dist: elasticsearch<9.0.0,>=8.0.0
Requires-Dist: psycopg2-binary
Requires-Dist: asyncpg
Requires-Dist: pymongo
Requires-Dist: oracledb
Provides-Extra: test
Requires-Dist: pytest; extra == "test"

# Service Routes

Component testing application — each "component" represents an external service (database, cache, broker, HTTP, etc.) that a Python application communicates with. Every supported Python module gets its own script file that tests all functionalities that module supports.

**Total: 611 routes across 22 modules**

## Quick Start

```bash
# Start infrastructure services
docker compose -f docker-compose.service.yaml up -d

# Create virtual environment and install
python -m venv .venv
source .venv/bin/activate
pip install -e .

# Run all tests
python -m pytest tests/ -v
```

## Project Structure

```
apm_component/       # All implementation scripts
  config.py          # Central config reader from components.ini
  components.ini     # INI-based connection settings per component
  routes.py          # Unified ROUTES dict importing all ROUTE_MAPs
  db_*.py            # Database modules
  cache_*.py         # Cache modules
  broker_*.py        # Message broker modules
  http_*.py          # HTTP client modules
docs/                # Documentation per component type
tests/               # Pytest test files per module
scripts/             # Build, deploy, and test runner scripts
```

## Component Services

| # | Service | Docker Service | Port | Modules |
|---|---------|---------------|------|---------|
| 1 | MySQL | `mysql` | 3306 | pymysql, mysql-connector-python, mysqlclient, sqlalchemy, aiomysql |
| 2 | MSSQL | `mssql` | 1433 | pymssql, pyodbc |
| 3 | SQLite | — (file-based) | — | sqlite3 (built-in) |
| 4 | Redis | `redis` | 6379 | redis, aioredis, aredis |
| 5 | Memcached | `memcached` | 11211 | pymemcache, python-memcached |
| 6 | RabbitMQ | `rabbitmq` | 5672 | pika, aio-pika |
| 7 | HTTP (httpbin.org) | — (external) | — | requests, httpx, aiohttp, urllib3, urllib, httplib2, http.client |

---

## Route Format

Every function is mapped to a route string in a global `ROUTE_MAP` dict:

```
/{component_type}/{subtype}/{module}/{function_name}
```

Access the unified registry:

```python
from apm_component.routes import ROUTES

# Call any function by route
result = ROUTES["/db/mysql/pymysql/connect"]()
print(result)  # {"status": "connected", "result": (1,)}
```

---

## Database — MySQL (231 routes)

### PyMySQL — `/db/mysql/pymysql/*` (28 routes)

| Route | Description |
|-------|-------------|
| `/db/mysql/pymysql/connect` | Basic connection |
| `/db/mysql/pymysql/connect_pool` | Connection pool via DBUtils |
| `/db/mysql/pymysql/get_connection_from_pool` | Acquire connection from pool |
| `/db/mysql/pymysql/connect_error_wrong_password` | Wrong password error |
| `/db/mysql/pymysql/connect_error_wrong_host` | Unreachable host error |
| `/db/mysql/pymysql/connect_error_unknown_db` | Non-existent database error |
| `/db/mysql/pymysql/connect_error_timeout` | Connection timeout error |
| `/db/mysql/pymysql/pool_error_exhaustion` | Pool exhaustion error |
| `/db/mysql/pymysql/execute_create_table` | DDL — create table |
| `/db/mysql/pymysql/execute_insert` | Single row insert |
| `/db/mysql/pymysql/execute_insert_many` | Batch insert via executemany |
| `/db/mysql/pymysql/execute_update` | Update rows |
| `/db/mysql/pymysql/execute_delete` | Delete rows |
| `/db/mysql/pymysql/execute_select` | Select query |
| `/db/mysql/pymysql/execute_parameterized` | Parameterized query |
| `/db/mysql/pymysql/execute_transaction` | Transaction with commit and rollback |
| `/db/mysql/pymysql/fetch_one` | Fetch single row |
| `/db/mysql/pymysql/fetch_all` | Fetch all rows |
| `/db/mysql/pymysql/fetch_many` | Fetch batch of rows |
| `/db/mysql/pymysql/fetch_dict_cursor` | Fetch as dictionaries |
| `/db/mysql/pymysql/fetch_ss_cursor` | Server-side unbuffered cursor |
| `/db/mysql/pymysql/fetch_ss_dict_cursor` | Server-side dictionary cursor |
| `/db/mysql/pymysql/call_stored_procedure` | Stored procedure call |
| `/db/mysql/pymysql/mogrify_query` | Inspect query without executing |
| `/db/mysql/pymysql/ping_reconnect` | Ping and reconnect |
| `/db/mysql/pymysql/dynamic_query` | Dynamic query building |
| `/db/mysql/pymysql/delayed_insert` | Insert after server-side delay |
| `/db/mysql/pymysql/race_condition_test` | Race condition with FOR UPDATE |

### mysql-connector-python — `/db/mysql/mysql_connector_python/*` (28 routes)

| Route | Description |
|-------|-------------|
| `/db/mysql/mysql_connector_python/connect` | Basic connection |
| `/db/mysql/mysql_connector_python/connect_pool` | Built-in connection pool |
| `/db/mysql/mysql_connector_python/connect_with_dict` | Connection using dict config |
| `/db/mysql/mysql_connector_python/get_connection_from_pool` | Acquire from pool |
| `/db/mysql/mysql_connector_python/connect_error_wrong_password` | Wrong password error |
| `/db/mysql/mysql_connector_python/connect_error_wrong_host` | Unreachable host error |
| `/db/mysql/mysql_connector_python/connect_error_unknown_db` | Non-existent database error |
| `/db/mysql/mysql_connector_python/connect_error_timeout` | Connection timeout error |
| `/db/mysql/mysql_connector_python/pool_error_exhaustion` | Pool exhaustion error |
| `/db/mysql/mysql_connector_python/execute_create_table` | DDL — create table |
| `/db/mysql/mysql_connector_python/execute_insert` | Single row insert |
| `/db/mysql/mysql_connector_python/execute_insert_many` | Batch insert |
| `/db/mysql/mysql_connector_python/execute_update` | Update rows |
| `/db/mysql/mysql_connector_python/execute_delete` | Delete rows |
| `/db/mysql/mysql_connector_python/execute_select` | Select query |
| `/db/mysql/mysql_connector_python/execute_parameterized` | Parameterized query |
| `/db/mysql/mysql_connector_python/execute_transaction` | Transaction commit/rollback |
| `/db/mysql/mysql_connector_python/execute_multi_statement` | Multi-statement execution |
| `/db/mysql/mysql_connector_python/fetch_one` | Fetch single row |
| `/db/mysql/mysql_connector_python/fetch_all` | Fetch all rows |
| `/db/mysql/mysql_connector_python/fetch_many` | Fetch batch |
| `/db/mysql/mysql_connector_python/fetch_dict_cursor` | Dictionary cursor |
| `/db/mysql/mysql_connector_python/fetch_named_tuple` | Named tuple cursor |
| `/db/mysql/mysql_connector_python/fetch_buffered` | Buffered cursor |
| `/db/mysql/mysql_connector_python/call_stored_procedure` | Stored procedure |
| `/db/mysql/mysql_connector_python/dynamic_query` | Dynamic query building |
| `/db/mysql/mysql_connector_python/delayed_insert` | Delayed insert |
| `/db/mysql/mysql_connector_python/race_condition_test` | Race condition test |

### mysqlclient — `/db/mysql/mysqlclient/*` (28 routes)

| Route | Description |
|-------|-------------|
| `/db/mysql/mysqlclient/connect` | Basic connection |
| `/db/mysql/mysqlclient/connect_pool` | Pool via DBUtils |
| `/db/mysql/mysqlclient/get_connection_from_pool` | Acquire from pool |
| `/db/mysql/mysqlclient/connect_error_wrong_password` | Wrong password error |
| `/db/mysql/mysqlclient/connect_error_wrong_host` | Unreachable host error |
| `/db/mysql/mysqlclient/connect_error_unknown_db` | Non-existent database error |
| `/db/mysql/mysqlclient/connect_error_timeout` | Connection timeout error |
| `/db/mysql/mysqlclient/pool_error_exhaustion` | Pool exhaustion error |
| `/db/mysql/mysqlclient/execute_create_table` | DDL — create table |
| `/db/mysql/mysqlclient/execute_insert` | Single row insert |
| `/db/mysql/mysqlclient/execute_insert_many` | Batch insert |
| `/db/mysql/mysqlclient/execute_update` | Update rows |
| `/db/mysql/mysqlclient/execute_delete` | Delete rows |
| `/db/mysql/mysqlclient/execute_select` | Select query |
| `/db/mysql/mysqlclient/execute_parameterized` | Parameterized query |
| `/db/mysql/mysqlclient/execute_transaction` | Transaction commit/rollback |
| `/db/mysql/mysqlclient/fetch_one` | Fetch single row |
| `/db/mysql/mysqlclient/fetch_all` | Fetch all rows |
| `/db/mysql/mysqlclient/fetch_many` | Fetch batch |
| `/db/mysql/mysqlclient/fetch_dict_cursor` | Dictionary cursor |
| `/db/mysql/mysqlclient/fetch_ss_cursor` | Server-side cursor |
| `/db/mysql/mysqlclient/fetch_ss_dict_cursor` | Server-side dict cursor |
| `/db/mysql/mysqlclient/call_stored_procedure` | Stored procedure |
| `/db/mysql/mysqlclient/escape_string` | String escaping |
| `/db/mysql/mysqlclient/ping_reconnect` | Ping and reconnect |
| `/db/mysql/mysqlclient/dynamic_query` | Dynamic query building |
| `/db/mysql/mysqlclient/delayed_insert` | Delayed insert |
| `/db/mysql/mysqlclient/race_condition_test` | Race condition test |

### SQLAlchemy — `/db/mysql/sqlalchemy/*` (38 routes)

| Route | Description |
|-------|-------------|
| `/db/mysql/sqlalchemy/connect` | Basic engine connection |
| `/db/mysql/sqlalchemy/connect_pool` | QueuePool connection |
| `/db/mysql/sqlalchemy/connect_nullpool` | NullPool (no pooling) |
| `/db/mysql/sqlalchemy/connect_error_wrong_password` | Wrong password error |
| `/db/mysql/sqlalchemy/connect_error_wrong_host` | Unreachable host error |
| `/db/mysql/sqlalchemy/connect_error_unknown_db` | Non-existent database error |
| `/db/mysql/sqlalchemy/connect_error_timeout` | Connection timeout error |
| `/db/mysql/sqlalchemy/pool_error_overflow` | Pool overflow error |
| `/db/mysql/sqlalchemy/execute_raw_create_table` | Raw DDL — create table |
| `/db/mysql/sqlalchemy/execute_raw_insert` | Raw insert |
| `/db/mysql/sqlalchemy/execute_raw_insert_params` | Raw parameterized insert |
| `/db/mysql/sqlalchemy/execute_raw_update` | Raw update |
| `/db/mysql/sqlalchemy/execute_raw_delete` | Raw delete |
| `/db/mysql/sqlalchemy/execute_raw_select` | Raw select |
| `/db/mysql/sqlalchemy/execute_core_insert` | Core API insert |
| `/db/mysql/sqlalchemy/execute_core_insert_many` | Core API batch insert |
| `/db/mysql/sqlalchemy/execute_core_update` | Core API update |
| `/db/mysql/sqlalchemy/execute_core_delete` | Core API delete |
| `/db/mysql/sqlalchemy/execute_core_select` | Core API select |
| `/db/mysql/sqlalchemy/execute_transaction` | Transaction commit/rollback |
| `/db/mysql/sqlalchemy/execute_savepoint` | Savepoint / nested transaction |
| `/db/mysql/sqlalchemy/fetch_one` | Fetch single row |
| `/db/mysql/sqlalchemy/fetch_all` | Fetch all rows |
| `/db/mysql/sqlalchemy/fetch_many` | Fetch batch |
| `/db/mysql/sqlalchemy/fetch_mappings` | Fetch as mapping dicts |
| `/db/mysql/sqlalchemy/fetch_scalars` | Fetch scalar values |
| `/db/mysql/sqlalchemy/fetch_stream` | Streaming fetch |
| `/db/mysql/sqlalchemy/orm_create_table` | ORM — create table |
| `/db/mysql/sqlalchemy/orm_insert` | ORM — insert |
| `/db/mysql/sqlalchemy/orm_select` | ORM — select |
| `/db/mysql/sqlalchemy/orm_update` | ORM — update |
| `/db/mysql/sqlalchemy/orm_delete` | ORM — delete |
| `/db/mysql/sqlalchemy/insert_on_duplicate` | Upsert (ON DUPLICATE KEY) |
| `/db/mysql/sqlalchemy/reflect_table` | Table reflection |
| `/db/mysql/sqlalchemy/event_hook` | Event hook listener |
| `/db/mysql/sqlalchemy/dynamic_query` | Dynamic query building |
| `/db/mysql/sqlalchemy/delayed_insert` | Delayed insert |
| `/db/mysql/sqlalchemy/race_condition_test` | Race condition test |

### aiomysql (async) — `/db/mysql/aiomysql/*` (27 routes)

| Route | Description |
|-------|-------------|
| `/db/mysql/aiomysql/connect` | Async basic connection |
| `/db/mysql/aiomysql/connect_pool` | Async connection pool |
| `/db/mysql/aiomysql/get_connection_from_pool` | Acquire from async pool |
| `/db/mysql/aiomysql/connect_error_wrong_password` | Wrong password error |
| `/db/mysql/aiomysql/connect_error_wrong_host` | Unreachable host error |
| `/db/mysql/aiomysql/connect_error_unknown_db` | Non-existent database error |
| `/db/mysql/aiomysql/connect_error_timeout` | Connection timeout error |
| `/db/mysql/aiomysql/pool_error_exhaustion` | Pool exhaustion error |
| `/db/mysql/aiomysql/execute_create_table` | DDL — create table |
| `/db/mysql/aiomysql/execute_insert` | Single row insert |
| `/db/mysql/aiomysql/execute_insert_many` | Batch insert |
| `/db/mysql/aiomysql/execute_update` | Update rows |
| `/db/mysql/aiomysql/execute_delete` | Delete rows |
| `/db/mysql/aiomysql/execute_select` | Select query |
| `/db/mysql/aiomysql/execute_parameterized` | Parameterized query |
| `/db/mysql/aiomysql/execute_transaction` | Transaction commit/rollback |
| `/db/mysql/aiomysql/fetch_one` | Fetch single row |
| `/db/mysql/aiomysql/fetch_all` | Fetch all rows |
| `/db/mysql/aiomysql/fetch_many` | Fetch batch |
| `/db/mysql/aiomysql/fetch_dict_cursor` | Dictionary cursor |
| `/db/mysql/aiomysql/fetch_ss_cursor` | Server-side cursor |
| `/db/mysql/aiomysql/call_stored_procedure` | Stored procedure |
| `/db/mysql/aiomysql/concurrent_queries` | Concurrent async queries |
| `/db/mysql/aiomysql/timeout_query` | Query timeout |
| `/db/mysql/aiomysql/dynamic_query` | Dynamic query building |
| `/db/mysql/aiomysql/delayed_insert` | Delayed insert |
| `/db/mysql/aiomysql/race_condition_test` | Race condition test |

## Database — MSSQL (53 routes)

### pymssql — `/db/mssql/pymssql/*` (25 routes)

| Route | Description |
|-------|-------------|
| `/db/mssql/pymssql/connect` | Basic connection |
| `/db/mssql/pymssql/connect_pool` | Pool via DBUtils |
| `/db/mssql/pymssql/get_connection_from_pool` | Acquire from pool |
| `/db/mssql/pymssql/connect_error_wrong_password` | Wrong password error |
| `/db/mssql/pymssql/connect_error_wrong_host` | Unreachable host error |
| `/db/mssql/pymssql/connect_error_unknown_db` | Non-existent database error |
| `/db/mssql/pymssql/connect_error_timeout` | Connection timeout error |
| `/db/mssql/pymssql/pool_error_exhaustion` | Pool exhaustion error |
| `/db/mssql/pymssql/execute_create_table` | DDL — create table |
| `/db/mssql/pymssql/execute_insert` | Single row insert |
| `/db/mssql/pymssql/execute_insert_many` | Batch insert |
| `/db/mssql/pymssql/execute_update` | Update rows |
| `/db/mssql/pymssql/execute_delete` | Delete rows |
| `/db/mssql/pymssql/execute_select` | Select query |
| `/db/mssql/pymssql/execute_parameterized` | Parameterized query |
| `/db/mssql/pymssql/execute_transaction` | Transaction commit/rollback |
| `/db/mssql/pymssql/fetch_one` | Fetch single row |
| `/db/mssql/pymssql/fetch_all` | Fetch all rows |
| `/db/mssql/pymssql/fetch_many` | Fetch batch |
| `/db/mssql/pymssql/fetch_as_dict` | Fetch as dictionaries |
| `/db/mssql/pymssql/call_stored_procedure` | Stored procedure |
| `/db/mssql/pymssql/multiple_result_sets` | Multiple result sets |
| `/db/mssql/pymssql/dynamic_query` | Dynamic query building |
| `/db/mssql/pymssql/delayed_insert` | Delayed insert |
| `/db/mssql/pymssql/race_condition_test` | Race condition test |

### pyodbc — `/db/mssql/pyodbc/*` (28 routes)

| Route | Description |
|-------|-------------|
| `/db/mssql/pyodbc/connect` | Basic ODBC connection |
| `/db/mssql/pyodbc/connect_pool` | Pool via DBUtils |
| `/db/mssql/pyodbc/get_connection_from_pool` | Acquire from pool |
| `/db/mssql/pyodbc/connect_error_wrong_password` | Wrong password error |
| `/db/mssql/pyodbc/connect_error_wrong_host` | Unreachable host error |
| `/db/mssql/pyodbc/connect_error_unknown_db` | Non-existent database error |
| `/db/mssql/pyodbc/connect_error_timeout` | Connection timeout error |
| `/db/mssql/pyodbc/pool_error_exhaustion` | Pool exhaustion error |
| `/db/mssql/pyodbc/toggle_odbc_pooling` | Toggle ODBC-level pooling |
| `/db/mssql/pyodbc/execute_create_table` | DDL — create table |
| `/db/mssql/pyodbc/execute_insert` | Single row insert |
| `/db/mssql/pyodbc/execute_insert_many` | Batch insert |
| `/db/mssql/pyodbc/execute_fast_executemany` | Fast executemany mode |
| `/db/mssql/pyodbc/execute_update` | Update rows |
| `/db/mssql/pyodbc/execute_delete` | Delete rows |
| `/db/mssql/pyodbc/execute_select` | Select query |
| `/db/mssql/pyodbc/execute_parameterized` | Parameterized query |
| `/db/mssql/pyodbc/execute_transaction` | Transaction commit/rollback |
| `/db/mssql/pyodbc/fetch_one` | Fetch single row |
| `/db/mssql/pyodbc/fetch_all` | Fetch all rows |
| `/db/mssql/pyodbc/fetch_many` | Fetch batch |
| `/db/mssql/pyodbc/fetch_as_dict` | Fetch as dictionaries |
| `/db/mssql/pyodbc/fetch_column_metadata` | Column metadata |
| `/db/mssql/pyodbc/call_stored_procedure` | Stored procedure |
| `/db/mssql/pyodbc/multiple_result_sets` | Multiple result sets |
| `/db/mssql/pyodbc/dynamic_query` | Dynamic query building |
| `/db/mssql/pyodbc/delayed_insert` | Delayed insert |
| `/db/mssql/pyodbc/race_condition_test` | Race condition test |

## Database — SQLite (29 routes)

### sqlite3 — `/db/sqlite/sqlite3/*` (29 routes)

| Route | Description |
|-------|-------------|
| `/db/sqlite/sqlite3/connect` | Basic file connection |
| `/db/sqlite/sqlite3/connect_memory` | In-memory database |
| `/db/sqlite/sqlite3/connect_pool` | Reusable connection holder |
| `/db/sqlite/sqlite3/get_connection_from_pool` | Acquire from holder |
| `/db/sqlite/sqlite3/close_pool` | Close shared connection |
| `/db/sqlite/sqlite3/connect_error_invalid_path` | Invalid path error |
| `/db/sqlite/sqlite3/connect_error_readonly` | Read-only error |
| `/db/sqlite/sqlite3/connect_error_corrupt_db` | Corrupt database error |
| `/db/sqlite/sqlite3/connect_error_timeout` | Lock timeout error |
| `/db/sqlite/sqlite3/execute_create_table` | DDL — create table |
| `/db/sqlite/sqlite3/execute_insert` | Single row insert |
| `/db/sqlite/sqlite3/execute_insert_many` | Batch insert |
| `/db/sqlite/sqlite3/execute_update` | Update rows |
| `/db/sqlite/sqlite3/execute_delete` | Delete rows |
| `/db/sqlite/sqlite3/execute_select` | Select query |
| `/db/sqlite/sqlite3/execute_parameterized` | Parameterized query |
| `/db/sqlite/sqlite3/execute_transaction` | Transaction commit/rollback |
| `/db/sqlite/sqlite3/execute_script` | Multi-statement executescript |
| `/db/sqlite/sqlite3/fetch_one` | Fetch single row |
| `/db/sqlite/sqlite3/fetch_all` | Fetch all rows |
| `/db/sqlite/sqlite3/fetch_many` | Fetch batch |
| `/db/sqlite/sqlite3/fetch_row_factory` | Dict-like rows via Row factory |
| `/db/sqlite/sqlite3/create_user_function` | User-defined function |
| `/db/sqlite/sqlite3/create_aggregate_function` | User-defined aggregate |
| `/db/sqlite/sqlite3/iterdump_database` | Export as SQL dump |
| `/db/sqlite/sqlite3/backup_database` | Backup API |
| `/db/sqlite/sqlite3/dynamic_query` | Dynamic query building |
| `/db/sqlite/sqlite3/delayed_insert` | Delayed insert |
| `/db/sqlite/sqlite3/race_condition_test` | Race condition test |

---

## Cache — Redis (85 routes)

### redis — `/cache/redis/redis/*` (35 routes)

| Route | Description |
|-------|-------------|
| `/cache/redis/redis/connect` | Basic connection |
| `/cache/redis/redis/connect_url` | Connection via URL |
| `/cache/redis/redis/connect_pool` | Connection pool |
| `/cache/redis/redis/connect_blocking_pool` | Blocking connection pool |
| `/cache/redis/redis/connect_error_wrong_host` | Wrong host error |
| `/cache/redis/redis/connect_error_wrong_port` | Wrong port error |
| `/cache/redis/redis/connect_error_wrong_password` | Wrong password error |
| `/cache/redis/redis/connect_error_timeout` | Timeout error |
| `/cache/redis/redis/pool_exhaustion_error` | Pool exhaustion error |
| `/cache/redis/redis/set_get` | Basic SET/GET |
| `/cache/redis/redis/set_with_ttl` | SET with expiry |
| `/cache/redis/redis/setnx` | SET if not exists |
| `/cache/redis/redis/getset` | GET and SET atomically |
| `/cache/redis/redis/append_value` | Append to value |
| `/cache/redis/redis/delete_key` | Delete key |
| `/cache/redis/redis/key_exists` | Check key existence |
| `/cache/redis/redis/key_type` | Check key type |
| `/cache/redis/redis/ttl_expiry_check` | TTL check |
| `/cache/redis/redis/expire_and_persist` | Expire and persist |
| `/cache/redis/redis/mset_mget` | Bulk MSET/MGET |
| `/cache/redis/redis/incr_decr` | Increment/decrement |
| `/cache/redis/redis/hash_operations` | Hash operations |
| `/cache/redis/redis/list_operations` | List operations |
| `/cache/redis/redis/set_operations` | Set operations |
| `/cache/redis/redis/sorted_set_operations` | Sorted set operations |
| `/cache/redis/redis/json_serialization` | JSON serialization |
| `/cache/redis/redis/scan_keys` | SCAN key iteration |
| `/cache/redis/redis/pipeline_operations` | Pipeline batching |
| `/cache/redis/redis/transaction_operations` | WATCH/MULTI transactions |
| `/cache/redis/redis/pubsub_operations` | Pub/Sub messaging |
| `/cache/redis/redis/lua_script` | Lua scripting |
| `/cache/redis/redis/dynamic_key_ops` | Dynamic key operations |
| `/cache/redis/redis/delayed_operations` | Delayed operations |
| `/cache/redis/redis/race_condition_test` | Race condition test |
| `/cache/redis/redis/flush_db` | Flush database |

### aioredis (async) — `/cache/redis/aioredis/*` (26 routes)

| Route | Description |
|-------|-------------|
| `/cache/redis/aioredis/connect` | Async connection |
| `/cache/redis/aioredis/connect_url` | Async URL connection |
| `/cache/redis/aioredis/connect_pool` | Async connection pool |
| `/cache/redis/aioredis/connect_error_wrong_host` | Wrong host error |
| `/cache/redis/aioredis/connect_error_wrong_port` | Wrong port error |
| `/cache/redis/aioredis/connect_error_timeout` | Timeout error |
| `/cache/redis/aioredis/set_get` | Async SET/GET |
| `/cache/redis/aioredis/set_with_ttl` | SET with expiry |
| `/cache/redis/aioredis/setnx` | SET if not exists |
| `/cache/redis/aioredis/delete_key` | Delete key |
| `/cache/redis/aioredis/key_exists` | Check key existence |
| `/cache/redis/aioredis/ttl_expiry_check` | TTL check |
| `/cache/redis/aioredis/expire_and_persist` | Expire and persist |
| `/cache/redis/aioredis/mset_mget` | Bulk MSET/MGET |
| `/cache/redis/aioredis/incr_decr` | Increment/decrement |
| `/cache/redis/aioredis/hash_operations` | Hash operations |
| `/cache/redis/aioredis/list_operations` | List operations |
| `/cache/redis/aioredis/set_operations` | Set operations |
| `/cache/redis/aioredis/json_serialization` | JSON serialization |
| `/cache/redis/aioredis/pipeline_operations` | Pipeline batching |
| `/cache/redis/aioredis/pubsub_operations` | Pub/Sub messaging |
| `/cache/redis/aioredis/dynamic_key_ops` | Dynamic key operations |
| `/cache/redis/aioredis/delayed_operations` | Delayed operations |
| `/cache/redis/aioredis/concurrent_operations` | Concurrent async ops |
| `/cache/redis/aioredis/race_condition_test` | Race condition test |
| `/cache/redis/aioredis/flush_db` | Flush database |

### aredis (async) — `/cache/redis/aredis/*` (24 routes)

| Route | Description |
|-------|-------------|
| `/cache/redis/aredis/connect` | Async connection |
| `/cache/redis/aredis/connect_pool` | Async connection pool |
| `/cache/redis/aredis/connect_error_wrong_host` | Wrong host error |
| `/cache/redis/aredis/connect_error_wrong_port` | Wrong port error |
| `/cache/redis/aredis/connect_error_timeout` | Timeout error |
| `/cache/redis/aredis/set_get` | Async SET/GET |
| `/cache/redis/aredis/set_with_ttl` | SET with expiry |
| `/cache/redis/aredis/setnx` | SET if not exists |
| `/cache/redis/aredis/delete_key` | Delete key |
| `/cache/redis/aredis/key_exists` | Check key existence |
| `/cache/redis/aredis/ttl_expiry_check` | TTL check |
| `/cache/redis/aredis/expire_and_persist` | Expire and persist |
| `/cache/redis/aredis/mset_mget` | Bulk MSET/MGET |
| `/cache/redis/aredis/incr_decr` | Increment/decrement |
| `/cache/redis/aredis/hash_operations` | Hash operations |
| `/cache/redis/aredis/list_operations` | List operations |
| `/cache/redis/aredis/set_operations` | Set operations |
| `/cache/redis/aredis/json_serialization` | JSON serialization |
| `/cache/redis/aredis/pipeline_operations` | Pipeline batching |
| `/cache/redis/aredis/dynamic_key_ops` | Dynamic key operations |
| `/cache/redis/aredis/delayed_operations` | Delayed operations |
| `/cache/redis/aredis/concurrent_operations` | Concurrent async ops |
| `/cache/redis/aredis/race_condition_test` | Race condition test |
| `/cache/redis/aredis/flush_db` | Flush database |

## Cache — Memcached (46 routes)

### pymemcache — `/cache/memcache/pymemcache/*` (23 routes)

| Route | Description |
|-------|-------------|
| `/cache/memcache/pymemcache/connect` | Basic connection |
| `/cache/memcache/pymemcache/connect_pool` | Connection pool |
| `/cache/memcache/pymemcache/connect_error_wrong_host` | Wrong host error |
| `/cache/memcache/pymemcache/connect_error_wrong_port` | Wrong port error |
| `/cache/memcache/pymemcache/connect_error_timeout` | Timeout error |
| `/cache/memcache/pymemcache/retry_client` | Retry client |
| `/cache/memcache/pymemcache/set_get` | Basic SET/GET |
| `/cache/memcache/pymemcache/set_with_ttl` | SET with expiry |
| `/cache/memcache/pymemcache/set_many_get_many` | Bulk set/get |
| `/cache/memcache/pymemcache/delete_key` | Delete key |
| `/cache/memcache/pymemcache/delete_many` | Delete multiple keys |
| `/cache/memcache/pymemcache/key_exists` | Check key existence |
| `/cache/memcache/pymemcache/incr_decr` | Increment/decrement |
| `/cache/memcache/pymemcache/add_key` | Add (set if not exists) |
| `/cache/memcache/pymemcache/replace_key` | Replace existing key |
| `/cache/memcache/pymemcache/append_prepend` | Append/prepend to value |
| `/cache/memcache/pymemcache/cas_operations` | Check-and-set (CAS) |
| `/cache/memcache/pymemcache/json_serialization` | JSON serialization |
| `/cache/memcache/pymemcache/get_stats` | Server stats |
| `/cache/memcache/pymemcache/flush_all` | Flush all keys |
| `/cache/memcache/pymemcache/dynamic_key_ops` | Dynamic key operations |
| `/cache/memcache/pymemcache/delayed_operations` | Delayed operations |
| `/cache/memcache/pymemcache/race_condition_test` | Race condition test |

### python-memcached — `/cache/memcache/python_memcached/*` (23 routes)

| Route | Description |
|-------|-------------|
| `/cache/memcache/python_memcached/connect` | Basic connection |
| `/cache/memcache/python_memcached/connect_error_wrong_host` | Wrong host error |
| `/cache/memcache/python_memcached/connect_error_wrong_port` | Wrong port error |
| `/cache/memcache/python_memcached/connect_error_timeout` | Timeout error |
| `/cache/memcache/python_memcached/set_get` | Basic SET/GET |
| `/cache/memcache/python_memcached/set_with_ttl` | SET with expiry |
| `/cache/memcache/python_memcached/set_multi_get_multi` | Bulk set/get |
| `/cache/memcache/python_memcached/delete_key` | Delete key |
| `/cache/memcache/python_memcached/delete_multi` | Delete multiple keys |
| `/cache/memcache/python_memcached/key_exists` | Check key existence |
| `/cache/memcache/python_memcached/incr_decr` | Increment/decrement |
| `/cache/memcache/python_memcached/add_key` | Add (set if not exists) |
| `/cache/memcache/python_memcached/replace_key` | Replace existing key |
| `/cache/memcache/python_memcached/append_prepend` | Append/prepend |
| `/cache/memcache/python_memcached/cas_operations` | Check-and-set (CAS) |
| `/cache/memcache/python_memcached/json_serialization` | JSON serialization |
| `/cache/memcache/python_memcached/pickle_serialization` | Pickle serialization |
| `/cache/memcache/python_memcached/get_stats` | Server stats |
| `/cache/memcache/python_memcached/flush_all` | Flush all keys |
| `/cache/memcache/python_memcached/disconnect_all` | Disconnect all |
| `/cache/memcache/python_memcached/dynamic_key_ops` | Dynamic key operations |
| `/cache/memcache/python_memcached/delayed_operations` | Delayed operations |
| `/cache/memcache/python_memcached/race_condition_test` | Race condition test |

---

## Message Broker — RabbitMQ (56 routes)

### pika — `/broker/rabbitmq/pika/*` (28 routes)

| Route | Description |
|-------|-------------|
| `/broker/rabbitmq/pika/connect` | Basic blocking connection |
| `/broker/rabbitmq/pika/connect_url` | Connection via AMQP URL |
| `/broker/rabbitmq/pika/connect_error_wrong_host` | Wrong host error |
| `/broker/rabbitmq/pika/connect_error_wrong_port` | Wrong port error |
| `/broker/rabbitmq/pika/connect_error_wrong_credentials` | Wrong credentials error |
| `/broker/rabbitmq/pika/declare_queue` | Declare a queue |
| `/broker/rabbitmq/pika/purge_queue` | Purge queue messages |
| `/broker/rabbitmq/pika/delete_queue` | Delete a queue |
| `/broker/rabbitmq/pika/declare_exchange` | Declare an exchange |
| `/broker/rabbitmq/pika/bind_queue_to_exchange` | Bind queue to exchange |
| `/broker/rabbitmq/pika/delete_exchange` | Delete an exchange |
| `/broker/rabbitmq/pika/publish_basic` | Publish to default exchange |
| `/broker/rabbitmq/pika/publish_to_exchange` | Publish to named exchange |
| `/broker/rabbitmq/pika/publish_with_properties` | Publish with headers/TTL/priority |
| `/broker/rabbitmq/pika/publish_bulk` | Bulk publish (10 messages) |
| `/broker/rabbitmq/pika/publish_json` | Publish JSON payload |
| `/broker/rabbitmq/pika/publish_binary` | Publish binary data |
| `/broker/rabbitmq/pika/publish_with_confirm` | Publisher confirms |
| `/broker/rabbitmq/pika/consume_basic_get` | Synchronous single fetch |
| `/broker/rabbitmq/pika/consume_with_ack` | Consume and acknowledge |
| `/broker/rabbitmq/pika/consume_with_nack` | Consume and negative ack |
| `/broker/rabbitmq/pika/consume_with_reject` | Consume and reject |
| `/broker/rabbitmq/pika/consume_with_qos` | Consume with prefetch QoS |
| `/broker/rabbitmq/pika/consume_json` | Consume JSON payload |
| `/broker/rabbitmq/pika/dead_letter_queue` | Dead letter queue handling |
| `/broker/rabbitmq/pika/error_consume_nonexistent_queue` | Non-existent queue error |
| `/broker/rabbitmq/pika/delayed_publish` | Delayed publish |
| `/broker/rabbitmq/pika/cleanup` | Cleanup all test queues/exchanges |

### aio-pika (async) — `/broker/rabbitmq/aio_pika/*` (28 routes)

| Route | Description |
|-------|-------------|
| `/broker/rabbitmq/aio_pika/connect` | Async robust connection |
| `/broker/rabbitmq/aio_pika/connect_basic` | Async basic connection |
| `/broker/rabbitmq/aio_pika/connect_error_wrong_host` | Wrong host error |
| `/broker/rabbitmq/aio_pika/connect_error_wrong_port` | Wrong port error |
| `/broker/rabbitmq/aio_pika/connect_error_wrong_credentials` | Wrong credentials error |
| `/broker/rabbitmq/aio_pika/declare_queue` | Declare a queue |
| `/broker/rabbitmq/aio_pika/purge_queue` | Purge queue messages |
| `/broker/rabbitmq/aio_pika/delete_queue` | Delete a queue |
| `/broker/rabbitmq/aio_pika/declare_exchange` | Declare an exchange |
| `/broker/rabbitmq/aio_pika/bind_queue_to_exchange` | Bind queue to exchange |
| `/broker/rabbitmq/aio_pika/delete_exchange` | Delete an exchange |
| `/broker/rabbitmq/aio_pika/publish_basic` | Async publish to default exchange |
| `/broker/rabbitmq/aio_pika/publish_to_exchange` | Async publish to named exchange |
| `/broker/rabbitmq/aio_pika/publish_with_properties` | Publish with headers/TTL/priority |
| `/broker/rabbitmq/aio_pika/publish_bulk` | Bulk publish (10 messages) |
| `/broker/rabbitmq/aio_pika/publish_json` | Publish JSON payload |
| `/broker/rabbitmq/aio_pika/publish_binary` | Publish binary data |
| `/broker/rabbitmq/aio_pika/publish_with_confirm` | Publisher confirms |
| `/broker/rabbitmq/aio_pika/consume_basic_get` | Async single fetch |
| `/broker/rabbitmq/aio_pika/consume_with_ack` | Consume and acknowledge |
| `/broker/rabbitmq/aio_pika/consume_with_nack` | Consume and negative ack |
| `/broker/rabbitmq/aio_pika/consume_with_reject` | Consume and reject |
| `/broker/rabbitmq/aio_pika/consume_with_qos` | Consume with prefetch QoS |
| `/broker/rabbitmq/aio_pika/consume_json` | Consume JSON payload |
| `/broker/rabbitmq/aio_pika/dead_letter_queue` | Dead letter queue handling |
| `/broker/rabbitmq/aio_pika/error_consume_nonexistent_queue` | Non-existent queue error |
| `/broker/rabbitmq/aio_pika/delayed_publish` | Delayed publish |
| `/broker/rabbitmq/aio_pika/cleanup` | Cleanup all test queues/exchanges |

---

## HTTP Clients (193 routes)

Each HTTP module implements the same set of functionalities. Route format: `/http/{module}/{function_name}`

### Common Functionalities Across All HTTP Modules

| Function | Description |
|----------|-------------|
| `http_get` | Basic GET request |
| `http_post_json` | POST with JSON body |
| `http_put` | PUT request |
| `http_delete` | DELETE request |
| `http_patch` | PATCH request |
| `http_get_with_params` | GET with query parameters |
| `http_post_form` | POST with form data |
| `http_custom_headers` | Custom request headers |
| `http_basic_auth` | Basic authentication |
| `http_bearer_auth` | Bearer token authentication |
| `http_response_json` | JSON response handling |
| `http_response_text` | Text response handling |
| `http_response_binary` | Binary response handling |
| `http_response_html` | HTML response handling |
| `http_response_xml` | XML response handling |
| `http_response_headers` | Response headers inspection |
| `http_redirect` | Redirect following |
| `http_ssl_verify` | SSL verification |
| `http_ssl_no_verify` | Skip SSL verification |
| `http_timeout_error` | Timeout error handling |
| `http_connection_error` | Connection error handling |
| `http_status_error` | HTTP status error handling |
| `http_delay_request` | Delayed request |
| `http_dynamic_request` | Dynamic request building |

### Modules

| Module | Route Prefix | Routes | Extras |
|--------|-------------|--------|--------|
| **requests** | `/http/requests/*` | 30 | `http_session_reuse`, `http_connection_pool`, `http_cookies`, `http_retry_logic`, `http_prepared_request`, `http_response_stream` |
| **httpx** | `/http/httpx/*` | 30 | `http_client_reuse`, `http_connection_pool`, `http_cookies`, `http_event_hooks`, `http_http2`, `http_response_stream` |
| **aiohttp** (async) | `/http/aiohttp/*` | 29 | `http_session_reuse`, `http_connection_pool`, `http_cookies`, `http_concurrent_requests`, `http_response_stream` |
| **urllib3** | `/http/urllib3/*` | 27 | `http_pool_manager`, `http_retry_logic`, `http_response_stream` |
| **urllib** (built-in) | `/http/urllib/*` | 25 | `http_response_stream` |
| **httplib2** | `/http/httplib2/*` | 26 | `http_connection_reuse`, `http_caching` |
| **http.client** (built-in) | `/http/httpclient/*` | 26 | `http_connection_reuse`, `http_response_stream` |

---

## Scripts

| Script | Description |
|--------|-------------|
| `./scripts/run_tests.sh local` | Run tests locally |
| `./scripts/run_tests.sh docker` | Run tests via Docker |
| `./scripts/deployment.sh up` | Start infrastructure services |
| `./scripts/deployment.sh down` | Stop infrastructure services |
| `./scripts/build.sh build --clean` | Build Python package |
| `./scripts/build.sh upload` | Upload to PyPI |
| `./scripts/build.sh build-upload` | Build and upload |

## Configuration

All connection settings are in `apm_component/components.ini` and can be overridden via environment variables.

To use a custom INI file location, set:

```bash
export APM_COMPONENT_INI_FILEPATH=/path/to/your/components.ini
```

If not set, it defaults to `apm_component/components.ini` bundled with the package.

### Environment Variable Overrides

| Service | Env Prefix | Default Host | Default Port |
|---------|-----------|-------------|-------------|
| MySQL | `MYSQL_` | 127.0.0.1 | 3306 |
| MSSQL | `MSSQL_` | 127.0.0.1 | 1433 |
| SQLite | `SQLITE_` | (file: component_test.db) | — |
| Redis | `REDIS_` | 127.0.0.1 | 6379 |
| Memcached | `MEMCACHED_` | 127.0.0.1 | 11211 |
| RabbitMQ | `RABBITMQ_` | 127.0.0.1 | 5672 |
| HTTP | `HTTP_` | httpbin.org | — |

### INI File Format

```ini
[mysql]
host = 127.0.0.1
port = 3306
user = root
password = your_password
database = your_database
pool_size = 5
connect_timeout = 10

[sqlite]
database = your_database.db

[http]
base_url = https://httpbin.org
timeout = 10
retries = 3
pool_connections = 5
pool_maxsize = 10

[mssql]
host = 127.0.0.1
port = 1433
user = sa
password = your_password
database = your_database
pool_size = 5
connect_timeout = 10

[redis]
host = 127.0.0.1
port = 6379
db = 0
password =
pool_size = 10
socket_timeout = 5

[memcached]
host = 127.0.0.1
port = 11211
connect_timeout = 5
timeout = 5

[rabbitmq]
host = 127.0.0.1
port = 5672
user = guest
password = guest
virtual_host = /
connect_timeout = 10

[cassandra]
host = 127.0.0.1
port = 9042
keyspace = your_keyspace
connect_timeout = 10

[elasticsearch]
host = 127.0.0.1
port = 9200
index = your_index
timeout = 10

[postgresql]
host = 127.0.0.1
port = 5432
user = your_user
password = your_password
database = your_database
pool_size = 5
connect_timeout = 10

[mongodb]
host = 127.0.0.1
port = 27017
user = your_user
password = your_password
database = your_database
collection = your_collection
connect_timeout = 10

[oracle]
host = 127.0.0.1
port = 1521
user = system
password = your_password
service_name = FREEPDB1
pool_size = 5
connect_timeout = 10
```
