Skip to content
Snippets Groups Projects
Commit 21ae6958 authored by David Schimmel's avatar David Schimmel
Browse files

Update: Adapt analytics logs (coscine/issues#1221)

parent de9389df
Branches
No related tags found
1 merge request!120WIP: Update: Adapt analytics logs (coscine/issues#1188)
......@@ -68,17 +68,17 @@
<Reference Include="Coscine.Configuration, Version=1.5.0.0, Culture=neutral, PublicKeyToken=ce3d7a32d7dc1e5a, processorArchitecture=MSIL">
<HintPath>..\packages\Coscine.Configuration.1.5.0\lib\net461\Coscine.Configuration.dll</HintPath>
</Reference>
<Reference Include="Coscine.Database, Version=1.27.0.0, Culture=neutral, PublicKeyToken=767d77427707b70a, processorArchitecture=MSIL">
<HintPath>..\packages\Coscine.Database.1.27.0\lib\net461\Coscine.Database.dll</HintPath>
<Reference Include="Coscine.Database, Version=1.28.0.0, Culture=neutral, PublicKeyToken=767d77427707b70a, processorArchitecture=MSIL">
<HintPath>..\packages\Coscine.Database.1.28.0-topic-1221-loggi0004\lib\net461\Coscine.Database.dll</HintPath>
</Reference>
<Reference Include="Coscine.Database.T4, Version=1.27.0.0, Culture=neutral, PublicKeyToken=84b4c404a0696261, processorArchitecture=MSIL">
<HintPath>..\packages\Coscine.Database.1.27.0\lib\net461\Coscine.Database.T4.dll</HintPath>
<Reference Include="Coscine.Database.T4, Version=1.28.0.0, Culture=neutral, PublicKeyToken=84b4c404a0696261, processorArchitecture=MSIL">
<HintPath>..\packages\Coscine.Database.1.28.0-topic-1221-loggi0004\lib\net461\Coscine.Database.T4.dll</HintPath>
</Reference>
<Reference Include="Coscine.JwtHandler, Version=1.2.0.0, Culture=neutral, PublicKeyToken=aaacf41df3a6253c, processorArchitecture=MSIL">
<HintPath>..\packages\Coscine.JwtHandler.1.2.0\lib\net461\Coscine.JwtHandler.dll</HintPath>
</Reference>
<Reference Include="Coscine.Logging, Version=1.2.0.0, Culture=neutral, PublicKeyToken=e1ed402bc3f6525e, processorArchitecture=MSIL">
<HintPath>..\packages\Coscine.Logging.1.2.0\lib\net461\Coscine.Logging.dll</HintPath>
<Reference Include="Coscine.Logging, Version=1.3.0.0, Culture=neutral, PublicKeyToken=e1ed402bc3f6525e, processorArchitecture=MSIL">
<HintPath>..\packages\Coscine.Logging.1.3.0-topic-1221-loggi0001\lib\net461\Coscine.Logging.dll</HintPath>
</Reference>
<Reference Include="Coscine.ProxyApi, Version=1.3.0.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\Coscine.ProxyApi.1.3.0\lib\net461\Coscine.ProxyApi.dll</HintPath>
......
......
......@@ -88,7 +88,7 @@
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="Coscine.Database" publicKeyToken="767d77427707b70a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-1.27.0.0" newVersion="1.27.0.0" />
<bindingRedirect oldVersion="0.0.0.0-1.28.0.0" newVersion="1.28.0.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.IdentityModel.Tokens.Jwt" publicKeyToken="31bf3856ad364e35" culture="neutral" />
......@@ -140,7 +140,7 @@
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="Coscine.Logging" publicKeyToken="e1ed402bc3f6525e" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-1.2.0.0" newVersion="1.2.0.0" />
<bindingRedirect oldVersion="0.0.0.0-1.3.0.0" newVersion="1.3.0.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="Microsoft.IdentityModel.Logging" publicKeyToken="31bf3856ad364e35" culture="neutral" />
......@@ -192,7 +192,7 @@
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="Coscine.Database.T4" publicKeyToken="84b4c404a0696261" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-1.27.0.0" newVersion="1.27.0.0" />
<bindingRedirect oldVersion="0.0.0.0-1.28.0.0" newVersion="1.28.0.0" />
</dependentAssembly>
</assemblyBinding>
</runtime>
......
......
......@@ -7,9 +7,9 @@
<package id="Coscine.Action" version="1.17.0" targetFramework="net472" />
<package id="Coscine.ApiCommons" version="1.11.0" targetFramework="net472" />
<package id="Coscine.Configuration" version="1.5.0" targetFramework="net472" />
<package id="Coscine.Database" version="1.27.0" targetFramework="net472" />
<package id="Coscine.Database" version="1.28.0-topic-1221-loggi0004" targetFramework="net472" />
<package id="Coscine.JwtHandler" version="1.2.0" targetFramework="net472" />
<package id="Coscine.Logging" version="1.2.0" targetFramework="net472" />
<package id="Coscine.Logging" version="1.3.0-topic-1221-loggi0001" targetFramework="net472" />
<package id="Coscine.ProxyApi" version="1.3.0" targetFramework="net472" />
<package id="Coscine.ResourceConfiguration" version="1.3.0" targetFramework="net472" />
<package id="Coscine.ResourceLoader" version="1.2.0" targetFramework="net472" />
......
......
......@@ -91,7 +91,7 @@
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="Coscine.Database" publicKeyToken="767d77427707b70a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-1.27.0.0" newVersion="1.27.0.0" />
<bindingRedirect oldVersion="0.0.0.0-1.28.0.0" newVersion="1.28.0.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.IdentityModel.Tokens.Jwt" publicKeyToken="31bf3856ad364e35" culture="neutral" />
......@@ -143,7 +143,7 @@
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="Coscine.Logging" publicKeyToken="e1ed402bc3f6525e" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-1.2.0.0" newVersion="1.2.0.0" />
<bindingRedirect oldVersion="0.0.0.0-1.3.0.0" newVersion="1.3.0.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="Microsoft.IdentityModel.Logging" publicKeyToken="31bf3856ad364e35" culture="neutral" />
......@@ -191,7 +191,7 @@
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="Coscine.Database.T4" publicKeyToken="84b4c404a0696261" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-1.27.0.0" newVersion="1.27.0.0" />
<bindingRedirect oldVersion="0.0.0.0-1.28.0.0" newVersion="1.28.0.0" />
</dependentAssembly>
</assemblyBinding>
</runtime>
......
......
......@@ -9,10 +9,12 @@ using Coscine.Database.ReturnObjects;
using Coscine.Database.Util;
using Coscine.Logging;
using Coscine.Metadata;
using Coscine.Metadata.Models;
using Coscine.ResourceLoader;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Linq;
......@@ -32,8 +34,11 @@ namespace Coscine.Api.Project.Controllers
private readonly Emitter _emitter;
private readonly ActivatedFeaturesModel _activatedFeaturesModel;
private readonly ProjectRoleModel _projectRoleModel;
private readonly ProjectQuotaModel _projectQuotaModel;
private readonly VisibilityModel _visibilityModel;
private readonly CoscineLogger _coscineLogger;
private readonly AnalyticsLogObject _analyticsLogObject;
private readonly ProjectInstituteModel _projectInstituteModel;
/// <summary>
/// ProjectController constructor
......@@ -47,8 +52,11 @@ namespace Coscine.Api.Project.Controllers
_emitter = new Emitter(_configuration);
_activatedFeaturesModel = new ActivatedFeaturesModel();
_projectRoleModel = new ProjectRoleModel();
_projectQuotaModel = new ProjectQuotaModel();
_visibilityModel = new VisibilityModel();
_coscineLogger = new CoscineLogger(logger);
_analyticsLogObject = new AnalyticsLogObject();
_projectInstituteModel = new ProjectInstituteModel();
}
/// <summary>
......@@ -94,7 +102,7 @@ namespace Coscine.Api.Project.Controllers
/// <summary>
/// This returns the the project if the user has access to it
/// </summary>
/// <param name="id">Id of the resource</param>
/// <param name="id">Id of the project</param>
/// <returns>Ok or Statuscode 401</returns>
[HttpGet("[controller]/{id}")]
public ActionResult<ProjectObject> Get(string id)
......@@ -144,7 +152,17 @@ namespace Coscine.Api.Project.Controllers
}).OrderBy(element => element.DisplayName);
if (Request.Query != null && Request.Query["noanalyticslog"] != "true")
{
LogAnalytics("View Project", null, resources, id, user); // intentionally log as view project to help identify the related user action
var projectObject = _projectModel.CreateReturnObjectFromDatabaseObject(_projectModel.GetById(project.Id));
LogAnalytics("View Project", // intentionally log as view project to help identify the related user action
null,
resources,
id,
user,
GetProjectQuotas(project.Id),
null,
projectObject.Disciplines,
projectObject.Organizations,
projectObject.Visibility.DisplayName);
}
return Json(resources);
}
......@@ -157,7 +175,7 @@ namespace Coscine.Api.Project.Controllers
/// <summary>
/// Retrieves the quota for the selected project
/// </summary>
/// <param name="id">Id of the resource</param>
/// <param name="id">Id of the project</param>
/// <returns>Json object or Statuscode 401</returns>
[HttpGet("[controller]/{id}/quotas")]
public ActionResult<IEnumerable<ProjectQuota>> Quotas(string id)
......@@ -168,38 +186,7 @@ namespace Coscine.Api.Project.Controllers
var project = _projectModel.GetById(guidId);
if (_projectModel.HasAccess(user, project, UserRoles.Owner))
{
ProjectQuotaModel projectQuotaModel = new ProjectQuotaModel();
var projectQuotas =
projectQuotaModel.GetAllWhere((projectQuota) =>
projectQuota.ProjectId == guidId
&& projectQuota.ResourceType.Enabled == true)
.Select((projectQuota) => projectQuotaModel.CreateReturnObjectFromDatabaseObject(projectQuota));
ResourceModel resourceModel = new ResourceModel();
RDSResourceTypeModel rdsResourceTypeModel = new RDSResourceTypeModel();
var returnList = new List<dynamic>();
foreach (var projectQuota in projectQuotas)
{
// TODO: Cleanup quota and give it to every resource, this hard coded solution seems not scalable
if (projectQuota.ResourceType.DisplayName == "rds")
{
var resources = resourceModel.GetAllWhere((resource) =>
resource.TypeId == projectQuota.ResourceType.Id
&& (from connection in resource.ProjectResourceResourceIdIds
where connection.ProjectId == guidId
select connection).Any());
var size = resources.Sum((resource) =>
rdsResourceTypeModel.GetById(resource.ResourceTypeOptionId.Value).Size);
returnList.Add(new {
type = projectQuota.ResourceType.DisplayName,
available = projectQuota.Quotas,
allocated = size
});
}
}
return Json(returnList);
return Json(GetProjectQuotas(guidId));
}
else
{
......@@ -210,7 +197,7 @@ namespace Coscine.Api.Project.Controllers
/// <summary>
/// Updates the selected project
/// </summary>
/// <param name="id">Id of the resource</param>
/// <param name="id">Id of the project</param>
/// <returns>Ok or Statuscode 401</returns>
[HttpPost("[controller]/{id}")]
public IActionResult Update(string id)
......@@ -218,9 +205,19 @@ namespace Coscine.Api.Project.Controllers
var user = _authenticator.GetUser();
var projectObject = ObjectFactory<ProjectObject>.DeserializeFromStream(Request.Body);
var project = _projectModel.GetById(Guid.Parse(id));
if (_projectModel.HasAccess(user, project, UserRoles.Owner))
{
LogAnalytics("Edit Project", null, null, id, user);
LogAnalytics("Edit Project", // intentionally log as view project to help identify the related user action
null,
null,
id,
user,
GetProjectQuotas(project.Id),
_projectModel.GetMetadataCompleteness(projectObject).ToString(),
projectObject.Disciplines,
projectObject.Organizations,
projectObject.Visibility.DisplayName);
return Ok(_projectModel.UpdateByObject(project, projectObject));
}
else
......@@ -232,16 +229,26 @@ namespace Coscine.Api.Project.Controllers
/// <summary>
/// Deletes the selected project
/// </summary>
/// <param name="id">Id of the resource</param>
/// <param name="id">Id of the project</param>
/// <returns>Json object or Statuscode 401</returns>
[HttpDelete("[controller]/{id}")]
public IActionResult Delete(string id)
{
var user = _authenticator.GetUser();
var project = _projectModel.GetById(Guid.Parse(id));
var projectObject = _projectModel.CreateReturnObjectFromDatabaseObject(project);
if (_projectModel.HasAccess(user, project, UserRoles.Owner))
{
LogAnalytics("Delete Project", null, null, id, user);
LogAnalytics("Delete Project", // intentionally log as view project to help identify the related user action
null,
null,
id,
user,
GetProjectQuotas(project.Id),
null,
projectObject.Disciplines,
projectObject.Organizations,
projectObject.Visibility.DisplayName);
DeleteProject(project);
return Json(_projectModel.CreateReturnObjectFromDatabaseObject(project));
}
......@@ -376,8 +383,16 @@ namespace Coscine.Api.Project.Controllers
Project = project,
ProjectOwner = user
});
LogAnalytics("Add Project", null, null, project.Id.ToString(), user);
LogAnalytics("Add Project",
null,
null,
project.Id.ToString(),
user,
GetProjectQuotas(project.Id),
_projectModel.GetMetadataCompleteness(projectObject).ToString(),
projectObject.Disciplines,
projectObject.Organizations,
projectObject.Visibility.DisplayName);
return Json(_projectModel.CreateReturnObjectFromDatabaseObject(project));
}
......@@ -411,17 +426,33 @@ namespace Coscine.Api.Project.Controllers
/// <param name="resources">Resources</param>
/// <param name="projectId">Id of the project</param>
/// <param name="user">User object</param>
/// <param name="quotaSize"></param>
/// <param name="metadataCompleteness"></param>
/// <param name="disciplines"></param>
/// <param name="organizations"></param>
/// <param name="visibility"></param>
private void LogAnalytics(string operation,
IEnumerable<ProjectObject> projects = null,
IEnumerable<ResourceObject> resources = null,
string projectId = null,
User user = null
User user = null,
List<dynamic> quotaSize = null,
string metadataCompleteness = null,
IEnumerable<DisciplineObject> disciplines = null,
IEnumerable<OrganizationObject> organizations = null,
string visibility = null
)
{
if (CoscineLoggerConfiguration.IsLogLevelActivated(LogType.Analytics))
if (true)
//if (CoscineLoggerConfiguration.IsLogLevelActivated(LogType.Analytics))
{
var _rdfStoreConnector = new RdfStoreConnector(Program.Configuration.GetStringAndWait("coscine/local/virtuoso/additional/url"));
List<string> organizationsList = new List<string>();
List<string> disciplinesList = new List<string>();
_analyticsLogObject.Type = "Action";
_analyticsLogObject.Operation = operation;
_analyticsLogObject.MetadataCompleteness = metadataCompleteness;
if (projects != null)
{
......@@ -449,8 +480,75 @@ namespace Coscine.Api.Project.Controllers
_analyticsLogObject.RoleId = _projectRoleModel.GetGetUserRoleForProject(new Guid(_analyticsLogObject.ProjectId), user.Id).ToString();
}
}
if (quotaSize != null)
{
string serialized = "";
foreach(var resourceQuota in quotaSize)
{
serialized += $"[{resourceQuota.type}: {resourceQuota.allocated}/{resourceQuota.available}],";
}
serialized = serialized.Remove(serialized.Length - 1);
_analyticsLogObject.QuoteSize = serialized;
}
if (disciplines != null && disciplines.Count() > 0)
{
foreach (var discipline in disciplines)
{
disciplinesList.Add(discipline.DisplayNameEn);
}
_analyticsLogObject.Disciplines = disciplinesList;
}
if (organizations != null && organizations.Count() > 0)
{
foreach (var organization in organizations)
{
organizationsList.Add(organization.Url);
}
_analyticsLogObject.Organizations = organizationsList;
}
if (visibility != null)
{
_analyticsLogObject.Visibility = visibility;
}
_coscineLogger.AnalyticsLog(_analyticsLogObject);
}
}
private List<dynamic> GetProjectQuotas(Guid guidId)
{
ProjectQuotaModel projectQuotaModel = new ProjectQuotaModel();
var projectQuotas =
projectQuotaModel.GetAllWhere((projectQuota) =>
projectQuota.ProjectId == guidId
&& projectQuota.ResourceType.Enabled == true)
.Select((projectQuota) => projectQuotaModel.CreateReturnObjectFromDatabaseObject(projectQuota));
ResourceModel resourceModel = new ResourceModel();
RDSResourceTypeModel rdsResourceTypeModel = new RDSResourceTypeModel();
var returnList = new List<dynamic>();
foreach (var projectQuota in projectQuotas)
{
// TODO: Cleanup quota and give it to every resource, this hard coded solution seems not scalable
if (projectQuota.ResourceType.DisplayName == "rds")
{
var resources = resourceModel.GetAllWhere((resource) =>
resource.TypeId == projectQuota.ResourceType.Id
&& (from connection in resource.ProjectResourceResourceIdIds
where connection.ProjectId == guidId
select connection).Any());
var size = resources.Sum((resource) =>
rdsResourceTypeModel.GetById(resource.ResourceTypeOptionId.Value).Size);
returnList.Add(new
{
type = projectQuota.ResourceType.DisplayName,
available = projectQuota.Quotas,
allocated = size
});
}
}
return returnList;
}
}
}
......@@ -63,17 +63,17 @@
<Reference Include="Coscine.Configuration, Version=1.5.0.0, Culture=neutral, PublicKeyToken=ce3d7a32d7dc1e5a, processorArchitecture=MSIL">
<HintPath>..\packages\Coscine.Configuration.1.5.0\lib\net461\Coscine.Configuration.dll</HintPath>
</Reference>
<Reference Include="Coscine.Database, Version=1.27.0.0, Culture=neutral, PublicKeyToken=767d77427707b70a, processorArchitecture=MSIL">
<HintPath>..\packages\Coscine.Database.1.27.0\lib\net461\Coscine.Database.dll</HintPath>
<Reference Include="Coscine.Database, Version=1.28.0.0, Culture=neutral, PublicKeyToken=767d77427707b70a, processorArchitecture=MSIL">
<HintPath>..\packages\Coscine.Database.1.28.0-topic-1221-loggi0004\lib\net461\Coscine.Database.dll</HintPath>
</Reference>
<Reference Include="Coscine.Database.T4, Version=1.27.0.0, Culture=neutral, PublicKeyToken=84b4c404a0696261, processorArchitecture=MSIL">
<HintPath>..\packages\Coscine.Database.1.27.0\lib\net461\Coscine.Database.T4.dll</HintPath>
<Reference Include="Coscine.Database.T4, Version=1.28.0.0, Culture=neutral, PublicKeyToken=84b4c404a0696261, processorArchitecture=MSIL">
<HintPath>..\packages\Coscine.Database.1.28.0-topic-1221-loggi0004\lib\net461\Coscine.Database.T4.dll</HintPath>
</Reference>
<Reference Include="Coscine.JwtHandler, Version=1.2.0.0, Culture=neutral, PublicKeyToken=aaacf41df3a6253c, processorArchitecture=MSIL">
<HintPath>..\packages\Coscine.JwtHandler.1.2.0\lib\net461\Coscine.JwtHandler.dll</HintPath>
</Reference>
<Reference Include="Coscine.Logging, Version=1.2.0.0, Culture=neutral, PublicKeyToken=e1ed402bc3f6525e, processorArchitecture=MSIL">
<HintPath>..\packages\Coscine.Logging.1.2.0\lib\net461\Coscine.Logging.dll</HintPath>
<Reference Include="Coscine.Logging, Version=1.3.0.0, Culture=neutral, PublicKeyToken=e1ed402bc3f6525e, processorArchitecture=MSIL">
<HintPath>..\packages\Coscine.Logging.1.3.0-topic-1221-loggi0001\lib\net461\Coscine.Logging.dll</HintPath>
</Reference>
<Reference Include="Coscine.Metadata, Version=1.5.0.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\Coscine.Metadata.1.5.0\lib\net461\Coscine.Metadata.dll</HintPath>
......
......
......@@ -7,9 +7,9 @@
<package id="Coscine.Action" version="1.17.0" targetFramework="net472" />
<package id="Coscine.ApiCommons" version="1.11.0" targetFramework="net472" />
<package id="Coscine.Configuration" version="1.5.0" targetFramework="net472" />
<package id="Coscine.Database" version="1.27.0" targetFramework="net472" />
<package id="Coscine.Database" version="1.28.0-topic-1221-loggi0004" targetFramework="net472" />
<package id="Coscine.JwtHandler" version="1.2.0" targetFramework="net472" />
<package id="Coscine.Logging" version="1.2.0" targetFramework="net472" />
<package id="Coscine.Logging" version="1.3.0-topic-1221-loggi0001" targetFramework="net472" />
<package id="Coscine.Metadata" version="1.5.0" targetFramework="net472" />
<package id="Coscine.ProxyApi" version="1.3.0" targetFramework="net472" />
<package id="Coscine.ResourceConfiguration" version="1.3.0" targetFramework="net472" />
......
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please to comment