Skip to content

Commit

Permalink
feat: Scheduled removal of unused user Qlik Sense license
Browse files Browse the repository at this point in the history
Implements #1042
  • Loading branch information
Göran Sander committed Apr 8, 2024
1 parent 1e769dd commit bac1258
Show file tree
Hide file tree
Showing 5 changed files with 438 additions and 111 deletions.
2 changes: 1 addition & 1 deletion src/butler.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ const start = async () => {
globals.logger.verbose(`START: Globals init done: ${globals.initialised}`);

const setupServiceMonitorTimer = (await import('./lib/service_monitor.js')).default;
const { setupQlikSenseLicenseMonitor, setupQlikSenseLicenseRelease } = await import('./lib/qliksense_license_monitor.js');
const { setupQlikSenseLicenseMonitor, setupQlikSenseLicenseRelease } = await import('./lib/qliksense_license.js');

// The build function creates a new instance of the App class and returns it.
const build = (await import('./app.js')).default;
Expand Down
30 changes: 27 additions & 3 deletions src/config/production_template.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -140,12 +140,36 @@ Butler:
qlikSenseLicense:
licenseMonitor:
enable: true
frequency: every 5 minutes
frequency: every 6 hours
destination:
influxDb: # Send service alerts to InfluxDB
influxDb: # Store license data in InfluxDB
enable: true
tag:
static: # Static attributes/dimensions to attach to the data sent to New Relic.
static: # Static attributes/tags to attach to the data sent to InflixDB
- name: foo
value: bar
licenseRelease:
enable: true
frequency: every 6 hours
neverReleaseUsers:
- userDir: 'INTERNAL'
userId: 'sa_repository'
- userDir: 'INTERNAL'
userId: 'sa_api'
- userDir: 'USERDIR'
userId: 'qs_admin_account'
licenseType: # License types to monitor and release
analyzer:
enable: true
releaseThresholdDays: 5
professional:
enable: true
releaseThresholdDays: 5
destination:
influxDb: # Store info about released licenses in InfluxDB
enable: true
tag:
static: # Static attributes/tags to attach to the data sent to InflixDB
- name: foo
value: bar

Expand Down
109 changes: 84 additions & 25 deletions src/lib/post_to_influxdb.js
Original file line number Diff line number Diff line change
Expand Up @@ -94,17 +94,33 @@ export async function postQlikSenseLicenseStatusToInfluxDB(qlikSenseLicenseStatu

const instanceTag = globals.config.has('Butler.influxDb.instanceTag') ? globals.config.get('Butler.influxDb.instanceTag') : '';

// Get tags from config file
// Stored in array Butler.qlikSenseLicense.licenseMonitor.destination.influxDb.tag
const configTags = globals.config.get('Butler.qlikSenseLicense.licenseMonitor.destination.influxDb.tag.static');

const tags = {
license_type: 'analyzer_access',
butler_instance: instanceTag,
};

// Add tags from config file
if (configTags) {
// eslint-disable-next-line no-restricted-syntax
for (const item of configTags) {
tags[item.name] = item.value;
}
}

// Build InfluxDB datapoint
let datapoint = [];

// Is there any data for "analyzerAccess" license type?
if (qlikSenseLicenseStatus.analyzerAccess.enabled === true) {
tags.license_type = 'analyzer_access';

datapoint.push({
measurement: 'qlik_sense_license',
tags: {
butler_instance: instanceTag,
license_type: 'analyzer_access',
},
tags,
fields: {
allocated: qlikSenseLicenseStatus.analyzerAccess.allocated,
available: qlikSenseLicenseStatus.analyzerAccess.available,
Expand All @@ -118,12 +134,11 @@ export async function postQlikSenseLicenseStatusToInfluxDB(qlikSenseLicenseStatu

// Is there any data for "analyzerTimeAccess" license type?
if (qlikSenseLicenseStatus.analyzerTimeAccess.enabled === true) {
tags.license_type = 'analyzer_time_access';

datapoint.push({
measurement: 'qlik_sense_license',
tags: {
butler_instance: instanceTag,
license_type: 'analyzer_time_access',
},
tags,
fields: {
allocatedMinutes: qlikSenseLicenseStatus.analyzerTimeAccess.allocatedMinutes,
unavailableMinutes: qlikSenseLicenseStatus.analyzerTimeAccess.unavailableMinutes,
Expand All @@ -134,12 +149,11 @@ export async function postQlikSenseLicenseStatusToInfluxDB(qlikSenseLicenseStatu

// Is there any data for "loginAccess" license type?
if (qlikSenseLicenseStatus.loginAccess.enabled === true) {
tags.license_type = 'login_access';

datapoint.push({
measurement: 'qlik_sense_license',
tags: {
butler_instance: instanceTag,
license_type: 'login_access',
},
tags,
fields: {
allocatedTokens: qlikSenseLicenseStatus.loginAccess.allocatedTokens,
tokenCost: qlikSenseLicenseStatus.loginAccess.tokenCost,
Expand All @@ -151,12 +165,11 @@ export async function postQlikSenseLicenseStatusToInfluxDB(qlikSenseLicenseStatu

// Is there any data for "professionalAccess" license type?
if (qlikSenseLicenseStatus.professionalAccess.enabled === true) {
tags.license_type = 'professional_access';

datapoint.push({
measurement: 'qlik_sense_license',
tags: {
butler_instance: instanceTag,
license_type: 'professional_access',
},
tags,
fields: {
allocated: qlikSenseLicenseStatus.professionalAccess.allocated,
available: qlikSenseLicenseStatus.professionalAccess.available,
Expand All @@ -170,12 +183,11 @@ export async function postQlikSenseLicenseStatusToInfluxDB(qlikSenseLicenseStatu

// Is there any data for "userAccess" license type?
if (qlikSenseLicenseStatus.userAccess.enabled === true) {
tags.license_type = 'user_access';

datapoint.push({
measurement: 'qlik_sense_license',
tags: {
butler_instance: instanceTag,
license_type: 'user_access',
},
tags,
fields: {
allocatedTokens: qlikSenseLicenseStatus.userAccess.allocatedTokens,
quarantinedTokens: qlikSenseLicenseStatus.userAccess.quarantinedTokens,
Expand All @@ -187,12 +199,11 @@ export async function postQlikSenseLicenseStatusToInfluxDB(qlikSenseLicenseStatu

// Are tokens available?
if (qlikSenseLicenseStatus.tokensEnabled === true) {
tags.license_type = 'tokens_available';

datapoint.push({
measurement: 'qlik_sense_license',
tags: {
butler_instance: instanceTag,
license_type: 'tokens_available',
},
tags,
fields: {
availableTokens: qlikSenseLicenseStatus.availableTokens,
totalTokens: qlikSenseLicenseStatus.totalTokens,
Expand All @@ -209,7 +220,55 @@ export async function postQlikSenseLicenseStatusToInfluxDB(qlikSenseLicenseStatu
);

datapoint = null;
globals.logger.info('INFLUXDB QLIK SENSE LICENSE STATUS: Sent Qlik Sense license status data to InfluxDB');
globals.logger.info('INFLUXDB QLIK SENSE LICENSE STATUS: Sent aggregated Qlik Sense license status to InfluxDB');
}

// Function to store info about released Qlik Sense licenses to InfluxDB
export async function postQlikSenseLicenseReleasedToInfluxDB(licenseInfo) {
globals.logger.verbose('INFLUXDB QLIK SENSE LICENSE RELEASE: Sending info on released Qlik Sense license to InfluxDB');

const instanceTag = globals.config.has('Butler.influxDb.instanceTag') ? globals.config.get('Butler.influxDb.instanceTag') : '';

// Get tags from config file
// Stored in array Butler.qlikSenseLicense.licenseMonitor.destination.influxDb.tag
const configTags = globals.config.get('Butler.qlikSenseLicense.licenseRelease.destination.influxDb.tag.static');

const tags = {
license_type: licenseInfo.licenseType,
user: `${licenseInfo.userDir}\\${licenseInfo.userId}`,
butler_instance: instanceTag,
};

// Add tags from config file
if (configTags) {
// eslint-disable-next-line no-restricted-syntax
for (const item of configTags) {
tags[item.name] = item.value;
}
}

// Build InfluxDB datapoint
let datapoint = [];

// Add data to InfluxDB datapoint
datapoint.push({
measurement: 'qlik_sense_license_release',
tags,
fields: {
days_since_last_use: licenseInfo.daysSinceLastUse,
},
});

// Write to InfluxDB
const deepClonedDatapoint = _.cloneDeep(datapoint);
await globals.influx.writePoints(deepClonedDatapoint);

globals.logger.silly(
`INFLUXDB QLIK SENSE LICENSE RELEASE: Influxdb datapoint for released Qlik Sense license: ${JSON.stringify(datapoint, null, 2)}`
);

datapoint = null;
globals.logger.debug('INFLUXDB QLIK SENSE LICENSE RELEASE: Sent info on released Qlik Sense license to InfluxDB');
}

// Function to store windows service status to InfluxDB
Expand Down
Loading

0 comments on commit bac1258

Please sign in to comment.