RCOSDP / LAaaS-docker

A Docker version of Learning Analytics as a Service (LAaaS)
MIT License
10 stars 5 forks source link

v4.1のリリース #66

Closed savvan0h closed 9 months ago

savvan0h commented 1 year ago

詳細

全般

Moodleのログ分析

Moodle

xAPIステートメント変換

Caliperステートメント変換

GakuNinLMS-LTI-MCの視聴ログ分析

起動スクリプト

前処理

xAPIステートメント変換

Caliperステートメント変換

Sakai

ドキュメントの改修

テスト内容

❯ git clone -b release-v4.1 --recurse-submodules https://github.com/RCOSDP/LAaaS-docker.git
Cloning into 'LAaaS-docker'...
remote: Enumerating objects: 2889, done.
remote: Counting objects: 100% (73/73), done.
remote: Compressing objects: 100% (57/57), done.
remote: Total 2889 (delta 38), reused 16 (delta 16), pack-reused 2816
Receiving objects: 100% (2889/2889), 89.04 MiB | 10.62 MiB/s, done.
Resolving deltas: 100% (1780/1780), done.
Submodule 'moodle/moodle' (https://github.com/moodle/moodle) registered for path 'moodle/moodle'
Cloning into '.../LAaaS-docker/moodle/moodle'...
remote: Enumerating objects: 1413562, done.        
remote: Counting objects: 100% (2296/2296), done.        
remote: Compressing objects: 100% (975/975), done.        
remote: Total 1413562 (delta 1349), reused 2054 (delta 1276), pack-reused 1411266        
Receiving objects: 100% (1413562/1413562), 702.09 MiB | 10.73 MiB/s, done.
Resolving deltas: 100% (997082/997082), done.
Submodule path 'moodle/moodle': checked out '76fe404dd5fca357152e9f71ae4800f557343486'

初期設定

❯ docker compose -f base.yaml up -d --no-build
[+] Running 9/9
 ⠿ Network laaas-docker_default    Created                                                                                     0.0s
 ⠿ Container jupyterhub            Started                                                                                     0.7s
 ⠿ Container learninglocker-mongo  Started                                                                                     0.4s
 ⠿ Container learninglocker-redis  Started                                                                                     0.6s
 ⠿ Container openlrw-mongo         Started                                                                                     0.7s
 ⠿ Container superset-db           Started                                                                                     0.5s
 ⠿ Container superset              Started                                                                                     0.8s
 ⠿ Container learninglocker        Started                                                                                     0.9s
 ⠿ Container openlrw               Started                                                                                     1.0s
❯ docker exec \
∙   -e EMAIL_ADDRESS=${EMAIL_ADDRESS} \
∙   -e ORGANIZATION=${ORGANIZATION} \
∙   -e PASSWORD=${PASSWORD} learninglocker bash -c '\
∙     source ~/.bashrc;
∙     node ./cli/dist/server createSiteAdmin "${EMAIL_ADDRESS}" "${ORGANIZATION}" "${PASSWORD}"'
...
2023-06-30 09:38:04:362 - info: Looking for sawano@udzuki.co.jp
2023-06-30 09:38:04:653 - info: User not found, creating...
2023-06-30 09:38:05:695 - error: Error sending email 
{ message: 'connect ECONNREFUSED 127.0.0.1:25',
  stack: 'Error: connect ECONNREFUSED 127.0.0.1:25\n    at TCPConnectWrap.afterConnect [as oncomplete] (net.js:1191:14)',
  errno: 'ECONNREFUSED',
  code: 'ECONNECTION',
  syscall: 'connect',
  address: '127.0.0.1',
  port: 25,
  command: 'CONN' }
2023-06-30 09:38:05:750 - info: Organisation not found, creating...
2023-06-30 09:38:06:217 - info: Adding user to organisation
2023-06-30 09:38:08:463 - info: Done!
image
❯ docker exec superset /init.sh
logging was configured successfully
2023-06-30 09:43:26,496:INFO:superset.utils.logging_configurator:logging was configured successfully
...
Syncing sql_lab perms
2023-06-30 09:44:25,168:INFO:superset.security.manager:Syncing sql_lab perms
Fetching a set of all perms to lookup which ones are missing
2023-06-30 09:44:26,137:INFO:superset.security.manager:Fetching a set of all perms to lookup which ones are missing
Creating missing datasource permissions.
2023-06-30 09:44:26,383:INFO:superset.security.manager:Creating missing datasource permissions.
Creating missing database permissions.
2023-06-30 09:44:26,399:INFO:superset.security.manager:Creating missing database permissions.
Cleaning faulty perms
2023-06-30 09:44:26,416:INFO:superset.security.manager:Cleaning faulty perms
Loaded your LOCAL configuration at [/root/.superset/superset_config.py]
{'id': 1, 'result': {'configuration_method': 'sqlalchemy_form', 'database_name': 'Learning Locker', 'expose_in_sqllab': True, 'para
meters': {'database': 'learninglocker', 'encryption': False, 'host': 'superset-db', 'password': 'superset', 'port': 5432, 'query': 
{}, 'username': 'superset'}, 'sqlalchemy_uri': 'postgresql://superset:XXXXXXXXXX@superset-db:5432/learninglocker'}}
{'id': 2, 'result': {'configuration_method': 'sqlalchemy_form', 'database_name': 'OpenLRW', 'expose_in_sqllab': True, 'parameters':
 {'database': 'openlrw', 'encryption': False, 'host': 'superset-db', 'password': 'superset', 'port': 5432, 'query': {}, 'username':
 'superset'}, 'sqlalchemy_uri': 'postgresql://superset:XXXXXXXXXX@superset-db:5432/openlrw'}}
{'id': 3, 'result': {'configuration_method': 'sqlalchemy_form', 'database_name': 'Jupyter', 'expose_in_sqllab': True, 'parameters':
 {'database': 'jupyter', 'encryption': False, 'host': 'superset-db', 'password': 'superset', 'port': 5432, 'query': {}, 'username':
 'superset'}, 'sqlalchemy_uri': 'postgresql://superset:XXXXXXXXXX@superset-db:5432/jupyter'}}
{'id': 1, 'result': {'database': 1, 'schema': 'public', 'table_name': 'xapi_statements'}}
{'id': 2, 'result': {'database': 2, 'schema': 'public', 'table_name': 'caliper_statements'}}

Moodleのログ分析

❯ docker compose up -d --no-build
...
 ⠿ Container caliper-log-db                     Started                                                                       0.7s
 ⠿ Container moodle-xapi                        Started                                                                       0.5s
 ⠿ Container learning-analytics-db              Started                                                                       0.7s
 ⠿ Container moodle-db                          Started                                                                       0.5s
 ⠿ Container openlrw-mongo                      Running                                                                       0.0s
 ⠿ Container learninglocker-mongo               Running                                                                       0.0s
 ⠿ Container jupyterhub                         Running                                                                       0.0s
 ⠿ Container learninglocker-redis               Running                                                                       0.0s
 ⠿ Container superset-db                        Running                                                                       0.0s
 ⠿ Container openlrw                            Running                                                                       0.0s
 ⠿ Container superset                           Running                                                                       0.0s
 ⠿ Container learninglocker                     Running                                                                       0.0s
 ⠿ Container moodle                             Started                                                                       1.6s
 ⠿ Container moodle-caliper                     Started                                                                       1.5s
image image image image image
❯ docker exec moodle-xapi npm start

> xapi@0.1.0 start /app
> node server.js

[2023-06-30 18:49:51.648] [INFO] - Starting xAPI statement generator.
[2023-06-30 18:49:51.802] [INFO] - [SEQ:1][SCOPE:default] Sending 3 statements...
[2023-06-30 18:49:52.171] [INFO] - [SEQ:1][SCOPE:default] 3 statements added.
[2023-06-30 18:49:52.218] [INFO] - [SEQ:1216][SCOPE:default] Sending 19 statements...
[2023-06-30 18:49:52.467] [INFO] - [SEQ:1216][SCOPE:default] 19 statements added.
[2023-06-30 18:49:52.473] [INFO] - Finished logstore_standard_logs translation.
[2023-06-30 18:49:52.476] [INFO] - Finished scorm_scoes_track translation.
❯ docker exec learning-analytics-db \
∙   psql -U learning_analytics learning_analytics \
∙   -c "SELECT count(*) FROM xapi_records_processed;"
 count 
-------
  1239
(1 row)
image
❯ npm test

> xapi@0.1.0 test
> istanbul cover --include-all-sources jasmine

Randomized with seed 04304
Started
........................................................................................................................................................

152 specs, 0 failures
Finished in 34.413 seconds
Randomized with seed 04304 (jasmine --random=true --seed=04304)

=============================== Coverage summary ===============================
Statements   : 97.85% ( 7566/7732 )
Branches     : 67.14% ( 188/280 )
Functions    : 92.67% ( 645/696 )
Lines        : 97.88% ( 7566/7730 )
================================================================================
❯ docker compose run --rm moodle-caliper
...
translating logstore_standard_log...
1239/1239 [============================] 100%

completed
It seems there is no scorm scoes track event in DB.
❯ docker exec openlrw-mongo \
∙   mongo --quiet ${OPENLRW_DATABASE} \
∙     -u ${OPENLRW_USERNAME} \
∙     -p ${OPENLRW_PASSWORD} \
∙     --eval 'db.mongoEvent.find().pretty()'
{
        "_id" : ObjectId("649ea5aba7670b2e1480d9f5"),
        "userId" : "2",
        "organizationId" : "dfb909b9-ee3a-47f7-affb-9ec2a178170a",
        "tenantId" : "649ea264a7670b2e1480d9f2",
        "event" : {
                "_id" : "urn:uuid:bc33d7fa-9c32-44e0-a610-eadbb84d8942",
                "context" : "http://purl.imsglobal.org/ctx/caliper/v1p2",
                "type" : "SessionEvent",
                "agent" : {
                        "_id" : "http://localhost:8000/user/profile.php?id=2",
                        "type" : "Person",
                        "name" : "8c6976e5b5410415bde908bd4dee15dfb167a9c873fc4bb8a81f6f2ab448a918",
                        "description" : ""
                },
                "action" : "LoggedIn",
                "object" : {
                        "_id" : "http://localhost:8000",
                        "type" : "SoftwareApplication"
                },
                "edApp" : {
                        "_id" : "http://localhost:8000",
                        "type" : "SoftwareApplication",
                        "name" : "moodle"
                },
                "eventTime" : ISODate("2023-06-29T08:47:52Z"),
                "timeZoneOffset" : NumberLong(0)
        },
        "_class" : "org.apereo.openlrw.events.service.repository.MongoEvent"
}
...
image image image image image image image image image

GakuNinLMS-LTI-MCのログ分析

❯ docker compose up -d --no-build
...
 ✔ Network laaas-docker_default                                                                                                                                      Created0.0s 
 ✔ Container superset-db                                                                                                                                               Started0.7s 
 ✔ Container jupyterhub                                                                                                                                                Started0.9s 
 ✔ Container lti-mc-caliper                                                                                                                                            Started0.5s 
 ✔ Container learninglocker-mongo                                                                                                                                   Started0.9s 
 ✔ Container learninglocker-redis                                                                                                                                      Started0.3s 
 ✔ Container lti-mc-xapi                                                                                                                                               Started0.5s  
 ✔ Container openlrw-mongo                                                                                                                                             Started0.8s 
 ✔ Container lti-mc-log-processor                                                                                                                                     Started0.4s 
 ✔ Container superset                                                                                                                                                  Started0.9s 
 ✔ Container openlrw                                                                                                                                                   Started1.1s 
 ✔ Container learninglocker                                                                                                                                            Started1.2s 
❯ ./run xapi test.log example.com
...
[2023-06-30 19:21:31.237] [INFO] - beforeunload-ended log translated.
[2023-06-30 19:21:31.237] [INFO] - hidden-ended log translated.
[2023-06-30 19:21:31.237] [INFO] - unload-ended log translated.
[2023-06-30 19:21:31.237] [INFO] - [SCOPE:default] Sending 60 statements to http://172.27.0.10:8081/data/xAPI/...
[2023-06-30 19:21:31.704] [INFO] - [SCOPE:default] 60 statements added.
[2023-06-30 19:21:34.246] [INFO] - Finished translation #Translated:6260 #Skipped:0
image
❯ npm test

> xapi@1.0.0 test
> istanbul cover --include-all-sources jasmine

Randomized with seed 22362
Started
.................

17 specs, 0 failures
Finished in 0.787 seconds
Randomized with seed 22362 (jasmine --random=true --seed=22362)
...
=============================== Coverage summary ===============================
Statements   : 95.99% ( 719/749 )
Branches     : 42.86% ( 6/14 )
Functions    : 91.53% ( 54/59 )
Lines        : 95.99% ( 719/749 )
================================================================================
❯ ./run caliper test.log example.com
Translating...
Finished: 6260 events are translated
❯ docker exec openlrw-mongo \
∙   mongo --quiet ${OPENLRW_DATABASE} \
∙     -u ${OPENLRW_USERNAME} \
∙     -p ${OPENLRW_PASSWORD} \
∙     --eval 'db.mongoEvent.find().pretty()'
{
    "_id" : ObjectId("6503db218abe9930352bf19b"),
    "userId" : "27314",
    "organizationId" : "dfb909b9-ee3a-47f7-affb-9ec2a178170a",
    "tenantId" : "649ea264a7670b2e1480d9f2",
    "event" : {
        "_id" : "urn:uuid:c7a71f3b-746f-44b0-9326-aecda1cb0bcf",
        "context" : "http://purl.imsglobal.org/ctx/caliper/v1p2",
        "type" : "ViewEvent",
        "agent" : {
            "_id" : "...",
            "type" : "Person",
            "name" : "...",
            "description" : ""
        },
        "action" : "Viewed",
        "object" : {
            "_id" : "https://example.com/62/75",
            "type" : "MediaLocation",
            "name" : "chilo087/m087_0308.mp4",
            "extensions" : {
                "courseId" : "62",
                "nonce" : "...",
                "videoplayerlog" : "videoplayerlog"
            },
            "currentTime" : "PT47.814599S"
        },
        "edApp" : {
            "_id" : "lms",
            "type" : "SoftwareApplication",
            "name" : "lms",
            "description" : ""
        },
        "eventTime" : ISODate("2022-09-20T15:00:23Z"),
        "timeZoneOffset" : NumberLong(0)
    },
    "_class" : "org.apereo.openlrw.events.service.repository.MongoEvent"
}
...
> vendor/bin/phpunit -c ./tests/ --colors=always
PHPUnit 8.5.19 by Sebastian Bergmann and contributors.

Supported Event (Tests\Translator\SupportedEvent)
 ✔ Exists method
 ✔ Is supported
 ✔ Is not supported
 ✔ Can get recipe class
 ✔ Can not get recipe class

Video Logs Event (Tests\Translator\VideoLogsEvent)
 ✔ Should be defined
 ✔ Should not be defined

Video Operation (Tests\Translator\VideoOperation)
 ✔ Exists method
 ✔ Translation

Sender (Tests\Sender\Sender)
 ✔ Should be registable
 ✔ Could not register

Video Changed Speed (Tests\Recipe\VideoChangedSpeed)
 ✔ Can get compiler
 ✔ Actor values
 ✔ Event time values
 ✔ Action values
 ✔ Object values
 ✔ Target values
 ✔ Edapp values
 ✔ Should be registable

Video Disabled Closed Captioning (Tests\Recipe\VideoDisabledClosedCaptioning)
 ✔ Can get compiler
 ✔ Actor values
 ✔ Event time values
 ✔ Action values
 ✔ Object values
 ✔ Target values
 ✔ Edapp values
 ✔ Should be registable

Video Enabled Closed Captioning (Tests\Recipe\VideoEnabledClosedCaptioning)
 ✔ Can get compiler
 ✔ Actor values
 ✔ Event time values
 ✔ Action values
 ✔ Object values
 ✔ Target values
 ✔ Edapp values
 ✔ Should be registable

Video Ended (Tests\Recipe\VideoEnded)
 ✔ Can get compiler
 ✔ Actor values
 ✔ Event time values
 ✔ Action values
 ✔ Object values
 ✔ Target values
 ✔ Edapp values
 ✔ Should be registable

Video Forwarded To (Tests\Recipe\VideoForwardedTo)
 ✔ Can get compiler
 ✔ Actor values
 ✔ Event time values
 ✔ Action values
 ✔ Object values
 ✔ Target values
 ✔ Edapp values
 ✔ Should be registable

Video Jumped To (Tests\Recipe\VideoJumpedTo)
 ✔ Can get compiler
 ✔ Actor values
 ✔ Event time values
 ✔ Action values
 ✔ Object values
 ✔ Target values
 ✔ Edapp values
 ✔ Should be registable

Video Paused (Tests\Recipe\VideoPaused)
 ✔ Can get compiler
 ✔ Actor values
 ✔ Event time values
 ✔ Action values
 ✔ Object values
 ✔ Target values
 ✔ Edapp values
 ✔ Should be registable

Video Resumed (Tests\Recipe\VideoResumed)
 ✔ Can get compiler
 ✔ Actor values
 ✔ Event time values
 ✔ Action values
 ✔ Object values
 ✔ Target values
 ✔ Edapp values
 ✔ Should be registable

Video Started (Tests\Recipe\VideoStarted)
 ✔ Can get compiler
 ✔ Actor values
 ✔ Event time values
 ✔ Action values
 ✔ Object values
 ✔ Target values
 ✔ Edapp values
 ✔ Should be registable

Video Viewed (Tests\Recipe\VideoViewed)
 ✔ Can get compiler
 ✔ Actor values
 ✔ Event time values
 ✔ Action values
 ✔ Object values
 ✔ Edapp values
 ✔ Should be registable

Generate (Tests\Generator\Generate)
 ✔ Generate
 ✔ Generate with invalid event
 ✔ Can not translate
 ✔ Can not send

Time: 94 ms, Memory: 6.00 MB

OK (94 tests, 222 assertions)
image image image image

Sakaiのログ分析

❯ docker compose up -d sakai --no-build
[+] Running 2/2
 ⠿ Container sakai-db  Started                                                                    2.6s
 ⠿ Container sakai     Started                                                                    1.6s

❯ docker compose up -d sakai-dummy-xapi --no-build
[+] Running 1/1
 ⠿ Container sakai-dummy-xapi  Started                                                           0.7s
image image
❯ docker compose exec sakai-dummy-xapi npm start

> dummy-xapi@0.1.0 start /usr/local/src/dummy-xapi
> node server.js

[2023-07-04 17:29:21.422] [INFO] - 100 statements added.
[2023-07-04 17:29:22.689] [INFO] - 100 statements added.
[2023-07-04 17:29:24.192] [INFO] - 100 statements added.
image image image image image

チェックリスト

uedahiro4 commented 10 months ago

「LRSの作成」以降のサブセクションの画像がこちらの環境では不可視となっておりますがご意図通りでしょうか?

savvan0h commented 10 months ago

ご指摘ありがとうございます。 画像の公開範囲が不適切であったため、差し替えました。失礼しました。

uedahiro4 commented 10 months ago

Caliper_statements.ipynb でOpenLRWから取得したapiKeyとapiSecretを設定するところがあります。apiKeyは moodle/caliper/config/lrw.php で取得したものがありますが apiSecretについて説明ございますでしょうか?

uedahiro4 commented 10 months ago

https://github.com/RCOSDP/LAaaS-docker/blob/release-v4.1/lti-mc/README.adoc#%E3%82%B9%E3%83%86%E3%83%BC%E3%83%88%E3%83%A1%E3%83%B3%E3%83%88%E5%A4%89%E6%8F%9B で「視聴ログをxAPIステートメントに変換する。

にはLMSから取得する情報に付与される oauth_consumer_key を指定する。」 について、oauth_consumer_key はどのように参照すれば宜しいでしょうか?
savvan0h commented 10 months ago

apiSecret

apiKey と同様に、 mongoOrg から取得します。

docker exec openlrw-mongo \
mongo --quiet ${OPENLRW_DATABASE} \
  -u ${OPENLRW_USERNAME} \
  -p ${OPENLRW_PASSWORD} \
  --eval 'db.mongoOrg.findOne()'

{
    ...
    "apiKey" : "...",
    "apiSecret" : "...",
        ...
}
savvan0h commented 10 months ago

「視聴ログをxAPIステートメントに変換する。

にはLMSから取得する情報に付与される oauth_consumer_key を指定する。」 について、oauth_consumer_key はどのように参照すれば宜しいでしょうか?

RCOSDP/GakuNinLMS-LTI-MC(やCHiBi-CHiLO)を導入したLMSに依存します。 入力となる視聴ログの11~13項目目に含まれる情報です。 本プロダクトのLMS自体は動画教材を提供しておらず、外部のLMS経由で出力した視聴ログを分析するための機能です。

uedahiro4 commented 10 months ago

apiSecretについて加筆をお願いするには何が必要でしょうか。

uedahiro4 commented 10 months ago

検証する上では、CONSUMER_KEYはダミーで問題ないでしょうか。

uedahiro4 commented 10 months ago

失礼しましたCONSUMER_KEYどころかダミーデータが必要ですね。

masui-motoo commented 10 months ago

@uedahiro4

LAaaS-docker の READMEについて、何件かご要望をいただいているかと思います。

apiSecretについて加筆をお願いするには何が必要でしょうか。

oauth_consumer_key はどのように参照すれば宜しいでしょうか?

ダミーデータが必要ですね。

これらのご要望について、v4.2以降のリリースでの対処を検討しますので、 お手数ですが、各件について、ご要望を Issue に起票頂けると幸いです。