简体   繁体   English

通过AppScript快速获取大量G Suite用户的用户信息

[英]Getting user information for a large number of G Suite users quickly with AppScript

I'm using a slightly modified version of this code snippet to get the last login time from a large number of users on a G Suite domain. 我正在使用此代码段的稍作修改的版本,以从G Suite域中的大量用户获取上次登录时间。 Due to the large number of users, this code can't finish running in under 30 minutes and hits the execution time limit of 30 minutes and fails. 由于用户数量众多,此代码无法在30分钟内完成运行,并且达到30分钟的执行时间限制并失败。 I'm looking for a way to speed up the execution. 我正在寻找一种加快执行速度的方法。

The application this runs on combines this data with a similar code snipped that reads values from the enterprise license manager API, which I expect will hit the same issue. 运行该应用程序的应用程序将这些数据与类似的代码合并在一起,该代码片段已从企业许可证管理器API读取值,我希望它将遇到相同的问题。

If it's not possible to make the code faster, I at least need to ensure it doesn't hit the execution time limit. 如果不可能使代码更快,我至少需要确保它没有达到执行时间限制。 I need to call this API for all users at least once for the application to work properly - it sorts a list of users by their last login time. 我需要为所有用户至少调用一次此API,以使应用程序正常运行-它按用户的上次登录时间对用户列表进行排序。 The app is in App Maker using App Script on a G Suite Enterprise domain. 该应用程序在G Suite Enterprise域上使用App Script的App Maker中。

function getParameterValues(parameters) {
  return parameters.reduce(function(result, parameter) {
    var name = parameter.name;
    var value;
    if (parameter.intValue !== undefined) {
      value = parameter.intValue;
    } else if (parameter.stringValue !== undefined) {
      value = parameter.stringValue;
    } else if (parameter.datetimeValue !== undefined) {
      value = new Date(parameter.datetimeValue);
    } else if (parameter.boolValue !== undefined) {
      value = parameter.boolValue;
    }
    result[name] = value;
    return result;
  }, {});
}

function generateLoginActivityReport() {
  var today = new Date();
  var oneWeekAgo = new Date(today.getTime() - (7 * 24 * 60 * 60 * 1000));
  var timezone = Session.getScriptTimeZone();
  var date = Utilities.formatDate(oneWeekAgo, timezone, 'yyyy-MM-dd');

  var parameters = [
    'accounts:last_login_time',
    'drive:num_items_created'
  ];
  var rows = [];
  var pageToken;
  var page;
    do {
    page = AdminReports.UserUsageReport.get('all', date, {
      parameters: parameters.join(','),
      maxResults: 500,
      pageToken: pageToken,
    });

    var reports = page.usageReports;

    if (reports) {
      for (var i = 0; i < reports.length; i++) { 
        var report = reports[i];
        try {
          var parameterValues = getParameterValues(report.parameters);
          var row = [
            report.date,
            report.entity.userEmail,
            parameterValues['accounts:last_login_time'],
            //parameterValues['drive:num_items_created']
          ];
          rows.push(row);
          //var ar = app.models.ActivityReport.newRecord();
          //ar.LastLogin = parameterValues['accounts:last_login_time'];
          console.log(report.entity.userEmail);
          //ar.DocsAdded = 0; //getting this value is another issue but unrelated so it's set to 0 for now.
          //ar.Email = report.entity.userEmail.toString();
          //app.saveRecords([ar]);
        }
        catch(error) {
          console.error("Error: \n"+error);
        }
      }
    }
  } while (pageToken);
  }

And here's a sample execution: 这是一个示例执行:

[19-07-15 15:58:30:784 CDT] Starting execution
[19-07-15 15:58:30:796 CDT] Session.getScriptTimeZone() [0 seconds]
[19-07-15 15:58:30:797 CDT] Utilities.formatDate([Mon Jul 08 13:58:30 PDT 2019, America/Mexico_City, yyyy-MM-dd]) [0 seconds]
[19-07-15 15:58:32:202 CDT] console.log([user1@test.mavenwave.com, []]) [0.003 seconds]
[19-07-15 15:58:32:203 CDT] console.log([ad.test.admin@test.mavenwave.com, []]) [0 seconds]
[19-07-15 15:58:32:204 CDT] console.log([user3@test.mavenwave.com, []]) [0 seconds]
///more entries, roughly 195 total
[19-07-15 15:58:32:441 CDT] console.log([user4@test.mavenwave.com, []]) [0 seconds]
[19-07-15 15:58:32:441 CDT] console.log([user5@test.mavenwave.com, []]) [0 seconds]
[19-07-15 15:58:32:443 CDT] Execution succeeded [1.645 seconds total runtime]


Instead of getting the last login using the Reports API, would it be faster to just get it directly from a list of all user records? 与其使用Reports API获得最后的登录信息,不如直接从所有用户记录的列表中获取登录信息会更快吗? Use AdminDirectory.Users.list and retrieve the user.lastLoginTime property? 使用AdminDirectory.Users.list并检索user.lastLoginTime属性?

If you still need the number of Drive items (that you have commented out above), you might have to run that through a separate function, but you could do it based on some other criteria or starting with the most recently logged in users first. 如果仍然需要驱动器项的数量(已在上面注释掉),则可能必须通过单独的功能来运行它,但是您可以基于其他条件或首先从最近登录的用户开始进行操作。

I got around this by using App Maker's client scripting. 我通过使用App Maker的客户端脚本解决了这个问题。 The client script calls the server script, which gets 100 users' reports and then passes the page token back to the client script, which calls it again using the page token- this gets around the 30 minute time limit and continues the call in order. 客户端脚本调用服务器脚本,该脚本获得100个用户的报告,然后将页面令牌传递回客户端脚本,客户端脚本再次使用页面令牌对其进行调用-这大约有30分钟的时间限制,并按顺序继续通话。

function crunLoginActivityReport(page) {
  // this loops over every page token and gets the data and writes it to the DB.
  console.log("Running activity report for page: " + page);
  google.script.run.withSuccessHandler(function(result) {
    console.log("Got the following from the server, handing back to client runner" + result);
    if (result === null) {
      console.log("Result was null, stopping get");
      return; 
    } else {
    crunLoginActivityReport(result); }
  }).runLoginActivityReport(page);
  return;
}

function cinitLoginActivityReport() {
  google.script.run.withSuccessHandler(function(result) {
    crunLoginActivityReport(result);
    return;
  }).initLoginActivityReport();
  return;
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM