Управление-Getl.md


Содержание

Опции Getl

Для установки опций работы Getl используйте оператор options:

options {
    // Автоматически загружать конфигурацию из файла getl-properties.conf
    // см. "Вынос опций Getl в ресурсный файл"
    autoInitFromConfig = true
    // Загрузить конфигурацию проекта с указанного файла
    // см. "Вынос опций проекта в ресурсный файл"
    projectConfigParams = "resource:/project.conf"
    // Проверять при регистрации, что объект еще не зарегистрирован
    // в случае отключения флага проверки все объекты будут регистрироваться поверх существующих
    validRegisterObjects = true
    // Включить автоматическое клонирование объектов репозитория для потоков
    useThreadModelCloning = true
    // Включить профилирование выполняемых команд JDBC источников в указанный директорий
    jdbcConnectionLoggingPath = '{LOG_PATH}/jdbc'
    // Включить профилирование выполняемых команд файловых менеджеров в указанный директорий
    fileManagerLoggingPath = '{LOG_PATH}/files'
    // Включить профилирование выполняемых команд встроенной БД в указанный директорий
    tempDBSQLHistoryFile = '{LOG_PATH}/embedded_database'
    // Уровень профилирования оператора ECHO, выполняемых с помощью оператора sql
    sqlEchoLogLevel = java.util.logging.Level.FINE
    // Выводить в лог сообщение о старте профилирования операции Getl
    processTimeDebug = false
    // Уровень вывода сообщений профилирования операций Getl в лог задачи
    processTimeLevelLog = java.util.logging.Level.FINER
    // Фиксировать в логе задачи время выполнения каждой операции Getl
    processTimeTracing = true

    // Имя датасета контроля разрешения запуска процессов
    // (если указан, то в датасете для каждой запускаемой задачи по имени класса проверяется, что enabled не выключен)
    processControlDataset = 'dwh.monitor:processes'
    // Имя логина, который нужно использовать для доступа к JDBC датасету контроля процессов
    // (если указан, то при обращении к датасету соединение переключается на нужный логин
    processControlLogin = 'user'
    // Проверять в датасете контроля запуска процессов на разрешение запустить задачу Getl
    checkProcessOnStart = true
    // Проверять в датасете контроля запуска процессов на разрешение стартовать поток выполняемой задачи Getl
    checkProcessForThreads = true
}

Управление конфигурациями

В Getl используются конфигурации в формате Groovy Slurper. Для работы с файлами конфигурации используйте оператор configuration:

configuration {
    // Путь к директорию, в котором по умолчанию лежат файлы с конфигурациями
    path = 'resource:/config'
    // Кодировка файлов конфигурации
    codePage = 'UTF-8'
    // Установить среду выполнения
    environment = 'dev'

    // Записать в конфигурацию секцию с параметрами
    configContent.config1 = [param1: 'Параметр 1', param2: 1]
    // Сохранить конфигурацию в файл
    save '{CONFIG_PATH}/file1.conf'
    
    // Очистить в памяти конфигурацию
    clear()
    
    // Загрузить конфигурацию из файла
    load '{CONFIG_PATH}/file1.conf'
}

В файлах конфигурации можно описать параметры для разных сред выполнения:

params {
    param1 = 'Параметр 1'
}

environment {
    dev {
        params {
            param2 = 1
        }
    }
    test {
        params {
            param2 = 2
        }
    }
    prod {
        params {
            param2 = 3
        }
    }
}

Можно использовать значения переменных файла конфигурации как параметров задачи Getl, считав конфигурацию и установив значения при запуске задачи:

// Параметры задачи
@Field String param1
@Field Integer param2

// Метод инициализации при старте задачи
void init() {
    configuration {
        // Считать файл конфигурации
        load '{CONFIG_PATH}/file1.conf'
        // Заполнить параметры задачи значениями из секции params считанной конфигурации
        readFields 'params'
    }
}

Логирование работы задачи

Для логирования работы Getl использует стандартный Java logger. Дополнительные компоненты могут использовать другие логгеры (log4j, slf4j и т.д.), для их настройки используйте конфигурационные файлы согласно инструкции производителя. Для настройки логирования используйте оператор logging:

logging {
    // Писать лог в указанный файл
    logFileName = '{LOG_PATH}/job1.{date}.log'
    // Выводить в лог сообщения по работе с конфигурационными файлами
    printConfigMessage = false
    // Выводить в лог трассировку кода, в котором возникла ошибка 
    printStackTraceError = false
}

В имени лог файла можно использовать следующие переменные:

  • date - подставить в имя файла лога текущую дату в формате “yyyy-MM-dd”
  • monthdate - подставить в имя файла лога текущую дату в формате “yyyy-MM”
  • yeardate - подставить в имя файла лога текущую дату в формате “yyyy”
  • time - подставить в имя файла лога текущую дату в формате “HH-mm-ss”
  • shorttime - подставить в имя файла лога текущую дату в формате “HH-mm”
  • hour - подставить в имя файла лога текущую дату в формате “HH”
  • datetime - подставить в имя файла лога текущую дату в формате “yyyy-MM-dd_HH-mm-ss”
  • shortdatetime - подставить в имя файла лога текущую дату в формате “yyyy-MM-dd_HH”

Для вывода в лог сообщений используйте команды логирования log*:

logConfig 'Загрузка конфигурации'

// Вывести в лог ряд последовательных сообщений без прерывания их сообщениями других потоков
logConsistently {
    logFinest 'Максимально детализированное отладочное сообщение'
    logFiner 'Детализированное отладочное сообщение'
    logFine 'Отладочное сообщение с наименьшей детализацией'
}

logInfo 'Информационное сообщение'
logWarn 'Предупреждающее сообщение!'
logError 'Сообщение об ошибке'

Профилирование работы задачи

При выполнении команд Getl автоматически фиксируется их время выполнения и производительность (при копировании данных между источниками и файловыми системами). Настройку профилирования можно произвести в опциях Getl. Так же можно дополнительно включать профилирование собственных участков кода для отладки времени их выполнения и оценки производительности. Для этого используйте команду profile:

profile('Этап 1', 'file') {
    def countFiles = fileman.copier() { /* код */ }
    
    // Установить количество обработанных объектов в ходе профилирования
    countRow = countFiles
}

Если в опциях Getl включен флаг для processTimeDebug, то при запуске команды профилирования в лог будет выдано сообщение о старте профилирования с указанным именем операции. По завершении кода внутри оператора профилирования в лог будет выдано сообщение о завершении работы операции и выдана статистика по скорости обработки объектов (если их количество указано в countRow).

Управление репозиторием Getl

При работе с именованными объектами Getl требует их регистрации в репозитории, который располагается в памяти. Для каждого типа объектов существует отдельный репозиторий со своим пространством имен. Список классов поддерживаемых репозиториев:

  • RepositoryConnections - репозиторий соединений источников данных
  • RepositoryDatasets - репозиторий датасетов источников данных
  • RepositoryFilemanagers - репозиторий файловых менеджеров
  • RepositoryHistorypoints - репозиторий инкрементальных точек захвата данных
  • RepositorySequences - репозиторий последовательностей БД (sequences)
  • RepositoryMapTables - репозиторий моделей маппинга источников данных
  • RepositoryMonitorRules - репозиторий моделей правил мониторинга состояния БД
  • RepositoryReferenceFiles - репозиторий моделей эталонных файлов
  • RepositoryReferenceVerticaTables - репозиторий моделей эталонных данных таблиц Vertica
  • RepositorySetOfTables - репозиторий моделей наборов датасетов источника данных

Для управления репозиториями в Getl используйте оператор repositoryStorageManager:

repositoryStorageManager {
    // Установить путь к хранилищу файлам репозитория в ресурсах проекта
    storagePath = 'resource:/repository'
    
    // Автоматически подгружать описания объектов в репозиторий из хранилища файлов, 
    // если имя объекта не найдено в репозитории при обращении к нему  
    autoLoadFromStorage = true

    // Автоматически подгружать описания объектов в репозиторий из хранилища файлов,
    // если при поиска объекта по имени он не был найден
    autoLoadForList = true
    
    // Кодировать пароли соединений и файловых менеджеров в файлах хранилища по указанному ключу
    storagePassword = 'Repository password'
    
    // Обработать список репозиториев всех типов объектов Getl
    listRepositories.each { repName ->
        // Получить ссылку на репозиторий указанного типа объектов Getl
        repository(repName).with {
            // Обработать в репозитории все объекты по указанной маске имени
            processObjects('group1:*') { objName ->
                // Код работы с объектом репозитория
            }
        }
    }

    // Установить путь к хранилищу файлам репозитория к директории на файловой системе
    storagePath = '{REPOSITORY_PATH}/files'

    // Сохранить из репозитория объекты по заданной маске имени в файлы хранилища 
    saveRepositories('group1:*')

    /** Очистить описание объектов с именем по указанной маске со всех репозиториев */
    clearRepositories('group1:*')
    
    // Загрузить в репозиторий с хранилища файлов описания объектов по заданной маске имени 
    loadRepositories('group1:*')
}

При работе с именованными объектами в задачах Getl нужно их сначала зарегистрировать в репозитории, для этого при обращении к объекту помимо его имени указывается включенный флаг регистрации:

// Регистрация таблицы Vertica с указанным именем в репозитории
verticaTable('dwh:table1', true) { 
    // код инициализации таблицы
}

// Обращение к уже зарегистрированному объекту репозитория по его имени
verticaTable('dwh:table1') {
    // код работы с таблицей
}

Если в коде будет идти обращение к объекту репозитория, который не был ранее зарегистрирован, то возникнет ошибка. Если объекты используются во множестве задач, то регистрация и инициализация объекта в коде каждой его использующей задачи является не оптимальным решением. В таком случае правильнее сохранить описание объекта в файл конфигурации хранилища репозитория. При обращении к несуществующему объекту в памяти репозитория Getl попытается найти подходящий файл конфигурации в хранилище и при успехе автоматически подгрузит его в репозиторий.

Сохранение объектов в конфигурационные файлы хранилища репозитория

Для облегчения процесса описания и сохранения именованных объектов репозитория в Getl предоставлен класс RepositorySave. Достаточно создать Groovy класс, который наследуется от этого класса и в нём в методах описать регистрацию объектов нужных типов, пометив методы аннотацией SaveToRepository. При запуске созданного класса будет выполнены каждый из методов регистрации объектов и все созданные объекты сохранены в конфигурационные файлы хранилища:

class MyRepository extends RepositorySave {
    static {
        // Указать текущий файл как главный при запуске
        UseSaver = this
    }
    
    // Инициализация Getl при запуске класса
    @Override
    protected void prepare() {
        // Установить путь для хранилища конфигурационных файлов репозитория
        repositoryStorageManager.storagePath = '{REPOSITORY_PATH}/files'
    }
    
    // Описание соединений для dev среды выполнения
    @SaveToRepository(type = 'Connections')
    void regConnectionsDev() {
        // Регистрация соединения Vertica
        verticaConnection('dwh:con', true) {
            // код инициализации для dev среды выполнения
        }

        // Регистрация соединения Oracle
        oracleConnection('ora:con', true) {
            // код инициализации для dev среды выполнения
        }
    }

    // Описание соединений для prod среды выполнения
    @SaveToRepository(type = 'Connections', env = 'prod')
    void regConnectionsProd() {
        // Регистрация соединения Vertica
        verticaConnection('dwh:con', true) {
            // код инициализации для prod среды выполнения
        }

        // Регистрация соединения Oracle
        oracleConnection('ora:con', true) {
            // код инициализации для prod среды выполнения
        }
    }

    // Описание датасетов
    @SaveToRepository(type = 'Datasets')
    void regDatasets() {
        // Регистрация таблицы Vertica
        verticaTable('dwh:table1', true) {
            useConnection verticaConnection('dwh:con')
            // Код инициализации таблицы
        }

        // Регистрация таблицы Oracle
        oracleTable('ora:table1', true) {
            useConnection oracleConnection('ora:con')
            // Код инициализации таблицы
        }
    }
    
    // Описание файловых менеджеров для dev и prod среды выполнения
    @SaveToRepository(type = 'Filemanagers', env = 'dev,prod')
    void regFilemanagers() {
        // Регистрация файлового менеджера локальной системы
        file('file:fs1', true) {
            // Код инициализации файлового менеджера
        }
    }
}

Для выполнения сохранения объектов, регистрируемых в методе, в аннотации SaveToRepository указывается тип сохраняемых объектов. Если в методе используются объекты других типов, они не будут сохранены. Поддерживаются следующие типы сохраняемых объектов: 1. Connections - соединения источников данных 1. Filemanagers - файловые менеджеры 1. Datasets - датасеты источников данных 1. Historypoints - инкрементальные точки захвата данных 1. Sequences - последовательности БД (sequences) 1. MapTables - модели маппинга источников данных 1. MonitorRules - модели мониторинга состояния БД 1. ReferenceFiles - модели эталонных файлов 1. ReferenceVerticaTables - модели эталонных данных таблиц Vertica 1. SetOfTables - модели набора датасетов источника данных

Перед стартом каждого метода с аннотацией SaveToRepository все объекты в репозитории Getl будут очищены. Если внутри метода идет обращение к объекту, который не был зарегистрирован в репозитории, то Getl попробует подгрузить его с хранилища файлов. Таким образом на момент выполнения метода, в репозитории будут только объекты, которые нужны для сохранения в хранилище файлов нужного типа объектов и при выполнении каждого метода среда выполнения репозиторий будет лишен лишних объектов.

Методы будут выполняться по очереди перечисления списка типов объектов выше вне зависимости от их порядка следования в классе. Это гарантирует, что при описании в классе взаимосвязанных объектов (соединения->датасеты->модели и т.д.) они будут созданы по очереди и не возникнет ошибка, когда объект ссылается на еще не описанный другой объект репозитория.

Вынос конфигурации Getl в файлы

Чтобы не указывать в коде конфигурацию работы Getl при запуске задачи, её можно вынести в файл getl-properties.conf, который должен располагаться в директории запуска задачи или в ресурсном файле. Так же можно явно задать путь к файлу конфигурации при старте задачи в аргументе командной строки в формате “getlprop.filename=путь_к_файлу_конфигурации”.

Дополнительно для конфигурирования Getl в режиме юнит тестов (GetlDslTest) или генератора объектов репозитория (RepositorySave) в корневом директории модулей можно разместить файл конфигурации тестирования getl-test-properties.conf и get-repository-env.conf, которые будут автоматически использованы при запуске юнит тестов модуля и генераторах объектов репозитория.

Файл конфигурации getl-properties.conf

Файл конфигурации опций Getl имеет формат Groovy Slurper и состоит из разделов и свойств. Как и для прочих файлов конфигураций Slurper в нём можно разделить конфигурацию для разных сред выполнения (environments) с помощью раздела environment.

Структура файла конфигурации getl-properties.conf:

// Опции проекта 
project {
    // Список требуемых для запуска переменных ОС 
    needEnvironments = ['PROJ_ENV1', 'PROJ_ENV2']
    
    // Имя ресурсного файла проекта, который требуется автоматически считать при старте лаунчера
    configFileName = 'resource:/project-properties.conf'
}

// Параметры репозитория
repository {
    // Путь к файлам репозитория
    path = 'resource:/repository'
    // Ключ шифрования паролей репозитория
    encryptKey = 'project-password-key'
    
    // Подгружать описания объектов из файлов репозитория при обращении к ним
    autoLoadFromStorage = true
    // Подгружать описания объектов из файлов репозитория при их поиске при вызовах методов list* и process*
    autoLoadForList = true

    // Путь для сохранения файлов репозитория при вызове процессов RepositorySave
    repositorySavePath = 'src/main/resources/repository'
}

// Опции логирования
logging {
    // Путь для записи сообщений в лог файл
    logFileName = '{PROJ_ENV1}/logs/{process}/{date}.log'
    // Путь для логирования SQL команд, посылаемых в JDBC источники
    jdbcLogPath = '{PROJ_ENV1}/logs/jdbc'
    // Путь для логирования команд, посылаемых в файловые источники
    filesLogPath = '{PROJ_ENV1}/logs/files'
    // Путь для логирования SQL команд, посылаемых встроенной БД
    tempDBLogFileName = '{PROJ_ENV1}/logs/tempdb'
    // Выводить при ошибке полную трассировку кода
    printStackTraceError = false
}

// Опции движка Getl
engine {
    // Запустить указанный класс инициализации до запуска лаунчером самого процесса
    initClass = 'my.project.init.InitClass'

    // Датасет контроля запуска процессов
    controlDataset = 'ver.monitor:s_processes'
    // При обращении к датасету использовать отдельное соединение под указанным логином
    controlLogin = 'service_user'
    // Проверять при старте лаунчером разрешение для запускаемого процесса в датасете контроля процессов
    controlStart = true
    // Проверять при старте каждого потока thread разрешение для выполняемого процесса в датасете контроля процессов  
    controlThreads = false
    
    // Включить клонирования объектов при обращении к ним из потоков thread
    useThreadModelCloning = true

    // Установить язык сообщений и ошибок
    language='RU'
}
// Опции профилирования
profile {
    // Разрешить профилирование выполняемых операторов Getl
    enabled = true
    // Уровень вывода сообщений профилирования в логе
    level = java.util.logging.Level.FINER
    // Уровень вывода команды ECHO из SQL скриптов в логе
    sqlEchoLevel = java.util.logging.Level.FINE
    // Включить режим отладки для более детальной информации при профилировании
    debug = false
}

Если проекта Gradle многомодульный, то можно в главном модуле расположить ресурсный файл getl-properties.conf с основной конфигурацией, а для каждого запускаемого модуля сделать дополнительный ресурсный файл getl-properties-ext.conf, в котором указать дополнительные свойства конфигурации. При старте каждого модуля главный и дополнительный файлы конфигурации будут считаны автоматически, конфигурация слита в единую и использована для работы.

Если при запуске задачи требуется перекрыть опции конфигурации Getl из файла конфигурации, то это можно сделать с помощью аргументов командной строки в формате “getlprop.опция=значение”:

java -cp <путь> getl.lang.Getl runclass=Job1 getlprop.logging.printStackTraceError=true getlprop.profile.debug=true

Файл конфигурации getl-test-properties.conf

Файл конфигурации тестирования Getl имеет формат Groovy Slurper.

Структура файла конфигурации getl-test-properties.conf:

// Использовать при запуске юнит тестов указанную среду выполнения
defaultEnv = 'PROJ_ENV1'

С помощью defaultEnv можно легко изменять среду выполнения для запускаемых юнит тестов. Каждый разработчик может создать себе собственный файл конфигурации в корне модуля с юнит тестами и использовать собственную среду тестирования. В этом случае рекомендуется добавить файл getl-test-properties.conf в игнорируемые файлы системы контроля версий, чтобы исключить их отслеживание и репликацию среди разработчиков.

P.S. Вместо файла конфигурации можно явно задавать юнит тесту среду выполнения с помощью системной переменной при запуске с помощью -D параметра Java: -Dgetl-test-env=PROJ_ENV1.

Файл конфигурации getl-repository-env.conf

Файл конфигурации генератора объектов Getl имеет формат Groovy Slurper.

Структура файла конфигурации getl-repository-env.conf:

// Использовать при запуске генератора объектов репозитория RepositorySave в качестве dev указанную среду выполнения
defaultEnv = 'PROJ_ENV1'

С помощью defaultEnv можно легко изменять среду выполнения по умолчанию для запускаемых генераторов объектов. Изначально установлена среда dev. Разработчик может создать себе собственный файл конфигурации в корне проекта и указать, что вместо dev нужно использовать другую среду выполнения для RepositorySave. В этом случае рекомендуется добавить файл getl-repository-env.conf в игнорируемые файлы системы контроля версий, чтобы исключить их отслеживание и репликацию среди разработчиков.

P.S. Вместо файла конфигурации можно явно задавать имя среду по умолчанию вместо dev с помощью системной переменной при запуске с помощью -D параметра Java: -Dgetl-repository-env=PROJ_ENV1.

Вынос опций проекта в ресурсный файл

Общие опции проекта, которые используются в процессах, можно вынести в собственный файл конфигурации и указать в getl-properties его для загрузки в project.configFileName. Если в конфигурационном файле проекта указаны версия, года разработки, название проекта и компании разработчика, то при старте лаунчером процесса это будет выведено в лог.

Переменные конфигурационного файла проекта будут загружены в options.projectConfigParams и доступны для использования в коде.

Структура файла конфигурации:

// Версия проекта
version='1.00'
// Года разработки
year='2010-2020'
// Наименование проекта
project='My project'
// Название компании разработчика проекта
company='My company'

// Другие параметры
regions=['Moscow', 'Sank-Petersburg', 'Kazan']

Пример использования переменной regions в коде процесса:

println "Регионы конфигурации: ${options.projectConfigParams.regions}"

Если вы хотите автоматически собирать ресурсный файл конфигурации проекта, включая в него версию компиляции проекта gradle, добавьте в build.gradle задачу генерации ресурсного файла:

processResources.dependsOn "generateProjectConfig"

task("generateProjectConfig") {
    def resDir = "$buildDir/resources/main"
    doLast {
        file(resDir).mkdirs()
        def curYear = LocalDateTime.now().year
        file("$resDir/${project.name}.conf").text = """/* 
Application Version Configuration File
Generated: ${LocalDateTime.now().format('yyyy-MM-dd HH:mm')} 
*/
version='$version'
year='2010-$curYear'
project='My project'
company='My company'
regions=['Moscow', 'Sankt Peterburg', 'Kazan']
"""
    }
}