use of org.killbill.billing.plugin.analytics.api.core.AnalyticsConfiguration in project killbill-analytics-plugin by killbill.
the class ReportsUserApi method getDataForReport.
public List<Chart> getDataForReport(final Iterable<String> rawReportNames, @Nullable final DateTime startDate, @Nullable final DateTime endDate, @Nullable final SmootherType smootherType, final TenantContext context) {
final Long tenantRecordId = getTenantRecordId(context);
final List<Chart> result = new LinkedList<Chart>();
final Map<String, Map<String, List<XY>>> timeSeriesData = new ConcurrentHashMap<String, Map<String, List<XY>>>();
// Parse the reports
final List<ReportSpecification> reportSpecifications = new ArrayList<ReportSpecification>();
for (final String rawReportName : rawReportNames) {
reportSpecifications.add(new ReportSpecification(rawReportName));
}
// Fetch the latest reports configurations
final Map<String, ReportsConfigurationModelDao> reportsConfigurations = reportsConfiguration.getAllReportConfigurations(tenantRecordId);
final AnalyticsConfiguration analyticsConfiguration = analyticsConfigurationHandler.getConfigurable(context.getTenantId());
final List<Future> jobs = new LinkedList<Future>();
for (final ReportSpecification reportSpecification : reportSpecifications) {
final String reportName = reportSpecification.getReportName();
final ReportsConfigurationModelDao reportConfiguration = getReportConfiguration(reportName, reportsConfigurations);
final String tableName = reportConfiguration.getSourceTableName();
final String prettyName = reportConfiguration.getReportPrettyName();
final ReportType reportType = reportConfiguration.getReportType();
jobs.add(dbiThreadsExecutor.submit(new Runnable() {
@Override
public void run() {
switch(reportType) {
case COUNTERS:
final List<DataMarker> counters = queryEngine.getCountersData(reportConfiguration, reportSpecification, dbEngine, startDate, endDate, analyticsConfiguration, tenantRecordId);
result.add(new Chart(ReportType.COUNTERS, prettyName, counters));
break;
case TIMELINE:
final Map<String, List<XY>> data = queryEngine.getTimeSeriesData(reportConfiguration, reportSpecification, dbEngine, startDate, endDate, tenantRecordId, analyticsConfiguration);
timeSeriesData.put(reportName, data);
break;
case TABLE:
final List<DataMarker> tables = queryEngine.getTablesData(reportConfiguration, reportSpecification, dbEngine, startDate, endDate, analyticsConfiguration, tenantRecordId);
result.add(new Chart(ReportType.TABLE, prettyName, tables));
break;
default:
throw new RuntimeException("Unknown reportType " + reportType);
}
}
}));
}
waitForJobCompletion(jobs);
//
if (!timeSeriesData.isEmpty()) {
normalizeAndSortXValues(timeSeriesData, startDate, endDate);
if (smootherType != null) {
final Smoother smoother = smootherType.createSmoother(timeSeriesData);
smoother.smooth();
result.addAll(buildNamedXYTimeSeries(smoother.getDataForReports(), reportsConfigurations));
} else {
result.addAll(buildNamedXYTimeSeries(timeSeriesData, reportsConfigurations));
}
}
return result;
}
use of org.killbill.billing.plugin.analytics.api.core.AnalyticsConfiguration in project killbill-analytics-plugin by killbill.
the class ReportsUserApi method getSQLForReport.
// Useful for testing
public List<String> getSQLForReport(final Iterable<String> rawReportNames, @Nullable final DateTime startDate, @Nullable final DateTime endDate, final TenantContext context) {
final AnalyticsConfiguration analyticsConfiguration = analyticsConfigurationHandler.getConfigurable(context.getTenantId());
final Long tenantRecordId = getTenantRecordId(context);
final List<String> sqlQueries = new LinkedList<String>();
for (final String rawReportName : rawReportNames) {
final ReportSpecification reportSpecification = new ReportSpecification(rawReportName);
final ReportsConfigurationModelDao reportConfigurationForReport = reportsConfiguration.getReportConfigurationForReport(reportSpecification.getReportName(), tenantRecordId);
if (reportConfigurationForReport != null) {
if (reportConfigurationForReport.getSourceTableName() != null) {
final SqlReportDataExtractor sqlReportDataExtractor = new SqlReportDataExtractor(reportConfigurationForReport.getSourceTableName(), reportSpecification, startDate, endDate, dbEngine, tenantRecordId);
sqlQueries.add(sqlReportDataExtractor.toString());
} else {
final SqlReportDataExtractor sqlReportDataExtractor = new SqlReportDataExtractor(reportConfigurationForReport.getSourceQuery(), reportSpecification, startDate, endDate, analyticsConfiguration, dbEngine, tenantRecordId);
sqlQueries.add(sqlReportDataExtractor.toString());
}
}
}
return sqlQueries;
}
use of org.killbill.billing.plugin.analytics.api.core.AnalyticsConfiguration in project killbill-analytics-plugin by killbill.
the class TestAnalyticsListener method testIgnoredGroups.
@Test(groups = "fast")
public void testIgnoredGroups() throws Exception {
final ExtBusEvent cfEvent = Mockito.mock(ExtBusEvent.class);
Mockito.when(cfEvent.getEventType()).thenReturn(ExtBusEventType.CUSTOM_FIELD_CREATION);
final ExtBusEvent accountEvent = Mockito.mock(ExtBusEvent.class);
Mockito.when(accountEvent.getEventType()).thenReturn(ExtBusEventType.ACCOUNT_CREATION);
final AnalyticsConfigurationHandler analyticsConfigurationHandler = new AnalyticsConfigurationHandler(null, AnalyticsActivator.PLUGIN_NAME, killbillAPI);
final AnalyticsConfiguration defaultConfigurable = new AnalyticsConfiguration();
defaultConfigurable.ignoredGroups.add("FIELDS");
analyticsConfigurationHandler.setDefaultConfigurable(defaultConfigurable);
final AnalyticsListener analyticsListener = new AnalyticsListener(killbillAPI, killbillDataSource, osgiConfigPropertiesService, null, locker, clock, analyticsConfigurationHandler, notificationQueueService);
Assert.assertTrue(analyticsListener.shouldIgnoreEvent(AnalyticsJobHierarchy.fromEventType(cfEvent.getEventType()), analyticsConfigurationHandler.getConfigurable(callContext.getTenantId())));
Assert.assertFalse(analyticsListener.shouldIgnoreEvent(AnalyticsJobHierarchy.fromEventType(accountEvent.getEventType()), analyticsConfigurationHandler.getConfigurable(callContext.getTenantId())));
}
use of org.killbill.billing.plugin.analytics.api.core.AnalyticsConfiguration in project killbill-analytics-plugin by killbill.
the class AnalyticsActivator method start.
@Override
public void start(final BundleContext context) throws Exception {
super.start(context);
killbillClock = clock.getClock();
final Executor executor = BusinessExecutor.newCachedThreadPool(configProperties);
final NotificationQueueConfig config = new ConfigurationObjectFactory(configProperties.getProperties()).buildWithReplacements(NotificationQueueConfig.class, ImmutableMap.<String, String>of("instanceName", "analytics"));
if ("notifications".equals(config.getTableName())) {
logger.warn("Analytics plugin mis-configured: you are probably missing the property org.killbill.notificationq.analytics.tableName=analytics_notifications");
}
if ("notifications_history".equals(config.getHistoryTableName())) {
logger.warn("Analytics plugin mis-configured: you are probably missing the property org.killbill.notificationq.analytics.historyTableName=analytics_notifications_history");
}
final DBI dbi = BusinessDBIProvider.get(dataSource.getDataSource());
dbi.registerMapper(new LowerToCamelBeanMapperFactory(BusEventModelDao.class));
dbi.registerMapper(new LowerToCamelBeanMapperFactory(NotificationEventModelDao.class));
final DefaultNotificationQueueService notificationQueueService = new DefaultNotificationQueueService(dbi, killbillClock, config, metricRegistry);
final String region = PluginEnvironmentConfig.getRegion(configProperties.getProperties());
analyticsConfigurationHandler = new AnalyticsConfigurationHandler(region, PLUGIN_NAME, roOSGIkillbillAPI);
analyticsConfigurationHandler.setDefaultConfigurable(new AnalyticsConfiguration());
// Timeout defines how long to sleep between retries to get the lock
final long lockSleepMilliSeconds = Long.parseLong(configProperties.getProperties().getProperty("org.killbill.analytics.lockSleepMilliSeconds", "100"));
final DBEngine dbEngine = PluginDao.getDBEngine(dataSource.getDataSource());
final GlobalLocker locker;
switch(dbEngine) {
case MYSQL:
locker = new MySqlGlobalLocker(dataSource.getDataSource(), lockSleepMilliSeconds, TimeUnit.MILLISECONDS);
break;
case POSTGRESQL:
locker = new PostgreSQLGlobalLocker(dataSource.getDataSource(), lockSleepMilliSeconds, TimeUnit.MILLISECONDS);
break;
case GENERIC:
case H2:
default:
locker = new MemoryGlobalLocker();
break;
}
analyticsListener = new AnalyticsListener(roOSGIkillbillAPI, dataSource, configProperties, executor, locker, killbillClock, analyticsConfigurationHandler, notificationQueueService);
jobsScheduler = new JobsScheduler(dataSource, killbillClock, notificationQueueService);
final ReportsConfiguration reportsConfiguration = new ReportsConfiguration(dataSource, jobsScheduler);
final AnalyticsUserApi analyticsUserApi = new AnalyticsUserApi(roOSGIkillbillAPI, dataSource, configProperties, executor, killbillClock, analyticsConfigurationHandler, analyticsListener);
reportsUserApi = new ReportsUserApi(roOSGIkillbillAPI, dataSource, configProperties, dbEngine, reportsConfiguration, jobsScheduler, analyticsConfigurationHandler);
final AnalyticsHealthcheck healthcheck = new AnalyticsHealthcheck(analyticsListener, jobsScheduler);
registerHealthcheck(context, healthcheck);
final ObjectMapper objectMapper = new ObjectMapper();
objectMapper.registerModule(new JodaModule());
objectMapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
objectMapper.enable(DeserializationFeature.READ_UNKNOWN_ENUM_VALUES_AS_NULL);
final PluginApp pluginApp = new PluginAppBuilder(PLUGIN_NAME, killbillAPI, dataSource, clock, configProperties).withRouteClass(AnalyticsHealthcheckResource.class).withRouteClass(ReportsResource.class).withRouteClass(// Needs to be last (to avoid matching /healthcheck or /reports)!
AnalyticsAccountResource.class).withService(analyticsUserApi).withService(reportsUserApi).withService(clock).withService(healthcheck).withObjectMapper(objectMapper).build();
final HttpServlet httpServlet = PluginApp.createServlet(pluginApp);
registerServlet(context, httpServlet);
registerHandlers();
}
use of org.killbill.billing.plugin.analytics.api.core.AnalyticsConfiguration in project killbill-analytics-plugin by killbill.
the class AnalyticsListener method handleAnalyticsJob.
private void handleAnalyticsJob(final AnalyticsJob job) throws AnalyticsRefreshException {
final AnalyticsConfiguration analyticsConfiguration = analyticsConfigurationHandler.getConfigurable(job.getTenantId());
if (!locker.isFree(ANALYTICS_REFRESH_LOCK_NAME, job.getAccountId().toString())) {
final Integer delaySec = analyticsConfiguration.rescheduleIntervalOnLockSeconds;
if (delaySec > 0) {
final DateTime nextRescheduleDt = clock.getUTCNow().plusSeconds(delaySec);
if (scheduleAnalyticsJob(job, analyticsConfiguration)) {
logger.info("Lock is busy for account {}, rescheduling job at time {}", job.getAccountId(), nextRescheduleDt);
return;
}
}
}
GlobalLock lock = null;
try {
lock = locker.lockWithNumberOfTries(ANALYTICS_REFRESH_LOCK_NAME, job.getAccountId().toString(), analyticsConfiguration.lockAttemptRetries);
handleAnalyticsJobWithLock(job);
} catch (final LockFailedException e) {
throw new RuntimeException(e);
} finally {
if (lock != null) {
lock.release();
}
}
}
Aggregations