Documentation Index
Fetch the complete documentation index at: https://otel.fyi/llms.txt
Use this file to discover all available pages before exploring further.
Github Receiver
Available in: contrib
Maintainers: @adrielp, @crobert-1, @TylerHelmuth
Source: opentelemetry-collector-contrib
Supported Telemetry
Overview
Overview
The GitHub receiver receives data from GitHub via two methods:
- Scrapes version control system metrics from GitHub repositories and
organizations using the GraphQL and REST APIs.
- Receives GitHub Actions events by serving a webhook endpoint, converting
those events into traces.
Metrics - Getting Started
The current default set of metrics can be found in
documentation.md.
These metrics can be used as leading indicators (capabilities)
to the DORA metrics; helping provide insight into modern-day
engineering practices.
The collection interval is common to all scrapers and is set to 30 seconds by default.
Note: Generally speaking, if the vendor allows for anonymous API calls, then you
won’t have to configure any authentication, but you may only see public repositories
and organizations. You may also run into significantly more rate limiting.
github:
collection_interval: <duration> #default = 30s recommended 300s
scrapers:
scraper/config-1:
scraper/config-2:
...
A more complete example using the GitHub scrapers with authentication is as follows:
extensions:
bearertokenauth/github:
token: ${env:GH_PAT}
receivers:
github:
initial_delay: 1s
collection_interval: 60s
scrapers:
scraper:
metrics: #Optional
vcs.contributor.count:
enabled: true
github_org: <myfancyorg>
search_query: "org:<myfancyorg> topic:<o11yalltheway>" # Recommended optional query override, defaults to "{org,user}:<github_org>"
concurrency_limit: 50 # Optional: (default: 50)
merged_pr_lookback_days: 30 # Optional: (default: 30)
endpoint: "https://selfmanagedenterpriseserver.com" # Optional
auth:
authenticator: bearertokenauth/github
service:
extensions: [bearertokenauth/github]
pipelines:
metrics:
receivers: [..., github]
processors: []
exporters: [...]
Configuration
github_org (required): Specify the GitHub organization or username to scrape.
endpoint (optional): Set this only when using a self-managed GitHub instance (e.g., https://selfmanagedenterpriseserver.com — SHOULD NOT include api subdomain or /graphql context path).
search_query (optional): A filter to narrow down repositories. Defaults to org:<github_org> (or user:<username>). For example, use repo:<org>/<repo> to target a specific repository. Any valid GitHub search syntax is allowed.
concurrency_limit (optional): Maximum number of concurrent repository processing goroutines. Defaults to 50 to stay under GitHub’s 100 concurrent request limit. Set to 0 for unlimited concurrency (not recommended for >100 repositories).
merged_pr_lookback_days (optional): Number of days to query back in time when fetching merged pull requests. Defaults to 30. Set to 0 to fetch all merged PRs.
metrics (optional): Enable or disable metrics scraping. See the metrics documentation for details.
Scraping
Important:
- The GitHub scraper does not emit metrics for branches that have not had
changes since creation from the default branch (trunk).
- Due to GitHub API limitations, it is possible for the branch time metric to
change when rebases occur, recreating the commits with new timestamps.
For additional context on GitHub scraper limitations and inner workings please
see the Scraping README.
GitHub Personal Access Token (PAT) Setup
To create a GitHub Personal Access Token (PAT), please refer to the official documentation.
Organization or Personal Access:
When generating the PAT, select the appropriate Resource owner — either your personal account or the organization and choose the correct Repository access type. For fine-grained tokens, explicitly configure the necessary Repository permissions or Organization permissions.
Note:
The PAT must have read access to the target repositories. If the PAT doesn’t have permission to access repositories in the target organization, only the repository count metric will be available. Detailed repository metrics cannot be fetched.
Traces - Getting Started
Workflow tracing support is accomplished through the processing of GitHub
Actions webhook events for workflows and jobs. The workflow_job and
workflow_run event payloads are then constructed into trace
telemetry.
Each GitHub Action workflow or job, along with its steps, are converted
into trace spans, allowing the observation of workflow execution times,
success, and failure rates. Each Trace and Span ID is deterministic. This
enables the underlying actions to emit telemetry from any command running in any
step. This can be achieved by using tools like the run-with-telemetry
action and otel-cli. The key is generating IDs in the same way
that this GitHub receiver does. The trace_event_handling.go file contains
the new*ID functions that generate deterministic IDs.
IMPORTANT - Workflow Job names MUST be unique in each workflow for
deterministic span IDs to not conflict with eachother. GitHub does not enforce
this behavior, but when linting a workflow, warns that there are duplicate job
names.
Receiver Configuration
IMPORTANT - Ensure your WebHook endpoint is secured with a secret and a Web
Application Firewall (WAF) or other security measure.
The WebHook configuration exposes the following settings:
endpoint: (default = localhost:8080) - The address and port to bind the WebHook to.
path: (default = /events) - The path for Action events to be sent to.
health_path: (default = /health) - The path for health checks.
secret: (optional) - The secret used to validates the payload.
required_header: (optional) - The required header key and value for incoming requests.
service_name: (optional) - The service name for the traces. See the
Configuring Service Name section for more
information.
include_span_events: (default = false) - When set to true, attaches the raw webhook event JSON as a span event. The workflow run event is attached to the workflow run span, and the workflow job event is attached to the job span.
The WebHook configuration block also accepts all the confighttp
settings.
An example configuration is as follows:
receivers:
github:
webhook:
endpoint: localhost:19418
path: /events
health_path: /health
secret: ${env:SECRET_STRING_VAR}
service_name: github-actions # single logical CI service (See Configuring Service Name section below)
required_headers:
WAF-Header: "value"
scrapers: # The validation expects at least a dummy scraper config
scraper:
github_org: open-telemetry
For tracing, all configuration is set under the webhook key. The full set
of exposed configuration values can be found in config.go.
Configuring Service Name
The service_name option in the WebHook configuration can be used to set a
pre-defined service.name resource attribute for all traces emitted by the
receiver. This value should represent the logical service producing telemetry
(as defined by OpenTelemetry resource semantics), not individual repositories or
components. For CI/CD usage, a typical choice is a single service such as
github-actions (optionally paired with service.namespace for ownership and
uniqueness).
If you choose to set service_name explicitly, consider running a separate
GitHub receiver (and/or GitHub App) for each distinct service that you want to
model.
If you do not set service_name, the receiver supports deriving it from
repository metadata. You can configure Custom Properties in each GitHub
repository by adding a service_name key; all events from that repository will
then carry the specified service.name. If no custom property is found, the
receiver will derive service.name from the repository name.
Note: Deriving service.name from repositories is a convenience and may
be sufficient for small setups. In larger organizations, mapping repositories
directly to service.name often leads to many pseudo-services and can make
cross-repository analysis harder. Prefer an explicit CI service name when
modeling your pipelines as a platform service.
Precedence for setting service.name:
service_name in the WebHook configuration.
service_name key in the repository’s Custom Properties.
service_name derived from the repository name.
service.name defaults to unknown_service per the semantic conventions.
Span Events
When include_span_events is enabled, the receiver attaches the raw GitHub webhook event JSON as a span event to the corresponding span:
- Workflow Run events: Attached as a span event named
github.workflow_run.event to the root workflow run span
- Workflow Job events: Attached as a span event named
github.workflow_job.event to the job span
The raw event is stored in the event.payload attribute as a JSON string. This allows for detailed inspection of the complete webhook payload, including fields that may not be mapped to span attributes.
Note: The raw event payload can be large (typically 5-50KB). Consider the impact on storage and performance before enabling this feature in production environments.
An example configuration with span events enabled:
receivers:
github:
webhook:
endpoint: localhost:19418
path: /events
health_path: /health
secret: ${env:SECRET_STRING_VAR}
required_headers:
WAF-Header: "value"
include_span_events: true
scrapers: # The validation expects at least a dummy scraper config
scraper:
github_org: open-telemetry
Configuring A GitHub App
To configure a GitHub App, you will need to create a new GitHub App within your
organization. Refer to the general GitHub App documentation for how to
create a GitHub App. During the subscription phase, subscribe to workflow_run and workflow_job events.
Custom Properties as Resource Attributes
The GitHub receiver supports adding custom properties from GitHub repositories as resource attributes in your telemetry data. This allows users to enrich traces and events with additional metadata specific to each repository.
How It Works
When a GitHub webhook event is received, the receiver extracts all custom properties from the repository and adds them as resource attributes with the prefix github.repository.custom_properties.
For example, if your repository has these custom properties:
classification: public
service-tier: critical
slack-support-channel: #observability-alerts
team-name: observability-engineering
They will be added as resource attributes:
github.repository.custom_properties.classification: "public"
github.repository.custom_properties.service_tier: "critical"
github.repository.custom_properties.slack_support_channel: "#observability-alerts"
github.repository.custom_properties.team_name: "observability-engineering"
To ensure consistency with OpenTelemetry naming conventions, all custom property keys are converted to snake_case format using the following rules:
- Hyphens, spaces, and dots are replaced with underscores
- Special characters like
$ and # are replaced with _dollar_ and _hash_
- CamelCase and PascalCase are converted to snake_case by inserting underscores before uppercase letters
- Multiple consecutive underscores are replaced with a single underscore
Examples of key transformations:
| Original Key | Transformed Key |
|---|
teamName | team_name |
API-Key | api_key |
Service.Level | service_level |
$Cost | _dollar_cost |
#Priority | _hash_priority |
Note:
The service_name custom property is handled specially and is not added as a resource attribute with the prefix. Instead, it’s used to set the service.name resource attribute directly, as described in the Configuring Service Name section.
Migration Notes
Semantic Conventions v1.37.0 Upgrade
The GitHub receiver has been updated to use OpenTelemetry semantic conventions v1.37.0. This brings standardization improvements and better alignment with the broader OpenTelemetry ecosystem.
Breaking Changes
Resource Attributes:
organization.name → vcs.owner.name - The resource attribute for organization/owner name has been standardized
vcs.vendor.name → vcs.provider.name - The VCS provider attribute has been standardized
Trace Attributes:
vcs.ref.head.type → vcs.ref.type - Some trace attributes now use standardized naming
What This Means for Users
For Dashboard and Alerting Users:
- Update your queries and dashboards to use the new attribute names
- Old attribute names are no longer emitted starting with this version
- The schema URL in telemetry data now references OpenTelemetry schemas v1.37.0
For Configuration Users:
- No configuration changes are required
- All existing receiver configurations continue to work unchanged
Migration Timeline:
- Before upgrading: Update downstream systems (dashboards, alerts, queries) to use new attribute names
- After upgrading: Verify that telemetry data is flowing correctly with the new attributes
For the complete list of semantic convention changes, see the OpenTelemetry semantic conventions v1.37.0 documentation.
Metrics
| Metric Name | Description | Unit | Type | Attributes |
|---|
✅ vcs.change.count | The number of changes (pull requests) in a repository, categorized by their state (either open or merged). | {change} | Gauge | vcs.repository.url.full, vcs.change.state, vcs.repository.name |
✅ vcs.change.duration | The time duration a change (pull request/merge request/changelist) has been in an open state. | s | Gauge | vcs.repository.url.full, vcs.repository.name, vcs.ref.head.name, vcs.change.state |
✅ vcs.change.time_to_approval | The amount of time it took a change (pull request) to go from open to approved. | s | Gauge | vcs.repository.url.full, vcs.repository.name, vcs.ref.head.name |
✅ vcs.change.time_to_merge | The amount of time it took a change (pull request) to go from open to merged. | s | Gauge | vcs.repository.url.full, vcs.repository.name, vcs.ref.head.name |
❌ vcs.contributor.count | The number of unique contributors to a repository. | {contributor} | Gauge | vcs.repository.url.full, vcs.repository.name |
✅ vcs.ref.count | The number of refs of type branch in a repository. | {ref} | Gauge | vcs.repository.url.full, vcs.repository.name, vcs.ref.type |
✅ vcs.ref.lines_delta | The number of lines added/removed in a ref (branch) relative to the default branch (trunk). | {line} | Gauge | vcs.repository.url.full, vcs.repository.name, vcs.ref.head.name, vcs.ref.head.type, vcs.ref.base.name, vcs.ref.base.type, vcs.line_change.type |
✅ vcs.ref.revisions_delta | The number of revisions (commits) a ref (branch) is ahead/behind the branch from trunk (default). | {revision} | Gauge | vcs.repository.url.full, vcs.repository.name, vcs.ref.head.name, vcs.ref.head.type, vcs.ref.base.name, vcs.ref.base.type, vcs.revision_delta.direction |
✅ vcs.ref.time | Time a ref (branch) created from the default branch (trunk) has existed. The vcs.ref.type attribute will always be branch. | s | Gauge | vcs.repository.url.full, vcs.repository.name, vcs.ref.head.name, vcs.ref.head.type |
✅ vcs.repository.count | The number of repositories in an organization. | {repository} | Gauge | |
Attributes
| Attribute Name | Description | Type | Values |
|---|
vcs.change.state | The state of a change (pull request) | string | open, merged |
vcs.line_change.type | The type of line change being measured on a ref (branch). | string | added, removed |
vcs.ref.base.name | The name of the VCS base reference (branch/tag) for comparison. | string | |
vcs.ref.base.type | The type of the base reference (branch, tag). | string | branch, tag |
vcs.ref.head.name | The name of the VCS head reference (branch). | string | |
vcs.ref.head.type | The type of the head reference (branch, tag). | string | branch, tag |
vcs.ref.type | The type of the reference in the repository. | string | branch, tag |
vcs.repository.name | The name of the VCS repository. | string | |
vcs.repository.url.full | The canonical URL of the repository providing the complete HTTPS address. | string | |
vcs.revision_delta.direction | The type of revision comparison. | string | ahead, behind |
Resource Attributes
| Attribute Name | Description | Type | Enabled |
|---|
vcs.owner.name | The group owner within the version control system | string | ✅ |
vcs.provider.name | The name of the version control system provider | string | ✅ |
Configuration
Example Configuration
receivers:
github:
initial_delay: 1s
collection_interval: 60s
scrapers:
scraper:
webhook:
endpoint: localhost:8080
read_timeout: "500ms"
write_timeout: "500ms"
path: "some/path"
health_path: "health/path"
required_headers:
key: value-present
github/customname:
initial_delay: 1s
collection_interval: 30s
scrapers:
scraper:
webhook:
endpoint: localhost:8080
read_timeout: "500ms"
write_timeout: "500ms"
path: "some/path"
health_path: "health/path"
required_headers:
key: value-present
processors:
nop:
exporters:
nop:
service:
pipelines:
metrics:
receivers: [github, github/customname]
processors: [nop]
exporters: [nop]
traces:
receivers: [github, github/customname]
processors: [nop]
exporters: [nop]
Last generated: 2026-04-20