Menu

#836 Ability to switch off program-wide interactive tracing in a METHOD which uses EXPOSE

5.1.0
unread
nobody
None
none
1
2024-06-30
2024-05-26
Dom Wise
No

When ::OPTIONS TRACE ?R (or similar with the interactive flag) is specified, all ROUTINEs and METHODs in a package have interactive tracing automatically switched on. This is very useful for debugging as adding one line switches tracing on everywhere but sometimes there might be a small number of ROUTINEs or METHODs (those called frequently and /or with known correct behaviour) for which this is not required or desired.

The global option can generally be overridden on a case by case basis by inserting CALL TRACE( '?') before the first instruction in a ROUTINE or METHOD, but it seems that in a METHOD that uses EXPOSE, the first instruction must be EXPOSE and interactive tracing will pause here before the earliest place the override code can be added and this limits the effectiveness of this method.

There is a workaround which is NOT to use the global option and instead add code to activate tracing to each ROUTINE or METHOD, and actually when the workaround is not available it does just add the requirement for an extra <enter> to the tracing process whenever the METHOD is called but it would be nice if this corner case could be addressed.</enter>

Related

Feature Requests: #836

Discussion

  • Jeremy Nicoll

    Jeremy Nicoll - 2024-05-26

    On Sun, 26 May 2024, at 20:09, Dom Wise wrote:

    When ::OPTIONS TRACE ?R (or similar with the interactive flag) is
    specified, all ROUTINEs and METHODs in a package have interactive
    tracing automatically switched on. This is very useful for debugging
    as adding one line switches tracing on everywhere but sometimes there
    might be a small number of ROUTINEs or METHODs (those called frequently
    and /or with known correct behaviour) for which this is not required or
    desired.

    In the mid 1980s I had a 16,000+ line interactive COBOL program (on a
    VM/CMS system) which had a raft of debugging facilities built in (eg the
    ability to trigger garbage collection of its internal heap, options for
    chaining through data in linked-lists, forcing a 'page' fault - it handled
    variable length strings whose total volume exceeded the max size of its
    addressable working storage so WS's contents got 'paged' in & out as
    needed) ... and part of that was a system which enabled me to turn
    tracing off/on (& maybe also set a level-of-detail - I can't remember
    now) for selected subroutines.

    I did it simply by giving each subroutine a partly numeric name. In
    REXX terms it's like the difference between having

    string_free: procedure ....
    return

    string_change_length: procedure ...
    return

    vv

    p810_string_free: procedure ....
    return

    p820_string_change_length: procedure ...
    return

    and then a particular routine would have (in REXX terms):

    p913_whatever: procedure expose ...
    if global_debug_flag[913] .... then do
    say "entered p913_ whatever" ...
    ...
    end
    ...
    return

    I ordered the subroutine defs (in the COBOL source) in numeric
    order, which made it considerably easier to find any of them,
    even if one was manually scrolling up & down.

    Latterly I went further & ensured my 'Xedit' profile defined labels
    for each routine's entry point as an edit session started, so that
    an: l .913 editor command would take me to the start of p913's
    code. (The command means 'locate' ie go to the line, labelled
    ".913".)

    Periodically I used an Xedit macro (ie a program that ran
    within Xedit) to check that all the trace-specific logic inside
    each subroutine nnn correctly referred to (in REXX terms)
    global_debug_flag[nnn].

    I kept families & sub-[sub-]* families of routines together. So eg
    the routines numbered 900-950 might all have been related to
    memory management; 930-949 might all have been related to
    garbage collection.

    [I was working in an academic environment; once in a while I
    took a program listing to the library where they had splendid
    wooden tables - which I suppose 12-20 people could sit at -
    and laid the listing out along one of those tables, spilling on
    to the floor at each end. I certainly got some funny looks...]

    Where was i? - oh yes: in the interactive debugger I could turn
    on/off debugging of (say) the whole 9xx range of routines in
    one command.

    I've used the same idea in a few Rexx programs since then, but
    not many.

    It's easy to do this for code that's entirely under one's own
    control.

    I can see that even if I wanted some level of tracing to
    apply to ALL of my own code, I wouldn't necessarily want
    any (or the some level of detail) applied to code in
    functions/classes incorporrted via ::REQUIRES directives.

    It might be sensible to try and formulate a "standard"
    way to control this sort of thing.

    /I/ don't mind having integer elements in the names of
    procedures (or subroutines) in /my own/ code, but
    something like that won't work for method names
    whose classes get included from elewhere in my
    code, nor - as far as I understand it - those implicity
    defined via eg ooDIalog.

    One could possibly have a class-specific debug
    flags data-structure, but how that would interact
    with super/sub-classes is way beyond me...

    --
    Jeremy Nicoll - my opinions are my own.

     
  • Anonymous

    Anonymous - 2024-06-25

    Thank you for the feedback so far.

    It would certainly be possible to have a small code snippet at the top of most, but not every code object that can configure tracing based on a flag in e.g. .local, rather than using global options though this does feel a bit cumbersome and is more code to slow things down

    I don't know if it would be possible but one thought I had was to have a trace (or just 'notrace') flag available for code objects such as methods and perhaps also routines that would override any global settings to enable tracing to be controlled for just that item. There wouldn't necessarily need to be keywords for this. So long it could be controlled in code a debugger would be able to configure traceability of its own code before it started intercepting tracing activity.

     
    • Dom Wise

      Dom Wise - 2024-06-25

      The comment above is from me but I didn't realise I wasn't logged in to SourceForge

       
  • Gil Barmwater

    Gil Barmwater - 2024-06-26

    At the 2014 Symposium I did a presentation that addressed this topic. René recently asked me to update the documentation for the purpose of publishing the RexxLA Symposium proceedings. Here is the opening section of that document.

    ooRexx Tracing through Metaprogramming

    A recent discussion on the RexxLA list regarding the lack of a "global trace" capability in ooRexx led to an analysis of tracing in an object oriented environment. Due to encapsulation, each method of a class begins execution with the default trace setting (Normal) in effect. Therefore to trace all the methods of a class would requiring editing each one to add a trace statement with the desired setting. The TRACECLS tool was developed to simplify the tracing of the methods of a class by using metaprogramming. In addition, the TRHILITE tool was written to assist in the identification of the trace output on the console. It may be used either alone or in conjunction with TRACECLS. It can prepend a "flag" string to each line of trace output and/or change the color attributes of that output line using the TXTCOLOR.CLS framework.

    Note that at that time I don't believe "::options trace" was available. The document is available as a PDF but hasn't been added to the website Symposium page for 2014 as of now. It describes the process and programs whose source is also included.

     
    • Dom Wise

      Dom Wise - 2024-06-26

      Hi Gil,

      That sounds really interesting. It's a shame it's not available. The work on global options has made it very easy to add tracing across all code objects, but it is an "all or nothing" setting.

      I'm glad you brought it up though because the whole "metaprogramming" concept got me thinking and led me to a nice workaround to this problem.

      The issue is I have a few methods that should ignore (in particular switch off) any global tracing options set at the package level for the source module which can easily be changed. I can't do this with any keywords but ooRexx has a rich API for manipulating packages, methods and classes and it turns out what I want can be achieved with the following:

      1. Create attributes in the class for accessing any object variables that are used by these methods and update the methods to use these attributes. This is needed because there's going to be subclassing.
      2. Construct a package object from source which defines the methods I want to control, extracting the source of each from my class. This package just has a bunch of floating methods whose trace status is fixed and determined by whatever trace options were in effect in the source of the package object (none) and not by any trace options set for the source file as a whole.
      3. Retrieve the floating methods directory/stringtable (depends on ooRexx version) for this new package object
      4. Create an instance of my class enhanced with the floating methods directory/stringtable from the package object. This replaces the existing methods (whose trace status can vary) with the new ones that are guaranteed to have tracing switched off

      This can all be done, including object creation, in 6 lines for 1 method, with 2 more for each additional method.

      I've only written a proof of concept so far but it does seem to work as expected and it's a small enough set of changes that I can at least try it out in my debugger without too much disruption to existing code

      I just love how flexible ooRexx is!

      Best Regards,
      Dom

       
  • Gil Barmwater

    Gil Barmwater - 2024-06-27

    Well, you have "discovered" the essence of what I did for that presentation 10 years ago. I am going to send you the PDF off-list so you can compare what I did with your proof of concept. While my program was concerned with adding trace statements to methods prior to their execution, the same approach could add a "call trace <whatever>" to suppress tracing in selective methods. I hope you can make use of the code in some form.</whatever>

     
    • Anonymous

      Anonymous - 2024-06-27

      Thank you for providing that. Very nice article and code!

      I'd forgotten that it's ok to 'define' (i.e. replace) methods in a non-core class. This means there is no subclassing needed so no requirement for replacing object variables with attributes . Also I've learned that a new package isn't needed to recompile a method without source module global ::OPTIONS - the method just needs to be rebuilt from source

      This makes the whole process very straightforward and each method can be protected against module level tracing with a single line and no code changes to the method itself:

      .MyClass~define("mymethod", .method~new("mymethod", .MyClass~method("mymethod")~source))

      Once all required methods have been updated new instances created in the usual way will incorporate the updated method(s).

      This approach does exlude all global options from the rebuilt method but any that are needed can be incorporated by appending suitable ::OPTIONS statements to the method source code before building it

       
  • Gil Barmwater

    Gil Barmwater - 2024-06-27

    Glad it was helpful!

     
  • Gil Barmwater

    Gil Barmwater - 2024-06-27

    I found it interesting that you found that no code changes were required, just creating a new method object from the same source would do the trick. I'm guessing the processing of the ::options trace directive must build a "list" of method objects to be traced and when one replaces or adds one (or more) of them with new objects, they will not be on the already created "list" and therefore not get traced. Good to know!

     
    • Rick McGuire

      Rick McGuire - 2024-06-27

      On Thu, Jun 27, 2024 at 1:56 PM Gil Barmwater orange-e@users.sourceforge.net wrote:

      I found it interesting that you found that no code changes were required,
      just creating a new method object from the same source would do the trick.
      I'm guessing the processing of the ::options trace directive must build a
      "list" of method objects to be traced and when one replaces or adds one (or
      more) of them with new objects, they will not be on the already created
      "list" and therefore not get traced. Good to know!

      A bad guess. The trace options are stored in the package object from which
      the method is created. However, if you create a new method object, it is
      associated with a different package object that does not have the same
      associated trace options.

      Rick


      [feature-requests:#836] Ability to switch off program-wide interactive
      tracing in a METHOD which uses EXPOSE

      Status: unread
      Milestone: 5.1.0
      Created: Sun May 26, 2024 07:09 PM UTC by Dom Wise
      Last Updated: Thu Jun 27, 2024 12:46 PM UTC
      Owner: nobody

      When ::OPTIONS TRACE ?R (or similar with the interactive flag) is
      specified, all ROUTINEs and METHODs in a package have interactive tracing
      automatically switched on. This is very useful for debugging as adding one
      line switches tracing on everywhere but sometimes there might be a small
      number of ROUTINEs or METHODs (those called frequently and /or with known
      correct behaviour) for which this is not required or desired.

      The global option can generally be overridden on a case by case basis by
      inserting CALL TRACE( '?') before the first instruction in a ROUTINE or
      METHOD, but it seems that in a METHOD that uses EXPOSE, the first
      instruction must be EXPOSE and interactive tracing will pause here before
      the earliest place the override code can be added and this limits the
      effectiveness of this method.

      There is a workaround which is NOT to use the global option and instead
      add code to activate tracing to each ROUTINE or METHOD, and actually when
      the workaround is not available it does just add the requirement for an
      extra <enter> to the tracing process whenever the METHOD is called but it
      would be nice if this corner case could be addressed.</enter>


      Sent from sourceforge.net because you indicated interest in <
      https://sourceforge.net/p/oorexx/feature-requests/836/>

      To unsubscribe from further messages, please visit <
      https://sourceforge.net/auth/subscriptions/>

       

      Related

      Feature Requests: #836

  • Gil Barmwater

    Gil Barmwater - 2024-06-28

    OK, fair enough. But I still find it "surprising" that the determination of the routine and method objects to be traced under "::options trace" is made when the directive is processed and not at run time.

     
    • Rick McGuire

      Rick McGuire - 2024-06-28

      On Fri, Jun 28, 2024 at 5:48 PM Gil Barmwater orange-e@users.sourceforge.net wrote:

      OK, fair enough. But I still find it "surprising" that the determination
      of the routine and method objects to be traced under "::options trace" is
      made when the directive is processed and not at run time.

      All directives are processed at translate time, none have a runtime
      component. One piece of information contained within a package object is
      the Initial trace settings. All executable units use that value when they
      start up. If not specified via a ::options statement, then those settings
      are just the default "Trace N" setting. The same thing happens with the
      ::options numeric settings.

      Rick


      [feature-requests:#836] Ability to switch off program-wide interactive
      tracing in a METHOD which uses EXPOSE

      Status: unread
      Milestone: 5.1.0
      Created: Sun May 26, 2024 07:09 PM UTC by Dom Wise
      Last Updated: Thu Jun 27, 2024 05:56 PM UTC
      Owner: nobody

      When ::OPTIONS TRACE ?R (or similar with the interactive flag) is
      specified, all ROUTINEs and METHODs in a package have interactive tracing
      automatically switched on. This is very useful for debugging as adding one
      line switches tracing on everywhere but sometimes there might be a small
      number of ROUTINEs or METHODs (those called frequently and /or with known
      correct behaviour) for which this is not required or desired.

      The global option can generally be overridden on a case by case basis by
      inserting CALL TRACE( '?') before the first instruction in a ROUTINE or
      METHOD, but it seems that in a METHOD that uses EXPOSE, the first
      instruction must be EXPOSE and interactive tracing will pause here before
      the earliest place the override code can be added and this limits the
      effectiveness of this method.

      There is a workaround which is NOT to use the global option and instead
      add code to activate tracing to each ROUTINE or METHOD, and actually when
      the workaround is not available it does just add the requirement for an
      extra <enter> to the tracing process whenever the METHOD is called but it
      would be nice if this corner case could be addressed.</enter>


      Sent from sourceforge.net because you indicated interest in <
      https://sourceforge.net/p/oorexx/feature-requests/836/>

      To unsubscribe from further messages, please visit <
      https://sourceforge.net/auth/subscriptions/>

       

      Related

      Feature Requests: #836

  • Dom Wise

    Dom Wise - 2024-06-30

    One thing to add.

    Method attributes such as "unguarded" are not part of the source of a method so if a method is to be fully rebuilt from source these need to be added with an appropriate call (e.g. setUnguarded) to the newly created method object.

    For the the example I gave earlier, if the original method is unguarded the method replacement code changes to:

    .MyClass~define("mymethod", .method~new("mymethod", .MyClass~method("mymethod")~source)~~setUnguarded)

     
    • Rick McGuire

      Rick McGuire - 2024-06-30

      On Sat, Jun 29, 2024 at 8:40 PM Dom Wise melcaspazar@users.sourceforge.net
      wrote:

      One thing to add.

      Method attributes such as "unguarded" are not part of the source of a
      method so if a method is to be fully rebuilt from source these need to
      be added with an appropriate call (e.g. setUnguarded) to the newly created
      method object.

      For the the example I gave earlier, if the original method is unguarded
      the method replacement code changes to:

      .MyClass~define("mymethod", .method~new("mymethod",
      .MyClass~method("mymethod")~source)~~setUnguarded)


      [feature-requests:#836] Ability to switch off program-wide interactive
      tracing in a METHOD which uses EXPOSE

      Status: unread
      Milestone: 5.1.0
      Created: Sun May 26, 2024 07:09 PM UTC by Dom Wise
      Last Updated: Fri Jun 28, 2024 09:47 PM UTC
      Owner: nobody

      When ::OPTIONS TRACE ?R (or similar with the interactive flag) is
      specified, all ROUTINEs and METHODs in a package have interactive tracing
      automatically switched on. This is very useful for debugging as adding one
      line switches tracing on everywhere but sometimes there might be a small
      number of ROUTINEs or METHODs (those called frequently and /or with known
      correct behaviour) for which this is not required or desired.

      The global option can generally be overridden on a case by case basis by
      inserting CALL TRACE( '?') before the first instruction in a ROUTINE or
      METHOD, but it seems that in a METHOD that uses EXPOSE, the first
      instruction must be EXPOSE and interactive tracing will pause here before
      the earliest place the override code can be added and this limits the
      effectiveness of this method.

      There is a workaround which is NOT to use the global option and instead
      add code to activate tracing to each ROUTINE or METHOD, and actually when
      the workaround is not available it does just add the requirement for an
      extra <enter> to the tracing process whenever the METHOD is called but it
      would be nice if this corner case could be addressed.</enter>


      Sent from sourceforge.net because you indicated interest in <
      https://sourceforge.net/p/oorexx/feature-requests/836/>

      To unsubscribe from further messages, please visit <
      https://sourceforge.net/auth/subscriptions/>

       

      Related

      Feature Requests: #836

Anonymous
Anonymous

Add attachments
Cancel