Skip to content
Merged
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
6 changes: 6 additions & 0 deletions .git-blame-ignore-revs
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
# Commits listed here are skipped by `git blame`.
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Why do we need this file, nothing is included

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

It exists so git blame doesn't attribute every line in the codebase to the Spotless reformat commit.

# Locally, run: git config blame.ignoreRevsFile .git-blame-ignore-revs
# GitHub honors this file automatically.

# Add the SHA of the one-shot Spotless reformat commit here once it lands:
# <reformat-commit-sha> style: apply Google Java Format via Spotless
70 changes: 70 additions & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
name: Release

on:
push:
tags:
- 'v*.*.*'

permissions:
contents: write
packages: write

jobs:
release:
name: Build and publish Docker image
runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v6

- name: Set up JDK 17
uses: actions/setup-java@v5
with:
java-version: '17'
distribution: 'temurin'

- name: Setup Gradle
uses: gradle/actions/setup-gradle@v6

- name: Build (Spotless + Spotbugs + tests)
run: ./gradlew build -x integrationTest

- name: Set up QEMU
uses: docker/setup-qemu-action@v3

- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3

- name: Log in to GHCR
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}

- name: Compute image tags
id: meta
uses: docker/metadata-action@v5
with:
images: ghcr.io/${{ github.repository_owner }}/ugroup
tags: |
type=semver,pattern={{version}}
type=semver,pattern={{major}}.{{minor}}
type=semver,pattern={{major}}
type=raw,value=latest

- name: Build and push image
uses: docker/build-push-action@v6
with:
context: .
file: docker/Dockerfile
platforms: linux/amd64,linux/arm64
push: true
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}

- name: Create GitHub Release
uses: softprops/action-gh-release@v2
with:
generate_release_notes: true
files: build/libs/*-boot.jar
21 changes: 16 additions & 5 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ Thank you for your interest in contributing to uGroup! This document explains ho

- **Tests required**: All new functionality must include automated tests. Bug fixes should include a test that reproduces the issue.
- **Build must pass**: Run `./gradlew build` before submitting. This runs unit tests, integration tests, static analysis, and coverage checks.
- **Formatting**: Run `./gradlew spotlessApply` before submitting. CI runs `spotlessCheck` as part of `build` and will fail on unformatted code.
- **Code coverage**: The project enforces a minimum coverage threshold via JaCoCo. New code should maintain or improve coverage.
- **No broken windows**: Fix any static analysis warnings introduced by your changes.

Expand All @@ -33,6 +34,15 @@ Thank you for your interest in contributing to uGroup! This document explains ho

# Run integration tests (requires Docker)
./gradlew integrationTest

# Apply Google Java Format
./gradlew spotlessApply
```

The repo includes a `.git-blame-ignore-revs` file that hides the one-shot Spotless reformat commit from `git blame`. GitHub honors it automatically; for local `git blame`, run once:

```bash
git config blame.ignoreRevsFile .git-blame-ignore-revs
```

## Reporting Issues
Expand All @@ -46,14 +56,15 @@ Use [GitHub Issues](https://github.com/uber/uGroup/issues) to report bugs or req

All pull requests require approval from at least one of the following code reviewers before merging:

| Reviewer | Email | Coverage Area |
|----------|-------|---------------|
| Qichao Chu | qichao@uber.com | All areas |
| Si Lao | sil@uber.com | All areas |
| Reviewer | GitHub | Coverage Area |
|----------|--------|---------------|
| Qichao Chu | [@ex172000](https://github.com/ex172000) | All areas |
| Si Lao | [@laosiaudi](https://github.com/laosiaudi) | All areas |
| Yulan Feng | [@yfeng21](https://github.com/yfeng21) | All areas |

**Review process:**
- Every PR must be reviewed and approved by at least one of the engineers listed above.
- For critical changes (security fixes, breaking changes, or core processing logic), approval from both reviewers is recommended.
- For critical changes (security fixes, breaking changes, or core processing logic), approval from two reviewers is recommended.
- Reviewers should be assigned via GitHub's reviewer request feature when opening a PR.
- Reviews should focus on correctness, test coverage, performance implications, and adherence to project conventions.

Expand Down
56 changes: 54 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,10 @@ uGroup monitors Kafka consumer groups by reading the `__consumer_offsets` topic

```bash
cd docker
docker-compose up -d
docker compose up -d
```

This starts Kafka, Zookeeper, and uGroup. Access the API at `http://localhost:8080`.
This starts Kafka, Zookeeper, and uGroup. Point uGroup at any consumer group running against the same broker and lag will appear at `http://localhost:8080`.

### Using Gradle

Expand All @@ -33,6 +33,58 @@ This starts Kafka, Zookeeper, and uGroup. Access the API at `http://localhost:80
KAFKA_BOOTSTRAP_SERVERS=localhost:9092 ./gradlew bootRun
```

## Usage

### Query lag via REST

```bash
# Lag for every topic a group consumes
curl http://localhost:8080/api/v1/lag/my-consumer-group

# Lag for one group/topic pair
curl http://localhost:8080/api/v1/lag/my-consumer-group/events-topic

# Liveness / status
curl http://localhost:8080/api/v1/status
```

### Scrape lag with Prometheus

uGroup exposes metrics at `/actuator/prometheus`. Example PromQL for the worst-lagging group in each cluster:

```promql
max by (cluster, group) (ugroup_consumer_lag)
```

See the [Metrics wiki page](https://github.com/uber/uGroup/wiki/Metrics) for the full metric and label reference.

## Common scenarios

uGroup decides which groups to monitor via `UGROUP_WATCHLIST_MODE`. Pick the mode that fits your use case and see the linked wiki page for the YAML/regex details.

**Monitor every consumer group in the cluster** — zero config, useful for ops dashboards:

```bash
UGROUP_WATCHLIST_MODE=all ./gradlew bootRun
```

**Monitor a curated list** — declare the exact groups + topics you care about in a YAML file (see [`watchlist-sample.yaml`](src/main/resources/watchlist-sample.yaml) and the [Watchlist wiki page](https://github.com/uber/uGroup/wiki/Watchlist-Configuration)):

```bash
UGROUP_WATCHLIST_MODE=static UGROUP_WATCHLIST_FILE=/etc/ugroup/watchlist.yaml ./gradlew bootRun
```

**Monitor by regex with a blocklist** — useful when group names follow a naming convention but a few should be excluded (see the [Blocklist wiki page](https://github.com/uber/uGroup/wiki/Blocklist-Configuration)):

```bash
UGROUP_WATCHLIST_MODE=regex \
UGROUP_INCLUDE_PATTERNS='prod-.*' \
UGROUP_BLOCKLIST_FILE=/etc/ugroup/blocklist.yaml \
./gradlew bootRun
```

For the full list of environment variables and their defaults, see the [Configuration wiki page](https://github.com/uber/uGroup/wiki/Configuration).

## Documentation

Full documentation is available on the [Wiki](https://github.com/uber/uGroup/wiki):
Expand Down
Loading