Skip to content

Commit

Permalink
Support for settings, optional telemetry improvements
Browse files Browse the repository at this point in the history
  • Loading branch information
Adrian Salceanu committed Aug 2, 2024
1 parent f751ec1 commit 0d563bd
Show file tree
Hide file tree
Showing 5 changed files with 121 additions and 27 deletions.
2 changes: 1 addition & 1 deletion Project.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
name = "GenieBuilder"
uuid = "c9453c14-af8a-11ec-351d-c7c9a2035d70"
authors = ["Adrian Salceanu"]
version = "0.17.3"
version = "0.17.4"

[deps]
Base64 = "2a0f44e3-6c83-55bd-87e4-b1978d98bd5f"
Expand Down
1 change: 1 addition & 0 deletions src/Actions.jl
Original file line number Diff line number Diff line change
Expand Up @@ -11,5 +11,6 @@ ACTION_START_REPL = "start_repl" # start REPL
ACTION_START_PKG_MNG = "start_pkg_mng" # start package manager
ACTION_STOP_PKG_MNG = "stop_pkg_mng" # stop package manager
ACTION_DOWNLOAD_APP = "download_app" # download app
ACTION_TELEMETRY_DISABLED = "telemetry_disabled" # telemetry disabled

end
35 changes: 27 additions & 8 deletions src/GenieBuilder.jl
Original file line number Diff line number Diff line change
Expand Up @@ -5,20 +5,26 @@ using GenieCache, GenieCacheFileCache

import Pkg

include("Generators.jl")
include("Licensing.jl")
include("Actions.jl")
using .Generators
using .Licensing
using .Actions

const GBDIR = Ref{String}("")
const DB_FOLDER = Ref{String}("")
const DB_CONFIG_FILE = Ref{String}("")
const LOG_FOLDER = Ref{String}("")
const RUN_STATUS = Ref{Symbol}() # :install or :update
const WS_PORT = 10102
const VERSION = "0.16.x"
const GBFOLDER = joinpath(homedir(), ".geniebuilder")

include("Generators.jl")
using .Generators

include("Settings.jl")
using .Settings

include("Licensing.jl")
using .Licensing

include("Actions.jl")
using .Actions

function __init__()
GBDIR[] = joinpath(Base.DEPOT_PATH[1], "geniebuilder")
Expand Down Expand Up @@ -53,6 +59,14 @@ function go(; port = get!(ENV, "GB_PORT", -1))
@info "Starting GenieBuilder v$(get_version())"
@async set_starting_flag() |> errormonitor

try
if ! GenieBuilder.Settings.data("telemetry")
GenieBuilder.Licensing.log(type = GenieBuilder.Actions.ACTION_TELEMETRY_DISABLED, force = true)
end
catch ex
@error ex
end

try
if Genie.Configuration.isprod()
@async withcache(; key="system_update_GB", expiration=60*60*24) do # 24 hours cache
Expand Down Expand Up @@ -155,7 +169,12 @@ function get_version()
end

function exit()
GenieBuilder.Licensing.log(type = Actions.ACTION_END_SESSION)
try
GenieBuilder.Licensing.log(type = Actions.ACTION_END_SESSION)
catch ex
@error ex
end

Genie.Server.down!()
Base.exit()
end
Expand Down
45 changes: 27 additions & 18 deletions src/Licensing.jl
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,23 @@ Licensing integration for JuliaHub
module Licensing

using Base64, HTTP, JSON, Logging, Random
import GenieBuilder, GenieBuilder.Settings
import Base: log

const LICENSE_API = get!(ENV, "GENIE_LICENSE_API", "https://genielicensing.hosting.genieframework.com/api/v1") # no trailing slash
# const LICENSE_API = get!(ENV, "GENIE_LICENSE_API", "http://127.0.0.1:3333/api/v1") # no trailing slash #TODO: change this to the production URL

const GBFOLDER = joinpath(homedir(), ".geniebuilder")
const GBFOLDER = GenieBuilder.GBFOLDER
const GBPASSFILE = joinpath(GBFOLDER, "pass")
const GBSESSIONFILE = joinpath(GBFOLDER, "sessionid")

const COMMERCIAL_LICENSE = Ref{Union{Bool,Nothing}}(nothing)
function commercial_license()
isnothing(COMMERCIAL_LICENSE[]) && status()
# @show COMMERCIAL_LICENSE[]
COMMERCIAL_LICENSE[] == true
end

function isregistered() :: Bool
isfile(GBPASSFILE)
end
Expand Down Expand Up @@ -227,17 +236,17 @@ end
function log(;
type::Union{AbstractString,Symbol},
metadata::AbstractDict = Dict(),
origin::AbstractString = ORIGIN)
origin::AbstractString = ORIGIN,
force::Bool = false)
# we check the telemetry settings only if the force flag is not set and the user has a commercial license
# otherwise we log the action regardless of the telemetry settings
! force && commercial_license() && GenieBuilder.Settings.@check_telemetry

if ! isloggedin()
@warn("User not logged in, skipping logging")
return
end

if ! TELEMETRY
@warn("Telemetry is disabled, skipping logging")
return
end

payload = Dict(
"origin" => origin,
"type" => type,
Expand All @@ -262,16 +271,15 @@ function log(;
end

function quotas()
# TODO: review this, quotas should not be affected by telemetry settings
# but let's understand how much traffic this generates first
GenieBuilder.Settings.@check_telemetry

if ! isloggedin()
@warn("User not logged in, skipping quotas")
return Dict()
end

if ! TELEMETRY
@warn("Telemetry is disabled, skipping quotas")
return Dict()
end

quotas_data = try
HTTP.get(LICENSE_API * "/quotas";
status_exception = true,
Expand All @@ -297,7 +305,7 @@ function quotas()
end

function status()
quotas_data = try
status_data = try
HTTP.get(LICENSE_API * "/status";
status_exception = true,
headers = headers()
Expand All @@ -308,14 +316,17 @@ function status()
return Dict()
end

if quotas_data.status != 200
@warn("Failed to get status: $(quotas_data.status)")
if status_data.status != 200
@warn("Failed to get status: $(status_data.status)")
return Dict()
end

try
(quotas_data.body |> String |> JSON.parse)
user_status = (status_data.body |> String |> JSON.parse)
COMMERCIAL_LICENSE[] = user_status["license"] != "trial" && user_status["license"] != "edu" && user_status["license_status"] != "expired"
return user_status
catch ex
@error ex
@warn("Failed to parse status data: $ex")
return Dict()
end
Expand All @@ -326,13 +337,11 @@ function __init__() #TODO: uncouple this
ENV["GENIE_USER_FULL_NAME"] = get(ENV, "JULIAHUB_USER_FULL_NAME", "")
ENV["GENIE_ORIGIN"] = get(ENV, "JULIA_PKG_SERVER", "local")
ENV["GENIE_METADATA"] = get(ENV, "JULIAHUB_APP_URL", "")
ENV["GENIE_TELEMETRY"] = get(ENV, "GENIE_TELEMETRY", "true")

@eval const USER_EMAIL = ENV["GENIE_USER_EMAIL"]
@eval const USER_FULL_NAME = ENV["GENIE_USER_FULL_NAME"]
@eval const ORIGIN = ENV["GENIE_ORIGIN"]
@eval const METADATA = ENV["GENIE_METADATA"]
@eval const TELEMETRY = lowercase(ENV["GENIE_TELEMETRY"]) == "true"
end


Expand Down
65 changes: 65 additions & 0 deletions src/Settings.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
module Settings

using JSON
import GenieBuilder
import Logging

export @check_telemetry

const SETTINGS = Ref{Dict{String, Any}}(Dict{String, Any}())
const ENV_KEYS = Dict(
"telemetry" => "GENIE_TELEMETRY"
)

macro check_telemetry()
return quote
if ! data("telemetry")
# @show("Telemetry is disabled, skipping logging")
return
else
# @show("Telemetry is enabled")
end
end
end

function default_from_env(key::String, default) :: Bool
haskey(ENV, key) || (ENV[key] = "") # default to empty string
(isempty(ENV[key]) || ENV[key] == string(default)) && return default # ENV vars are strings
end

function load_settings()
if isfile(joinpath(GenieBuilder.GBFOLDER, "settings.json"))
SETTINGS[] = try
JSON.parsefile(joinpath(GenieBuilder.GBFOLDER, "settings.json"))
catch ex
@error ex
Dict{String, Any}()
end
end

# @show SETTINGS[]

haskey(SETTINGS[], "settings") || (SETTINGS[] = Dict{String, Any}("settings" => Dict{String, Any}()))
haskey(SETTINGS[]["settings"], "telemetry") || (SETTINGS[]["settings"]["telemetry"] = default_from_env(ENV_KEYS["telemetry"], true))

# env overrides settings
haskey(ENV, ENV_KEYS["telemetry"]) && ! isempty(ENV[ENV_KEYS["telemetry"]]) && (SETTINGS[]["settings"]["telemetry"] = ENV[ENV_KEYS["telemetry"]])

nothing
end

function data()
haskey(SETTINGS[], "settings") || load_settings()
@show SETTINGS[]
return SETTINGS[]["settings"]
end

function data(key::String)
return data()[key]
end

function __init__()
load_settings()
end

end

0 comments on commit 0d563bd

Please sign in to comment.