Docs Labs Stream Jira Issues to Redpanda for Real-Time Metrics Page options Copy as Markdown Copied! View as plain text Ask AI about this topic Add MCP server to VS Code This lab demonstrates a production-ready pipeline that streams Jira issues to Redpanda topics in real-time. The pipeline transforms raw Jira API responses into a normalized, consumer-friendly schema and routes issues to different topics, enabling use cases SLA monitoring and team performance analytics. Architecture Redpanda Connect periodically queries the Jira REST API for recently updated issues in your project. Each issue is transformed to extract key fields, flatten nested objects, and compute flags like is_high_priority and is_completed. Based on these flags, issues are routed to different Redpanda topics: jira.issues.all: All issues jira.issues.high-priority: Issues with Highest/High priority jira.issues.completed: Issues marked as Done/Closed/Resolved Use cases SLA monitoring and alerting Automatically detect stale high-priority issues. Send alerts when issues haven’t been updated in a certain number of days. Track response times and prevent SLA breaches. Route critical issues to on-call teams. Team performance analytics Calculate team velocity and throughput. Identify bottlenecks in the development process. Track individual contributor metrics. Generate sprint reports automatically. Compliance and audit trail Maintain a complete history of issue changes. Immutable event log in Redpanda. Audit who changed what and when. Prerequisites You must have the following installed on your host machine: Docker and Docker Compose rpk (Redpanda CLI) - required to generate the Enterprise license This lab also requires: Jira instance with API access Jira API token from Atlassian This lab is intended for Linux and macOS users. If you are using Windows, you must use the Windows Subsystem for Linux (WSL) to run the commands in this lab. Run the lab Clone the repository: git clone https://github.com/redpanda-data/redpanda-labs.git Change into the docker-compose/jira-metrics-pipeline/ directory: cd redpanda-labs/docker-compose/jira-metrics-pipeline Copy the example environment file: cp .env.example .env Edit the .env file and configure: # Versions (optional - defaults are provided) REDPANDA_VERSION=v25.3.1 REDPANDA_CONSOLE_VERSION=v3.3.1 REDPANDA_CONNECT_VERSION=4.70.0 # Jira credentials (required) JIRA_BASE_URL=https://<domain>.atlassian.net JIRA_USERNAME=<email-address> JIRA_API_TOKEN=<api-token> JIRA_PROJECT=<jira-project-key> Generate a Redpanda Enterprise trial license: rpk generate license \ --name "<first-name>" \ --last-name "<last-name>" \ --email "<email-address>" \ --company "<company-name>" This creates a 30-day trial license in ./redpanda.license. Export the license as a shell environment variable: export REDPANDA_LICENSE=$(cat ./redpanda.license) The REDPANDA_LICENSE must be exported in your shell. It cannot be loaded from the .env file. The --env-file flag loads application variables (like JIRA_*), but the license must be exported separately. Start the Docker containers: docker compose up -d Create the Kafka topics: docker compose exec redpanda rpk topic create jira.issues.all -p 3 docker compose exec redpanda rpk topic create jira.issues.high-priority -p 3 docker compose exec redpanda rpk topic create jira.issues.completed -p 3 Open Redpanda Console at localhost:8080 to view your topics and messages. Monitor the Jira issues streaming into Redpanda: # Watch all issues docker compose exec redpanda rpk topic consume jira.issues.all --format json # Watch high-priority issues docker compose exec redpanda rpk topic consume jira.issues.high-priority --format json # Watch completed issues docker compose exec redpanda rpk topic consume jira.issues.completed --format json How it works The pipeline performs the following steps: Query Jira: Every 30 seconds, Redpanda Connect queries Jira for recently updated issues in your project Transform data: Each Jira issue is transformed into a normalized schema: Flattened fields: status, priority, issue type (extracted from nested Jira objects) Null-safe people fields: assignee and reporter (defaults to "Unassigned"/"Unknown") Raw timestamps: created, updated, resolved (preserved in original Jira format) Extracted component names from component objects Computed boolean flags: is_completed, is_high_priority Generated issue URL: {JIRA_BASE_URL}/browse/{key} Pipeline processing timestamp Route messages: Issues are intelligently routed to topics based on computed flags: High priority (Highest/High) → jira.issues.high-priority Completed (Done/Closed/Resolved) → jira.issues.completed All others → jira.issues.all Consume and analyze: Multiple downstream applications can consume from these topics independently: Metrics dashboards (Grafana, Kibana) Alert systems (Slack, PagerDuty) Data warehouses (Snowflake, BigQuery) Workflow automation Pipeline configuration The complete Redpanda Connect pipeline configuration: # JIRA Metrics Pipeline # # This pipeline queries JIRA issues and streams them to Redpanda topics # for real-time metrics, alerting, and analytics. # # Environment variables required: # - REDPANDA_LICENSE: Enterprise license (must be exported in shell) # - JIRA_BASE_URL: https://your-domain.atlassian.net # - JIRA_USERNAME: your-email@example.com # - JIRA_API_TOKEN: your-api-token # - JIRA_PROJECT: YOUR_PROJECT_KEY # - REDPANDA_BROKERS: redpanda:9092 (set in docker-compose.yml) input: generate: mapping: | # Query JIRA for recent issues (last 7 days for testing) root.jql = "project = ${JIRA_PROJECT} AND updated >= -7d ORDER BY updated DESC" root.maxResults = 10 root.fields = [ "key", "summary", "status", "priority", "assignee", "reporter", "created", "updated", "resolutiondate", "issuetype", "labels", "components" ] # Query every 30 seconds interval: 30s pipeline: processors: # Execute JIRA query - jira: base_url: "${JIRA_BASE_URL}" username: "${JIRA_USERNAME}" api_token: "${JIRA_API_TOKEN}" max_results_per_page: 100 request_timeout: 30s max_retries: 10 # Transform and enrich each issue with metrics - mapping: | # Basic issue info root.issue_key = this.key root.summary = this.fields.summary root.status = this.fields.status.name root.priority = this.fields.priority.name root.issue_type = this.fields.issuetype.name root.url = "${JIRA_BASE_URL}/browse/" + this.key # People root.assignee = if this.fields.assignee != null { this.fields.assignee.displayName } else { "Unassigned" } root.reporter = if this.fields.reporter != null { this.fields.reporter.displayName } else { "Unknown" } # Dates (keep original format for downstream processing) root.created = this.fields.created root.updated = this.fields.updated root.resolved = this.fields.resolutiondate # Labels and components root.labels = this.fields.labels root.components = this.fields.components.map_each(c -> c.name) # Flags for routing root.is_completed = this.fields.status.name.lowercase().contains("done") || this.fields.status.name.lowercase().contains("closed") || this.fields.status.name.lowercase().contains("resolved") root.is_high_priority = ["Highest", "High"].contains(this.fields.priority.name) # Note: Timestamp-based metrics (age, staleness, lead time) can be calculated # by downstream consumers using the raw `created`, `updated`, and `resolved` fields. # Add pipeline processing timestamp root.pipeline_timestamp = now() # Route to primary topic based on issue properties - mapping: | # Route based on priority and completion status meta kafka_topic = if this.is_high_priority { "jira.issues.high-priority" } else if this.is_completed { "jira.issues.completed" } else { "jira.issues.all" } output: kafka: addresses: ["${REDPANDA_BROKERS}"] topic: '${! meta("kafka_topic") }' max_in_flight: 1 batching: count: 100 period: 1s compression: snappy Customize the pipeline Adjust polling frequency Edit connect-configs/jira-pipeline.yaml: input: generate: interval: 60s # Change from 30s to 1m, 5m, etc. Modify JQL query Target different issues by changing the JQL query: root.jql = "project = YOUR_PROJECT AND status != Closed AND updated >= -1h" Add custom fields Include Jira custom fields in your pipeline: root.fields = [ "key", "summary", "customfield_10001", # Add your custom field ID # ... other fields ] Add more routing rules Route issues to additional topics based on labels, components, or other criteria: - mapping: | meta kafka_topic = if this.labels.contains("security") { "jira.issues.security" } else { deleted() } View logs and metrics Redpanda Connect logs docker compose logs -f connect Redpanda logs docker compose logs -f redpanda Redpanda Connect metrics curl http://localhost:4195/metrics Troubleshooting License errors If you see license-related errors in the Connect logs: Verify the license is exported: echo $REDPANDA_LICENSE If the environment variable is empty, regenerate and export the license: rpk generate license --name "Your Name" \ --last-name "Last" \ --email "you@example.com" \ --company "Company" export REDPANDA_LICENSE=$(cat ./redpanda.license) Restart the containers: docker compose restart connect Jira authentication errors If you receive 401 Unauthorized errors: Verify your API token is correct. Ensure you’re using your email address as the username. Check that your Jira instance URL is correct (include https://). Test your credentials with curl: curl -u "${JIRA_USERNAME}:${JIRA_API_TOKEN}" \ "${JIRA_BASE_URL}/rest/api/3/myself" No issues appearing If no issues are being published: Check the JQL query returns results in Jira directly. Verify the JIRA_PROJECT environment variable matches your project key. Check Connect logs for errors: docker compose logs connect Adjust the query timeframe: root.jql = "project = YOUR_PROJECT AND updated >= -24h" # Last 24 hours Rate limiting If you hit Jira rate limits (HTTP 429): Increase the polling interval in connect-configs/jira-pipeline.yaml: interval: 60s # Reduce frequency to 60 seconds Increase retry settings: - jira: max_retries: 20 request_timeout: 60s Use more specific JQL queries to reduce result sizes. Clean up To shut down and delete the containers along with all cluster data: docker compose down -v Next steps After you have Jira issues streaming into Redpanda, you can extend this pipeline with Redpanda Connect outputs: Send alerts and notifications Slack: Post issue updates to channels using the slack_post output Discord: Send notifications with the discord output HTTP/Webhooks: Trigger PagerDuty, Opsgenie, or custom webhooks using the http_client output Stream to data warehouses Snowflake: Load issues into Snowflake with the snowflake_streaming output BigQuery: Stream to Google BigQuery using the gcp_bigquery output PostgreSQL/MySQL: Store in relational databases with sql_insert or sql_raw outputs Calculate metrics Use the raw timestamp fields (created, updated, resolved) to calculate: Lead time: Average time from creation to completion Cycle time: Average time from "In Progress" to "Done" Throughput: Issues completed per time period Aging: Distribution of issue ages SLA compliance: Percentage of issues resolved within target timeframes Suggested reading Jira Processor Reference Jira REST API Documentation JQL Query Guide Redpanda Quickstart Back to top × Simple online edits For simple changes, such as fixing a typo, you can edit the content directly on GitHub. Edit on GitHub Or, open an issue to let us know about something that you want us to change. Open an issue Contribution guide For extensive content updates, or if you prefer to work locally, read our contribution guide . Was this helpful? thumb_up thumb_down group Ask in the community mail Share your feedback group_add Make a contribution 🎉 Thanks for your feedback!