/* * (C) Copyright 2015 Nuxeo SA (http://nuxeo.com/) and others. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * Contributors: * Antoine Taillefer <ataillefer@nuxeo.com> */ package org.nuxeo.elasticsearch.audit; import java.util.Calendar; import java.util.Collections; import java.util.List; import java.util.TimeZone; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.nuxeo.ecm.core.api.security.SecurityConstants; import org.nuxeo.ecm.core.work.AbstractWork; import org.nuxeo.ecm.platform.audit.api.AuditLogger; import org.nuxeo.ecm.platform.audit.api.LogEntry; import org.nuxeo.ecm.platform.audit.service.AuditBackend; import org.nuxeo.ecm.platform.audit.service.NXAuditEventsService; import org.nuxeo.ecm.platform.audit.service.extension.AuditBackendDescriptor; import org.nuxeo.runtime.api.Framework; import org.nuxeo.runtime.transaction.TransactionHelper; /** * Work for the SQL to Elasticsearch audit migration. * * @since 7.10 */ public class ESAuditMigrationWork extends AbstractWork { private static final long serialVersionUID = 3764830939638449534L; private static final Log log = LogFactory.getLog(ESAuditMigrationWork.class); protected int batchSize; public ESAuditMigrationWork(String id, int batchSize) { super(id); this.batchSize = batchSize; } @Override public String getTitle() { return "Audit migration worker"; } @Override public void work() { NXAuditEventsService auditService = (NXAuditEventsService) Framework.getRuntime().getComponent( NXAuditEventsService.NAME); AuditBackendDescriptor config = new AuditBackendDescriptor(); AuditBackend sourceBackend = config.newInstance(auditService); sourceBackend.onApplicationStarted(); try { @SuppressWarnings("unchecked") List<Long> res = (List<Long>) sourceBackend.nativeQuery("select count(*) from LogEntry", 1, 20); long nbEntriesToMigrate = res.get(0); AuditLogger destBackend = auditService.getBackend(); TransactionHelper.commitOrRollbackTransaction(); long t0 = System.currentTimeMillis(); long nbEntriesMigrated = 0; int pageIdx = 1; while (nbEntriesMigrated < nbEntriesToMigrate) { @SuppressWarnings("unchecked") List<LogEntry> entries = (List<LogEntry>) sourceBackend.nativeQuery( "from LogEntry log order by log.id asc", pageIdx, batchSize); if (entries.size() == 0) { log.warn("Migration ending after " + nbEntriesMigrated + " entries"); break; } setProgress(new Progress(nbEntriesMigrated, nbEntriesToMigrate)); destBackend.addLogEntries(entries); pageIdx++; nbEntriesMigrated += entries.size(); log.info("Migrated " + nbEntriesMigrated + " log entries on " + nbEntriesToMigrate); double dt = (System.currentTimeMillis() - t0) / 1000.0; if (dt != 0) { log.info("Migration speed: " + (nbEntriesMigrated / dt) + " entries/s"); } } log.info("Audit migration from SQL to Elasticsearch done: " + nbEntriesMigrated + " entries migrated"); // Log technical event in audit as a flag to know if the migration has been processed at application // startup AuditLogger logger = Framework.getService(AuditLogger.class); LogEntry entry = logger.newLogEntry(); entry.setCategory("NuxeoTechnicalEvent"); entry.setEventId(ESAuditBackend.MIGRATION_DONE_EVENT); entry.setPrincipalName(SecurityConstants.SYSTEM_USERNAME); entry.setEventDate(Calendar.getInstance(TimeZone.getTimeZone("UTC")).getTime()); destBackend.addLogEntries(Collections.singletonList(entry)); } finally { sourceBackend.onApplicationStopped(); } } }