Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found
Select Git revision
  • dev
  • main
  • Issue/3142-kpiGenerator
  • Hotfix/3115-userReportingEmpty2
  • Hotfix/3115-userReportingEmpty
  • Issue/3073-kpi
  • Issue/2492-respOrg
  • Issue/3005-kpiReportingBroken
  • Issue/2982-kpiDataPub
  • gitkeep
  • Issue/2847-reporting
  • Issue/2850-removeGrantId
  • Issue/2432-publicationKpi
  • Hotfix/xxxx-rors
  • Issue/2666-adminCronjobs-theSequal
  • Issue/2666-adminCronjobs
  • Issue/2568-betterLogging
  • Issue/2518-docs
  • Hotfix/2388-sensitive
  • Issue/2330-fixNaNQuotainAdmin
  • Fix/xxxx-organization
  • Fix/xxxx-wrap
  • Hotfix/2332-userInstitutesInReporting
  • Issue/2283-activityFix
  • Issue/2304-virtuosoRoars
  • Fix/xxxx-indexOutOfRange
  • Fix/xxxx-minorFixes
  • Issue/2186-systemStatusReporting
  • Issue/2184-kpiGeneratorProject
  • Issue/2183-kpiGeneratorResource
  • Issue/2185-kpiGeneratorAP
  • Issue/2182-kpiGeneratorUser
  • Issue/2181-kpiGeneratorBase
  • v0.1.0
  • v0.1.1
  • v0.1.10
  • v0.1.11
  • v0.1.12
  • v0.1.13
  • v0.1.14
  • v0.1.15
  • v0.1.16
  • v0.1.17
  • v0.1.18
  • v0.1.19
  • v0.1.2
  • v0.1.20
  • v0.1.21
  • v0.1.22
  • v0.1.23
  • v0.1.3
  • v0.1.4
  • v0.1.5
  • v0.1.6
  • v0.1.7
  • v0.1.8
  • v0.1.9
  • v1.0.1
  • v1.0.2
  • v1.0.3
  • v1.0.4
  • v1.0.5
  • v1.0.6
  • v1.0.7
  • v1.0.8
  • v1.0.9
  • v1.1.0
  • v1.1.1
  • v1.2.0
  • v1.2.1
  • v1.2.10
  • v1.2.2
  • v1.2.3
  • v1.2.4
  • v1.2.5
  • v1.2.6
  • v1.2.7
  • v1.2.8
  • v1.2.9
79 results

Target

Select target project
  • Coscine / backend / scripts / KPI Reporting Generator
1 result
Select Git revision
  • dev
  • main
  • Issue/3142-kpiGenerator
  • Hotfix/3115-userReportingEmpty2
  • Hotfix/3115-userReportingEmpty
  • Issue/3073-kpi
  • Issue/2492-respOrg
  • Issue/3005-kpiReportingBroken
  • Issue/2982-kpiDataPub
  • gitkeep
  • Issue/2847-reporting
  • Issue/2850-removeGrantId
  • Issue/2432-publicationKpi
  • Hotfix/xxxx-rors
  • Issue/2666-adminCronjobs-theSequal
  • Issue/2666-adminCronjobs
  • Issue/2568-betterLogging
  • Issue/2518-docs
  • Hotfix/2388-sensitive
  • Issue/2330-fixNaNQuotainAdmin
  • Fix/xxxx-organization
  • Fix/xxxx-wrap
  • Hotfix/2332-userInstitutesInReporting
  • Issue/2283-activityFix
  • Issue/2304-virtuosoRoars
  • Fix/xxxx-indexOutOfRange
  • Fix/xxxx-minorFixes
  • Issue/2186-systemStatusReporting
  • Issue/2184-kpiGeneratorProject
  • Issue/2183-kpiGeneratorResource
  • Issue/2185-kpiGeneratorAP
  • Issue/2182-kpiGeneratorUser
  • Issue/2181-kpiGeneratorBase
  • v0.1.0
  • v0.1.1
  • v0.1.10
  • v0.1.11
  • v0.1.12
  • v0.1.13
  • v0.1.14
  • v0.1.15
  • v0.1.16
  • v0.1.17
  • v0.1.18
  • v0.1.19
  • v0.1.2
  • v0.1.20
  • v0.1.21
  • v0.1.22
  • v0.1.23
  • v0.1.3
  • v0.1.4
  • v0.1.5
  • v0.1.6
  • v0.1.7
  • v0.1.8
  • v0.1.9
  • v1.0.1
  • v1.0.2
  • v1.0.3
  • v1.0.4
  • v1.0.5
  • v1.0.6
  • v1.0.7
  • v1.0.8
  • v1.0.9
  • v1.1.0
  • v1.1.1
  • v1.2.0
  • v1.2.1
  • v1.2.10
  • v1.2.2
  • v1.2.3
  • v1.2.4
  • v1.2.5
  • v1.2.6
  • v1.2.7
  • v1.2.8
  • v1.2.9
79 results
Show changes

Commits on Source 4

57 files
+ 353
167
Compare changes
  • Side-by-side
  • Inline

Files

+0 −0
Original line number Diff line number Diff line
+27 −0
Original line number Diff line number Diff line
# Development container for dotnet
FROM mcr.microsoft.com/devcontainers/dotnet:8.0 as develop

ARG USERNAME=vscode
ARG USER_UID=1000
ARG USER_GID=$USER_UID

# Remove any existing user with the same UID (if it's not the specified user)
RUN if id -u $USER_UID >/dev/null 2>&1; then \
        existing_user=$(getent passwd $USER_UID | cut -d: -f1); \
        if [ "$existing_user" != "$USERNAME" ]; then \
            userdel -f $existing_user; \
        fi; \
    fi

# Change the user's GID and UID
RUN groupmod -g $USER_GID $USERNAME \
    && usermod -u $USER_UID -g $USER_GID $USERNAME

# Change user folder owner and group
RUN chown -R $USER_GID:$USER_GID /home/$USERNAME

# [Optional] Set the default user. Omit if you want to keep the default as root.
USER $USERNAME 

# Add nuget sources for private packages (here: api-client)
RUN dotnet nuget add source "https://git.rwth-aachen.de/api/v4/projects/88930/packages/nuget/index.json" -n "api-client"
 No newline at end of file
+22 −0
Original line number Diff line number Diff line
version: "3.9"

services:

  app:
    build:
      target: develop
    user: vscode
    userns_mode: keep-id:uid=1000,gid=1000
    environment:
      SSH_AUTH_SOCK: /.ssh/ssh-agent.sock
    command: /bin/sh -c "while sleep 2s; do :; done"
    volumes:
      - ..:/workspace/kpi-generator:cached
      - ./.vscode-server:/home/vscode/.vscode-server/:cached
      - ${SSH_AUTH_SOCK}:/.ssh/ssh-agent.sock
    networks:
      - default

networks:
  default:
    driver: bridge
+32 −0
Original line number Diff line number Diff line
{
    "name": "KPI Reporting Generator",
    "dockerComposeFile": [
        "compose.yml"
    ],
    "service": "app",
    "workspaceFolder": "/workspace/kpi-generator",
    "updateRemoteUserUID": false,
    "remoteUser": "vscode",
    "containerUser": "vscode",
    "postAttachCommand": "bash",
    "customizations": {
        "vscode": {
            "settings": {
                "NugetGallery.sources": [
                    "{\"name\":\"nuget.org\",\"url\":\"https://api.nuget.org/v3/index.json\"}",
                    "{\"name\":\"api-client\",\"url\":\"https://git.rwth-aachen.de/api/v4/projects/88930/packages/nuget/index.json\"}"
                ],
                "nuget.includePrereleasePackageVersions": true
            },
            "extensions": [
                "ms-dotnettools.csdevkit",
                "ms-azuretools.vscode-docker",
                "ms-dotnettools.csharp",
                "mhutchie.git-graph",
                "mutantdino.resourcemonitor",
                "patcx.vscode-nuget-gallery"
            ]
        }
    },
    "forwardPorts": []
}
 No newline at end of file
+15 −0
Original line number Diff line number Diff line
/.devcontainer/.vscode-server/*
!/.devcontainer/.vscode-server/.gitkeep

/.devcontainer/.data/*
!/.devcontainer/.data/.gitkeep

.logs/
Output/*
internallog.txt

## Ignore the secrets settings
appsettings.Development.json
appsettings.Staging.json
appsettings.Production.json

## Ignore Visual Studio temporary files, build results, and
## files generated by popular Visual Studio add-ons.

+7 −2
Original line number Diff line number Diff line
@@ -2,14 +2,14 @@ include:
  - project: coscine/tools/gitlab-ci-templates
    file: 
      - /dotnet.yml
      - /container.yml

stages:
  - build
  - publish


variables:
  DOTNET_MAIN_PROJECT_FOLDER: "KPI Generator"
  DOTNET_MAIN_PROJECT_FOLDER: "KpiGenerator"

build-branch:
  extends: .build-branch
@@ -22,3 +22,8 @@ publish-gitlab-release:
  
publish:
  extends: .publish-artifact-release

publish-container:
  variables:
    CONTAINER_CONTEXT_FOLDER_PATH: $CI_PROJECT_DIR/src/$DOTNET_MAIN_PROJECT_FOLDER
  extends: .publish-container-gitlab

.vscode/launch.json

0 → 100644
+22 −0
Original line number Diff line number Diff line
{
    // Use IntelliSense to learn about possible attributes.
    // Hover to view descriptions of existing attributes.
    // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
    "version": "0.2.0",
    "configurations": [
        {
            "name": "C#: KPI Reporting Generator Debug",
            "type": "coreclr",
            "request": "launch",
            "preLaunchTask": "dotnet: build",
            "program": "${workspaceFolder}/src/KpiGenerator/bin/Debug/net8.0/Coscine.KpiGenerator.dll",
            "args": [],
            "cwd": "${workspaceFolder}/src/KpiGenerator",
            "stopAtEntry": false,
            "console": "internalConsole",
            "env": {
                "DOTNET_ENVIRONMENT": "Development"
            }
        }
    ]
}
 No newline at end of file

.vscode/settings.json

0 → 100644
+1 −0
Original line number Diff line number Diff line
{}
 No newline at end of file
+0 −9
Original line number Diff line number Diff line
using System.Text.Json.Serialization;

namespace Coscine.KpiGenerator.Models;

public record PublicationRequestReport
{
    [JsonPropertyName("Timestamp")]
    public DateTime Timestamp { get; set; }
}
 No newline at end of file

src/KPI Generator/nlog.config

deleted100644 → 0
+0 −81
Original line number Diff line number Diff line
<?xml version="1.0" encoding="utf-8" ?>
<nlog xmlns="http://www.nlog-project.org/schemas/NLog.xsd"
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      throwConfigExceptions="true"
      throwExceptions="false"
	  internalLogFile="Logs/internal-nlog.txt"
	  internalLogLevel="Trace">

	<targets>
		<!-- Write logs to File -->
		<target xsi:type="FallbackGroup" 
			name="fileGroup">
			<target 
				xsi:type="File" 
				name="fileLogD" 
				fileName="D:/coscine/logs/${assembly-name}/${assembly-version}/log-${shortdate}.log"
				maxArchiveFiles="7"
			>
				<layout xsi:type="CompoundLayout">
					<layout xsi:type="JsonLayout" EscapeForwardSlash="true">
						<attribute layout="${longdate}" name="Timestamp"/>
						<attribute layout="${level:upperCase=true}" name="Level"/>
						<attribute layout="${message}" name="Message"/>
						<attribute layout="${exception:format=tostring,StackTrace}" name="Exception"/>
						<attribute layout="${ndlc}" name="Context"/>
						<attribute layout="${event-properties:item=Metric}" name="Alarm" encode="false"/>
						<attribute name="EventProperties" encode="false" >
							<layout xsi:type='JsonLayout' includeAllProperties="true"  maxRecursionLimit="2"/>
						</attribute>
					</layout>
					<layout xsi:type='SimpleLayout' text="," />
				</layout>
			</target>
			<target 
				xsi:type="File" 
				name="fileLogC" 
				fileName="C:/coscine/logs/${assembly-name}/${assembly-version}/log-${shortdate}.log"
				maxArchiveFiles="7"
			>
				<layout xsi:type="CompoundLayout">
					<layout xsi:type="JsonLayout" EscapeForwardSlash="true">
						<attribute layout="${longdate}" name="Timestamp"/>
						<attribute layout="${level:upperCase=true}" name="Level"/>
						<attribute layout="${message}" name="Message"/>
						<attribute layout="${exception:format=tostring,StackTrace}" name="Exception"/>
						<attribute layout="${ndlc}" name="Context"/>
						<attribute layout="${event-properties:item=Metric}" name="Alarm" encode="false"/>
						<attribute name="EventProperties" encode="false" >
							<layout xsi:type='JsonLayout' includeAllProperties="true"  maxRecursionLimit="2"/>
						</attribute>
					</layout>
					<layout xsi:type='SimpleLayout' text="," />
				</layout>
			</target>
		</target>

		<!-- Write colored logs to Console -->
		<target name="consoleLog" xsi:type="ColoredConsole" layout="[${uppercase:${level}}]: ${message}">
			<highlight-row condition="level == LogLevel.Debug" foregroundColor="DarkGray" />
			<highlight-row condition="level == LogLevel.Info" foregroundColor="White" />
			<highlight-row condition="level == LogLevel.Warn" foregroundColor="Yellow" />
			<highlight-row condition="level == LogLevel.Error" foregroundColor="DarkRed" />
			<highlight-row condition="level == LogLevel.Fatal" foregroundColor="Red" backgroundColor="White" />
		</target>
	</targets>


	<rules>
		<!--All logs, including from Microsoft, Level Trace-->
		<logger name="*" minlevel="Trace" writeTo="fileGroup">
		</logger>

		<!--All logs, including from Microsoft, Level Info-->
		<logger name="*" minlevel="Info" writeTo="consoleLog">
			<filters defaultAction="Log">
				<when condition="contains('${ndlc}','/api/heartbeat')" action="Ignore"/>
			</filters>
		</logger>

	</rules>
</nlog>
 No newline at end of file
+1 −1
Original line number Diff line number Diff line
@@ -3,7 +3,7 @@ Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17
VisualStudioVersion = 17.2.32526.322
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "KPI Generator", "KPI Generator\KPI Generator.csproj", "{2B402E93-467B-49C1-8350-9277BDEDA9C3}"
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "KpiGenerator", "KpiGenerator\KpiGenerator.csproj", "{2B402E93-467B-49C1-8350-9277BDEDA9C3}"
EndProject
Global
	GlobalSection(SolutionConfigurationPlatforms) = preSolution
+33 −0
Original line number Diff line number Diff line
FROM mcr.microsoft.com/dotnet/sdk:8.0 AS build-env
WORKDIR /App

# Copy everything
COPY . ./

# Add nuget sources for private packages (here: api-client)
RUN dotnet nuget add source "https://git.rwth-aachen.de/api/v4/projects/88930/packages/nuget/index.json" -n "api-client"

# Restore as distinct layers
RUN dotnet restore

# Build and publish a release
RUN dotnet publish -c Release -o out

# Build runtime image
FROM mcr.microsoft.com/dotnet/aspnet:8.0

# Install cron and other necessary packages
RUN apt-get update && \
    apt-get install -y cron && \
    apt-get clean

WORKDIR /App
COPY --from=build-env /App/out .

# Set the build-time argument and default environment variable
ENV DOTNET_ENVIRONMENT=Development

# Create the log file
RUN touch /var/log/cron.log

ENTRYPOINT /bin/sh -c "/App/Coscine.KpiGenerator all"
 No newline at end of file
+11 −5
Original line number Diff line number Diff line
@@ -7,7 +7,7 @@
		<AssemblyName>Coscine.KpiGenerator</AssemblyName>
		<ImplicitUsings>enable</ImplicitUsings>
		<Nullable>enable</Nullable>
		<Version>1.2.3</Version>
		<Version>1.2.4</Version>
	</PropertyGroup>

	<PropertyGroup>
@@ -21,7 +21,7 @@
		<PackageReference Include="AutoMapper" Version="12.0.1" />
		<PackageReference Include="AutoMapper.Extensions.Microsoft.DependencyInjection" Version="12.0.1" />
		<PackageReference Include="CommandLineParser" Version="2.9.1" />
		<PackageReference Include="Coscine.ApiClient" Version="1.6.0" />
		<PackageReference Include="Coscine.ApiClient" Version="1.9.2" />
		<PackageReference Include="dotNetRdf.Core" Version="3.1.1" />
		<PackageReference Include="GitLabApiClient" Version="1.8.1-beta.5" />
		<PackageReference Include="Microsoft.Extensions.Caching.Memory" Version="8.0.0" />
@@ -35,6 +35,12 @@
	</ItemGroup>

	<ItemGroup>
		<None Update="appsettings.json">
		  <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
		</None>
		<None Update="appsettings.Development.json">
		  <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
		</None>
		<None Update="nlog.config">
			<CopyToOutputDirectory>Always</CopyToOutputDirectory>
		</None>
+9 −6
Original line number Diff line number Diff line
@@ -17,7 +17,8 @@ public class MappingProfiles : Profile
            .ForMember(pr => pr.Deleted, opt => opt.MapFrom(dto => dto.Deleted))
            .ForMember(pr => pr.ProjectVisibility, opt => opt.MapFrom(dto => dto.Visibility))
            .ForMember(pr => pr.Users, opt => opt.MapFrom(dto => dto.ProjectRoles.Count))
            .ForMember(pr => pr.ResourceTypeQuota, opt => opt.MapFrom(dto => dto.ProjectQuota));
            .ForMember(pr => pr.ResourceTypeQuota, opt => opt.MapFrom(dto => dto.ProjectQuota))
            .ForMember(pr => pr.PublicationRequests, opt => opt.MapFrom(dto => dto.PublicationRequests));

        CreateMap<ResourceAdminDto, ResourceReport>()
            .ForMember(rr => rr.Id, opt => opt.MapFrom(dto => dto.Id))
@@ -50,12 +51,12 @@ public class MappingProfiles : Profile
            .ForMember(lp => lp.DisplayName, opt => opt.MapFrom(dto => dto.DisplayName));

        CreateMap<UserInstituteDto, Organization>()
            .ForMember(o => o.ReadOnly, opt => opt.MapFrom(dto => dto.VarReadOnly))
            .ForMember(o => o.ReadOnly, opt => opt.MapFrom(dto => dto.ReadOnly))
            .ForMember(o => o.Name, opt => opt.MapFrom(dto => dto.DisplayName))
            .ForMember(o => o.RorUrl, opt => opt.MapFrom(dto => dto.Uri));

        CreateMap<UserOrganizationDto, Organization>()
            .ForMember(o => o.ReadOnly, opt => opt.MapFrom(dto => dto.VarReadOnly))
            .ForMember(o => o.ReadOnly, opt => opt.MapFrom(dto => dto.ReadOnly))
            .ForMember(o => o.Name, opt => opt.MapFrom(dto => dto.DisplayName))
            .ForMember(o => o.RorUrl, opt => opt.MapFrom(dto => dto.Uri));

@@ -93,7 +94,9 @@ public class MappingProfiles : Profile
            .ForMember(rtq => rtq.Allocated, opt => opt.MapFrom(dto => dto.Allocated))
            .ForMember(rtq => rtq.Maximum, opt => opt.MapFrom(dto => dto.Maximum));

        CreateMap<ActivityLogDto, PublicationRequestReport>()
            .ForMember(pr => pr.Timestamp, opt => opt.MapFrom(dto => dto.ActivityTimestamp));
        CreateMap<ProjectPublicationRequestDto, PublicationRequestReport>()
            .ForMember(prr => prr.PublicationServiceRorId, opt => opt.MapFrom(dto => dto.PublicationServiceRorId))
            .ForMember(prr => prr.DateCreated, opt => opt.MapFrom(dto => dto.DateCreated))
            .ForMember(prr => prr.Resources, opt => opt.MapFrom(dto => dto.Resources));
        }
}
+1 −1
Original line number Diff line number Diff line
@@ -5,7 +5,7 @@
/// </summary>
public class ApplicationProfileReport
{
    public List<string> Titles { get; set; } = new();
    public IReadOnlyList<string> Titles { get; set; } = [];
    public string Uri { get; set; } = null!;
    public string? Publisher { get; set; } = null!;
    public string? Rights { get; set; } = null!;
+24 −0
Original line number Diff line number Diff line
@@ -15,6 +15,17 @@ public class ReportingConfiguration
    /// </summary>
    public bool IsEnabled { get; init; }

    /// <summary>
    /// API token for the coscine API.
    /// Requires the administrator role.
    /// </summary>
    public string ApiKey { get; set; } = null!;

    /// <summary>
    /// Address of the Coscine API.
    /// </summary>
    public string Endpoint { get; set; } = null!;

    /// <summary>
    /// Local storage configuration settings.
    /// </summary>
@@ -23,6 +34,14 @@ public class ReportingConfiguration
    /// </value>
    public LocalStorageConfiguration? Local { get; init; }

    /// <summary>
    /// Logger configuration settings.
    /// </summary>
    /// <value>
    /// The logger storage configuration settings, or <c>null</c> if not configured.
    /// </value>
    public LoggerConfiguration? Logger { get; init; }

    /// <summary>
    /// GitLab configuration settings.
    /// </summary>
@@ -67,4 +86,9 @@ public class ReportingConfiguration
        /// </summary>
        public Organization? OtherOrganization { get; init; }
    }

    /// <summary>
    /// Represents the configuration settings for the logger.
    /// </summary>
    public record LoggerConfiguration(string? LogLevel, string? LogHome);
}
+16 −0
Original line number Diff line number Diff line
using System.Text.Json.Serialization;
using Coscine.ApiClient.Core.Model;

namespace Coscine.KpiGenerator.Models;

public record PublicationRequestReport
{
    [JsonPropertyName("PublicationServiceRorId")]
    public Uri PublicationServiceRorId { get; init; } = null!;

    [JsonPropertyName("DateCreated")]
    public DateTime DateCreated { get; set; }

    [JsonPropertyName("Resources")]
    public IReadOnlyList<ResourceMinimalDto> Resources { get; set; } = null!;
}
 No newline at end of file
+38 −13
Original line number Diff line number Diff line
@@ -19,9 +19,14 @@ namespace Coscine.KpiGenerator;
public class Program
{
    private static IServiceProvider _serviceProvider = null!;
    private static string? _environmentName;

    public static int Main(string[] args)
    public static async Task<int> Main(string[] args)
    {
        _environmentName = Environment.GetEnvironmentVariable("DOTNET_ENVIRONMENT");

        Console.WriteLine($"Running in environment: {_environmentName ?? "environment is null"}");

        InitializeServices();

        var logger = _serviceProvider.GetRequiredService<ILogger<Program>>();
@@ -37,13 +42,13 @@ public class Program
                SystemReportingOptions
            >(args);

            var result = parserResult.MapResult(
                (CompleteReportingOptions opts) => _serviceProvider.GetRequiredService<CompleteReporting>().RunAsync(opts).Result,
                (ProjectReportingOptions opts) => _serviceProvider.GetRequiredService<ProjectReporting>().RunAsync(opts).Result,
                (ResourceReportingOptions opts) => _serviceProvider.GetRequiredService<ResourceReporting>().RunAsync(opts).Result,
                (UserReportingOptions opts) => _serviceProvider.GetRequiredService<UserReporting>().RunAsync(opts).Result,
                (ApplicationProfileReportingOptions opts) => _serviceProvider.GetRequiredService<ApplicationProfileReporting>().RunAsync(opts).Result,
                (SystemReportingOptions opts) => _serviceProvider.GetRequiredService<SystemReporting>().RunAsync(opts).Result,
            var result = await parserResult.MapResult(
                (CompleteReportingOptions opts) => _serviceProvider.GetRequiredService<CompleteReporting>().RunAsync(opts),
                (ProjectReportingOptions opts) => _serviceProvider.GetRequiredService<ProjectReporting>().RunAsync(opts),
                (ResourceReportingOptions opts) => _serviceProvider.GetRequiredService<ResourceReporting>().RunAsync(opts),
                (UserReportingOptions opts) => _serviceProvider.GetRequiredService<UserReporting>().RunAsync(opts),
                (ApplicationProfileReportingOptions opts) => _serviceProvider.GetRequiredService<ApplicationProfileReporting>().RunAsync(opts),
                (SystemReportingOptions opts) => _serviceProvider.GetRequiredService<SystemReporting>().RunAsync(opts),
                HandleParseError
            );

@@ -89,7 +94,8 @@ public class Program

        // Add Consul as a configuration source
        var configuration = configBuilder
            .AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
            .AddJsonFile("appsettings.json", optional: false, reloadOnChange: true)
            .AddJsonFile($"appsettings.{_environmentName}.json", optional: true, reloadOnChange: true)
                        .AddConsul(
                "coscine/Coscine.Infrastructure/KpiGenerator/appsettings",
                options =>
@@ -102,6 +108,18 @@ public class Program
                    options.OnLoadException = exceptionContext => exceptionContext.Ignore = true;
                }
            )
            .AddConsul(
                $"coscine/Coscine.Infrastructure/KpiGenerator/appsettings.{_environmentName}.json",
                options =>
                {
                    options.ConsulConfigurationOptions =
                        cco => cco.Address = new Uri(consulUrl);
                    options.Optional = true;
                    options.ReloadOnChange = true;
                    options.PollWaitTime = TimeSpan.FromSeconds(5);
                    options.OnLoadException = exceptionContext => exceptionContext.Ignore = true;
                }
            )
            .AddEnvironmentVariables()
            .Build();

@@ -126,6 +144,14 @@ public class Program
            builder.AddNLog();
        });

        var reportingConfiguration = new ReportingConfiguration();
        configuration.Bind(ReportingConfiguration.Section, reportingConfiguration);

        // Set the default LogLevel
        LogManager.Configuration.Variables["logLevel"] = reportingConfiguration.Logger?.LogLevel ?? "Trace";
        // Set the log location
        LogManager.Configuration.Variables["logHome"] = reportingConfiguration.Logger?.LogHome ?? Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Logs");

        // Add AutoMapper
        services.AddAutoMapper(typeof(Program));

@@ -162,7 +188,7 @@ public class Program
        }
    }

    private static bool HandleParseError(IEnumerable<Error> errs)
    private static Task<bool> HandleParseError(IEnumerable<Error> errs)
    {
        var logger = _serviceProvider.GetService<ILogger<Program>>();

@@ -183,10 +209,9 @@ public class Program
        }

        // Since there were errors, we typically return false to indicate that the program should not proceed
        return false;
        return Task.FromResult(false);
    }


    public static TResult SanitizeOptions<TResult>(TResult unsanitizedOptions)
    {
        // Sanitize all input that accepts an array or is a list of inputs.
+4 −31
Original line number Diff line number Diff line
@@ -49,10 +49,10 @@ public class ProjectReporting

        var configuration = new Configuration()
        {
            BasePath = "http://localhost:7206/coscine",
            BasePath = $"{_reportingConfiguration.Endpoint.TrimEnd('/')}/coscine",
            ApiKeyPrefix = { { "Authorization", "Bearer" } },
            ApiKey = { { "Authorization", ApiConfigurationUtil.GenerateAdminToken(ApiConfigurationUtil.RetrieveJwtConfiguration()) } },
            Timeout = 300000, // 5 minutes
            ApiKey = { { "Authorization", _reportingConfiguration.ApiKey } },
            Timeout = 300000 // 5 minutes
        };

        AdminApi = new AdminApi(configuration);
@@ -81,7 +81,7 @@ public class ProjectReporting
    {
        _logger.LogDebug("Woring on projects asynchronously...");
        var projects = PaginationHelper.GetAllAsync<ProjectAdminDtoPagedResponse, ProjectAdminDto>(
                (currentPage) => AdminApi.GetAllProjectsAsync(includeDeleted: false, includeQuotas: true, pageNumber: currentPage, pageSize: 50));
                (currentPage) => AdminApi.GetAllProjectsAsync(includeDeleted: false, includeQuotas: true, includePublicationRequests: true, pageNumber: currentPage, pageSize: 50));

        var reportingFiles = new List<ReportingFileObject>();
        var returnObjects = new List<ProjectReport>();
@@ -91,33 +91,6 @@ public class ProjectReporting
        {
            _logger.LogDebug("Processing project {projectId}...", project.Id);
            var returnObject = _mapper.Map<ProjectReport>(project);

            // Get the activity logs for publication requests for the project
            var utcTimestampBefore = DateTime.UtcNow.Date;
            var utcTimestampAfter = utcTimestampBefore.AddDays(-1);
            _logger.LogDebug("Processing activity logs from {timestampAfter} to {timestampBefore}...", utcTimestampAfter.ToString("yyyy-MM-dd HH:mm:ss"), utcTimestampBefore.ToString("yyyy-MM-dd HH:mm:ss"));
            //lang=regex
            var regex = @$"{project.Slug}.*publication"; // The slug is used to filter the logs to only those related to the project
            _logger.LogDebug("Processing logs with regular expression {regex}...", regex);
            var activityLogs = new List<ActivityLogDto>();
            await foreach (var log in PaginationHelper.GetAllAsync<ActivityLogDtoPagedResponse, ActivityLogDto>(
                currentPage => AdminApi.GetAllActivityLogsAsync(
                    activityTimestampBefore: utcTimestampBefore,
                    activityTimestampAfter: utcTimestampAfter,
                    regularExpression: regex,
                    guid: null, // Note on project ID vs. slug
                    httpMethod: CoscineHttpMethod.POST,
                    pageNumber: currentPage,
                    pageSize: 50)))
            {
                if (log is not null)
                {
                    activityLogs.Add(log);
                }
            }
            _logger.LogDebug("{n} activity logs processed.", activityLogs.Count);
            returnObject.PublicationRequests = _mapper.Map<List<PublicationRequestReport>>(activityLogs);
            _logger.LogDebug("Processed publication requests...");
            returnObjects.Add(returnObject);
        }
        _logger.LogInformation("{n} projects mapped.", returnObjects.Count);
+5 −12
Original line number Diff line number Diff line
@@ -5,20 +5,13 @@ using Microsoft.Extensions.Options;

namespace Coscine.KpiGenerator.Utils;

public class FileSystemStorageService : IStorageService
{
    private readonly ReportingConfiguration _reportingConfiguration;
    private readonly ILogger<FileSystemStorageService> _logger;
    private string? _localStoragePath;

    public FileSystemStorageService(
public class FileSystemStorageService(
    ILogger<FileSystemStorageService> logger,
        IOptionsMonitor<ReportingConfiguration> reportingConfiguration
    )
    IOptionsMonitor<ReportingConfiguration> reportingConfiguration) : IStorageService
{
        _reportingConfiguration = reportingConfiguration.CurrentValue;
        _logger = logger;
    }
    private readonly ReportingConfiguration _reportingConfiguration = reportingConfiguration.CurrentValue;
    private readonly ILogger<FileSystemStorageService> _logger = logger;
    private string? _localStoragePath;

    public Task EnsureInformationIsSetAndCorrectAsync()
    {
+19 −0
Original line number Diff line number Diff line
{
  "ReportingConfiguration": {
    "ApiKey": null,
    "Endpoint": null,
    "GitLab": {
      "Token": null,
      "Branch": null
    }
  },
  "KpiConfiguration": {
    "SystemKpi": {
      "Maintenance": {
        "Username": null,
        "Password": null,
        "BasicAuthToken": null
      }
    }
  }
}
 No newline at end of file
+12 −6
Original line number Diff line number Diff line
{
  "ReportingConfiguration": {
    "IsEnabled": true,
    "ApiKey": null,
    "Endpoint": null,
    "Local": {
      "StoragePath": "C:/coscine/reporting/"
    },
    "Logger": {
      "LogLevel": "Information",
      "LogHome": "./Logs"
    },
    "GitLab": {
      "HostUrl": "https://git.rwth-aachen.de/",
      "Token": "",
      "Branch": "",
      "Token": null,
      "Branch": null,
      "ProjectId": 76546
    },
    "Organizations": {
@@ -34,10 +40,10 @@
    "SystemKpi": {
      "FileName": "system_status.json",
      "Maintenance": {
        "Url": "",
        "Username": "",
        "Password": "",
        "BasicAuthToken": ""
        "Url": "https://maintenance.itc.rwth-aachen.de/ticket/api/coscine/tickets",
        "Username": null,
        "Password": null,
        "BasicAuthToken": null
      }
    },
    "UserKpi": {
+54 −0
Original line number Diff line number Diff line
<?xml version="1.0" encoding="utf-8" ?>
<nlog xmlns="http://www.nlog-project.org/schemas/NLog.xsd"
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        autoReload="true"
        internalLogLevel="Warn"
        internalLogFile="./internal_logs/internallog.txt">

	<variable name="logHome" value="${basedir}/Logs" />
	<variable name="logLevel" value="Warn" />
	
	<!-- This variable is used to remove ANSI escape codes from the log message. -->
	<variable name="message_raw" value="${replace:inner=${message}:searchFor=\x1B\[[0-9;]*[A-Za-z]:replaceWith=:regex=true}" />

	<!--Possible aspnet- variables: https://nlog-project.org/config/?tab=layout-renderers&search=package:nlog.web-->
	<variable name="layout" value="${longdate} | [${level:uppercase=true}] ${message_raw} ${exception:format=tostring}" />

	<targets>
		<!-- Write logs to File -->
		<target
			name="fullfile"
			xsi:type="File"
			layout="${var:layout}"
			fileName="${var:logHome}/full_${shortdate}.log"
			keepFileOpen="false"
			archiveFileName="${var:logHome}/Archive/full_${shortdate}.log"
			archiveNumbering="Sequence"
			archiveEvery="Day"
			maxArchiveFiles="7"
		/>

		<!-- Write colored logs to Console -->
		<target name="consoleLog" xsi:type="ColoredConsole" layout="[${uppercase:${level}}]: ${message}">
			<highlight-word text="[TRACE]" foregroundColor="DarkGray" />
			<highlight-word text="[Debug]" foregroundColor="Gray" />
			<highlight-word text="[INFO]" foregroundColor="Green" />
			<highlight-word text="[WARN]" foregroundColor="Yellow" />
			<highlight-word text="[ERROR]" foregroundColor="Red" />
			<highlight-word text="[FATAL]" foregroundColor="DarkRed" backgroundColor="White" />
		</target>
	</targets>


	<rules>
		<!--All logs, including Microsoft-->
		<logger name="*" minlevel="${var:logLevel}" writeTo="fullfile" />

		<!--Skip non-critical Microsoft logs and so log only own logs (BlackHole).-->
		<logger name="Microsoft.*" maxlevel="Info" final="true" />
		<logger name="System.Net.Http.*" maxlevel="Info" final="true" />
		
		<!--All logs, including from Microsoft, Level Info-->
		<logger name="*" minlevel="${var:logLevel}" writeTo="consoleLog" />
	</rules>
</nlog>
 No newline at end of file