Last updatedMar 5, 2020

Rate this page:

Auditing your events

Bitbucket Server includes auditing functionality allowing events to be audited. Audited events are recorded in a log file and persisted in the database (which are then viewable via the audit UI). Plugins are also able to add audit events.

Bitbucket Server 7.0 onward

The following section explains how to use the @Auditable API to add audit events to the system. This API was added in Bitbucket Server 7.0 and should be used for all auditing going forwards. It is recommended to update any usages of the legacy @Audited to use @Auditable instead for better control over how your events are audited.

How to add your events to the audit feature

Adding audit events to the application involves annotating an object with @Auditable (typically a class extends ApplicationEvent), then publishing this object using the event framework.

The following arguments are required on the @Auditable annotation:

  • category: a free String field representing the category of the event, used for searching (Bitbucket Server provides some categories which can be used in the AuditCategory class)
  • converter: a class implementing AuditEventConverter, which is invoked by the system during audit processing to convert the annotated object into an AuditEvent
  • coverageLevel: the CoverageLevel that the event should be audited at (this is an enum, so select the most appropriate level)

Event with annotation:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
@Auditable(
        category = AuditCategory.REPOSITORIES,
        converter = MyConverter.class,
        coverageLevel = CoverageLevel.BASE)
class MyEvent extends ApplicationEvent {
    private final String data;
    private final Repository repository;
    
    public MyEvent(Object source, String data, Repository repository) {
        super(source);

        this.data = data;
        this.repository = repository;
    }

    public String getData() {
        return data;
    }

    public Repository getRepository() {
        return repository;
    }
}

Converter:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
public class MyConverter implements AuditEventConverter<MyEvent> {
    @Nonnull
    @Override
    public AuditEvent convert(@Nonnull MyEvent event,
                              @Nonnull AuditEvent.Builder builder) {
          return builder
              //AuditUtils contains helper methods for adding affected objects for Bitbucket Server entities like projects and repositories
              //Other affected objects can be added by creating an AuditResource directly
              .affectedObjects(AuditUtils.auditResourcesForProjectAndRepository(event.getRepository()))
              //Extra attributes can be added via the extraAttributes builder method and creating an AuditAttribute
              .extraAttributes(new AuditAttribute("my-key", event.getData()))
              .build();
    }
}

Usage:

1
eventPublisher.publish(new MyEvent(this));

Additional information about using @Auditable:

  • Many of the audit event fields are set automatically by the system (e.g. author, timestamp, source, node)
  • The action field of the AuditEvent defaults to the event class but this can be overridden in the converter
  • If migrating an event that used to use the @Audited annotation, see the API changelog for how the old AuditEntry model and the new AuditEvent/AuditEntity models relate

Choosing a coverage level

CoverageLevel is an enum field which represents the level that the event should be logged at. A system administrator has the ability to configure all plugin events to a specific CoverageLevel (or OFF). For example, a system administrator could set the CoverageLevel for plugins events to BASE, which would mean all ADVANCED and FULL plugin events would not be not audited.

Note that a Data Center license is required for using ADVANCED and FULL events. If you want your event to be audited on an instance with a Server license, it must be a BASE event.

Choosing a category

The category specified in the @Auditable annotation is a free String field that is used in the auditing UI for searching and grouping events. Bitbucket Server categories are available via the AuditCategory class and it is recommended to use one of these categories where appropriate (e.g. AuditCategory.REPOSITORIES if your event if repository related). However it is also possible to specify your own category, which is useful if your plugin doesn't relate to any of the categories provided by Bitbucket Server.

Prior to Bitbucket Server 7.0

The following section explains how to use the legacy @Audited API to add audit events to the system. This API was deprecated in 7.0. It is recommended to use the new @Auditable API instead for better control over how your event is audited.

How to add your events to the audit feature

Adding audit events to the application involves annotating an object with @Audited (typically a class extends ApplicationEvent), then publishing this object using the event framework.

Event with annotation:

1
2
3
4
5
6
7
8
9
10
11
12
@Audited(converter=MyConverter.class, channels={Channels.REPOSITORY_UI}, priority = Priority.HIGH)
class MyEvent extends ApplicationEvent {
    private final Repository repository;

    public MyEvent(Object source, Repository repository) {
        super(source);
    }

    public Repository getRepository() {
        return repository;
    }
}

Converter:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
public class MyConverter implements AuditEntryConverter<MyEvent> {
    @Nonnull
    @Override
    public AuditEntry convert(@Nonnull MyEvent event,
                              @Nonnull AuditEntryBuilder builder) {
          return builder
              .action(event.getClass())
              .timestamp(new Date())
              .details(getDetails(event))
              .user(event.getUser())
              .repository(event.getRepository())
              .build();
    }
}

Usage:

1
eventPublisher.publish(new MyEvent(this));

Additional information about using @Audited:

  • Adding a repository or project: If you are specifying that the event should be displayed in the project or repository UI you must tell the auditing system which project or repository by adding them in the builder. Note that from Bitbucket Server 7.0 onward, all events are persisted (and viewable in the UI).
  • Event details: the events added to the audit system by Bitbucket Server use a JSON format in their details strings for consistency although it is not required.
  • Data: all the required information must be available in the event for use in the converter.

Choosing a priority

The priority of your event should reflect the event's importance to users. HIGH priority events will be logged by default so they should be of interest to all Bitbucket Server administrators. Generally speaking events occurring due to normal development workflow are considered LOW or MEDIUM priority events. Events which alter the server's configuration or allow users greater privileges are considered HIGH priority.

Note that Priority was deprecated in Bitbucket Server 7.0, and the priority specified via an @Audited annotation will be ignored. Switch to use @Auditable and supply a CoverageLevel instead.

Add it to the UI?

Adding an event to the project or repository audit tab incurs a cost to the system (storing the data in the database). Events which are added to the UI should not be fired frequently. Events in the UI should be those which an administrator would want quick access to. Most events are intended for general auditing and so are just available to system administrators via the log file.

Note that from Bitbucket Server 7.0 onward, all audit events are persisted regardless of Channels (or lack thereof). Giving your event the best CoverageLevel (via @Auditable) will assist in making sure it is only shown in the UI where appropriate.

Common mistakes

  • Using the deprecated @Audited API. The system internally converts legacy AuditEntrys supplied by an AuditEntryConverter to the new AuditEvent/AuditEntity model via a best effort conversion, but this is not perfect. Audit events supplied in this way will have a default fallback CoverageLevel set for example. For full control over how your events are audited in Bitbucket Server 7.0 and onward, it is recommended to switch to the new @Auditable API (using an AuditEventConverter).
  • Publishing audited events too often. There is a system overhead for processing auditing events. While effort is made to process events as efficiently as possible (e.g. taking processing off the event thread, processing in batches, and other optimizations), excessive publishing of audited actions could slow the system down or cause audit events to be dropped.
  • Subclassing Bitbucket Server events. Although it is possible to subclass Bitbucket Server events it is discouraged as it may have unintended effects. The event system will pass a subclass to the internal auditing handlers which are expecting the parent class. Annotating a subclassed Bitbucket Server event for auditing is likely to result in the event being audited twice.

Rate this page: