Skip to content

Add RuntimeLogs() method for retrieving application runtime logs#124

Merged
ramonskie merged 1 commit intomainfrom
add-runtime-logs-api
Dec 18, 2025
Merged

Add RuntimeLogs() method for retrieving application runtime logs#124
ramonskie merged 1 commit intomainfrom
add-runtime-logs-api

Conversation

@ramonskie
Copy link
Contributor

Summary

Adds a platform-agnostic RuntimeLogs() API for retrieving logs from running applications after deployment succeeds. This complements the existing staging logs returned by platform.Deploy.Execute() by providing access to post-deployment application output.

This PR also refactors the log fetching logic introduced in #121 (commit 8fb0d65) by extracting a shared FetchRecentLogs() helper function, eliminating code duplication between staging failure logs and runtime logs retrieval.

Key Changes

  • Add Deployment.RuntimeLogs() method - Retrieves runtime logs for both CloudFoundry and Docker platforms
  • Extract cloudfoundry.FetchRecentLogs() helper - Shared log fetching logic used by both staging failures and runtime logs
  • Add comprehensive tests - 37 tests pass (2 new tests for helper function)
  • Update README - Documents the new RuntimeLogs() API with clear examples

API Design

The API provides clear separation between staging logs (build-time) and runtime logs:

// Staging logs (build-time) - returned from Execute()
deployment, stagingLogs, err := platform.Deploy.Execute(name, path)

// Runtime logs (post-deployment) - explicit method call
runtimeLogs, err := deployment.RuntimeLogs()

Staging Logs (Build-Time)

  • Returned as 2nd parameter from platform.Deploy.Execute()
  • Contains buildpack detection, compilation, and staging output
  • Available even when deployment fails
  • Use for testing: buildpack detection, compilation errors, build-time env vars

Runtime Logs (Post-Deployment)

  • Retrieved via deployment.RuntimeLogs() method
  • Contains application startup and runtime output
  • Only available after successful deployment
  • Use for testing: app startup, service connections, module loading, runtime config

Use Cases

This enhancement simplifies buildpack integration tests that need to verify runtime behavior:

Before (manual workaround):

var cmd *exec.Cmd
if settings.Platform == "docker" {
    cmd = exec.Command("docker", "container", "logs", deployment.Name)
} else {
    cfHome := filepath.Join(os.TempDir(), deployment.Name)
    cmd = exec.Command("cf", "logs", deployment.Name, "--recent")
    cmd.Env = append(os.Environ(), fmt.Sprintf("CF_HOME=%s", cfHome))
}
output, _ := cmd.CombinedOutput()
Expect(string(output)).To(ContainSubstring("Application started"))

After (simple API):

deployment, _, err := platform.Deploy.Execute(name, path)
runtimeLogs, err := deployment.RuntimeLogs()
Expect(runtimeLogs).To(ContainSubstring("Application started"))

Example: Testing Both Staging and Runtime

it("Compiles dependencies and connects to database", func() {
    deployment, stagingLogs, err := platform.Deploy.
        WithBuildpacks("python_buildpack").
        WithServices(map[string]Service{
            "postgres": {"uri": "postgresql://localhost:5432/testdb"},
        }).
        Execute(name, filepath.Join(fixtures, "django-app"))
    
    Expect(err).NotTo(HaveOccurred())
    
    // Verify build-time behavior
    Expect(stagingLogs.String()).To(ContainSubstring("Installing dependencies"))
    Expect(stagingLogs.String()).To(ContainSubstring("Building psycopg2"))
    
    // Verify runtime behavior
    runtimeLogs, err := deployment.RuntimeLogs()
    Expect(err).NotTo(HaveOccurred())
    Expect(runtimeLogs).To(ContainSubstring("Connected to database"))
    Expect(runtimeLogs).To(ContainSubstring("Server started on port 8080"))
})

Benefits

  • Clear separation between staging logs and runtime logs
  • Platform-agnostic - works identically for CloudFoundry and Docker
  • DRY principle - consolidates duplicate log fetching code
  • Self-documenting - explicit method names make intent clear
  • No breaking changes - existing tests work without modification
  • Comprehensive tests - 37 tests pass including new functionality

Improvements Over PR #121

This PR builds upon the staging failure logs work from #121 by:

  1. Extracting shared logic - The cf logs --recent code is now in a reusable FetchRecentLogs() helper
  2. Adding runtime logs API - Tests can now verify post-deployment behavior
  3. Reducing code size - stage.go log fetching reduced from 15 lines to 5 lines
  4. Adding test coverage - New tests for the shared helper function

Testing

All tests pass:

  • ✅ 37 total tests (2 new tests for FetchRecentLogs())
  • ✅ CloudFoundry runtime logs retrieval tested
  • ✅ Docker runtime logs retrieval tested
  • ✅ No regressions in existing tests

Related

Provides a platform-agnostic API for retrieving runtime logs from
deployed applications after staging completes. This complements the
existing staging logs returned by platform.Deploy.Execute() by adding
access to post-deployment application output.

This change also refactors the log fetching logic introduced in commit
8fb0d65 by extracting a shared FetchRecentLogs() helper function,
eliminating code duplication between staging failure logs and runtime
logs retrieval.

Key additions:
- Add Deployment.RuntimeLogs() method for runtime log retrieval
- Extract cloudfoundry.FetchRecentLogs() shared helper function
- Add comprehensive tests for both CloudFoundry and Docker platforms
- Update README with RuntimeLogs() usage examples

Benefits:
- Clear separation between staging logs (build-time) and runtime logs
- Tests can verify application startup, service connections, module loading
- Simplifies buildpack integration tests (no manual cf/docker logs commands)
- Consolidates log fetching logic (DRY principle)
- Self-documenting API with explicit method names

Use cases:
- Testing application startup messages
- Verifying service connection logs (Redis, PostgreSQL, etc.)
- Checking module/extension loading (PHP extensions, npm packages)
- Validating runtime configuration
- Debugging runtime errors

Example usage:
  deployment, stagingLogs, err := platform.Deploy.Execute(name, path)
  Expect(err).NotTo(HaveOccurred())

  // stagingLogs contains build-time output
  Expect(stagingLogs).To(ContainSubstring("Installing dependencies"))

  // RuntimeLogs() retrieves application output
  runtimeLogs, err := deployment.RuntimeLogs()
  Expect(err).NotTo(HaveOccurred())
  Expect(runtimeLogs).To(ContainSubstring("Application started"))
@ramonskie ramonskie merged commit aafedd6 into main Dec 18, 2025
2 checks passed
@ramonskie ramonskie deleted the add-runtime-logs-api branch December 18, 2025 09:48
Copy link
Contributor

@ivanovac ivanovac left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants