Plugin Development FAQ
How to use logging
The TeamCity code uses the Log4j logging library with a centralized configuration on the server and agent. Logging is usually done via a utility wrapper
com.intellij.openapi.diagnostic.Logger rather than the default Log4j classes. You can use the
jetbrains.buildServer.log.Loggers class to get instances of the Loggers, e.g. use
jetbrains.buildServer.log.Loggers.SERVER to add a message to the
For plugin-specific logging, it is recommended to log into a log category matching the full name of your class. This is usually achieved by defining the logger field in a class as
private static Logger LOG = Logger.getInstance(YourClass.class.getName());.
If your plugin source code is located under the
jetbrains.buildServer package, the logging will automatically go into
If you use another package, you might need to add a corresponding category handling into the
conf/teamcity-server-log4j.xml file (mentioned at TeamCity Server Logs or the corresponding agent file).
For debugging you might consider creating a customized Log4j configuration file and put it as a logging preset into
<TeamCity Data Directory>\config\logging directory. This way one will be able to activate the preset via the Administration | Diagnostics page, Troubleshooting tab.
How to adapt plugin for secondary node
TeamCity administrators can set up secondary nodes to work alongside the main TeamCity server. Such nodes provide a read-only user interface to ensure high availability when the main node is unavailable. Optionally, they can be assigned to certain responsibilities and perform writing operations.
Not all custom plugins can run on a secondary node. Here is the expected configuration:
teamcity-plugin.xmlfile must have the following attribute:
A plugin should use
jetbrains.buildServer.serverSide.IOGuardto wrap network and I/O operations which do not change the state of the external systems.
A secondary node runs under the Security Manager and often does not have permissions to change anything outside it. For instance, if it runs as read-only, all I/O operations – even reading – will be prohibited by default. To allow reading operations, wrap them with IOGuard in the plugin code.
If a plugin only shows information in the UI, these measures should be sufficient and will allow loading it on a secondary node. With these settings, the plugin will also work fine on the main node.
If a plugin needs to perform any actions, it should check the context of its assigned responsibilities. This API is still in progress – see TW-58322 for details.