# DORA Metrics Backend Plugin for Backstage

This plugin provides the backend API for retrieving DORA (DevOps Research and Assessment) metrics data from Apache DevLake for visualization in Backstage. It works in conjunction with the [@enginuity-io/dora-metrics](https://www.npmjs.com/package/@enginuity-io/dora-metrics) frontend plugin.

> **Note:** Version 0.1.3+ includes pre-compiled TypeScript with declaration files for seamless integration with Backstage apps.
>
> **Version Compatibility:**
> - Version 0.1.6: Compatible with Backstage ~1.3.x (legacy integration only)
> - Version 0.1.4: Compatible with Backstage 1.15+ (supports both new and legacy integration)

## Features

- API endpoints for retrieving DORA metrics:
  - Deployment Frequency
  - Lead Time for Changes
  - Mean Time to Restore
  - Change Failure Rate
- Connection to Apache DevLake database
- Metrics summary and performance level calculation
- Time range filtering for metrics analysis
- Project filtering for multi-project environments
- Authentication integration with Backstage

## Prerequisites

- Backstage app version 1.0.0 or higher
- Apache DevLake instance with DORA metrics data
- MySQL client libraries for database connectivity

## Installation

```bash
# From your Backstage root directory
yarn add --cwd packages/backend @enginuity-io/dora-metrics-backend
```

## Configuration

Add the following to your `app-config.yaml`:

```yaml
doraMetrics:
  # Optional: Backend port (default: 8001)
  backendPort: 8001
  
  # Optional: Frontend URL for CORS configuration
  frontendUrl: http://localhost:3000
  
  # Database configuration (required)
  database:
    connection:
      host: localhost      # DevLake database host
      port: 3306           # DevLake database port
      user: devlake        # Database user
      password: devlake    # Database password
      database: devlake    # Database name
      # Optional: Additional database connection options
      # ssl: true          # Enable SSL
      # timezone: 'UTC'    # Set timezone
```

## Usage

### Register the plugin in your Backstage backend

#### For Version 0.1.5 (Backstage ~1.3.x)

Version 0.1.5 supports only the legacy integration approach for compatibility with Backstage ~1.3.x:

1. Create a new file at `packages/backend/src/plugins/dora-metrics.ts`:

```typescript
import { createRouter } from '@enginuity-io/dora-metrics-backend';
import { Router } from 'express';
import { PluginEnvironment } from '../types';

export default async function createPlugin(
  env: PluginEnvironment,
): Promise<Router> {
  return await createRouter({
    logger: env.logger,
    config: env.config,
  });
}
```

2. Add the plugin to your backend in `packages/backend/src/index.ts`:

```typescript
import doraMetrics from './plugins/dora-metrics';

// Inside the main function:
const doraMetricsEnv = useHotMemoize(module, () => createEnv('dora-metrics'));
```

#### For Version 0.1.4 (Backstage 1.15+)

Version 0.1.4 supports both new and legacy integration approaches:

##### Option 1: Using the new backend plugin API (recommended for Backstage 1.15+)

Register the plugin in your `packages/backend/src/index.ts`:

```typescript
import { doraMetricsPlugin } from '@enginuity-io/dora-metrics-backend';

// Inside your backend.add() calls:
backend.add(doraMetricsPlugin);
```

This will automatically register the plugin with the correct dependencies and mount it at the `/api/dora-metrics` path.

##### Option 2: Using the legacy backend system

1. Create a new file at `packages/backend/src/plugins/dora-metrics.ts`:

```typescript
import { createRouter } from '@enginuity-io/dora-metrics-backend';
import { Router } from 'express';
import { PluginEnvironment } from '../types';

export default async function createPlugin(
  env: PluginEnvironment,
): Promise<Router> {
  return await createRouter({
    logger: env.logger,
    config: env.config,
  });
}
```

2. Add the plugin to your backend in `packages/backend/src/index.ts`:

```typescript
import doraMetrics from './plugins/dora-metrics';

// Inside the main function:
const doraMetricsEnv = useHotMemoize(module, () => createEnv('dora-metrics'));
apiRouter.use('/dora-metrics', await doraMetrics(doraMetricsEnv));
```

### Complete Integration

For complete integration, you need to install and configure both the frontend and backend plugins. Here's a step-by-step guide for both the new plugin system (recommended) and the legacy plugin system.

#### Using the New Plugin System (Backstage 1.15+)

1. Install both plugins:
```bash
# From your Backstage root directory
yarn add --cwd packages/app @enginuity-io/dora-metrics
yarn add --cwd packages/backend @enginuity-io/dora-metrics-backend
```

2. Register the frontend plugin in `packages/app/src/App.tsx`:
```typescript
import { doraMetricsPlugin } from '@enginuity-io/dora-metrics';
import { DoraMetricsPage } from '@enginuity-io/dora-metrics';

// Inside your FlatRoutes component:
<Route path="/dora-metrics" element={<DoraMetricsPage />} />

// Add to your plugins list
const app = createApp({
  apis,
  plugins: [
    // ... other plugins
    doraMetricsPlugin,
  ],
});
```

3. Register the backend plugin in `packages/backend/src/index.ts`:
```typescript
import { doraMetricsPlugin } from '@enginuity-io/dora-metrics-backend';

// Inside your backend.add() calls:
backend.add(doraMetricsPlugin);
```

4. Add the configuration to your `app-config.yaml` as described in the Configuration section.

#### Using the Legacy Plugin System

1. Install both plugins:
```bash
# From your Backstage root directory
yarn add --cwd packages/app @enginuity-io/dora-metrics
yarn add --cwd packages/backend @enginuity-io/dora-metrics-backend
```

2. Register the frontend plugin in your app as described in the frontend plugin's README.

3. Register the backend plugin in `packages/backend/src/plugins/dora-metrics.ts`:
```typescript
import { createRouter } from '@enginuity-io/dora-metrics-backend';
import { Router } from 'express';
import { PluginEnvironment } from '../types';

export default async function createPlugin(
  env: PluginEnvironment,
): Promise<Router> {
  return await createRouter({
    logger: env.logger,
    config: env.config,
  });
}
```

4. Import and use the plugin in `packages/backend/src/index.ts`:
```typescript
import doraMetrics from './plugins/dora-metrics';

// Inside the main function:
const doraMetricsEnv = useHotMemoize(module, () => createEnv('dora-metrics'));
apiRouter.use('/dora-metrics', await doraMetrics(doraMetricsEnv));
```

5. Add the configuration to your `app-config.yaml` as described in the Configuration section.

## API Endpoints

### Health and System

- `GET /api/dora-metrics/health`: Health check endpoint
  - Returns: `{ status: 'ok' }` if the service is running

### Projects

- `GET /api/dora-metrics/projects`: List available projects
  - Query parameters:
    - `limit` (optional): Maximum number of projects to return
    - `offset` (optional): Offset for pagination
  - Returns: Array of project objects `{ id: string, name: string }`

### Metrics

- `GET /api/dora-metrics/metrics/deployment-frequency`: Get deployment frequency data
  - Query parameters:
    - `projectId` (required): ID of the project
    - `startDate` (optional): Start date in ISO format
    - `endDate` (optional): End date in ISO format
  - Returns: `{ value: number, level: string, trend: string, history: Array }`

- `GET /api/dora-metrics/metrics/lead-time`: Get lead time for changes data
  - Query parameters: Same as deployment-frequency
  - Returns: Same structure as deployment-frequency

- `GET /api/dora-metrics/metrics/mttr`: Get mean time to restore data
  - Query parameters: Same as deployment-frequency
  - Returns: Same structure as deployment-frequency

- `GET /api/dora-metrics/metrics/failure-rate`: Get change failure rate data
  - Query parameters: Same as deployment-frequency
  - Returns: Same structure as deployment-frequency

- `GET /api/dora-metrics/metrics/summary`: Get summary of all DORA metrics
  - Query parameters: Same as deployment-frequency
  - Returns: Object containing all four metrics with their values, levels, and trends

## Database Schema

The plugin expects Apache DevLake's database schema with the following key tables:

- `project`: Contains project information
- `deployments`: Contains deployment data
- `pull_requests`: Contains PR/MR data for lead time calculation
- `incidents`: Contains incident data for MTTR calculation

Refer to the [Apache DevLake documentation](https://devlake.apache.org/docs/DataModels/DevLakeDomainLayerSchema) for the complete schema.

## Development

```bash
# From your Backstage root directory
yarn start # Starts both frontend and backend
```

For development in isolation:

```bash
# From the plugin directory
yarn build
yarn start
```

## Testing

```bash
# From the plugin directory
yarn test
```

You can also use the standalone test app in the repository:

```bash
# From the test-app directory
yarn install
yarn start
```

## Publishing to npm

To publish the package to npm:

```bash
# From the plugin directory
yarn build
npm login  # Login to your npm account
npm publish --access public  # For scoped packages
```

## Troubleshooting

- **Database connection errors**: 
  - Verify your database connection settings in app-config.yaml
  - Ensure the DevLake database is accessible from your Backstage instance
  - Check that the database user has appropriate permissions

- **Missing data**: 
  - Confirm that Apache DevLake has collected and processed data for your projects
  - Check that the project IDs being used match those in DevLake

- **API errors**: 
  - Check the Backstage backend logs for detailed error messages
  - Verify CORS settings if frontend and backend are on different domains

## Links

- [Backstage Backend Plugin Documentation](https://backstage.io/docs/plugins/backend-plugin)
- [Apache DevLake](https://devlake.apache.org/)
- [DORA Metrics Information](https://cloud.google.com/blog/products/devops-sre/using-the-four-keys-to-measure-your-devops-performance)
- [npm Package](https://www.npmjs.com/package/@enginuity-io/dora-metrics-backend)
