TL;DR;
If you’re using GitHub, you’re probably familiar with GitHub Actions — a simple and clean CI/CD that helps to build automation around your code repositories. In this blog post, I’ll guide you through how to sync your GitHub Actions workflow logs into Elasticsearch.
Once you become a GitHub Actions user, you’ll probably want to add some monitoring and reporting to your CI/CD. You may want some statistics on the average time of a specific workflow, or how many of your jobs are being failed over time.
The first step to achieve your goal is to stream your logs into central log storage. At anecdotes.ai, our logs are streamed to Elasticsearch, so it was intuitive to stream the logs produced by the CI/CD workflows to Elasticsearch too.
However, I was surprised to find out that there isn’t a way to do it. You can manually download specific workflow logs and upload them yourself, but of course, that’s not something we want to do.
So I took the opportunity to develop a GitHub Action that will do it for you. There were several obstacles in developing the action, but I’ll cover them in another more technical blog post.
In this blog post, I’ll focus on how to use the GitHub Action to easily stream your workflow logs to Elastic.
To make this even easier to understand, let’s review some code. For the purposes of this post, I’ve created a python-demo repository with an example workflow, which just triggers the app entrypoint.
Notice that the repository is private, since we use sensitive information such as the Elasticsearch credentials (which, of course, are protected in GitHub Secrets).
main.py
def main():
# echo output
for i in range(100):
print("XXX" * i)
print(i)
print ("XXX" * i)
if __name__ == '__main__':
main()
name: Example workflow
on:
workflow_dispatch
jobs:
run-demo-app:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v2
with:
submodules: 'recursive'
token: ${{ secrets.GITHUB }}
- name: Set up Python 3.7.8
uses: actions/setup-python@v2
with:
python-version: '3.7.8'
- name: Run script that echo outputs
run: python main.py
Triggering the workflow will produce the following logs:
example workflow runs
And our final goal is to stream them to Elastic.
The first (and only) thing you’ll need to change in your code is to add a new job that collects your workflow logs to Elastic.
Add this step to each of your workflows:
upload-logs-to-elastic:
runs-on: ubuntu-latest
needs: run-demo-app
if: always()
steps:
- name: Upload GitHub Action workflows logs to elastic
uses: shahargl/upload-github-workflow-logs-to-elastic@1.0.13
with:
github_token: "${{ secrets.GITHUB }}"
github_org: "shahargl"
github_repository: "python-demo"
github_run_id: "${{ github.run_id }}"
elastic_host: "${{ secrets.ELASTIC_HOST }}"
elastic_api_key_id: "${{ secrets.ELASTIC_KEY_ID }}"
elastic_api_key: "${{ secrets.ELASTIC_API_KEY }}"
elastic_index: "ci-cd"
Where:
GitHub has pretty good documentation on how to generate GitHub PAT. The permission that you’ll need is “workflow” so you’ll be able to read the workflow logs.
Then, copy the token and add it as a secret.
To get an elastic API key, just login into Kibana and go to “Dev Tools”:
Now create an API key:
POST /_security/api_key
{
"name": "api-key-for-github",
"expiration": "1d" # notice it's api key for one day, after you sure everything works for you, generate a new api key with longer expiration
}
The response should be something like:
{
"id" : "4NtdXXXXXXXXXXXXXX",
"name" : "api-key-for-github",
"expiration" : 1618909336568,
"api_key" : "BAs-XXXXXXXXXXXXXXXXXXXXXXXXXXXX"
}
Now, store the value of “id” and “api_key” in the GitHub secrets store.
Your repository secrets should look like this:
Now to the interesting part, let’s run the workflow. Go to your repository actions and run your workflow with the upload-logs-to-elastic step:
We can see that the demo app created the following logs:
Now let’s finally review them on Elastic!
The first thing we need to do (after login into your Kibana) is to create an index pattern for the ci-cd index.
Go to Elastic -> Stack Management -> Kibana -> Index Patterns:
And then “Create index pattern”:
In the index pattern name, just write the prefix you choose (“ci-cd”) and then just click “next”. For the “Time field”, choose “@timestamp”:
Finally, click “Create index pattern” and go again to Kibana to review the logs:
And there you have it! If you've been following along, you should have successfully integrated GitHub Action logs into your Elasticsearch. This should allow you to easily and quickly stream logs produced by GitHub Actions workflows to Elasticsearch and use it for monitoring, alerting, and continuous improvement.