Get started with Bitbucket Cloud
New to Bitbucket Cloud? Check out our get started guides for new users.
The functionality outlined here is NOT SUPPORTED by the Bitbucket Cloud support team.
The functionalities documented on this page are for customers with highly sophisticated on-premise runner operations who are comfortable with extremely high levels of technical complexity.
This documentation is provided as a reference only.
Usually, build logs from Pipelines executions done on the Pipelines runner are sent to Bitbucket Cloud and can be retrieved via the Bitbucket Cloud API.
However, there may be situations where you want to collect those build logs locally from the machine running the Pipelines runner itself, without having to call the Bitbucket Cloud API.
To do this, you can configure the runner to capture build logs as part of the overall runner system logs, and then ingest them using your log management tool of choice.
Add -e BITBUCKET_PIPELINES_RUNNER_BUILD_LOG_ENABLED=TRUE to the usual runner docker run command
Example
1
2
3
4
5
docker container run \
...
-e BITBUCKET_PIPELINES_RUNNER_BUILD_LOG_ENABLED=TRUE \
...
runner:latest
Set BITBUCKET_PIPELINES_RUNNER_BUILD_LOG_ENABLED environment variable to TRUE, before running the usual runner start.sh script
Example
1
2
3
4
5
6
export BITBUCKET_PIPELINES_RUNNER_BUILD_LOG_ENABLED=TRUE
start.sh
# or
BITBUCKET_PIPELINES_RUNNER_BUILD_LOG_ENABLED=TRUE start.sh
The Pipelines runner supports configuration of logging through the use of a customer provided logger configuration file.
Logback (https://logback.qos.ch) is the logging utility used for logging in the Pipelines runner. To customize your runner logging configuration, you need to do the following:
Prepare an .xml configuration file accessible from the runner. See the corresponding steps below.
Configure the LOGBACK_CONFIGURATION_FILE environment variable for the runner to use that file. See the corresponding steps below.
A local .xml is need. (e.g my-logback-config.xml).
Atlassian have provided a set of pre-made configuration files, including the default configuration, at the bottom of this section.
See Chapter 3: Configuration for syntax guidelines.
Mount the logback config file so that it can be accessed from the runner and pass an environment variable LOGBACK_CONFIGURATION_FILE argument that points to the path of the configuration file to the docker run command.
Example
1
2
3
4
5
6
docker container run \
...
-v /path/on/host/to/custom-logback.xml:/tmp/custom-logback.xml:ro \
-e LOGBACK_CONFIGURATION_FILE=/tmp/custom-logback.xml \
...
runner:latest
Set LOGBACK_CONFIGURATION_FILE environment variable to /path/on/host/to/custom-logback.xml
Example
1
2
3
4
5
6
export LOGBACK_CONFIGURATION_FILE=/path/on/host/to/custom-logback.xml
start.sh
# or
LOGBACK_CONFIGURATION_FILE=/path/on/host/to/custom-logback.xml start.sh
Example of a default logback config file
This is a copy of the default Logback configuration file used in the runner without any changes.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
<configuration>
<define name="BASE_LOG_PATH" class="com.atlassian.pipelines.runner.core.log.BaseLogPathPropertyDefiner"/>
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<filter class="ch.qos.logback.core.filter.EvaluatorFilter">
<evaluator>
<expression>com.atlassian.pipelines.stargate.client.core.exceptions.StargateForbiddenException.class.isInstance(throwable)</expression>
</evaluator>
<onMatch>DENY</onMatch>
</filter>
<encoder>
<!-- print [buildLogName] from SystemLogAppenderFilter if exists, otherwise do not print empty [] -->
<pattern>[%date{ISO8601}]%replace([%X{buildLogName}]){'\[\]',''} %message%n%rootException</pattern>
</encoder>
</appender>
<appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>${BASE_LOG_PATH}/runner.log</file>
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
<fileNamePattern>${BASE_LOG_PATH}/runner.%d.%i.log</fileNamePattern>
<maxHistory>7</maxHistory>
<maxFileSize>100MB</maxFileSize>
<totalSizeCap>1GB</totalSizeCap>
</rollingPolicy>
<encoder>
<!-- print [buildLogName] from SystemLogAppenderFilter if exists, otherwise do not print empty [] -->
<pattern>[%date{ISO8601}]%replace([%X{buildLogName}]){'\[\]',''} %message%n%rootException</pattern>
</encoder>
</appender>
<contextListener class="ch.qos.logback.classic.jul.LevelChangePropagator">
<resetJUL>true</resetJUL>
</contextListener>
<root level="INFO">
<appender-ref ref="STDOUT" />
<appender-ref ref="FILE" />
</root>
<logger name="com.atlassian.pipelines.runner" level="${BITBUCKET_PIPELINES_RUNNER_LOG_LEVEL:-INFO}" />
<logger name="build" level="INFO" />
<logger name="build.service.auth-proxy" level="OFF" />
<logger name="com.netflix" level="OFF" />
<logger name="com.atlassian.pipelines.stargate" level="OFF" />
<logger name="com.github.dockerjava" level="OFF" />
</configuration>
Example of a verbose logging config file
This is a copy of a Logback configuration file setup for verbose logging.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
<configuration>
<define name="BASE_LOG_PATH" class="com.atlassian.pipelines.runner.core.log.BaseLogPathPropertyDefiner"/>
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<filter class="ch.qos.logback.core.filter.EvaluatorFilter">
<evaluator>
<expression>com.atlassian.pipelines.stargate.client.core.exceptions.StargateForbiddenException.class.isInstance(throwable)</expression>
</evaluator>
<onMatch>DENY</onMatch>
</filter>
<encoder>
<!-- print [buildLogName] from SystemLogAppenderFilter if exists, otherwise do not print empty [] -->
<pattern>[%date{ISO8601}]%replace([%X{buildLogName}]){'\[\]',''} %message%n%rootException</pattern>
</encoder>
</appender>
<appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>${BASE_LOG_PATH}/runner.log</file>
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
<fileNamePattern>${BASE_LOG_PATH}/runner.%d.%i.log</fileNamePattern>
<maxHistory>7</maxHistory>
<maxFileSize>100MB</maxFileSize>
<totalSizeCap>1GB</totalSizeCap>
</rollingPolicy>
<encoder>
<!-- print [buildLogName] from SystemLogAppenderFilter if exists, otherwise do not print empty [] -->
<pattern>[%date{ISO8601}]%replace([%X{buildLogName}]){'\[\]',''} %message%n%rootException</pattern>
</encoder>
</appender>
<contextListener class="ch.qos.logback.classic.jul.LevelChangePropagator">
<resetJUL>true</resetJUL>
</contextListener>
<root level="INFO">
<appender-ref ref="STDOUT" />
<appender-ref ref="FILE" />
</root>
<logger name="com.atlassian.pipelines.runner" level="${BITBUCKET_PIPELINES_RUNNER_LOG_LEVEL:-INFO}" />
<logger name="build" level="INFO" />
</configuration>
Example of a JSON logging config file
Output logs as JSON to stdout instead of plain text.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
<configuration>
<define name="BASE_LOG_PATH" class="com.atlassian.pipelines.runner.core.log.BaseLogPathPropertyDefiner"/>
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<filter class="ch.qos.logback.core.filter.EvaluatorFilter">
<evaluator>
<expression>com.atlassian.pipelines.stargate.client.core.exceptions.StargateForbiddenException.class.isInstance(throwable)</expression>
</evaluator>
<onMatch>DENY</onMatch>
</filter>
<encoder class="net.logstash.logback.encoder.LogstashEncoder" />
</appender>
<appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>${BASE_LOG_PATH}/runner.log</file>
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
<fileNamePattern>${BASE_LOG_PATH}/runner.%d.%i.log</fileNamePattern>
<maxHistory>7</maxHistory>
<maxFileSize>100MB</maxFileSize>
<totalSizeCap>1GB</totalSizeCap>
</rollingPolicy>
<encoder>
<!-- print [buildLogName] from SystemLogAppenderFilter if exists, otherwise do not print empty [] -->
<pattern>[%date{ISO8601}]%replace([%X{buildLogName}]){'\[\]',''} %message%n%rootException</pattern>
</encoder>
</appender>
<contextListener class="ch.qos.logback.classic.jul.LevelChangePropagator">
<resetJUL>true</resetJUL>
</contextListener>
<root level="INFO">
<appender-ref ref="STDOUT" />
<appender-ref ref="FILE" />
</root>
<logger name="com.atlassian.pipelines.runner" level="${BITBUCKET_PIPELINES_RUNNER_LOG_LEVEL:-INFO}" />
<logger name="build" level="INFO" />
<logger name="build.service.auth-proxy" level="OFF" />
<logger name="com.netflix" level="OFF" />
<logger name="com.atlassian.pipelines.stargate" level="OFF" />
<logger name="com.github.dockerjava" level="OFF" />
</configuration>
Example of a configured log path config file
Change base log path to /tmp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
<configuration>
<variable name="BASE_LOG_PATH" value="/tmp" />
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<filter class="ch.qos.logback.core.filter.EvaluatorFilter">
<evaluator>
<expression>com.atlassian.pipelines.stargate.client.core.exceptions.StargateForbiddenException.class.isInstance(throwable)</expression>
</evaluator>
<onMatch>DENY</onMatch>
</filter>
<encoder class="net.logstash.logback.encoder.LogstashEncoder" />
</appender>
<appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>${BASE_LOG_PATH}/runner.log</file>
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
<fileNamePattern>${BASE_LOG_PATH}/runner.%d.%i.log</fileNamePattern>
<maxHistory>7</maxHistory>
<maxFileSize>100MB</maxFileSize>
<totalSizeCap>1GB</totalSizeCap>
</rollingPolicy>
<encoder>
<!-- print [buildLogName] from SystemLogAppenderFilter if exists, otherwise do not print empty [] -->
<pattern>[%date{ISO8601}]%replace([%X{buildLogName}]){'\[\]',''} %message%n%rootException</pattern>
</encoder>
</appender>
<contextListener class="ch.qos.logback.classic.jul.LevelChangePropagator">
<resetJUL>true</resetJUL>
</contextListener>
<root level="INFO">
<appender-ref ref="STDOUT" />
<appender-ref ref="FILE" />
</root>
<logger name="com.atlassian.pipelines.runner" level="${BITBUCKET_PIPELINES_RUNNER_LOG_LEVEL:-INFO}" />
<logger name="build" level="INFO" />
<logger name="build.service.auth-proxy" level="OFF" />
<logger name="com.netflix" level="OFF" />
<logger name="com.atlassian.pipelines.stargate" level="OFF" />
<logger name="com.github.dockerjava" level="OFF" />
</configuration>
Was this helpful?