team@coreconcepts.design, Author at FusionReactor Observability & APM https://fusion-reactor.com/author/teamcoreconcepts-design/ Wed, 21 Aug 2024 19:57:40 +0000 en-US hourly 1 https://wordpress.org/?v=6.6.2 https://fusion-reactor.com/wp-content/uploads/2024/03/cropped-icon-32x32.png team@coreconcepts.design, Author at FusionReactor Observability & APM https://fusion-reactor.com/author/teamcoreconcepts-design/ 32 32 Save 25% on Adobe ColdFusion Upgrades https://fusion-reactor.com/blog/evangelism/coldfusion-hot-sale/ Thu, 15 Dec 2022 08:35:33 +0000 https://fronprem.dev.onpressidium.com/2022/12/15/coldfusion-hot-sale/ [vc_row height=”small”][vc_column][vc_row_inner][vc_column_inner width=”2/3″][vc_column_text] Exclusive ColdFusion Upgrade Promo from FusionReactor [/vc_column_text][vc_column_text]Adobe ColdFusion Sale. Upgrades to Adobe ColdFusion are now available at an exclusive rate, saving you 25% of the usual price. Upgrade to ColdFusion 21 if you have CF9, 10, 11, … Read More

The post Save 25% on Adobe ColdFusion Upgrades appeared first on FusionReactor Observability & APM.

]]>
[vc_row height=”small”][vc_column][vc_row_inner][vc_column_inner width=”2/3″][vc_column_text]

Exclusive ColdFusion Upgrade Promo from FusionReactor

[/vc_column_text][vc_column_text]Adobe ColdFusion Sale. Upgrades to Adobe ColdFusion are now available at an exclusive rate, saving you 25% of the usual price. Upgrade to ColdFusion 21 if you have CF9, 10, 11, or 2016 and get the following deal:[/vc_column_text][vc_column_text]

25% discount compared to the full price of CF21

This offer is exclusively from the FusionReactor team – If you’re not already a customer, then you can also add FusionReactor into the offer and save even more. FusionReactor prices start from $19 per month, see our APM pricing page.[/vc_column_text][us_separator size=”small”][vc_column_text]

Get all the benefits of FusionReactor

Your CF applications will be stable, error-free, and perform as they should.

Deal ends February 28th, 2023

If you have questions then use the form or book a slot to discuss your needs. See what ColdFusion customers think of FusionReactor.[/vc_column_text][vc_column_text]

We Recommend Adobe Platinum Support

We strongly recommend you look at Adobe’s Platinum Support option. Platinum is an optional annual maintenance/support product. The big advantage it gives you is that if you’re in support, you will automatically receive the next major version of ColdFusion e.g. CF2023.

Whilst we cannot say for sure when this will be released, it’s been usual that Adobe released in 2-3 year cycles – the last one was in Fall 2020.  If you’re in support, the new license key will automatically be placed on your Adobe LWS account.  Platinum support also includes 24-7 access to Adobe support engineers.  Please note, that you can ONLY purchase Platinum together with a new, or upgrade CF license – you cannot buy Platinum support after the fact. Read more about Platinum support here.[/vc_column_text][vc_column_text]

Older versions of CF are no longer supported by Adobe

[/vc_column_text][us_separator size=”small”][vc_column_text]

Version Released Core Support ends
ColdFusion 2021 November 11, 2020 November 10, 2025
ColdFusion 2018 July 12, 2018 July 13, 2023
ColdFusion 2016 February 16, 2016 Ended
ColdFusion 11 April 29, 2014 Ended
ColdFusion 10 May 15, 2012 Ended

[/vc_column_text][/vc_column_inner][vc_column_inner width=”1/3″][us_image image=”43963″ size=”thumbnail”][vc_column_text]Tell us which CF Edition you need and how many licenses you’re upgrading from and we will send you a personalized quote.[/vc_column_text][us_cform items=”%5B%7B%22type%22%3A%22info%22%2C%22inputmode%22%3A%22text%22%2C%22date_format%22%3A%22d%20MM%20yy%22%2C%22value%22%3A%22CF%20Upgrade%20estimate%20request%22%2C%22required%22%3A%220%22%2C%22is_used_as_from_email%22%3A%220%22%2C%22is_used_as_from_name%22%3A%220%22%2C%22move_label%22%3A%220%22%2C%22file_max_size%22%3A%2210MB%22%2C%22cols%22%3A%221%22%7D%2C%7B%22type%22%3A%22text%22%2C%22inputmode%22%3A%22text%22%2C%22date_format%22%3A%22d%20MM%20yy%22%2C%22placeholder%22%3A%22Name%22%2C%22required%22%3A%220%22%2C%22is_used_as_from_email%22%3A%220%22%2C%22is_used_as_from_name%22%3A%220%22%2C%22move_label%22%3A%220%22%2C%22file_max_size%22%3A%2210MB%22%2C%22cols%22%3A%221%22%7D%2C%7B%22type%22%3A%22email%22%2C%22inputmode%22%3A%22text%22%2C%22date_format%22%3A%22d%20MM%20yy%22%2C%22placeholder%22%3A%22Email%22%2C%22required%22%3A%220%22%2C%22is_used_as_from_email%22%3A%220%22%2C%22is_used_as_from_name%22%3A%220%22%2C%22move_label%22%3A%220%22%2C%22file_max_size%22%3A%2210MB%22%2C%22cols%22%3A%221%22%7D%2C%7B%22type%22%3A%22checkboxes%22%2C%22inputmode%22%3A%22text%22%2C%22date_format%22%3A%22d%20MM%20yy%22%2C%22values%22%3A%22Existing%20FusionReactor%20Customer%5CnNew%20to%20FusionReactor%22%2C%22required%22%3A%220%22%2C%22is_used_as_from_email%22%3A%220%22%2C%22is_used_as_from_name%22%3A%220%22%2C%22move_label%22%3A%220%22%2C%22file_max_size%22%3A%2210MB%22%2C%22cols%22%3A%221%22%7D%2C%7B%22type%22%3A%22text%22%2C%22inputmode%22%3A%22text%22%2C%22date_format%22%3A%22d%20MM%20yy%22%2C%22label%22%3A%22%23%20Of%20CF%20ENTERPRISE%20licenses%22%2C%22required%22%3A%220%22%2C%22is_used_as_from_email%22%3A%220%22%2C%22is_used_as_from_name%22%3A%220%22%2C%22move_label%22%3A%220%22%2C%22file_max_size%22%3A%2210MB%22%2C%22cols%22%3A%221%22%7D%2C%7B%22type%22%3A%22text%22%2C%22inputmode%22%3A%22text%22%2C%22date_format%22%3A%22d%20MM%20yy%22%2C%22label%22%3A%22%23%20Of%20CF%20STANDARD%20licenses%22%2C%22required%22%3A%220%22%2C%22is_used_as_from_email%22%3A%220%22%2C%22is_used_as_from_name%22%3A%220%22%2C%22move_label%22%3A%220%22%2C%22file_max_size%22%3A%2210MB%22%2C%22cols%22%3A%221%22%7D%2C%7B%22type%22%3A%22textarea%22%2C%22inputmode%22%3A%22text%22%2C%22date_format%22%3A%22d%20MM%20yy%22%2C%22label%22%3A%22Any%20questions%3F%22%2C%22required%22%3A%220%22%2C%22is_used_as_from_email%22%3A%220%22%2C%22is_used_as_from_name%22%3A%220%22%2C%22move_label%22%3A%220%22%2C%22file_max_size%22%3A%2210MB%22%2C%22cols%22%3A%221%22%7D%5D” receiver_email=”sales@fusion-reactor.com, david@fusion-reactor.com, nick_flewitt@intergral.com” success_message=”VGhhbmslMjB5b3UlMjElMjBZb3VyJTIwbWVzc2FnZSUyMHdhcyUyMHNlbnQu”][us_separator][/vc_column_inner][/vc_row_inner][us_separator size=”small”][vc_column_text]

Adobe ColdFusion Mega Sale – Useful resources

[/vc_column_text][vc_row_inner][vc_column_inner width=”1/3″][us_separator][vc_video link=”https://www.youtube.com/watch?v=QQBHnQExFqc&list=PLDIpVdHiiEMcAakCDYNpu4_0szhiAd5jF&index=13″][us_separator][vc_column_text]Intergral GmbH is an Authorized Adobe Reseller[/vc_column_text][us_image image=”67407″ align=”left”][/vc_column_inner][vc_column_inner width=”1/3″][us_separator][vc_video link=”https://www.youtube.com/watch?v=LN0_31YTwp8&list=PLDIpVdHiiEMcAakCDYNpu4_0szhiAd5jF&index=14″][/vc_column_inner][vc_column_inner width=”1/3″][/vc_column_inner][/vc_row_inner][/vc_column][/vc_row][vc_row disable_element=”yes”][vc_column][vc_column_text]

This summer, we are pleased to offer some special discounted pricing on the Adobe ColdFusion suite! If you purchase before the end of August 2019, you will receive 10% discount on the following Adobe ColdFusion 2018 products – see conditions below.

Contact Sales

ColdFusion® 2018 Enterprise Edition – AOO
8 Core
Part# – US: 65293676JA EU: 65293674FA
Rapidly build and deploy scalable, high-performing web and mobile applications
ColdFusion® 2018 Enterprise Edition (Upsell License FLP CSTD)
8 Core
Part# – EU: 65293690FA
This license is for customers who wish to upgrade from CF Standard to Enterprise, though you must be currently using ColdFusion® 2018, to use this.

RRP:
$ 9,499.00
Discount:
$ 950.00 (10%)
Our Price:
$ 8,549.00

RRP:
$ 7,699.00
Discount:
$ 770.00 (10%)
Our Price:
$ 6,929.00
ColdFusion® 2018 Enterprise Edition UPG CF ENT From 1 Version Back
8 Core
Part# – US: 65293699JA EU: 65293701FA
This license allows you to upgrade from ColdFusion® 2016 Enterprise to ColdFusion® 2018 Enterprise
ColdFusion® 2018 Standard Edition – AOO
2 Core
Part# – US: 65293630JA EU: 65293629FA
Rapidly build and deploy scalable, high-performing web and mobile applications

RRP:
$ 4,749.00
Discount:
$ 474.00 (10%)
Our Price:
$ 4,275.00

RRP:
$ 2,499.00
Discount:
$ 250.00 (10%)
Our Price:
$ 2,249.00
ColdFusion® 2018 Standard Edition UPG CF STD 1 Version Back
2 Core
Part# – US: 65293592JA EU: 65293591FA
This license allows you to upgrade from ColdFusion® 2016 Standard to ColdFusion® 2018 Standard
ColdFusion® Builder 2018 – AOO
Part# – US: 65293525JA EU: 65293527FA
ColdFusion® Builder™ 4 software is the only professional IDE for quickly and easily building ColdFusion applications.

RRP:
$ 1,249.00
Discount:
$ 124.00 (10%)
Our Price:
$ 1,125.00

RRP:
$ 299.00
Discount:
$ 30.00 (10%)
Our Price:
$ 269.00

Conditions:

  • This discount will be effective immediately.
  • All orders must be received by our sales team by EOB on 31-August-2019.
  • All orders must be made directly with the Intergral sales team.
  • These discounted offers are not available via our online store: https://www.buy-adobe-software.com

[/vc_column_text][/vc_column][/vc_row]

The post Save 25% on Adobe ColdFusion Upgrades appeared first on FusionReactor Observability & APM.

]]>
What’s new in FusionReactor 8.3.0 https://fusion-reactor.com/blog/evangelism/whats-new-in-fusionreactor-8-3/ Mon, 10 Feb 2020 11:02:52 +0000 https://fronprem.dev.onpressidium.com/2020/02/10/whats-new-in-fusionreactor-8-3/ [vc_row][vc_column][vc_column_text] Improved alerting, Event Snapshots, improved Cloud UI and more FusionReactor 8.3 has new CPU alerts in crash protection. We have redeveloped Event Snapshot for ColdFusion users which means that it no longer courses server issues. FusionReactor Cloud now lets … Read More

The post What’s new in FusionReactor 8.3.0 appeared first on FusionReactor Observability & APM.

]]>
[vc_row][vc_column][vc_column_text]

Improved alerting, Event Snapshots, improved Cloud UI and more

FusionReactor 8.3 has new CPU alerts in crash protection. We have redeveloped Event Snapshot for ColdFusion users which means that it no longer courses server issues. FusionReactor Cloud now lets you choose your theme and gives you better warning notifications. As well as a host of other smaller improvements and bug fixes.

FusionReactor 8.3 is now available for download now!

[/vc_column_text][us_separator][vc_column_text]

CPU alerting in Crash Protection

This feature has been requested a lot. If you have a long-running request, large GC issues or problems with background tasks or threads then FusionReactor 8.3 Crash Protection can send you an alert.

[/vc_column_text][us_separator][us_image image=”57978″][vc_column_text]

Threshold set to 50% and the duration is set to 10 seconds

[/vc_column_text][us_separator][vc_column_text]

It is easy to use and works in a similar way to Memory Protection. You simply set the required threshold, the minimum duration and your alerting strategy.

When the alert threshold is hit, you will have 3 available alerting strategies:

 

  • Send an email containing the details of the stack, running requests and system metrics into your inbox
  • Queue requests entering the application server until the CPU is below the threshold
  • Reject requests entering the application server until the CPI is below the threshold

[/vc_column_text][us_separator][us_image image=”57980″][vc_column_text]

In our inbox we have an alert email which gives us all of the relevant details and links you back into FR

[/vc_column_text][us_separator][vc_column_text]

Event Snapshot for ColdFusion in FusionReactor 8.3

Every error now has an Event Snapshot, historically if you were a CF user then this might have had a negative effect on your server; this was down to CF error handling.

We have now redeveloped this feature so that it no longer impacts your server and enabled Event Snapshots by default.

[/vc_column_text][us_separator][us_image image=”57983″][vc_column_text]

All errors now have an Event Snapshot

[/vc_column_text][us_separator][vc_column_text]

Any recurring errors tracked by FusionReactor will now automatically generate an Event Snapshot, in the snapshot you will see the Exception, source code, stack frames and variables.

Note that for snapshots generated for Adobe ColdFusion servers, variables will only be available for the top stack frame.

[/vc_column_text][us_separator][us_image image=”57986″][vc_column_text]

Click the “Event Snapshot” link and you will see the variables, stack trace, log messages and the exact line of source code where the error occurred

[/vc_column_text][us_separator][vc_column_text]

Improvements to the Cloud UI

We have made a number of smaller improvements to the FusionReactor Cloud that make a large difference to the usability.

[/vc_column_text][us_separator][vc_column_text]

Themes

Everyone has a preference to whether they use a light theme or a dark theme so Cloud will now let you choose. Simply go into account settings or use the keyboard shortcut Q and you can decide on a light or a dark theme. Cloud trails are free – even if you are an existing customer.

[/vc_column_text][us_separator][us_image image=”57989″][vc_column_text]

The futures’ bright, or dark – you choose

[/vc_column_text][us_separator][vc_column_text]

Better warning messages

We have improved our messaging for offline servers and for when data is not available. You will now be prompted to change the timeframe to and adjust set filters to find the relevant data.

[/vc_column_text][us_separator][us_image image=”57990″][vc_column_text]

You now get a clear warning when you try and look at data from before you connected your server

[/vc_column_text][us_separator][vc_column_text]

Other Improvements

 

  • Brand new documentation to be released soon
  • Middle click support in local FR UI
  • Support for upcoming CommandBox 4.9
  • Fix for ColdBox tracking
  • Support for Arm 64  / Aarch 64 architectures
  • Support for Wildfly 14 – 19
  • Tracking for RMI calls in applications (Java 1.7 – 1.9)
  • Kubernetes detection

[/vc_column_text][us_separator][vc_column_text]

Want to know more about FusionReactor 8.3 or have any questions?

Our support team is holding a Live Stream Q&A tomorrow at 11 am PST.

[/vc_column_text][/vc_column][/vc_row]

The post What’s new in FusionReactor 8.3.0 appeared first on FusionReactor Observability & APM.

]]>
What’s new in FusionReactor 8.3.0 – Live Stream Support https://fusion-reactor.com/blog/whats-new-in-fusionreactor-8-3-0-live-stream-support/ Wed, 29 Jan 2020 09:14:33 +0000 https://fronprem.dev.onpressidium.com/2020/01/29/whats-new-in-fusionreactor-8-3-0-live-stream-support/ On February 11th at 7PM UTC (11AM PST; see your local time), we are running our first live demo and Q&A session on the FusionReactor YouTube channel, covering what’s new in FusionReactor 8.3.0, which is releasing very soon. This session … Read More

The post What’s new in FusionReactor 8.3.0 – Live Stream Support appeared first on FusionReactor Observability & APM.

]]>
On February 11th at 7PM UTC (11AM PST; see your local time), we are running our first live demo and Q&A session on the FusionReactor YouTube channel, covering what’s new in FusionReactor 8.3.0, which is releasing very soon.

This session will be hosted by Michael Flewitt, a technical support engineer for FusionReactor and the FusionReactor Cloud and features Charlie Arehart, a ColdFusion consultant and all-around expert as a guest.

Our intention is to host a regular demo and Q&A sessions covering everything related to the FusionReactor product, CFML/Java development and other exciting projects we are working on at Intergral.

During these sessions, you will have the opportunity to ask us any questions you may have and get direct advice from our support team.

Our first session will cover what’s new in FusionReactor 8.3.0! 

We have been working hard to give you powerful new features and an improved user experience with FusionReactor including;

  • Enhanced Crash Protection
  • Superior error detection in ColdFusion
  • Interactive and intuitive self-service support
  • Significant user experience improvements in the Cloud
  • A load more cool features

Subscribe to the FusionReactor Youtube channel and set a reminder here!

The demo should take around 30 minutes, at which point we will have time to answer all your questions.

We look forward to chatting with you soon!

The post What’s new in FusionReactor 8.3.0 – Live Stream Support appeared first on FusionReactor Observability & APM.

]]>
[FRS-443] FR Cloud – Subtransaction Culling https://fusion-reactor.com/blog/frs-443/ Tue, 28 Jan 2020 20:17:45 +0000 https://fronprem.dev.onpressidium.com/2020/01/28/frs-443/ [FRS-443] FR Cloud - Subtransaction Culling … Read More

The post [FRS-443] FR Cloud – Subtransaction Culling appeared first on FusionReactor Observability & APM.

]]>

FusionReactor Cloud Transport: Transaction Shipping

When licensed with a CLOUD-* key, FusionReactor will connect to FusionReactor Cloud and begin shipping metric data periodically.

Apart from numeric metrics like memory and CPU Usage, FusionReactor will also ship certain transactions to FusionReactor Cloud. These key transactions are visible in the Transactions tab, after selecting a server.

Transaction Shipping

Master (also known as ‘parent’) transactions are selected for shipping to the cloud based on a set of criteria buckets. There is one set of buckets per application. Only the first 100 distinct applications are tracked per minute, and there’s also a global limit of 100 master transactions per minute too.

  • Error Transactions – the first 4 transactions to close in error (e.g. web requests resulting in 500-series results) are selected.
  • Long – the longest 4 transactions which ran longer than 500ms are selected.
  • Slow – the longest 4 transactions which were slower than the threshold set in FusionReactor > Requests > Settings > WebRequest History > Slow Request Threshold are selected.

All of the subtransactions of these masters are also kept and transferred (but see the section on Subtransaction Trimming later).

Effect of Limits

If a transaction is seen which would fall into one of these buckets, but:

  • It belongs to the 101st or laster application to be seen that minute, or
  • There are already 100 transactions in all buckets across all applications,

… then that transaction will not be sent to the Cloud.

Subtransaction Trimming

Transactions can have a virtually-unlimited quantity of subtransactions. For example: a ColdFusion page (which is tracked as a parent transaction) can perform a CFHTTP call to a REST endpoint. That call will be detected and tracked as a subtransaction on the CF page. This could happen multiple times and they would all be tracked by FusionReactor.

In order to keep the size of shipped data within an acceptable margin, a culling algorithm ensures that at most, 500 subtransactions are shipped to the cloud.

The algorithm looks at culling subtransactions of the long bucket first, then slow, and then error last. We do it in this order so that the error transactions are less likely to be trimmed because they’re most important.

If subtransactions were trimmed from the shipped data, this will be indicated in FusionReactor Cloud.


Issue Details

Type Technote
Issue Number FRS-443
Components Cloud
Resolution Fixed
Last Updated 2020-01-28T20:16:51.897+0000
Fix Version(s) 7.2.0

The post [FRS-443] FR Cloud – Subtransaction Culling appeared first on FusionReactor Observability & APM.

]]>
Using The FusionReactor API (FRAPI) To Add Custom Instrumentation In Lucee CFML 5.2.9.40 https://fusion-reactor.com/blog/evangelism/using-the-fusionreactor-api-frapi-to-add-custom-instrumentation-in-lucee-cfml-5-2-9-40/ Mon, 27 Jan 2020 16:15:41 +0000 https://fronprem.dev.onpressidium.com/2020/01/27/using-the-fusionreactor-api-frapi-to-add-custom-instrumentation-in-lucee-cfml-5-2-9-40/ [vc_row][vc_column][vc_column_text] Written By Ben Nadel on January 25, 2020, original article reproduced with kind permission. Now that InVision is migrating from the New Relic APM to the FusionReactor APM (Application Performance Management) for our Lucee CFML servers, I wanted to take some time to familiarize myself with the API … Read More

The post Using The FusionReactor API (FRAPI) To Add Custom Instrumentation In Lucee CFML 5.2.9.40 appeared first on FusionReactor Observability & APM.

]]>
[vc_row][vc_column][vc_column_text]

Written By Ben Nadel on January 25, 2020, original article reproduced with kind permission.

Now that InVision is migrating from the New Relic APM to the FusionReactor APM (Application Performance Management) for our Lucee CFML servers, I wanted to take some time to familiarize myself with the API exposed by the FusionReactor Java Agent. On its own, the FusionReactor core functionality is already quite insightful. However, I am constantly using feature flags to experiment with code optimization; so, it would be even more helpful if I could graph the impact of my experimentation alongside the performance of our Lucee CFML 5.2.9.40 servers.

[/vc_column_text][us_separator][vc_column_text]

[/vc_column_text][us_separator][vc_column_text]

Much like the New Relic Java Agent, once you have the FusionReactor Java Agent installed, you can access its API directly from within your ColdFusion CFML code. I couldn’t find many examples of this online. So, much of what follows is based on an old article from the FusionReactor blog, dumping out the FRAPI Java Objects, and several bouts of trial-and-error.

To figure out how everything works, I created a small ColdFusion script that exercises several of the FRAPI methods in the context of a simulated feature flag. The idea below is to branch some CPU-intensive processing, and then use the FusionReactor API to help see which version of the code is more performant.

 

NOTE: The following CFML code has a lot of comments. Those represents all of the confusion that I had about how things worked, especially with regard to the differences between the Standalone dashboard and the Cloud dashboard.

[/vc_column_text][us_separator][vc_column_text]

<cfscript>
    
    // Get the running FusionReactor API (FRAPI) instance from the FRAPI factory class.
    // --
    // Java Docs: http://fusionreactor.dev.onpressidium.com/frapi/7_0_0/com/intergral/fusionreactor/api/FRAPI.html
    frapi = createObject( "java", "com.intergral.fusionreactor.api.FRAPI" )
        .getInstance()
    ;
    // ------------------------------------------------------------------------------- //
    // ------------------------------------------------------------------------------- //
    // By default, FusionReactor will use the name of the application as defined in the
    // Application.cfc ColdFusion framework component. However, we can set the name
    // programmatically.
    frapi.setTransactionApplicationName( "FRAPI-Testing" );
    // By default, FusionReactor will calculate the transaction name based on the request
    // context. It actually seems to "understand" the fact that we're using Framework One
    // (FW/1) in production and uses the "action" value as the transaction name. That's
    // the beauty of using an APM product that is embedded within the ColdFusion and CFML
    // community. That said, we can set the transaction name programmatically.
    // --
    // See Framework Support: http://fusionreactor.dev.onpressidium.com/support/kb/frs-431/
    frapi.setTransactionName( "GET/feature-flag-test" );
    // ------------------------------------------------------------------------------- //
    // ------------------------------------------------------------------------------- //
    // SIMULATE FEATURE FLAG setting.
    shouldUseExperiment = randRange( 0, 1 );
    // We can use the trace() method to aggregate arbitrary time-stamped data along with
    // the request. This data gets placed in a "Traces" tab in the Request detail.
    // --
    // CAUTION: At the time of this writing, this data is not accessible on the Cloud
    // dashboard, only on the STANDALONE dashboard. And, this data SHOULD NOT be
    // confused with the "Tracing" tab on the CLOUD dashboard, which is concerned with
    // nested Transactions only.
    frapi.trace( "Starting Experiment." );
    // Try tracing a Struct.
    frapi.trace({
        usingExpeirment: yesNoFormat( shouldUseExperiment )
    });
    // Try tracing an Array.
    frapi.trace([
        "DATE",
        dateFormat( now() ),
        "TIME (EST)",
        timeFormat( now() )
    ]);
    // Let's imagine that this page is going to represent two different algorithms: the
    // base one and an experimental one that we are testing with a feature flag. In
    // order to see if our experiment is worthwhile, we're going to track the relative
    // execution time of each approach.
    startedAt = getTickCount();
    // CASE: Experiment.
    if ( shouldUseExperiment ) {
        frapi.trace( "Starting experimental case." );
        // We can associate arbitrary key-value pairs with the request. These will show
        // up in the "Properties" tab of the request detail.
        // --
        // NOTE: At the time of this writing, these properties are not accessible on the
        // Cloud dashboard, only on the Standalone dashboard.
        frapi.getActiveTransaction()
            .setProperty( "Features - Optimizations - Test", "True" )
        ;
        // In addition to the timing metrics which we are going to record, we can also
        // create segments, aka "sub transactions", that help us map the relative
        // execution time for parts of the request.
        // --
        // NOTE: In the CLOUD dashboard, these show up in the "Traces" tab of a
        // Transaction detail. In the STANDALONE dashboard, these who up in the
        // "Relations" tab of a Transaction detail.
        // --
        // NOTE: In the CLOUD dashboard, these can also be found in the "Flavor" dropdown
        // of the Transactions tab. In the STANDALONE dashboard, these can also be
        // graphed under the Transactions section.
        // --
        // NOTE: When naming a transaction, I was running into issues in the STANDALONE
        // dashboard if I used any kind of path-style notation (either "/" or "."): only
        // the last segment of the "path" would show up, but would have no values.
        try {
            subtransaction = frapi.createTrackedTransaction( "HeavyProcessing-Exp-Start" );
            // SIMULTATE algorithm time.
            sleep( randRange( 25, 50 ) );
        } finally {
            subtransaction.close();
        }
        try {
            subtransaction = frapi.createTrackedTransaction( "HeavyProcessing-Exp-End" );
            // SIMULTATE algorithm time.
            sleep( randRange( 25, 50 ) );
        } finally {
            subtransaction.close();
        }
    // CASE: Default.
    } else {
        frapi.trace( "Starting default case." );
        // We can associate arbitrary key-value pairs with the request. These will show
        // up in the "Properties" tab of the request detail.
        // --
        // NOTE: At the time of this writing, these properties are not accessible on the
        // Cloud dashboard, only on the Standalone dashboard.
        frapi.getActiveTransaction()
            .setProperty( "Features - Optimizations - Test", "False" )
        ;
        // In addition to the timing metrics which we are going to record, we can also
        // create segments, aka "sub transactions", that help us map the relative
        // execution time for parts of the request.
        // --
        // NOTE: In the CLOUD dashboard, these show up in the "Traces" tab of a
        // Transaction detail. In the STANDALONE dashboard, these who up in the
        // "Relations" tab of a Transaction detail.
        // --
        // NOTE: In the CLOUD dashboard, these can also be found in the "Flavor" dropdown
        // of the Transactions tab. In the STANDALONE dashboard, these can also be
        // graphed under the Transactions section.
        // --
        // NOTE: When naming a transaction, I was running into issues in the STANDALONE
        // dashboard if I used any kind of path-style notation (either "/" or "."): only
        // the last segment of the "path" would show up, but would have no values.
        try {
            subtransaction = frapi.createTrackedTransaction( "HeavyProcessing-Base-Start" );
            // SIMULTATE algorithm time.
            sleep( randRange( 1000, 2500 ) );
        } finally {
            subtransaction.close();
        }
        try {
            subtransaction = frapi.createTrackedTransaction( "HeavyProcessing-Base-End" );
            // SIMULTATE algorithm time.
            sleep( randRange( 1000, 2500 ) );
        } finally {
            subtransaction.close();
        }
    } // END: Processing experiment.
    duration = ( getTickCount() - startedAt );
    // In addition to the Transaction-based recording we're doing above, we can also
    // record custom metrics which we can then graph in the FusionReactor dashboard.
    // --
    // NOTE: FusionReactor's documentation seems to use a path-style notation when naming
    // custom metrics. As such, I am just following the same pattern in the following
    // metric examples.
    // --
    // NOTE: The metrics are always available in the STANDALONE version of the
    // FusionReactor dashboard; but, to stream them to the CLOUD dashboard as well, the
    // metric has to be explicitly enabled with .enableCloudMetric(), and only works for
    // NUMERIC AGGREGATE metrics.
    if ( shouldUseExperiment ) {
        
        frapi.postNumericAggregateMetric( "/optimizations/exp/duration", duration );
        frapi.enableCloudMetric( "/optimizations/exp/duration" );
    } else {
        frapi.enableCloudMetric( "/optimizations/base/duration" );
        frapi.postNumericAggregateMetric( "/optimizations/base/duration", duration );
    }
    frapi.trace( "Ending Experiment." );
</cfscript>

<!--- ------------------------------------------------------------------------------ --->
<!--- ------------------------------------------------------------------------------ --->

<script>
    // Simulate regular throughput / traffic to this endpoint by refreshing.
    setTimeout(
        function() {
            window.location.reload();
        },
        1000
    );
</script>

view rawtest.cfm hosted with ❤ by GitHub

[/vc_column_text][us_separator][vc_column_text]

As you can see, this ColdFusion code runs, sits there for 1-second, and then refreshes itself using JavaScript. Within the code, I’m using the following FRAPI methods:

 

  • setTransactionApplicationName()
  • setTransactionName()
  • trace()
  • getActiveTransaction()
  • setProperty()
  • createTrackedTransaction()
  • postNumericAggregateMetric()
  • enableCloudMetric()

Let’s look at these methods individually to see what they do and how they show up in the various FusionReactor dashboards.

[/vc_column_text][us_separator][vc_column_text]

FRAPI.setTransactionApplicationName() Method

The Transaction Application Name is the name of the ColdFusion application framework instance that is processing the current request. By default, FusionReactor will use the name that you provide inside the Application.cfc component (using this.name). However, you can override it programmatically as I am doing above.

Since you can have N-number of ColdFusion applications running within a single ColdFusion instance, your FusionReactor dashboard may pickup Transactions from several concurrently-running applications. Having a sensible, human-readable name for your “Transaction Application” name will help differentiate the various recordings within the dashboard.

[/vc_column_text][us_separator][vc_column_text]

FRAPI.setTransactionName() Method

Just as with the Transaction Application Name, FusionReactor will automatically get the Transaction Name from current request. And, as an added bonus, FusionReactor is built to understand several of the popular ColdFusion Application frameworks (like ColdBox, Framework/One, and Fusebox). This means that FusionReactor will automatically use the framework action variable to help identify the Transaction.

So, for example, if you were to make a Framework/One (FW/1) request to:

GET /subsystem:section/item/foo/bar/meep/moop/

… FusionReactor would automatically give the Transaction the following name:

subsystem:section/item

Of course, if you are using an unsupported ColdFusion framework, or want to override the Transaction name, you can use the .setTransactionName() method.

 

ASIDE: It’s this kind of tight integration that sets FusionReactor apart from other Java APMs. Yes, it can monitor any type of JVM-based application; but, it clearly goes above and beyond to make ColdFusion developers happy! You gotta love that mindset.

[/vc_column_text][us_separator][vc_column_text]

FRAPI.trace() Method

The .trace() method allows you to log arbitrary time-stamped values along with the request. As you can see from my example, I’m logging a String, a Struct, and an Array. Each of these values is handled properly by the FusionReactor API and is rendered within the “Traces” tab of a Transaction detail:

[/vc_column_text][us_separator][us_image image=”57954″][us_separator][vc_column_text]

As you can see, the trace output is associated with the Transaction; but, it’s not intermingled with the rest of the request metadata – it stands on its own. To get more intermingled timing data, we can use sub-transactions, which we’ll look at shortly.

As far as I can tell, the Traces tab is only available in the Standalone dashboard – I could not find this data in the Cloud dashboard. The Cloud dashboard does have a “Tracing” tab; but, that tab deals with sub-transactions, not with the .trace() output.

[/vc_column_text][us_separator][vc_column_text]

FRAPI.getActiveTransaction() Method

The .getActiveTransaction() method gives you access to the Transaction associated with the current thread. If you are in the parent request, this gives you the same result as calling .getActiveMasterTransaction() (not demonstrated in my example). However, if you are in a sub-transaction, calling .getActiveTransaction() will give you the sub-transaction, not the master transaction.

NOTE: The BaseTransaction and TrackedTransction classes have a load of methods on them which don’t seem to be documented anywhere – not even in the FRAPI Java Docs. To see what is available, you have to grab the Java object and dump() it out to the screen. Among the potentially interesting methods that I saw, there are:

 

  • setProperty()
  • setSubFlavour()
  • setExplanation()
  • setDescription()

… and many more which may prove interesting for really low-level debugging.

[/vc_column_text][us_separator][vc_column_text]

Transaction.setProperty() Method

Once I have the currently-executing Transaction, I call .setProperty() to store arbitrary key-value pairs. The values must be Strings; and are rendered in the “Properties” tab of the Transaction detail:

[/vc_column_text][us_separator][us_image image=”57956″][us_separator][vc_column_text]

I usually use this type of functionality to store the associated User ID with the request.

I have confirmed with the FusionReactor Support team that the Properties values are only accessible in the Standalone dashboard – these values are not streamed to the Cloud dashboard.

[/vc_column_text][us_separator][vc_column_text]

FRAPI.createTrackedTransaction() Method

Creating nested transactions allows us to segment our code in such a way that makes the execution time of the code much more visible within the FusionReactor dashboard. There are two ways to create nested transactions:

 

  • .createTrackedTransaction()
  • .createTransaction()

 

CAUTION: Each transaction has to be explicitly closed via .close(). While I didn’t test this, I assume that if you don’t call .close(), the timing of the sub-transaction will be corrupted and will likely time-out at some point, making it appear as if the transaction took substantially longer than it really did.

Both of these create a nested transaction that is visible within the breakdown of a parent transaction / request. But, only the “tracked” transaction can be seen in an “activity” graph within the dashboard.

In my demo, each branch of the simulated feature flag is further segmented into two sub-transactions. In the Standalone dashboard, these sub-transactions are visible in the “Relations” tab of a given Transaction:

[/vc_column_text][us_separator][us_image image=”57957″][us_separator][vc_column_text]

As you can see, the relative execution times of each sub-transaction is visible under the overall execution time of the parent transaction / request.

Sub-transaction can also be viewed on their own, independently of any parent transaction, in the Transactions section of the Standalone dashboard via the “Transactions” dropdown:

[/vc_column_text][us_separator][us_image image=”57960″][us_separator][vc_column_text]

In the Cloud dashboard, this same data is available in the “Tracing” tab of a given Transaction:

[/vc_column_text][us_separator][us_image image=”57962″][us_separator][vc_column_text]

Or, to view them on their own, independent of any parent request, you can select them in the “Flavor” dropdown on the Transactions tab:

[/vc_column_text][us_separator][us_image image=”57963″][us_separator][vc_column_text]

I ran into a lot of trouble when naming my sub-transactions. It looks as if including any kind of “path style” notation in the transaction name creates some unexpected behaviors in the dashboard. For example:

 

  • /my/transaction/name
  • my.transaction.name

Using either a / or a . in the name seemed to cause unexpected rendering in the dashboard that I couldn’t understand. Maybe this has something to do with the “flavors” that can be associated with the Transactions? I’m not sure. Furthermore, the behavior seemed to be a bit different in the Standalone dashboard vs. the Cloud dashboard.

For now, I’m just going to stick with non-pathed Transaction names.

One of the really cool features of the Standalone dashboard is that these sub-transactions can be easily graphed right alongside the JVM’s Heap and CPU graphs.

[/vc_column_text][us_separator][us_image image=”57966″][us_separator][vc_column_text]

I could not figure out how to create the same side-by-side comparison in the Cloud dashboard. I suspect that it would require creating a Custom graph; but, I couldn’t figure out how to find those transactions in the graph queries.

[/vc_column_text][us_separator][vc_column_text]

FRAPI.postNumericAggregateMetric() Method

In addition to segmenting my code with nested Transactions, I can also use various “metric” methods on the FRAPI to track arbitrary timing data. In this case, I’m using the generic “numeric” method; but, there are several methods that help ensure the appropriate data-type is stored:

 

  • postMetric()
  • postNumericAggregateMetric()
  • postNumericAggregateMetricFloat()
  • postNumericAggregateMetricLong()
  • postNumericAggregateMetrics()
  • postNumericMetric()
  • postNumericMetricFloat()
  • postNumericMetricLong()

The difference between the “vanilla” metric and the “aggregate” metric is that the aggregate metric will give you a roll-up graph (hour, day, week) in addition to the “live” graph. The vanilla metrics, on the other hand, will only give you the “live” graph.

In the Standalone dashboard, these metrics can be seen in the “Custom Series” of the Metrics graphs:

[/vc_column_text][us_separator][us_image image=”57968″][us_separator][vc_column_text]

In the Cloud dashboard, it’s a bit tricker to get at this data – you have to create a custom graph in the Metrics section:

[/vc_column_text][us_separator][us_image image=”57969″][us_separator][vc_column_text]

Note that the name of the metric has been automatically prefixed with /custom to differentiate it from other metrics that are implicitly provided by FusionReactor.

Only “aggregate numeric” metrics can be streamed to the Cloud dashboard. And, to do so, you have to explicitly call .enableCloudMetric() to target a specific metric name for Cloud consumption.

[/vc_column_text][us_separator][vc_column_text]

Using The FusionReactor API (FRAPI)

Hopefully I didn’t get any of this wildly wrong. I am still trying to get a grip on FusionReactor’s Cloud dashboard – it’s got a lot of the same functionality, but feels very different than the older Standalone dashboard. And, the whole “custom graph” thing is a bit confusing as well, especially when it comes to adding those graphs to the Graphs tab. In fact, it looks as if the custom graphs can’t keep up with the “Live” view of the Cloud dashboard.

But, this little exploration should get be far enough into the custom instrumentation that I can do with FusionReactor’s FRAPI object in Lucee CFML 5.2.9.40. If anyone else has any tips on what they can do, I’d love to hear it.

[/vc_column_text][/vc_column][/vc_row]

The post Using The FusionReactor API (FRAPI) To Add Custom Instrumentation In Lucee CFML 5.2.9.40 appeared first on FusionReactor Observability & APM.

]]>
[FRS-434] Direct links to download the latest version of FusionReactor https://fusion-reactor.com/blog/frs-434/ Mon, 20 Jan 2020 16:59:48 +0000 https://fronprem.dev.onpressidium.com/2020/01/20/frs-434/ [FRS-434] Direct links to download the latest version of FusionReactor … Read More

The post [FRS-434] Direct links to download the latest version of FusionReactor appeared first on FusionReactor Observability & APM.

]]>

Using the new download location for FusionReactor, you will guarantee to always download the latest available version of FusionReactor for your platform.

We highly recommend you use this link if possible, particularly if you are using automatic deployment tools or spun up virtual machines. You can then ensure you have all the latest features and bug fixes available to you and avoid the hassle of manually updating all your instances.

Download files are now found here

The links for each platform are listed below:
Manual Installation files
FusionReactor Single Jar – https://intergral-dl.s3.amazonaws.com/FR/Latest/fusionreactor.jar
Debug Native Libraries – https://s3-us-west-1.amazonaws.com/intergral-dl/FR/Latest/debuglibs.zip
Debug Library for Windows (frjvmti_x64.dll) – https://s3-us-west-1.amazonaws.com/intergral-dl/FR/Latest/frjvmti_x64.dll
Debug Library for Mac OS (libfrjvmti_x64.dylib) – https://s3-us-west-1.amazonaws.com/intergral-dl/FR/Latest/libfrjvmti_x64.dylib
Debug Library for Linux (libfrjvmti_x64.so) – https://s3-us-west-1.amazonaws.com/intergral-dl/FR/Latest/libfrjvmti_x64.so

Installers
FusionReactor Full Installer (Mac OS) – https://intergral-dl.s3.amazonaws.com/FR/Latest/FusionReactor_macos.dmg
FusionReactor Full Installer (Linux 64 bit) – https://intergral-dl.s3.amazonaws.com/FR/Latest/FusionReactor_linux-x64.sh
FusionReactor Full Installer (Windows 64 bit) – https://intergral-dl.s3.amazonaws.com/FR/Latest/FusionReactor_windows-x64.exe
Pre Configured No JRE (Unix) – https://intergral-dl.s3.amazonaws.com/FR/Latest/FusionReactor_unix_nojre.tar.gz
Pre Configured No JRE (Windows) – https://intergral-dl.s3.amazonaws.com/FR/Latest/FusionReactor_windows_nojre.zip

To find the exact version of FusionReactor is the latest, you can download the version.json file
You can download this file at https://s3-us-west-1.amazonaws.com/intergral-dl/FR/Latest/version.json


Issue Details

Type Technote
Issue Number FRS-434
Components Documentation
Resolution Fixed
Last Updated 2020-01-20T16:53:29.587+0000
Fix Version(s) Pending

The post [FRS-434] Direct links to download the latest version of FusionReactor appeared first on FusionReactor Observability & APM.

]]>
[FRS-465] Performance issue with Redis session management on Adobe ColdFusion servers with FusionReactor or Adobe Performance Monitoring Toolset (PMT) https://fusion-reactor.com/blog/frs-465/ Thu, 16 Jan 2020 16:02:56 +0000 https://fronprem.dev.onpressidium.com/2020/01/16/frs-465/ [FRS-465] Performance issue with Redis session management on Adobe ColdFusion servers with FusionReactor or Adobe Performance Monitoring Toolset (PMT) … Read More

The post [FRS-465] Performance issue with Redis session management on Adobe ColdFusion servers with FusionReactor or Adobe Performance Monitoring Toolset (PMT) appeared first on FusionReactor Observability & APM.

]]>

Introduction

We recently had a performance issue in FusionReactor where a user saw high CPU when running FusionReactor reported into our technical support team. Upon investigating the issue, we found this was due to both FusionReactor and the Adobe PMT tracking sessions by making a large number of calls to the Redis database.

In FusionReactor 8.2.3 we released a fix that will stop session tracking if Redis sessions are in use. The result of this is that you will only see an overview of total session activity, there are no metrics for the active, created or destroyed sessions from ColdFusion.

In the Sessions page of FusionReactor you would only see something like:

Abode have an open bug for this (https://tracker.adobe.com/#/view/CF-4205489), this fix has been scheduled for a HF7 release. Until Adobe fixes the issue, we do not enable full session tracking when using Redis sessions in ColdFusion 2018.

To confirm if you are affected by this issue

Go to Transactions > Activity and filer by Redis transactions. You will see something similar to:

Performance issue with Redis

This performance issue is caused by two factors:

  • A bug in FusionReactor that every second sends 2 get requests to Redis for each active session
  • A bug in the Adobe PMT that every second sends 1 get request to Redis for each active session

These Redis calls are all tracked by FusionReactor which slows down the performance of the server due to the volume of requests when a ColdFusion server has a high number of sessions even if these sessions where created on a different ColdFusion server but are using the same Redis server for the sessions.

The Workaround

To work around this issue please upgrade to version 8.2.1 or higher of FusionReactor which disabled session tracking from FusionReactor. Note that in this version, there will still be one set of Redis calls made to Redis if you are viewing the session information in the Adobe PMT.

When the bug for session tracking is fixed in ColdFusion 2018, we will update FusionReactor to reenable session tracking.


Issue Details

Type Technote
Issue Number FRS-465
Attachments Selection_419.jpg
Selection_420.jpg
Selection_421.jpg
Selection_422.jpg
Components JDBC, Session
Resolution Fixed
Last Updated 2020-01-16T16:00:39.057+0000
Affects Version(s) 8.2.0
Fix Version(s) Pending

The post [FRS-465] Performance issue with Redis session management on Adobe ColdFusion servers with FusionReactor or Adobe Performance Monitoring Toolset (PMT) appeared first on FusionReactor Observability & APM.

]]>
Understanding StackTraces in Java https://fusion-reactor.com/blog/understanding-stacktraces-in-java/ Wed, 15 Jan 2020 13:38:46 +0000 https://fronprem.dev.onpressidium.com/2020/01/15/understanding-stacktraces-in-java/ [vc_row][vc_column][vc_column_text] By guest author Thorben Janssen   The StackTrace is one of the key concepts in Java. It’s a call stack for the thread and lists all method calls since the start of the thread. You have probably seen its … Read More

The post Understanding StackTraces in Java appeared first on FusionReactor Observability & APM.

]]>
[vc_row][vc_column][vc_column_text]

By guest author Thorben Janssen

 

The StackTrace is one of the key concepts in Java. It’s a call stack for the thread and lists all method calls since the start of the thread. You have probably seen its textual representation in your log file or console output. It gets printed to System.out whenever an exception is thrown and not handled by your application. The following snippet shows a typical example of such an output.

java.lang.NumberFormatException: For input string: "123a45"
	at java.base/java.lang.NumberFormatException.forInputString(NumberFormatException.java:68)
	at java.base/java.lang.Long.parseLong(Long.java:699)
	at java.base/java.lang.Long.valueOf(Long.java:1151)
	at org.thoughts.on.java.TestStackTrace.testStackTrace(TestStackTrace.java:17)
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.base/java.lang.reflect.Method.invoke(Method.java:567)
	...

Using monitoring tools, like FusionReactor, or by calling the getStackTrace() method on the current thread, you can access the StackTrace for all active threads in your JVM. But there are other ways to examine and work with a StackTrace.

In most cases, you will not look at a StackTrace until you need to analyze an Exception. The StackTrace is part of an Exception object, and it shows all method calls that happened until the exception was thrown. That shows you where the exception occurred and how you reached that specific part of the code.

In the next step, you can then analyze your code and find out what caused the exception. But that’s a topic for a different article. In this one, I want to tell you more about exceptions with their StackTraces and all the information they provide, so that you have a better understanding of StackTraces in Java.

[/vc_column_text][us_separator][vc_column_text]

Exceptions in Java

An exception gets thrown whenever an error happens within a Java application. It gets represented by an object of the java.lang.Exception class or one of its subclasses. The JDK provides you with a huge set of different Exception classes. If you want, you can also implement your own business exceptions.

It’s a general best practice to use the most specific exception class for each error. A typical example for that is the valueOf method of the java.lang.Long class. You can call it with a java.lang.String and it throws a java.lang.NumberFormatException if the String has a format that can’t be parsed to a Long. The NumberFormatException is a subclass of the IllegalArgumentException, which indicates that an invalid argument value was passed to a method. As you can see, the IllegalArgumentException would describe the error situation, but the NumberFormatException is more specific and should be preferred.

private Long parseToLong(String s) {
	return Long.valueOf(s);
}

Long l;
try {
	l = parseToLong(s);
} catch (NullPointerException npe) {
	// handle NullPointerException
	log.error("No value provided. Using 0 as default.", npe);
	l = 0L;
}
log.info(l);

Using the most specific exception class makes your code easier to read, and it enables you to implement a different catch clause for each exception class. This allows you to handle each error situation differently.

You could, for example, decide to throw a NullPointerException if the provided String is null and throw a NumberFormatException if it doesn’t have the correct format.

private Long parseToLong(String s) {
	if (s == null) {
		throw new NullPointerException("String can't be null");
	}
	return Long.valueOf(s);
}

In the code that calls this method, you can then implement 2 separate catch blocks that handle the NullPointerException and the NumberFormatExceptions in different ways. I did that in the following code snippet to provide different error messages for both situations. But you could, of course, use the same approach to implement a more complex error handling or to provide a fallback to default values.

Long l;
try {
	l = parseToLong(s);
} catch (NullPointerException npe) {
	// handle NullPointerException
	log.error("No value provided. Using 0 as default.", npe);
	l = 0L;
} catch (NumberFormatException nfe)	{
	// handle NullPointerException
	log.error("Provided value was invalid. Using 0 as default.", nfe);
	l = 0L;
}
log.info(l);

[/vc_column_text][us_separator][vc_column_text]

The structure of a StackTrace

In the previous code snippet, I wrote log messages that contained the caught exception objects. The following snippet shows an example of such a message in the log file. Your application writes a similar message for all unhandled exceptions to your console.

15:28:34,694  ERROR TestStackTrace:26 - Provided value was invalid. Using 0 as default.
java.lang.NumberFormatException: For input string: "123a45"
	at java.base/java.lang.NumberFormatException.forInputString(NumberFormatException.java:68)
	at java.base/java.lang.Long.parseLong(Long.java:699)
	at java.base/java.lang.Long.valueOf(Long.java:1151)
	at org.thoughts.on.java.TestStackTrace.parseToLong(TestStackTrace.java:39)
TestStackTrace.java:39
	at org.thoughts.on.java.TestStackTrace.testStackTrace(TestStackTrace.java:18)
TestStackTrace.java:18
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.base/java.lang.reflect.Method.invoke(Method.java:567)

As you can see, the log message contains a long list of class and method names. This is the textual representation of the StackTrace of the exception. Whenever a new method gets called, it gets added to the top of the stack, and after it got executed, it gets removed from the stack. Based on this approach, the last method that got called before the exception occurred is at the top of the StackTrace and logged first. The following elements in the StackTrace and lines in the log file show which methods were previously called to reach the part of the code that caused the exception.

[/vc_column_text][us_separator][vc_column_text]

Using StackTraces to analyze incidents

If you take another look at the previously shown StackTrace, you can see that the exception was created in the forInputString method of the NumberFormatException class. The actual problem occurred in the parseLong method of the Long class, which was called by the valueOf method of the same class, which was called by parseToLong method of my TestStackTrace class. As you can see, the StackTrace provided by the NumberFormatException clearly shows where the exception happened and which chain of method calls lead to it.

This information is a good start to analyze an exception and to find the actual cause of it. But quite often, you will need more information to understand the issue. The Exception object and its StackTrace only describe which kind of error occurred and where it happened. But they don’t provide you with any additional information, like the values of certain variables. This can make it very hard to reproduce the error in a test case.

[/vc_column_text][us_separator][vc_column_text]

How FusionReactor can help

FusionReactor can provide you more information about the error situation. If you want, you can even debug the issues on your live system when it occurs next time.

[/vc_column_text][us_separator][us_image image=”57857″][us_separator][vc_column_text]

The only thing you need to do is to log into the web interface of the FusionReactor instance that monitors your application, select the exception from the “Error History” and go to the “Error Details” tab. There you can activate the debugger for this specific exception.

After you’ve done that, FusionReactor will send you an email when the exception occurs again and pause the thread for a configured amount of time. The email contains the stack trace and information about the variable context. As long as the thread is paused, you can also use FusionReactor’s Production Debugger to debug the error in a similar way as you would in your IDE without affecting any of the other threads of your application.

[/vc_column_text][us_separator][us_image image=”57860″][/vc_column][/vc_row]

The post Understanding StackTraces in Java appeared first on FusionReactor Observability & APM.

]]>
Our move from Confluence to mkdocs https://fusion-reactor.com/blog/our-move-from-confluence-to-mkdocs/ Wed, 18 Dec 2019 07:14:45 +0000 https://fronprem.dev.onpressidium.com/2019/12/18/our-move-from-confluence-to-mkdocs/ [vc_row][vc_column][vc_column_text] For many years the FusionReactor product documentation has been ran on a confluence server. We maintained our own server for many years and currently use the cloud version, but its never really been ticking all the boxes for our … Read More

The post Our move from Confluence to mkdocs appeared first on FusionReactor Observability & APM.

]]>
[vc_row][vc_column][vc_column_text]

For many years the FusionReactor product documentation has been ran on a confluence server. We maintained our own server for many years and currently use the cloud version, but its never really been ticking all the boxes for our product documentation.

For each major release of FusionReactor we have a separate confluence space on the confluence cloud server. This allows users to see the documentation for the each version (excluding minor / bug fix releases) that the customer is running to ensure the screenshots are accurate.

The problem with having many copies of the documentation, for different version of the product, is that users don’t realize that they are reading documentation for the wrong version. This is not something which can be blamed on confluence but how we have been managing this system in the past. Google returns the search results which are most popular and as our 6.2.8 release was the newest release for the longest time, there has been a trend of people finding and using the docs from 6.2.8. Now its difficult for new releases of the documentation to be returned higher in googles search results.

This can be shown by googling for
site:docs.fusion-reactor.com crash protection
you get the following:

[/vc_column_text][us_image image=”57830″][us_separator][vc_column_text]

The image above shows that the actual page for FusionReactor Crash Protection hit doesn’t appear and the first FR 8 crash protection related page is the 7th search result and this is an 8.0.0 hit not 8.2.0. (results will vary from region to region). When google returns so many old versions before the newest FR version it causes customer confusion and impacts our support team.

Another major issue we had when updating documentation for a new release, was that we found it very difficult to update images. We had no idea if there was a screen shot of some UI component on a specific page, so we had to check every page we could find to update the screenshot based UI change.

We have been using markdown and mkdocs for some time in other areas of documentation (like the FR Cloud docs) so we knew that this worked but moving from confluence was not going to be automatic and we had not done this before.

First we needed to get the space content out of Confluence. You can do this by going to the confluence space, selecting “Space Settings”. Then under “Content Tools” there is an “Export” tab, which shows :

[/vc_column_text][us_image image=”57833″][us_separator][vc_column_text]

If you select “HTML” then “Normal Export” to get a HTML file per space page. Once you press “Export” the task will run and give you a zip file of the content to download.

We then converted all the html files to markdown

for i in *.html ; do echo "$i" && pandoc -f html -t markdown_strict -s $i -o $i.md ; done

 

We then use rename and mmv to rename the files to get them from filenames with a name like Weekly-Report_245548143.html.md to Weekly-Report.md.

Using following commands :

rename 's/.html.md$/.md/' *
mmv '*_[0-9]*.md' '#1.md'

 

The following image shows how the html files were converted to markdown files. We can now delete the html files if we want.

[/vc_column_text][us_separator][us_image image=”57834″][us_separator][vc_column_text]

The renaming of files on disk also needs to be reflected in the markdown content. This was relatively simply using replace all with the same regex as we used with the mmv and rename commands.

We then setup the mkdocs and followed this mkdocs-material setup guide and made some customisation to use the FusionReactor icons and social links.

[/vc_column_text][us_separator][us_image image=”57837″][us_separator][vc_column_text]

We managed to quickly get the docs running inside mkdocs as shown above.

The next problem we have going forward, before mkdocs actually replaces the current docs, is to update the documentation and fix it.

On our confluence versions of the docs we had lots of copy and paste content which was updated in one place and not another and we had a lot of broken links and out of date images.

We will continue to repair and improve our mkdocs over the next few weeks and months and then change the DNS entry.

[/vc_column_text][us_separator][vc_column_text]

Benefits of mkdocs

Below is a list of the benefits for mkdocs (as we see it) compared to our confluence documentation system.

 

  • Ability to run automated tools against the docs.
    • Allows checking of dead links.
    • Automate spell checking and readability tools.
    • Easy to find duplicate content and use markdown-include
  • Ability to find and update images in a simply way.

[/vc_column_text][/vc_column][/vc_row]

The post Our move from Confluence to mkdocs appeared first on FusionReactor Observability & APM.

]]>
Signing, Notarizing and Stapling on macOS https://fusion-reactor.com/blog/signing-notarizing-and-stapling-on-macos/ Fri, 13 Dec 2019 07:06:17 +0000 https://fronprem.dev.onpressidium.com/2019/12/13/signing-notarizing-and-stapling-on-macos/ [vc_row][vc_column][vc_column_text] The Gatekeeper system has protected macOS users against malicious software since its introduction in OS X 10.7.3 (Lion). This system assures users that software comes from a trusted source and doesn’t contain malicious content. But how does it work? … Read More

The post Signing, Notarizing and Stapling on macOS appeared first on FusionReactor Observability & APM.

]]>
[vc_row][vc_column][vc_column_text]

The Gatekeeper system has protected macOS users against malicious software since its introduction in OS X 10.7.3 (Lion). This system assures users that software comes from a trusted source and doesn’t contain malicious content. But how does it work?

[/vc_column_text][us_separator][vc_column_text]

Introduction

The Mac software ecosystem has historically been fairly untroubled by malicious viruses and software. This was due in part to the comparatively small user base and partly because the system — which is based on Unix — is naturally partitioned into users and groups, making it difficult for malicious code to obtain administrative privileges.

But the platform is increasing in popularity. Apple’s desktop operating system accounted for approximately 10% of desktop market share in 2019. The same kernel — Apple XNU, a modified Mach microkernel — is also used by the company’s IOS devices: iPhone and Apple Watch. This increasing install base makes the platform an attractive target for malicious software.

Apple has two main strategies in place to protect its users. We’ll look at each stage of this protection regime in the next sections, but broadly they comprise:

 

  • Code Signing: this ensures that code comes from a known, trusted source, and hasn’t been altered since it was signed.
  • Notarization: the code is inspected by Apple to ensure it falls within its safety guidelines; the resulting receipt can be attached to the software permanently, in a process known as “stapling.”

[/vc_column_text][us_separator][vc_column_text]

Code Signing

Signing ensures the code belongs to us and can’t be changed after it’s signed. This is done by the codesign tool, which:

 

  • Creates a secure hash of the code itself (this hash will change if the code is tampered-with after the fact)
  • Signs the hash and the code with our Developer Certificate. This puts our name and details on the code. Apple has checked our credentials and has also signed our Developer Certificate to say that we are a valid, trusted developer.
  • Stamps the resulting signature with the current time. This ensures that if our certificate expires, you can continue to use this software.

Here’s how we test-sign the FusionReactor macOS Native Library, which is used by the FusionReactor Production Debugger:

xcrun codesign --verbose --strict --keychain /Users/jhawksley/Library/Keychains/login.keychain -s CERT_ID_HERE --timestamp target/libfrjvmti_x64.dylib

[/vc_column_text][us_separator][vc_column_text]

Notarization and Stapling

The second stage is to have Apple actually check our code.

The Notarization command looks like this:

xcrun altool --notarize-app --username "our_apple_id@intergral.com" --password "our_password" --primary-bundle-id "com.intergral.bundleid" --file bundle.zip

Before we ship the library to Apple for Notarization, we have to sign it using codesign, and we have to zip it up to minimize the transfer size. The username and password are those of a valid Apple Developer Account.

Notarization is an automated service, which — while not providing usability or design feedback, like App Review — does checks code is correctly signed, and doesn’t contain malicious content.

The result of this is a Notarization Ticket, which is a piece of secure data that Apple sends back to us and also publishes online in the Gatekeeper Code Directory Catalog.

Some types of software — for instance the native library we showed in Code Signing above — don’t have space in their structure for a ticket, so they can’t be stapled. Other types of software, like the FusionReactor macOS Installer, do have space, and the Notarization Ticket obtained above can be stapled to them.

When you run our software on your machine, Gatekeeper automatically checks to see if the software is valid. If there’s a network connection available, Gatekeeper uses the online Code Directory to look up the ticket and checks it against the software. Should no network is available, Gatekeeper uses the stapled ticket.

If a valid ticket is located, Gatekeeper knows that Apple has checked this software and that it meets their standards — and can run.

[/vc_column_text][us_separator][vc_column_text]

Why Bother?

Apple has been gradually tightening up the conditions under which unsigned software can run. In macOS Catalina, this is still possible (you have to turn Gatekeeper off using Terminal commands) although in the future even that may no longer be possible.

When macOS tries to use or install unsigned content on macOS Catalina, you’ll see the following dialog (which can’t be bypassed) — and the content is not opened.

[/vc_column_text][us_separator][us_image image=”57819″][us_separator][vc_column_text]

When content has been correctly signed, Gatekeeper tells you where it came from and lets you decide whether to open it. Here’s what we see when open our (signed, notarized, stapled) installer from our build server.

[/vc_column_text][us_separator][us_image image=”57822″][us_separator][vc_column_text]

Trust, but Verify

If you want to check a signature, this is easy to do. Open the Terminal app, and use the codesign command to retrieve the certificate:

codesign -d --verbose=4 ~/Downloads/FusionReactor_macos_8_3_0-SNAPSHOT.dmg

This spits out the following (excerpted for clarity):

Identifier=FusionReactor_macos_8_3_0-SNAPSHOT
CodeDirectory v=20100 size=179 flags=0x0(none) hashes=1+2 location=embedded
CandidateCDHashFull sha256=f684fe6584f8249c3bfb60c188dd18c614adc29e6539490094947e1e09bbb6c8
Authority=Developer ID Application: Intergral Information Solutions GmbH (R3VQ6KXHEL)
Authority=Developer ID Certification Authority
Authority=Apple Root CA
Timestamp=Dec 5, 2019 at 14:52:15

The Identifier is the file name (minus extension) we signed, and the Identifier and CandidateCDHashFull values tell Gatekeeper how to perform an online lookup of our Notarization Ticket.

The three Authority lines are the chain of trust: they show that Apple has trusted us by checking our details and issued a certificate, whose serial number is R3VQ6KXHEL.

Finally, the Timestamp shows when we actually signed this software. If you try to use it in future, perhaps when our certificate has expired (hopefully there’ll be many new versions of FusionReactor before then!), the Timestamp assures Gatekeeper that the software was signed within the certificate validity period, and should be treated as if the certificate was still valid. Gatekeeper should then continue to open this software indefinitely.

[/vc_column_text][us_separator][vc_column_text]

Automation

It’s possible to automate the signing, notarization and stapling process, but it’s not exactly straightforward.

Apple’s development tool – the venerable Xcode – handles signing, notarization and stapling seamlessly as part of its user interface. Apple does provide command-line tools to perform these tasks (codesign, altool and stapler) but these all make some assumptions that the user running them is logged in.

The exact mechanics of automated signing of Apple binaries are rather beyond the scope of this article. However, we can give you some hints:

 

  • A Jenkins node running on a Mac Mini is used. Apple doesn’t allow virtualization of its hardware, and Docker on Mac is a linux environment, so the node must be a bare-metal Apple environment. Mac Minis are excellent little machines for this.
  • The user under which the Jenkins node is running:
    • Must be logged in to the desktop. This creates an Aqua desktop session for the user — which is valid even if the Jenkins node is launched as that user using ssh. The Aqua session is required to use the code signing tools. The login can be done on the Mac itself, or using Apple Screen Sharing (which is a customized VNC) but the session should be ended by closing the window, not logging the user out.
    • Must have the Apple Developer ID code signing certificate, along with the corresponding private key, installed into its Login Keychain (the default keychain).
    • Must have the keychain unlocked prior to code signing using the command security unlock-keychain

Another wrinkle in the automation of this procedure is that the notarization command (xcrun altool --notarize-app) is asynchronous. Once the code is submitted (which itself can take a couple of minutes), the Apple Notarization Service returns some XML containing a RequestUUID. You have to then poll the Service using this UUID until it returns either success or failure. This can take up to 10 minutes, in our experience. If you don’t parallelize this part of your build, it will be impose a long delay.

[/vc_column_text][/vc_column][/vc_row]

The post Signing, Notarizing and Stapling on macOS appeared first on FusionReactor Observability & APM.

]]>