Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
119 changes: 53 additions & 66 deletions QUICK_START_LOGGING.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@
## ⚡ TL;DR - 3 Step Process

1. **Import the logger**: `from codegen.shared.logging.get_logger import get_logger`
2. **Add `extra={}` to your log calls**: `logger.info("message", extra={"key": "value"})`
3. **Enable telemetry**: `codegen config telemetry enable`
1. **Add `extra={}` to your log calls**: `logger.info("message", extra={"key": "value"})`
1. **Enable telemetry**: `codegen config telemetry enable`

**That's it!** Your logs automatically go to Grafana Cloud when telemetry is enabled.

Expand All @@ -22,11 +22,14 @@ from codegen.shared.logging.get_logger import get_logger
logger = get_logger(__name__)

# Find any existing console.print() or error handling and add:
logger.info("Operation completed", extra={
"operation": "command_name",
"org_id": org_id, # if available
"success": True
})
logger.info(
"Operation completed",
extra={
"operation": "command_name",
"org_id": org_id, # if available
"success": True,
},
)
```

### 2. Test the Integration Right Now
Expand All @@ -38,7 +41,7 @@ codegen config telemetry enable
# 2. Run the demo
python example_enhanced_agent_command.py

# 3. Run any CLI command
# 3. Run any CLI command
codegen agents # or any other command

# 4. Check status
Expand All @@ -48,69 +51,56 @@ codegen config telemetry status
## 📝 Copy-Paste Patterns

### Pattern 1: Operation Start/End

```python
logger = get_logger(__name__)

# At start of function
logger.info("Operation started", extra={
"operation": "command.subcommand",
"user_input": relevant_input
})

# At end of function
logger.info("Operation completed", extra={
"operation": "command.subcommand",
"success": True
})
logger.info("Operation started", extra={"operation": "command.subcommand", "user_input": relevant_input})

# At end of function
logger.info("Operation completed", extra={"operation": "command.subcommand", "success": True})
```

### Pattern 2: Error Handling

```python
try:
# your existing code
pass
except SomeSpecificError as e:
logger.error("Specific error occurred", extra={
"operation": "command.subcommand",
"error_type": "specific_error",
"error_details": str(e)
}, exc_info=True)
logger.error("Specific error occurred", extra={"operation": "command.subcommand", "error_type": "specific_error", "error_details": str(e)}, exc_info=True)
# your existing error handling
```

### Pattern 3: API Calls

```python
# Before API call
logger.info("Making API request", extra={
"operation": "api.request",
"endpoint": "agent/run",
"org_id": org_id
})
logger.info("Making API request", extra={"operation": "api.request", "endpoint": "agent/run", "org_id": org_id})

# After successful API call
logger.info("API request successful", extra={
"operation": "api.request",
"endpoint": "agent/run",
"response_id": response.get("id"),
"status_code": response.status_code
})
logger.info("API request successful", extra={"operation": "api.request", "endpoint": "agent/run", "response_id": response.get("id"), "status_code": response.status_code})
```

## 🎯 What to Log (Priority Order)

### 🔥 High Priority (Add These First)

- **Operation start/end**: When commands begin/complete
- **API calls**: Requests to your backend
- **Authentication events**: Login/logout/token issues
- **Authentication events**: Login/logout/token issues
- **Errors**: Any exception or failure
- **User actions**: Commands run, options selected

### ⭐ Medium Priority

- **Performance**: Duration of operations
- **State changes**: Status updates, configuration changes
- **External tools**: Claude CLI detection, git operations

### 💡 Low Priority (Nice to Have)

- **Debug info**: Internal state, validation steps
- **User behavior**: Which features are used most

Expand All @@ -126,30 +116,30 @@ logger = get_logger(__name__)

def create(prompt: str, org_id: int | None = None, ...):
"""Create a new agent run with the given prompt."""

# ADD: Log start
logger.info("Agent creation started", extra={
"operation": "agent.create",
"org_id": org_id,
"prompt_length": len(prompt)
})

# Your existing code...
try:
response = requests.post(url, headers=headers, json=payload)
agent_run_data = response.json()
# ADD: Log success

# ADD: Log success
logger.info("Agent created successfully", extra={
"operation": "agent.create",
"agent_run_id": agent_run_data.get("id"),
"status": agent_run_data.get("status")
})

except requests.RequestException as e:
# ADD: Log error
logger.error("Agent creation failed", extra={
"operation": "agent.create",
"operation": "agent.create",
"error_type": "api_error",
"error": str(e)
})
Expand All @@ -163,52 +153,49 @@ def create(prompt: str, org_id: int | None = None, ...):

logger = get_logger(__name__)


def _run_claude_interactive(resolved_org_id: int, no_mcp: bool | None) -> None:
session_id = generate_session_id()

# ADD: Log session start
logger.info("Claude session started", extra={
"operation": "claude.session_start",
"session_id": session_id[:8], # Short version for privacy
"org_id": resolved_org_id
})

logger.info(
"Claude session started",
extra={
"operation": "claude.session_start",
"session_id": session_id[:8], # Short version for privacy
"org_id": resolved_org_id,
},
)

# Your existing code...

try:
process = subprocess.Popen([claude_path, "--session-id", session_id])
returncode = process.wait()

# ADD: Log session end
logger.info("Claude session completed", extra={
"operation": "claude.session_complete",
"session_id": session_id[:8],
"exit_code": returncode,
"status": "COMPLETE" if returncode == 0 else "ERROR"
})

logger.info(
"Claude session completed", extra={"operation": "claude.session_complete", "session_id": session_id[:8], "exit_code": returncode, "status": "COMPLETE" if returncode == 0 else "ERROR"}
)

except Exception as e:
# ADD: Log session error
logger.error("Claude session failed", extra={
"operation": "claude.session_error",
"session_id": session_id[:8],
"error": str(e)
})
logger.error("Claude session failed", extra={"operation": "claude.session_error", "session_id": session_id[:8], "error": str(e)})
```

## 🧪 Verification

After making changes:

1. **Run the command**: Execute your enhanced CLI command
2. **Check telemetry status**: `codegen config telemetry status`
3. **Look for logs in Grafana Cloud**: Search for your operation names
4. **Test with telemetry disabled**: `codegen config telemetry disable` - should still work normally
1. **Check telemetry status**: `codegen config telemetry status`
1. **Look for logs in Grafana Cloud**: Search for your operation names
1. **Test with telemetry disabled**: `codegen config telemetry disable` - should still work normally

## 🚀 Progressive Enhancement

**Week 1**: Add basic operation logging to 2-3 commands
**Week 2**: Add error logging to all commands
**Week 2**: Add error logging to all commands
**Week 3**: Add performance metrics and detailed context
**Week 4**: Create Grafana dashboards using the collected data

Expand Down
7 changes: 6 additions & 1 deletion docs/docs.json
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,12 @@
},
{
"group": "Settings",
"pages": ["settings/repo-rules", "settings/model-configuration"]
"pages": [
"settings/repo-rules",
"settings/model-configuration",
"settings/team-roles",
"settings/agent-permissions"
]
}
]
},
Expand Down
111 changes: 111 additions & 0 deletions docs/settings/team-roles.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
---
title: "Team Member Roles"
sidebarTitle: "Team Roles"
icon: "users"
---

Team member roles control what actions users can perform within your Codegen organization. The role system uses a hierarchical permission model to ensure proper access control while allowing teams to delegate responsibilities appropriately.

## Role Hierarchy

There are **three roles** in the system with a hierarchical structure where higher roles inherit all permissions from lower roles:

`MEMBER` < `MANAGER` < `ADMIN`

## Role Definitions

### 🔴 **ADMIN** (Highest Level)

Admins have **full administrative access** to the organization and can perform all actions:

- **Manage billing** and subscription settings
- **Delete repositories** (only admins can do this)
- **Change user roles** (promote/demote team members)
- **Manage integrations** (GitHub, Linear, Slack, etc.)
- **Access organization settings**
- **View cost breakdowns and analytics**
- **Invite users to the organization**

### 🟡 **MANAGER** (Middle Level)

Managers have operational permissions but lack administrative controls:

- **Manage integrations** (GitHub, Linear, Slack, etc.)
- **View and manage organization integrations**
- **Cannot** access billing information
- **Cannot** manage user roles
- **Cannot** delete repositories

### 🟢 **MEMBER** (Basic Level)

Members have basic permissions for day-to-day work:

- **View agent traces and runs**
- **Use main application features** (creating agents, viewing repos, etc.)
- **View their own profile and settings**
- **Cannot** manage integrations
- **Cannot** access billing information
- **Cannot** manage other users
- **Cannot** delete repositories

## Permission Matrix

| Feature | Member | Manager | Admin |
|---------|--------|---------|-------|
| View repositories | ✅ | ✅ | ✅ |
| Create and run agents | ✅ | ✅ | ✅ |
| View agent traces | ✅ | ✅ | ✅ |
| Manage integrations | ❌ | ✅ | ✅ |
| Delete repositories | ❌ | ❌ | ✅ |
| Access billing | ❌ | ❌ | ✅ |
| Change user roles | ❌ | ❌ | ✅ |
| Organization settings | Limited | Limited | Full |
| Invite users | ❌ | ❌ | ✅ |

## Managing Team Roles

### Default Role Assignment

- New team members are assigned the **MEMBER** role by default
- This ensures new users have basic access without administrative privileges

### Changing Roles

Only **ADMIN** users can promote or demote other team members:

1. Navigate to your organization's team management page
2. Find the user whose role you want to change
3. Select the new role from the dropdown
4. Confirm the change

### Role Restrictions

- You cannot assign a role higher than your own
- The system prevents privilege escalation attacks
- At least one ADMIN must remain in each organization

## Best Practices

### Security Considerations

- **Principle of Least Privilege**: Assign the minimum role necessary for each team member's responsibilities
- **Regular Audits**: Periodically review team member roles and adjust as needed
- **Onboarding**: Start new team members as MEMBER and promote as they gain experience

### Role Assignment Guidelines

- **MEMBER**: Developers, contractors, or team members who primarily work with code and agents
- **MANAGER**: Team leads, project managers, or senior developers who need to manage integrations
- **ADMIN**: Organization owners, DevOps engineers, or senior leadership who need full control

### Workflow Integration

- Consider your team's structure when assigning roles
- Ensure critical functions (billing, user management) are accessible to multiple admins
- Document role assignments and responsibilities for your team

## Related Documentation

- [Agent Permissions](/settings/agent-permissions) - Configure what actions agents can perform
- [Organization Rules](/settings/organization-rules) - Set organization-wide rules
- [Repository Rules](/settings/repo-rules) - Configure repository-specific behavior
1 change: 1 addition & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ dependencies = [
"unidiff>=0.7.5",
"datamodel-code-generator>=0.26.5",
"fastmcp>=2.9.0",
"mcp-python>=0.1.4",
# OpenTelemetry logging dependencies
"opentelemetry-api>=1.26.0",
"opentelemetry-sdk>=1.26.0",
Expand Down
2 changes: 2 additions & 0 deletions src/codegen/cli/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
from codegen.cli.commands.integrations.main import integrations_app
from codegen.cli.commands.login.main import login
from codegen.cli.commands.logout.main import logout
from codegen.cli.commands.mcp.main import mcp
from codegen.cli.commands.org.main import org
from codegen.cli.commands.profile.main import profile_app
from codegen.cli.commands.repo.main import repo
Expand Down Expand Up @@ -65,6 +66,7 @@ def version_callback(value: bool):
main.command("init", help="Initialize or update the Codegen folder.")(init)
main.command("login", help="Store authentication token.")(login)
main.command("logout", help="Clear stored authentication token.")(logout)
main.command("mcp", help="Start the Codegen MCP server.")(mcp)
main.command("org", help="Manage and switch between organizations.")(org)
main.command("repo", help="Manage repository configuration and environment variables.")(repo)
main.command("style-debug", help="Debug command to visualize CLI styling (spinners, etc).")(style_debug)
Expand Down
1 change: 0 additions & 1 deletion src/codegen/cli/commands/claude/__init__.py
Original file line number Diff line number Diff line change
@@ -1,2 +1 @@
"""Claude Code integration commands."""

Loading
Loading