Для измерения времени выполнение кода (или блока) использую следующую конструкцию.
Результаты измерений соответственно отражаются логе загрузки.
CONSTANTS:
c_msg_header(24) type c value 'RSRMON W000',
c_seconds type i value 1000000.
MOVE c_msg_header TO monitor_rec.
.
.
.
.
GET RUN TIME FIELD l_timer1.
.
. <измеряемый код>
.
GET RUN TIME FIELD l_timer2.
monitor_rec-msgv1 = 'Block XX:'.
monitor_rec-msgv2 = |{ ( l_timer2 - l_timer1 ) / c_seconds } сек ({ ( l_timer2 - l_timer1 ) NUMBER = USER })|.
append monitor_rec to MONITOR.
(другая тема)
Пример функции replace в string template
L_VNAM = |{ replace( val = I_VNAM off = strlen( I_VNAM ) - 1 len = 1 with = '0' ) }|.
(ещё одна другая тема - ведущий ноль)
DATA:
l_val(2) type c,
l_val2 type string.
l_val = |{ sy-index WIDTH = 2 ALIGN = RIGHT PAD = '0' }|.
l_val2 = |{ sy-index WIDTH = 2 ALIGN = RIGHT PAD = '0' }|.
DATA: l_str TYPE string.
l_str = |{ 'START:' } { sy-uname } { sy-datum DATE = USER } { sy-uzeit TIME = USER }|.
понедельник, 3 февраля 2014 г.
среда, 22 января 2014 г.
0PROJECT Conversion Routine
Я как то привык что CONVERSION_EXIT_* подпрограммы основаны на различных преобразованиях к идентификатором признака, ну там 0-ли добавить убрать и т.п..
Но рутина для 0PROJECT слегка удивила (CONVERSION_EXIT_PROJ_OUTPUT), оказалось что представление кода проекта она считывает из таблицы мастер-данных проекта /BI0/MPROJECT- 0PROJECT_EX.
В общем типа не палимся :)
Но рутина для 0PROJECT слегка удивила (CONVERSION_EXIT_PROJ_OUTPUT), оказалось что представление кода проекта она считывает из таблицы мастер-данных проекта /BI0/MPROJECT- 0PROJECT_EX.
В общем типа не палимся :)
среда, 25 декабря 2013 г.
Повторное использование кода в трансформации
Понадобилось тут реализовать алгорим таким образом, что он содержал 4 абсолютно одинаковых, достаточно больших куска кода.
Некрасиво как-то... да и поддерживать не удобно. Захотелось красиво использовать повторяющийся код.
Варианты:
PERFORM - не работает в классах с одной стороны, и не знает ничего о типах внутри класса с другой. Описывать допольнительно тип из класса, тоже не интересно.
ФМ - т.к. код тупой и не предполагается его где-либо использовать, некрасиво. Опять же типы.
INCLUDE - тоже вариант, но не самый безопасный.
Предлагаемый выход - создать свой метод.
1) Объявляем свой метод внутри класса
*$*$ begin of global - insert your declaration only below this line *-*
METHODS
simple
EXPORTING
MONITOR type rstr_ty_t_monitors
CHANGING
RESULT_PACKAGE type _ty_t_TG_1.
*$*$ end of global - insert your declaration only before this line *-*
2) Создаем реализацию (т.с. самая фишка - нам доступен только метод end_routine или inverse)
Но не все потеряно, мы закрываем метод end_routine просто написав ENDMETHOD.
А ниже пишем реализацию своего класса, которая будет закрываться ENDMETHOD, который нам достался от метода end_routine.
*----------------------------------------------------------------------*
* Method end_routine
*----------------------------------------------------------------------*
* Calculation of result package via end routine
* Note: Update of target fields depends on rule assignment in
* transformation editor. Only fields that have a rule assigned,
* are updated to the data target.
*----------------------------------------------------------------------*
* <-> result package->
*----------------------------------------------------------------------*
METHOD end_routine.
*=== Segments ===
FIELD-SYMBOLS:
TYPE _ty_s_TG_1.
DATA:
MONITOR_REC TYPE rstmonitor.
*$*$ begin of routine - insert your code only below this line *-*
... "insert your code here
*-- fill table "MONITOR" with values of structure "MONITOR_REC"
*- to make monitor entries
... "to cancel the update process
* raise exception type CX_RSROUT_ABORT.
"Вызов нашего метода
me->SIMPLE(
* IMPORTING
* MONITOR =
CHANGING
RESULT_PACKAGE = RESULT_PACKAGE
).
ENDMETHOD. "закрываем метод end_routine
"реализация нашего метода
METHOD simple.
FIELD-SYMBOLS:
TYPE _ty_s_TG_1.
DATA:
MONITOR_REC TYPE rstmonitor.
BREAK-POINT.
*$*$ end of routine - insert your code only before this line *-*
ENDMETHOD. "end_routine
upd. Будет работать только если нет ни одной рутины
Варианты:
PERFORM - не работает в классах с одной стороны, и не знает ничего о типах внутри класса с другой. Описывать допольнительно тип из класса, тоже не интересно.
ФМ - т.к. код тупой и не предполагается его где-либо использовать, некрасиво. Опять же типы.
INCLUDE - тоже вариант, но не самый безопасный.
Предлагаемый выход - создать свой метод.
1) Объявляем свой метод внутри класса
*$*$ begin of global - insert your declaration only below this line *-*
METHODS
simple
EXPORTING
MONITOR type rstr_ty_t_monitors
CHANGING
RESULT_PACKAGE type _ty_t_TG_1.
*$*$ end of global - insert your declaration only before this line *-*
2) Создаем реализацию (т.с. самая фишка - нам доступен только метод end_routine или inverse)
Но не все потеряно, мы закрываем метод end_routine просто написав ENDMETHOD.
А ниже пишем реализацию своего класса, которая будет закрываться ENDMETHOD, который нам достался от метода end_routine.
*----------------------------------------------------------------------*
* Method end_routine
*----------------------------------------------------------------------*
* Calculation of result package via end routine
* Note: Update of target fields depends on rule assignment in
* transformation editor. Only fields that have a rule assigned,
* are updated to the data target.
*----------------------------------------------------------------------*
* <-> result package->
*----------------------------------------------------------------------*
METHOD end_routine.
*=== Segments ===
FIELD-SYMBOLS:
DATA:
MONITOR_REC TYPE rstmonitor.
*$*$ begin of routine - insert your code only below this line *-*
... "insert your code here
*-- fill table "MONITOR" with values of structure "MONITOR_REC"
*- to make monitor entries
... "to cancel the update process
* raise exception type CX_RSROUT_ABORT.
"Вызов нашего метода
me->SIMPLE(
* IMPORTING
* MONITOR =
CHANGING
RESULT_PACKAGE = RESULT_PACKAGE
).
ENDMETHOD. "закрываем метод end_routine
"реализация нашего метода
METHOD simple.
FIELD-SYMBOLS:
DATA:
MONITOR_REC TYPE rstmonitor.
BREAK-POINT.
*$*$ end of routine - insert your code only before this line *-*
ENDMETHOD. "end_routine
upd. Будет работать только если нет ни одной рутины
среда, 4 декабря 2013 г.
Инфо-источник типа без контекта
Давненько с этим не сталкивался, даже как то подзабыл.
Ситуация. По help'y нашли источник, вроде оно - активируем в RSA5
Тиражируем источник как новый- все ок. Он появился, сделали пару загрузок, данные устраивают... пытаемся найти следующие трансформации и цели.
И вот тут нас поджидает облом, т.к. в бизнес-контенте нету такого источника, ни нового, ни старого. Куб если находиться то активируется без трансформации\update rule к источнику.
Решение. Конвертируем с помощью RSDS в старый тип источника. Заходим, активируем и вот тут появляться окошко которое предлагает поднять данные из бизнес-контента. Когда старый data staging поднят, то его потом можно мигрировать в новые типы.
доп.фишка... по поводу суслика которого не видно, а он есть. Если Вы сделали пакеты к источнику, а потом его вернули к старому типу с помощью RSDS, то пакетов Вы не увидите, хотя они есть. Но пакеты созданные в старом источнике после миграции видны.
Ситуация. По help'y нашли источник, вроде оно - активируем в RSA5
Тиражируем источник как новый- все ок. Он появился, сделали пару загрузок, данные устраивают... пытаемся найти следующие трансформации и цели.
И вот тут нас поджидает облом, т.к. в бизнес-контенте нету такого источника, ни нового, ни старого. Куб если находиться то активируется без трансформации\update rule к источнику.
Решение. Конвертируем с помощью RSDS в старый тип источника. Заходим, активируем и вот тут появляться окошко которое предлагает поднять данные из бизнес-контента. Когда старый data staging поднят, то его потом можно мигрировать в новые типы.
доп.фишка... по поводу суслика которого не видно, а он есть. Если Вы сделали пакеты к источнику, а потом его вернули к старому типу с помощью RSDS, то пакетов Вы не увидите, хотя они есть. Но пакеты созданные в старом источнике после миграции видны.
понедельник, 25 ноября 2013 г.
Замеры времени при выполнении трансформации
Пришлось тут доказывать что код написанный мной оптимален, а нанятый человек - ошибся.
+ осложнение - код в трансформации.
На скорую руку родился вот такой код.
DATA:
l_t0 type i,
l_t1 type i,
l_t2 type i,
l_t3 type i,
l_t4 type i,
l_t5 type string,
l_t6 type string.
GET RUN TIME FIELD l_t0. "Get time for transformation
GET RUN TIME FIELD l_t1. "Get time for block
"
" some code
"
GET RUN TIME FIELD l_t2. l_t3 = ( l_t2 - l_t1 ).
l_t4 = l_t3 / 1000000.
monitor_rec-msgid = 'RSRMON'.
monitor_rec-msgty = 'W'.
monitor_rec-msgno = '000'.
monitor_rec-msgv1 = 'start '. "block name
l_t5 = l_t3.
l_t6 = l_t4.
CONCATENATE l_t6 '( ' l_t5 ' )' INTO monitor_rec-msgv2.
DESCRIBE TABLE RESULT_PACKAGE LINES l_t3.
l_t5 = l_t3.
l_t6 = l_t4.
CONCATENATE ' RESULT_PACKAGE - ( ' l_t5 ' )' INTO monitor_rec-msgv3.
monitor_rec-msgv4 = SPACE.
append monitor_rec to MONITOR.
И так "цать раз + в конце вычисляем общее время
l_t3 = ( l_t2 - l_t0 ).
l_t4 = l_t3 / 1000000.
monitor_rec-msgid = 'RSRMON'.
monitor_rec-msgty = 'W'.
monitor_rec-msgno = '000'.
monitor_rec-msgv1 = 'TOTAL'.
l_t5 = l_t3.
l_t6 = l_t4.
CONCATENATE l_t6 '( ' l_t5 ' )' INTO monitor_rec-msgv2.
monitor_rec-msgv3 = SPACE.
monitor_rec-msgv4 = SPACE.
append monitor_rec to MONITOR.
На скорую руку родился вот такой код.
DATA:
l_t0 type i,
l_t1 type i,
l_t2 type i,
l_t3 type i,
l_t4 type i,
l_t5 type string,
l_t6 type string.
GET RUN TIME FIELD l_t0. "Get time for transformation
GET RUN TIME FIELD l_t1. "Get time for block
"
" some code
"
GET RUN TIME FIELD l_t2. l_t3 = ( l_t2 - l_t1 ).
l_t4 = l_t3 / 1000000.
monitor_rec-msgid = 'RSRMON'.
monitor_rec-msgty = 'W'.
monitor_rec-msgno = '000'.
monitor_rec-msgv1 = 'start '. "block name
l_t5 = l_t3.
l_t6 = l_t4.
CONCATENATE l_t6 '( ' l_t5 ' )' INTO monitor_rec-msgv2.
DESCRIBE TABLE RESULT_PACKAGE LINES l_t3.
l_t5 = l_t3.
l_t6 = l_t4.
CONCATENATE ' RESULT_PACKAGE - ( ' l_t5 ' )' INTO monitor_rec-msgv3.
monitor_rec-msgv4 = SPACE.
append monitor_rec to MONITOR.
И так "цать раз + в конце вычисляем общее время
l_t3 = ( l_t2 - l_t0 ).
l_t4 = l_t3 / 1000000.
monitor_rec-msgid = 'RSRMON'.
monitor_rec-msgty = 'W'.
monitor_rec-msgno = '000'.
monitor_rec-msgv1 = 'TOTAL'.
l_t5 = l_t3.
l_t6 = l_t4.
CONCATENATE l_t6 '( ' l_t5 ' )' INTO monitor_rec-msgv2.
monitor_rec-msgv3 = SPACE.
monitor_rec-msgv4 = SPACE.
append monitor_rec to MONITOR.
Виртуальный куб, дайте два
Понадобилось тут в виде эксперимента протестировать изменения логики виртуального куба. Решил сделать обработку в одном модуле, но привязать её к имени куба и соответственно сделать второй мультик но на том же ФМ. И все это хозяйство в один мультик было положено.
Система падала в дамп при попытке выполнить любой отчет на этом мультике. Пришлось дублировать модуль, тогда все заработало нормально.
Подписаться на:
Сообщения (Atom)