【问题标题】:Getting user information for a large number of G Suite users quickly with AppScript使用 AppScript 快速获取大量 G Suite 用户的用户信息
【发布时间】:2019-07-15 20:48:29
【问题描述】:

我正在使用此代码 sn-p 的略微修改版本来获取 G Suite 域上大量用户的上次登录时间。由于用户众多,此代码无法在 30 分钟内完成运行,并达到 30 分钟的执行时间限制并失败。我正在寻找一种方法来加快执行速度。

运行此应用程序的应用程序将这些数据与从企业许可证管理器 API 读取值的类似代码截断相结合,我预计这会遇到同样的问题。

如果无法让代码更快,我至少需要确保它不会达到执行时间限制。我需要为所有用户至少调用一次此 API 以使应用程序正常工作 - 它按用户的上次登录时间对用户列表进行排序。该应用在应用制作工具中使用 G Suite Enterprise 域上的应用脚本。

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);
  }

这是一个示例执行:

[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]


【问题讨论】:

  • 包括你的执行记录,这样我们就可以看到花费最多的时间,这可以在View &gt; Execution transcript找到。
  • @ross 我用执行日志的示例更新了问题,并确保代码可以独立运行。我还必须注意,注释掉的部分是写入数据库的 App Maker 特定功能,但该日志在 AppMaker 中似乎不可用。
  • 即使提高执行时间速度,如果用户数继续增加,迟早也会遇到同样的问题。相反,您应该考虑使用此处描述的解决方案stackoverflow.com/a/8608327/5983596。我使用这个解决方案,我很擅长。
  • 我在搜索中看到了该帖子,但我无法弄清楚如何使用活动报告在每个循环中获取正确的用户。您可以获取一个用户或所有用户,但不能获取一个列表,即使我可以给它一个列表,我也不确定我会如何管理它。
  • @IanHyzy 您的域中有多少用户?

标签: google-apps-script google-apps google-app-maker google-workspace


【解决方案1】:

与其使用 Reports API 获取上次登录信息,不如直接从所有用户记录的列表中获取它会更快吗?使用AdminDirectory.Users.list 并检索user.lastLoginTime 属性?

如果您仍然需要云端硬盘项目的数量(您已在上面注释掉),您可能需要通过单独的函数来运行它,但您可以根据其他一些标准或从最近登录的开始用户至上。

【讨论】:

  • 我考虑过这样做(首先获取用户列表,然后在每页的基础上获取登录时间),但我仍在研究如何最好地获取给定的 lastLoginTime用户列表,而不是一个用户或所有人。
  • 即使只是拉取域中所有用户的列表也超过了 30 分钟的执行时间。
  • 有很多用户,是的。不幸的是,除非有直接证据表明存在错误,否则 Google 支持将退回有关 App Script 的票证。不幸的是,这并不算是一个错误。
  • 如果您的帐户是通过 G Suite 转销商提供的,他们可能会代表您完成。祝你好运!
【解决方案2】:

我通过使用 App Maker 的客户端脚本解决了这个问题。客户端脚本调用服务器脚本,该脚本获取 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;
}

【讨论】:

    猜你喜欢
    • 2020-04-21
    • 1970-01-01
    • 2018-11-30
    • 1970-01-01
    • 2017-10-03
    • 1970-01-01
    • 2021-01-12
    • 2020-11-30
    • 2017-08-14
    相关资源
    最近更新 更多