Search in sources :

Example 1 with AnalyticsConfiguration

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;
}
Also used : AnalyticsConfiguration(org.killbill.billing.plugin.analytics.api.core.AnalyticsConfiguration) XY(org.killbill.billing.plugin.analytics.json.XY) DataMarker(org.killbill.billing.plugin.analytics.json.DataMarker) ArrayList(java.util.ArrayList) ArrayList(java.util.ArrayList) LinkedList(java.util.LinkedList) List(java.util.List) ConcurrentHashMap(java.util.concurrent.ConcurrentHashMap) Chart(org.killbill.billing.plugin.analytics.json.Chart) ReportType(org.killbill.billing.plugin.analytics.reports.configuration.ReportsConfigurationModelDao.ReportType) ReportsConfigurationModelDao(org.killbill.billing.plugin.analytics.reports.configuration.ReportsConfigurationModelDao) LinkedList(java.util.LinkedList) Future(java.util.concurrent.Future) Map(java.util.Map) ConcurrentHashMap(java.util.concurrent.ConcurrentHashMap) Smoother(org.killbill.billing.plugin.analytics.reports.analysis.Smoother)

Example 2 with AnalyticsConfiguration

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;
}
Also used : AnalyticsConfiguration(org.killbill.billing.plugin.analytics.api.core.AnalyticsConfiguration) ReportsConfigurationModelDao(org.killbill.billing.plugin.analytics.reports.configuration.ReportsConfigurationModelDao) LinkedList(java.util.LinkedList)

Example 3 with AnalyticsConfiguration

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())));
}
Also used : AnalyticsConfiguration(org.killbill.billing.plugin.analytics.api.core.AnalyticsConfiguration) ExtBusEvent(org.killbill.billing.notification.plugin.api.ExtBusEvent) AnalyticsConfigurationHandler(org.killbill.billing.plugin.analytics.api.core.AnalyticsConfigurationHandler) Test(org.testng.annotations.Test)

Example 4 with AnalyticsConfiguration

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();
}
Also used : AnalyticsConfiguration(org.killbill.billing.plugin.analytics.api.core.AnalyticsConfiguration) AnalyticsConfigurationHandler(org.killbill.billing.plugin.analytics.api.core.AnalyticsConfigurationHandler) GlobalLocker(org.killbill.commons.locker.GlobalLocker) MemoryGlobalLocker(org.killbill.commons.locker.memory.MemoryGlobalLocker) MySqlGlobalLocker(org.killbill.commons.locker.mysql.MySqlGlobalLocker) PostgreSQLGlobalLocker(org.killbill.commons.locker.postgresql.PostgreSQLGlobalLocker) DBEngine(org.killbill.billing.plugin.dao.PluginDao.DBEngine) ReportsResource(org.killbill.billing.plugin.analytics.http.ReportsResource) ReportsConfiguration(org.killbill.billing.plugin.analytics.reports.ReportsConfiguration) DBI(org.skife.jdbi.v2.DBI) MySqlGlobalLocker(org.killbill.commons.locker.mysql.MySqlGlobalLocker) MemoryGlobalLocker(org.killbill.commons.locker.memory.MemoryGlobalLocker) Executor(java.util.concurrent.Executor) BusEventModelDao(org.killbill.bus.dao.BusEventModelDao) AnalyticsHealthcheck(org.killbill.billing.plugin.analytics.core.AnalyticsHealthcheck) PluginApp(org.killbill.billing.plugin.core.resources.jooby.PluginApp) PostgreSQLGlobalLocker(org.killbill.commons.locker.postgresql.PostgreSQLGlobalLocker) DefaultNotificationQueueService(org.killbill.notificationq.DefaultNotificationQueueService) ReportsUserApi(org.killbill.billing.plugin.analytics.reports.ReportsUserApi) ObjectMapper(com.fasterxml.jackson.databind.ObjectMapper) PluginAppBuilder(org.killbill.billing.plugin.core.resources.jooby.PluginAppBuilder) AnalyticsUserApi(org.killbill.billing.plugin.analytics.api.user.AnalyticsUserApi) HttpServlet(javax.servlet.http.HttpServlet) JodaModule(com.fasterxml.jackson.datatype.joda.JodaModule) ConfigurationObjectFactory(org.skife.config.ConfigurationObjectFactory) JobsScheduler(org.killbill.billing.plugin.analytics.reports.scheduler.JobsScheduler) NotificationQueueConfig(org.killbill.notificationq.api.NotificationQueueConfig) LowerToCamelBeanMapperFactory(org.killbill.commons.jdbi.mapper.LowerToCamelBeanMapperFactory) NotificationEventModelDao(org.killbill.notificationq.dao.NotificationEventModelDao)

Example 5 with AnalyticsConfiguration

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();
        }
    }
}
Also used : AnalyticsConfiguration(org.killbill.billing.plugin.analytics.api.core.AnalyticsConfiguration) GlobalLock(org.killbill.commons.locker.GlobalLock) LockFailedException(org.killbill.commons.locker.LockFailedException) DateTime(org.joda.time.DateTime)

Aggregations

AnalyticsConfiguration (org.killbill.billing.plugin.analytics.api.core.AnalyticsConfiguration)9 AnalyticsConfigurationHandler (org.killbill.billing.plugin.analytics.api.core.AnalyticsConfigurationHandler)3 LinkedList (java.util.LinkedList)2 DateTime (org.joda.time.DateTime)2 Invoice (org.killbill.billing.invoice.api.Invoice)2 ReportsConfigurationModelDao (org.killbill.billing.plugin.analytics.reports.configuration.ReportsConfigurationModelDao)2 TenantContext (org.killbill.billing.util.callcontext.TenantContext)2 ObjectMapper (com.fasterxml.jackson.databind.ObjectMapper)1 JodaModule (com.fasterxml.jackson.datatype.joda.JodaModule)1 BigDecimal (java.math.BigDecimal)1 ArrayList (java.util.ArrayList)1 Date (java.util.Date)1 List (java.util.List)1 Map (java.util.Map)1 Properties (java.util.Properties)1 UUID (java.util.UUID)1 ConcurrentHashMap (java.util.concurrent.ConcurrentHashMap)1 Executor (java.util.concurrent.Executor)1 Future (java.util.concurrent.Future)1 HttpServlet (javax.servlet.http.HttpServlet)1