19 declare(strict_types=1);
34 return (
bool)
$ilSetting->get(
'session_statistics',
'1');
40 public static function createRawEntry(
string $a_session_id,
int $a_session_type,
int $a_timestamp,
int $a_user_id): void
46 if (!$a_user_id || !$a_session_id || !self::isActive()) {
54 'usr_session_stats_raw',
56 'session_id' => [
'text', $a_session_id]
59 'type' => [
'integer', $a_session_type],
60 'start_time' => [
'integer', $a_timestamp],
61 'user_id' => [
'integer', $a_user_id]
79 if (!self::isActive()) {
84 if (!is_array($a_session_id)) {
86 $end_time = $a_expired_at;
90 $sql =
'UPDATE usr_session_stats_raw' .
91 ' SET end_time = ' .
$ilDB->quote($end_time,
'integer');
93 $sql .=
',end_context = ' .
$ilDB->quote($a_context,
'integer');
95 $sql .=
' WHERE session_id = ' .
$ilDB->quote($a_session_id,
'text') .
96 ' AND end_time IS NULL';
97 $ilDB->manipulate($sql);
100 elseif (!$a_expired_at) {
101 $sql =
'UPDATE usr_session_stats_raw' .
102 ' SET end_time = ' .
$ilDB->quote(time(),
'integer');
104 $sql .=
',end_context = ' .
$ilDB->quote($a_context,
'integer');
106 $sql .=
' WHERE ' .
$ilDB->in(
'session_id', $a_session_id,
false,
'text') .
107 ' AND end_time IS NULL';
108 $ilDB->manipulate($sql);
112 foreach ($a_session_id as
$id => $ts) {
113 $sql =
'UPDATE usr_session_stats_raw' .
114 ' SET end_time = ' .
$ilDB->quote($ts,
'integer');
116 $sql .=
',end_context = ' .
$ilDB->quote($a_context,
'integer');
118 $sql .=
' WHERE session_id = ' .
$ilDB->quote(
$id,
'text') .
119 ' AND end_time IS NULL';
120 $ilDB->manipulate($sql);
134 $ilDB = $DIC[
'ilDB'];
137 $sql =
'SELECT MAX(slot_end) previous_slot_end' .
138 ' FROM usr_session_stats';
141 $previous_slot_end = $row[
'previous_slot_end'];
145 if (!$previous_slot_end) {
146 $slot = (
int) (floor(date(
'i') / self::SLOT_SIZE));
149 $current_slot_begin = mktime((
int) date(
'H', $a_now) - 1, 60 - self::SLOT_SIZE, 0);
153 $current_slot_begin = mktime((
int) date(
'H', $a_now), ($slot - 1) * self::SLOT_SIZE, 0);
156 $current_slot_begin = $previous_slot_end + 1;
159 $current_slot_end = $current_slot_begin + (60 * self::SLOT_SIZE) - 1;
162 if ($current_slot_end < $a_now) {
163 return [$current_slot_begin, $current_slot_end];
172 $ilDB = $DIC[
'ilDB'];
174 $sql =
'SELECT COUNT(*) counter FROM usr_session_stats_raw' .
175 ' WHERE (end_time IS NULL OR end_time >= ' .
$ilDB->quote($a_time,
'integer') .
')' .
176 ' AND start_time <= ' .
$ilDB->quote($a_time,
'integer') .
180 return (
int) $row[
'counter'];
186 protected static function getRawData(
int $a_begin,
int $a_end): array
190 $ilDB = $DIC[
'ilDB'];
192 $sql =
'SELECT start_time,end_time,end_context FROM usr_session_stats_raw' .
193 ' WHERE start_time <= ' .
$ilDB->quote($a_end,
'integer') .
194 ' AND (end_time IS NULL OR end_time >= ' .
$ilDB->quote($a_begin,
'integer') .
')' .
196 ' ORDER BY start_time';
214 $ilDB = $DIC[
'ilDB'];
216 $ilAtomQuery =
$ilDB->buildAtomQuery();
217 $ilAtomQuery->addTableLock(
'usr_session_stats');
221 $slot = self::getCurrentSlot($a_now);
222 if (!is_array($slot)) {
229 'slot_begin' => [
'integer', $slot[0]],
230 'slot_end' => [
'integer', $slot[1]],
232 $ilDB->
insert(
'usr_session_stats', $fields);
245 if (!self::isActive()) {
249 $slot = self::createNewAggregationSlot($a_now);
250 while (is_array($slot)) {
251 self::aggregateRawHelper($slot[0], $slot[1]);
252 $slot = self::createNewAggregationSlot($a_now);
256 self::deleteAggregatedRaw($a_now);
267 $ilDB = $DIC[
'ilDB'];
277 $closed_counter = $events = [];
279 foreach (self::getRawData($a_begin, $a_end) as $item) {
288 if ($item[
'start_time'] >= $a_begin) {
290 $events[$item[
'start_time']][] = 1;
293 if ($item[
'end_time'] && $item[
'end_time'] <= $a_end) {
294 if (in_array($item[
'end_context'], $separate_closed,
true)) {
295 if (!isset($closed_counter[$item[
'end_context']])) {
296 $closed_counter[$item[
'end_context']] = 0;
299 $closed_counter[$item[
'end_context']]++;
301 $closed_counter[0] = ($closed_counter[0] ?? 0) + 1;
303 $events[$item[
'end_time']][] = -1;
308 $active_begin = self::getNumberOfActiveRawSessions($a_begin - 1);
309 $active_end = $active_min = $active_max = $active_avg = $active_begin;
312 if (count($events)) {
313 $last_update_avg = $a_begin - 1;
314 $slot_seconds = self::SLOT_SIZE * 60;
319 foreach ($events as $ts => $actions) {
321 foreach ($actions as $action) {
333 if ($active_end > $active_max) {
334 $active_max = $active_end;
338 if ($active_end < $active_min) {
339 $active_min = $active_end;
343 $diff = $ts - $last_update_avg;
344 $active_avg += $diff / $slot_seconds * $active_end;
345 $last_update_avg = $ts;
349 if ($last_update_avg < $a_end) {
350 $diff = $a_end - $last_update_avg;
351 $active_avg += $diff / $slot_seconds * $active_end;
354 $active_avg = round($active_avg);
360 'active_min' => [
'integer', $active_min],
361 'active_max' => [
'integer', $active_max],
362 'active_avg' => [
'integer', $active_avg],
363 'active_end' => [
'integer', $active_end],
364 'opened' => [
'integer', $opened_counter],
366 'closed_expire' => [
'integer', (
int) ($closed_counter[ilSession::SESSION_CLOSE_EXPIRE] ?? 0)],
368 'closed_misc' => [
'integer', (
int) ($closed_counter[0] ?? 0)],
374 'slot_begin' => [
'integer', $a_begin],
375 'slot_end' => [
'integer', $a_end]
387 $ilDB = $DIC[
'ilDB'];
390 $cut = $a_now - (60 * 60 * 24 * 7);
393 'DELETE FROM usr_session_stats_raw' .
394 ' WHERE start_time <= ' .
$ilDB->quote($cut,
'integer')
405 $ilDB = $DIC[
'ilDB'];
407 $sql =
'SELECT SUM(opened) opened, SUM(closed_manual) closed_manual,' .
408 ' SUM(closed_expire) closed_expire,' .
409 ' SUM(closed_login) closed_login, SUM(closed_misc) closed_misc' .
410 ' FROM usr_session_stats' .
411 ' WHERE slot_end > ' .
$ilDB->quote($a_from,
'integer') .
412 ' AND slot_begin < ' .
$ilDB->quote($a_to,
'integer');
420 public static function getActiveSessions(
int $a_from,
int $a_to): array
425 $ilDB = $DIC[
'ilDB'];
427 $sql =
'SELECT slot_begin, slot_end, active_min, active_max, active_avg' .
428 ' FROM usr_session_stats' .
429 ' WHERE slot_end > ' .
$ilDB->quote($a_from,
'integer') .
430 ' AND slot_begin < ' .
$ilDB->quote($a_to,
'integer') .
431 ' ORDER BY slot_begin';
436 foreach ($row as $key => $value) {
437 $entry[$key] = (
int) $value;
451 $ilDB = $DIC[
'ilDB'];
453 $sql =
'SELECT max(slot_end) latest FROM usr_session_stats';
456 if ($row[
'latest']) {
457 return (
int) $row[
'latest'];
static getNumberOfActiveRawSessions(int $a_time)
static getNumberOfSessionsByType(int $a_from, int $a_to)
Get session counters by type (opened, closed)
insert(string $table_name, array $values)
static createRawEntry(string $a_session_id, int $a_session_type, int $a_timestamp, int $a_user_id)
Create raw data entry.
const int SESSION_CLOSE_LOGIN
static deleteAggregatedRaw(int $a_now)
Remove already aggregated raw data.
static aggretateRaw(int $a_now)
Aggregate raw session data (older than given time)
while($session_entry=$r->fetchRow(ilDBConstants::FETCHMODE_ASSOC)) return null
static aggregateRawHelper(int $a_begin, int $a_end)
Aggregate statistics data for one slot.
static getLastAggregation()
Get timestamp of last aggregation.
static getCurrentSlot(int $a_now)
Get next slot to aggregate.
const int SESSION_CLOSE_USER
static closeRawEntry($a_session_id, ?int $a_context=null, $a_expired_at=null)
Close raw data entry.
static getRawData(int $a_begin, int $a_end)
Read raw data for timespan.
static isActive()
Is session statistics active at all?
static array $session_types_controlled
const int SESSION_CLOSE_EXPIRE
$id
plugin.php for ilComponentBuildPluginInfoObjectiveTest::testAddPlugins
static createNewAggregationSlot(int $a_now)
Create new slot (using table lock)