XCMetrics logo

Backstage XCMetrics Plugin

Created by Spotify

XCMetrics is an open source tool from Spotify that collects and analyzes Xcode build logs. It parses xcactivitylog files to surface build times, warnings, errors, target compile times, and more. You run the backend yourself so the data stays under your control.

The XCMetrics Backstage plugin brings those metrics into your developer portal. It connects to your XCMetrics backend and presents a simple web view for teams. You get an overview of recent builds, trend charts, and ways to inspect details when something slows down. It is a quick way to make build health visible next to your catalogs, docs, and workflows.

Common use cases include tracking build times across projects, spotting slow targets before they hurt release cadence, watching warning growth, comparing CI and local builds, and checking the impact of Xcode upgrades or refactors. The data helps you plan fixes and verify results without leaving Backstage.

Spotify reports using XCMetrics at scale across its iOS apps. As their docs note, “XCMetrics has collected almost 1 million builds and over 10 billion steps from all Spotify iOS applications since its introduction.”

Installation Instructions

These instructions apply to self-hosted Backstage only.

Install the frontend package

Copy
yarn --cwd packages/app add @backstage-community/plugin-xcmetrics

Add the route in the app

Open packages/app/src/App.tsx. Import the page. Add a route.

Copy
// packages/app/src/App.tsx
import React from 'react';
import { Route } from 'react-router-dom';
import { FlatRoutes } from '@backstage/core-app-api';
import { XcmetricsPage } from '@backstage-community/plugin-xcmetrics';

export const App = () => {
  return (
    <FlatRoutes>
      {/* other routes */}
      <Route path="/xcmetrics" element={<XcmetricsPage />} />
    </FlatRoutes>
  );
};

Open packages/app/src/components/Root/Root.tsx. Add a sidebar item that points to the page.

Copy
// packages/app/src/components/Root/Root.tsx
import React from 'react';
import { SidebarItem } from '@backstage/core-components';
import BarChartIcon from '@mui/icons-material/BarChart';

// find the Sidebar section and add this item among the others
<SidebarItem icon={BarChartIcon} to="/xcmetrics" text="XCMetrics" />

Set the proxy to your XCMetrics server

Add the proxy entry in app-config.yaml. Point it at your XCMetrics API.

Copy
# app-config.yaml
proxy:
  '/xcmetrics':
    target: http://127.0.0.1:8080/v1

Backend set up old backend system

If your backend already runs the proxy plugin, you only need the app config above. If not, add the proxy backend.

Add the package.

Copy
yarn --cwd packages/backend add @backstage/plugin-proxy-backend

Create the proxy router.

Copy
// packages/backend/src/plugins/proxy.ts
import { createRouter } from '@backstage/plugin-proxy-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,
    discovery: env.discovery,
    tokenManager: env.tokenManager,
  });
}

Wire it in the backend index.

Copy
// packages/backend/src/index.ts
import proxy from './plugins/proxy';

// inside the main bootstrap where apiRouter is created
const proxyEnv = useHotMemoize(module, () => createEnv('proxy'));
apiRouter.use('/proxy', await proxy(proxyEnv));

The frontend will call the path under api proxy which maps to the config you set.

Backend set up new backend system

If your backend already includes the proxy plugin, you only need the app config above. If not, add it.

Add the package.

Copy
yarn --cwd packages/backend add @backstage/plugin-proxy-backend

Register the proxy plugin.

Copy
// packages/backend/src/index.ts or packages/backend/src/main.ts
import { createBackend } from '@backstage/backend-defaults';
import { proxyPlugin } from '@backstage/plugin-proxy-backend';

const backend = createBackend();

backend.add(proxyPlugin());

backend.start();

What the plugin exports

The plugin exports a page component and a plugin instance.

Copy
import { XcmetricsPage, xcmetricsPlugin } from '@backstage-community/plugin-xcmetrics';

You use XcmetricsPage in your app route as shown above. The xcmetricsPlugin export is not required for basic routing.

Changelog

This changelog is produced from commits made to the XCMetrics plugin since a year ago, and based on the code located here. It may not contain information about all commits. Releases and version bumps are intentionally omitted. This changelog is generated by AI.

Breaking changes

None

Maintenance

  • Remove unused devDependency canvas. 6 months ago. PR #3565
  • Update repo tools to 0.13.0 to reduce false positives in knip reports. 7 months ago. PR #3018

Set up Backstage in minutes with Roadie