Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Learner history migration tool #42

Closed
jlowe64 opened this issue Jan 25, 2016 · 22 comments
Closed

Learner history migration tool #42

jlowe64 opened this issue Jan 25, 2016 · 22 comments
Assignees
Labels
Milestone

Comments

@jlowe64
Copy link
Contributor

jlowe64 commented Jan 25, 2016

Motive
Migrate all relevant logstore data to LRS upon first install.

Result
logstore data would populate the LRS with all Moodle history located in logstore_standard_log.

Additional information
The major problem with this is that we only want this to ever happen 1 time. To stop this from happening you would have an "install" date and a boolean that says "legacy_data_migration." The booleon would tell the settings page whether or not that feature should be shown to the user.

@garemoko
Copy link
Contributor

+1 this would be a really nice feature

@ryasmi
Copy link
Member

ryasmi commented Jan 25, 2016

Yeah +1 here also, sounds good. This might be resolved in someway by #37 which should hopefully try to send batches of events pulled from the log store.

@jlowe64
Copy link
Contributor Author

jlowe64 commented Jan 25, 2016

I'll keep this in the back until we get through that, because it's much more important.

@ryasmi
Copy link
Member

ryasmi commented Jan 25, 2016

Ok @jlowe64

@caperneoignis
Copy link
Contributor

I'd ask if we could add an option to also do it for an update. Reason being, some of us have access to the LRS and can clear it upon request. Then when we update the plugin, we can select to have the log migrated again, with the new statements, recreating the Log store on the LRS. Especially with a big update, where fields have been added to statements or a bug gets corrected that would result in new information in the records. Example: the new score fields for quizzes, would be nice to have on all the previous quizzes and not just going forward.

@garemoko
Copy link
Contributor

garemoko commented May 3, 2016

What I have in mind is two config fields: since and until. If those fields are populated, the cron task will grab all events in that time period and then clear those fields.

@caperneoignis
Copy link
Contributor

That sounds great!

@jlowe64 jlowe64 modified the milestones: v2.0.0, v1.1.0 Jun 2, 2016
@ryasmi
Copy link
Member

ryasmi commented Oct 5, 2016

Just copying some useful bits and pieces from Gitter

As far as I'm aware, if the plugin is configured to use a cron job, you should be able to move historical data from Moodle's log store table, to the plugin's log store table using SQL. The cron job uses data from the plugin's log store table, hence, the next time the cron job runs it should start using your historical data. I hope that makes sense. I'm not 100% sure what the table names are exactly, it's been a while since I looked them. Obviously the SQL query to move the data between the two tables will depend entirely on what and how much historical data you want

@davidfkane

INSERT INTO mdl_logstore_xapi_log (SELECT * FROM mdl_logstore_standard_log LIMIT 1000);
php schedule_task.php --execute=\\logstore_xapi\\task\\emit_task
php schedule_task.php --execute=\\logstore_legacy\\task\\cleanup_task
php schedule_task.php --execute=\\logstore_standard\\task\\cleanup_task

@caperneoignis
Copy link
Contributor

Will this be included in the next milestone release? I ask because we use this on a production site, so it's much easier to update the moodle-logstore_xapi plugin as a whole, then by using composer. I don't mind testing it on a dev site with a composer build.

@ryasmi
Copy link
Member

ryasmi commented Oct 6, 2016

Those were just notes of commands that can be used to get historical data @caperneoignis. Nothing has changed in the plugin.

@caperneoignis
Copy link
Contributor

My bad, now I feel a bit dim. I may try that on a dev system to see what happens. Thanks!

@ryasmi
Copy link
Member

ryasmi commented Oct 6, 2016

Ha no worries 😄 Sounds good. You're welcome @caperneoignis

@davidfkane
Copy link

I am going to attach my solution below. Should work fine. Lots of explanatory HTML.

@davidfkane
Copy link

<?php
/*
* Script designed to increment through old logs for export to LL
* 
* 
* author: David Kane, 10th November 2016
* dkane@wit.ie
*/



// INITIAL VARIABLES //
$logfile = "./LogstoreLegacyMigrate.log";  //stores only the last as JSON.
$moodlepath = "/var/www/moodle/";
$increment = 7;
$lastValue = 0; // the last value of the database
$count = 10;  // the number of queries that we want to execute in the loop (a value of zero means that there is no limit);
$output = array(
        "lastValue" => 0, 
        "increment" => $increment, 
        "loop" => 0
);
$sourceTable = "mdl_logstore_subset_log";
$destinationTable = "mdl_logstore_xapi_log";
$DEBUGGING = TRUE;
$host = 'localhost';
$user = 'yourMYSQLusername';
$password = 'yourMYSQLpassword';
$db = 'moodleDatabase';
if($DEBUGGING){
?>
<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="utf-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <!-- Latest compiled and minified CSS -->
        <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">

        <!-- jQuery library -->
        <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script>

        <!-- Latest compiled JavaScript -->
        <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
    </head>
    <body>
        <div class="container-fluid">
        <div class="page-header">
            <h1>Legacy xAPI Load <small>This is normally run at the command line.  Currently running in debug mode.</small></h1>
        </div>
        <div class="row">
<div class="col-md-8">


                <div class="panel panel-primary">
                <div class="panel-heading">
                About this script
                </div>
                <div class="panel-body">
                    <div class="alert alert-warning" role="alert"><strong>! NOTE:</strong> <br/>This HTML guff disappears when the debug variable is set to false.  However, the script works the same with or without the debug variable being set.  It is up to you to delete the records from the LRS yourself, maybe use a tool like <a href="https://robomongo.org/" target="_blank">Robomongo</a>, if you have exported them in error.  Otherwise you might like to modify this script.</div>
                <p>New users of xAPI, who have just installed the Moodle Logstore xAPI plugin are faced with the problem of extracting old data and converting it to xAPI statements in the learning record store.</p>
                <p>This script is designed to take existing log data from a moodle installation, and import it &mdash; via the Logstore xAPI Moodle plugin &mdash; to the learning record store.</p>  
                <p>It does this by paging the <em>logstore_standard_log</em>, transferring the records to a temporary database table (of the same structure) and running export commands on the data stored there.  This is what it does normally, except the <em>logstore_standard_log</em> is only parsed for the last <em>n</em> records, where <em>n</em> is set in the settngs.</p>
                <h2>Command line tasks executed</h2>
                <pre># in directory admin/tool/task/cli/

php schedule_task.php --execute=<span style="background-color: #BFA3BA">\\logstore_xapi\\task\\<span style="background-color: #F2CEEC">emit_task</span></span> 

php schedule_task.php --execute=<span style="background-color: #A3BFBF">\\logstore_legacy\\task\\<span style="background-color: #CEF2F2">cleanup_task</span></span>

php schedule_task.php --execute=<span style="background-color: #A3BFA3">\\logstore_standard\\task\\<span style="background-color: #CEF2CE">cleanup_task</span></span> 
</pre>
<p>The data is also logged to a file called<em><?php echo($logfile); ?></em>.  This file is overwritten with the data from each loop and is never very long.  It is also stored as JSON, which struck me as a good idea at the time.</p>
                </div>

                </div><!-- end panel -->
            </div><!-- end column -->

            <div class="col-md-4">
<div class="panel panel-primary">
                <div class="panel-heading">
                INITIAL VARIABLES
                </div>

                <div class="panel-body">
        <table class="table table-striped">
            <tr><th>increment</th><td><?php echo($increment);?></td></tr>
            <tr><th>lastValue</th><td><?php echo($lastValue);?></td></tr>
            <tr><th>moodlepath</th><td><?php echo($moodlepath);?></td></tr>
            <tr><th>logfile</th><td><?php echo($logfile);?></td></tr>
            <tr><th>Source DB Table (normally <em>mdl_logstore_standard_log)</em> </th><td><?php echo($sourceTable);?></td></tr>
            <tr><th>Source DB Table (normally <em>mdl_logstore_xapi_log)</em> </th><td><?php echo($destinationTable);?></td></tr>
            <tr><th>Debug</th><td>TRUE</td></tr>
            <tr><th>Author</th><td>David Kane, dkane@wit.ie, Nov 2016</td></tr>
        </table>
    </div></div>
</div><!-- end column -->
            </div><!-- end row -->
            <div class="row">
<div class="col-md-12">
<div class="panel panel-info">
        <div class="panel-heading">The Loop</div>
        <div class="panel-body">
        <table class="table table-striped">
            <tr>
            <th>Iteration (count)</th>
            <th>SQL Query</th>
            <th>Affected Rows</th>
            <th>Last Insert ID</th>
            <th>Task Outputs</th>
            </tr>
<?php
}
for($i = 0; $i < $count; $i++){
    if($DEBUGGING){
        echo "\t\t\t<tr>\n";
        echo "\t\t\t\t<td>$i of $count</td>";
    }
    $conn = new mysqli($host, $user, $password, $db);
    if ($conn->connect_error) {
        trigger_error('Database connection failed: '  . $conn->connect_error, E_USER_ERROR);
    }
    $sql = "insert into mdl_logstore_xapi_log (select * from mdl_logstore_subset_log where id > " . $lastValue . " order by id limit " . $increment . ");";
    if($DEBUGGING){echo "\t\t\t\t<td>$sql</td>\n";}

    if($conn->query($sql) === false) {
          trigger_error('Wrong SQL: ' . $sql . ' Error: ' . $conn->error, E_USER_ERROR);
          break;
    } else {
        $lastValue = $conn->insert_id;
        $affected_rows = $conn->affected_rows;
        $output["lastValue"] = $lastValue;
        $output["loop"] = $i;
        if($DEBUGGING){
            echo "\t\t<td>$affected_rows</td>\n";
            print "\t\t<td>$lastValue</td>\n";
        }
        //echo "executing commands";
        exec("php ".$moodlepath."admin/tool/task/cli/schedule_task.php --execute=\\\\logstore_xapi\\\\task\\\\emit_task ", $output["emit"]);
        exec("php ".$moodlepath."admin/tool/task/cli/schedule_task.php --execute=\\\\logstore_legacy\\\\task\\\\cleanup_task", $output["cleanupLegacy"]);
        exec("php ".$moodlepath."admin/tool/task/cli/schedule_task.php --execute=\\\\logstore_standard\\\\task\\\\cleanup_task", $output["cleanupStandard"]);
        if($DEBUGGING){
            // PRINT OUT THE VARIABLES, IF DEBUGGING
            echo "<td><span style='background-color: #F2CEEC'>"; 
                    foreach ($output["emit"] as $key => $value) {
                        echo "$value <br/>";
                    }
            echo "</span><span style='background-color: #CEF2F2'>"; 
                    foreach ($output["cleanupLegacy"] as $key => $value) {
                        echo "$value <br/>";
                    }
            echo "</span><span style='background-color: #CEF2CE'>"; 
                    foreach ($output["cleanupStandard"] as $key => $value) {
                        echo "$value <br/>";
                    }
            echo "</span></td>";
        }
        unset($output["emit"]);
        unset($output["cleanupLegacy"]);
        unset($output["cleanupStandard"]);

        $log = fopen($logfile, 'w');
        fwrite($log, json_encode($output));
        fwrite($log, "\n");
        fclose($log);

        if($affected_rows < $increment){
            // no more rows left - time to leave the loop.
            if($DEBUGGING){echo "\t</tr>\n\t<tr>\n\t\t<td colspan='5'><em>Breaking out of loop at \$count = $i.</em></td>\n\t</tr>\n";}
            break;
        }
    }
    if($DEBUGGING){echo "\t</tr>\n";}
}

if($DEBUGGING){
?>
            </table>
        </div><!-- end panel body -->
        <div class="panel-footer">End of Loop</div>
        </div><!-- end panel -->

            </div>
            </div>

        </div>
    </body>
</html>
<?php
}
exit;

@davidfkane
Copy link

There. Hopefully somebody can spot anything I miss.

@ryasmi
Copy link
Member

ryasmi commented Oct 11, 2016

Nice @davidfkane! 😄 I'm sure that will be super useful for a lot of people.

@nadavkav
Copy link
Contributor

Super useful!!! Thanks 👍

@ryasmi ryasmi modified the milestones: v2.0.0, v2.1.0 Jun 15, 2017
@davidpesce davidpesce removed this from the v2.2.0 milestone Feb 22, 2018
@davidpesce davidpesce added this to the v3.0.0 milestone Feb 22, 2018
@davidpesce
Copy link
Collaborator

Let's add this as a CLI option to the plugin. Tagged for 3.0 release.

@ryasmi
Copy link
Member

ryasmi commented Feb 22, 2018 via email

@davidfkane
Copy link

Great! I am glad my piece of work can help you in your efforts. The plugin will be much better with that option.

@ryasmi
Copy link
Member

ryasmi commented Jul 31, 2018

#204

@davidpesce davidpesce assigned davidpesce and unassigned jlowe64 Aug 3, 2018
@ryasmi
Copy link
Member

ryasmi commented Aug 28, 2018

Actually going to close this for now since we have a fairly straightforward process in our documentation now.

@ryasmi ryasmi closed this as completed Aug 28, 2018
ScottVerbeek added a commit to ScottVerbeek/moodle-logstore_xapi that referenced this issue Jan 12, 2024
FlorianTolk pushed a commit to adlnet/moodle-logstore_xapi that referenced this issue Oct 29, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

7 participants